Forum: Mikrocontroller und Digitale Elektronik Wieso wird alles kompiliert?


von Marcel K. (viewer)


Lesenswert?

Hallo zusammen hier im Forum,

ich programmiere unter WINAVR mit Eclipse Helios an einem Programm mit 
einem Mega128. Dort habe ich eine Tabelle erstellt, mit 256 Elementen. 
Naja, dann waren die Werte nicht ganz zufriedenstellend und dann habe 
ich die Tabelle einfach kopiert, umbenannt und ein paar Werte geändert. 
Wie es natürlich so ist, habe ich das ein drittes Mal gemacht. Also 
hatte ich zum Schluss drei Tabellen mit jeweils 256 Elementen. Alle 
hatten einen anderen Namen und es wurde im Quellcode auch wirklich nur 
einer der drei Tabellen verwendet.

Zu meiner Verwunderung werden aber alle drei Tabellen kompiliert. Das 
kann ich daran erkennen, dass beim „Build“ zum Schluss die benötigten 
RAM-Bytes angezeigt werden. Nur wenn ich die nicht benötigten Tabellen 
wirklich „auskomentiere“ dann werden sie auch nicht verwendet.

Kann man das irgendwo einstellen, dass wirklich nur das kompiliert wird, 
was benötigt wird? Ich habe bereits alle Optimierungsstufen ausprobiert, 
hat aber keinen Erfolg gebracht.
Grüße,
Marcel

von Krapao (Gast)


Lesenswert?

Packe jede Tabelle in ein eigenes Sourcefile! Innerhalb des gleichen 
Sourcefiles schmeisst der Linker ohne Tricks bei den Optionen (Suche im 
Forum...) keine unbenutzte Objekte raus

von Eddy C. (chrisi)


Lesenswert?

Es geht ihm ja nur ums Prinzip. Schreibe mal static vor die Tabellen, 
das könnte helfen.

von Marcel K. (viewer)


Lesenswert?

Hallo Eddy Current,
Du hast recht gehabt, mit führenden "static" bekomme ich jetzt den 
Hinweis, dass diese Tabelle nicht verwendet wird.
Allerdings kann ich das ja bei normalen Variablen kein Static davor 
schreiben. Denn die werden auch kompiliert, auch wenn man sie gar nicht 
im Code verwendet!

Das verstehe ich echt nicht? Dafür ist doch ein Kompiler, dass nichts 
unnötiges kompiliert wird?

Auf jeden Fall schon mal danke für den Tipp!! :o)

von Lukas K. (carrotindustries)


Lesenswert?

Es bietet sich hier an, die Tabellen im Programmspeicher abzuspeichern 
und mit dem Funktionen aus <avr/pgmspace.h> darauf zuzugreifen.

von Oktavian G. (Firma: Hochschule Karlsruhe) (tavin)


Lesenswert?

Marcel K. schrieb:
>> Das verstehe ich echt nicht? Dafür ist doch ein Kompiler, dass nichts
> unnötiges kompiliert wird?

Falsch, der Compiler kompiliert zuerst jeden stück Text was er vors 
Gesicht bekommt. Er ist gar nicht in der Lage zu entscheiden ob es 
benötigt oder überflüssig wird deswegen erstellt er einfach brav seine 
.o Dateien . Das entfernen von Ballast das ist die Aufgabe des Linkers 
und der geht zuerst ganz vorsichtig vor - er läst alles drinn. Er mus 
erst durch bestimmte optionen "Scharfgestellt" werden dammit er 
überflüssiges entfernt.

von Marcel K. (viewer)


Lesenswert?

Guten Morgen zusammen,

@Lukas
Du hast recht, ich habe das jetzt im Forum auch schon öfters gelsen. 
Werde es bei Zeit auch so änderen.

@Oktavian Gniot
Ja ich kann mich auch dunkel daran erinneren, das ich dies mal vor 
langer Zeit irgenwo gelesen habe. Danke für den Hinweis!

Ich habe denoch eine Frage...
Ich habe hier:

http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung

ganz untern in der Rubrik:

"Unbenutzte Funktionen und/oder Variablen entfernen"

gelesen, dass man dem GNU Linker mit --gc-sections, sagen kann, dass er 
unbenutze Sektionen rauswerfen kann. Wo kann ich das den eintragen??

Schönen Tag noch und Grüße,
Marcdel (",)

von testgast (Gast)


Lesenswert?

mach doch einfach um die tabellen ein paar präprozessor-direktiven, so a 
la #ifdef bezeichner... #endif.
dann musst dur nur noch beim compiler den den parameter -D_Bezeichner 
eintragen und kannst zischen mehreren varianten umschalten. und weißßt 
noch, was der compiler macht.

von Krapao (Gast)


Lesenswert?

Linkeroptionen können auf der Kommandozeile (bei direktem Aufruf), im 
Makefile (bei Benutzung von make) oder in den Projektoptionen (bei 
Benutzung einer IDE wie AVR Studio) eingetragen werden.

Ich befürchte aber, das bringt dir bei den Tabellen so ohne weiteres 
nix. Du müsstest IMHO zuerst die Tabellen je in eine extra Sektion 
legen. Derzeit werden die wohl alle in der DATA Sektion liegen. Kannst 
du aber herausfinden, wenn du dir die Linkermap erzeugen lässt und 
anschaust.

von Thomas E. (thomase)


Lesenswert?

Marcel K. schrieb:
> Kann man das irgendwo einstellen, dass wirklich nur das kompiliert wird,
> was benötigt wird?
Schon mal was von Auskommentieren gehört?
Man kann sich die Hose auch mit der Kneifzange anziehen.

mfg.

von robertsl (Gast) (Gast)


Lesenswert?

>> Kann man das irgendwo einstellen, dass wirklich nur das kompiliert wird,
>> was benötigt wird?
>Schon mal was von Auskommentieren gehört?

Oder arebeite doch mit #define, #ifdef, #endif
1
#define Tabelle2
2
3
#ifdef Tabelle1
4
....  // Definiere hier die Tabelle 1
5
#endif
6
7
#ifdef Tabelle2
8
....  // Definiere hier die Tabelle 2
9
#endif
10
11
#ifdef Tabelle3
12
....  // Definiere hier die Tabelle 3
13
#endif

von Marcel K. (viewer)


Lesenswert?

Hallo alle zusammen,
danke für die vielen Antworten!!

Ich weiß das man mit #define arbeiten kann, das mache ich ja auch 
häufig. Ich arbeite aber auch mit dem IAR-Kompiler, dort ist das ganze 
halt viel einfacher. Was nicht benötigt wird, wird auch nicht kopiliert. 
"That's it"

Ich weiß jetzt in Zukunft, dass ich an dieser Stelle halt aufpassen 
muss, ist ja jetzt kein Beinbruch. Schade halt.

Danke für Eure Mühe und bis bald...

Marcel (",)

von Cyblord -. (cyblord)


Lesenswert?

Dateien welche man nicht benötigt lässt man auch auf dem "Build Path" 
sondern nimmt sie von dort raus. Dann werden sie auch nicht kompiliert.
Eclipse erlaubt ja sogar beliebig viele Profile anzulegen, und für jedes 
Profil kann man festlegen welche Dateien gebaut werden und welche nicht. 
So kann man mit einem Klick umschalten welche Tabelle man verwenden 
möchte für den nächste Build.

Wenn die alte Tabelle höchst wahrscheinlich gar nicht mehr gebraucht 
wird,  benutzt ein Versionsverwaltunssystem (CVS,SVN,Git usw.) dann kann 
man bedenkenlos nicht benötigte Dateien löschen. Schützt auch vor 
Auskommentierungsorgien im Code.

Zu einer sauberen SW Entwicklung gehört auch die korrekte Nutzung 
moderner Tools.

gruß cyblord

von Cyblord -. (cyblord)


Lesenswert?

Korrektur:
> Dateien welche man nicht benötigt lässt man auch NICHT auf dem "Build Path"

von Peter D. (peda)


Lesenswert?

Marcel K. schrieb:
> Ich arbeite aber auch mit dem IAR-Kompiler, dort ist das ganze
> halt viel einfacher. Was nicht benötigt wird, wird auch nicht kopiliert.

Der AVR-GCC kann auch eine über alles Optimierung vornehmen:
1
-Wl,--relax --combine -fwhole-program

Alle nicht benötigten Daten/Funktionen fliegen raus, alle nur einmal 
benutzten Funktionen werden geinlined.
Eigene init-Sections muß man daher als used markieren.


Peter

von Marcel K. (viewer)


Lesenswert?

Hallo Peter,

Ddanke für Deine Antwort!
Ich habe solche "Befehle" schon öfters gelesen. Aber ich habe noch nicht 
gefunden wo man das reinschreibt!
Muss das in ein "Makefile"?
Leider benutze ich kein "Makefile"

Kannst Du mir sagen was Du mit "inlie-Section" meinst?
Wo gibt es Infos dazu?

Grüße,
Marcel (",)

von Cyblord -. (cyblord)


Lesenswert?

Es gibt Linker Optionen und Compiler Optionen. Man schreibt das Makefile 
nicht selber, das generiert Eclipse für einen. Man kann in den 
Einstellungen zum Projekt in Eclipse Optionen für Linker und Compiler 
(und viele mehr) einstellen und auch eigene hinzufügen.

Die Befehle von Peter sind natürlich Linker Befehle.

Auf das Projekt -> Properties -> C/C++ Build --> Settings

PS:
> Ich arbeite aber auch mit dem IAR-Kompiler, dort ist das ganze
> halt viel einfacher. Was nicht benötigt wird, wird auch nicht kopiliert.

Du meinst evt. den IAR-Linker?

Denn wie oben schon geschrieben wurde kann ein Compiler gar nicht wissen 
ob öffentliche Funktionen oder Variablen noch gebraucht werden oder 
nicht. Das kann nur der Linker entscheiden. Allerdings sind dann schon 
Dateien compilliert welche aber vom Linker nicht verwendet werden. 
Deshalb nicht benötigte Dateien gar nicht erst dem Compiler zufüttern 
sondern rausnehmen.



gruß cyblord

von Marcel K. (viewer)


Lesenswert?

Hallo zusammen,

@Julian
Wo ich die Linkersettings finde, weiß ich. Allerdings weiß ich nicht wo 
ich die oben erwähnte Zeile eintragen muss.
Wird es unter "Command" eingetragen? Oder bei "other Arguments"?
Du schreibst auch etwas von "Profile". Wie erstellt man den diese? Geht 
das über C/C++ Build/Manage Configurations... ? Wie kann man dann die 
Profile anwählen?
Fragen über Fragen, ich weiß ;o)

Grüße, Marcel(",)

von Cyblord -. (cyblord)


Lesenswert?

Marcel K. schrieb:
> Hallo zusammen,
>
> @Julian
> Wo ich die Linkersettings finde, weiß ich. Allerdings weiß ich nicht wo
> ich die oben erwähnte Zeile eintragen muss.
> Wird es unter "Command" eingetragen? Oder bei "other Arguments"?

"Other Arguments" ist richtig. Du musst bedenken, jede Einstellung dort 
schlägt sich einfach in einem bestimmten Kommandozeilenparameter nieder 
welcher dem Linker beim Aufruf mitgegeben wird. Dafür gibts auch eine 
Vorschau welche das komplette Kommando zeigt.

> Du schreibst auch etwas von "Profile". Wie erstellt man den diese? Geht
> das über C/C++ Build/Manage Configurations... ? Wie kann man dann die
> Profile anwählen?

Ja stimmt, nicht Profile sonder Configurations heißen die. Eclipse hat 
z.B. ein Symbol oben in der Toolleiste in Form eines kleinen 
Drehschalters (bei neben dem Hammer). Dort kann man alle Configurations 
sehen anwählen welche Aktiv sein soll. Sehr viele Einstellungen in 
Eclipse kann man dann für jede Config einzeln einstellen. Auch wenn du 
auf eine Datei im Project Explorer klickst, kannst du auf Ressource 
Configuration und dann auf "Exclude from build" und dort kannst du sagen 
für welche Configs diese Datei NICHT im Build path sein soll. Man kann 
sämtliche AVRDude einstellungen von solchen Configs abhängig machen, wie 
Programmer, Fuses, Taktraten usw usw.
Auch deine Settings sind immer von der Config abhängig, zu sehen oben an 
der Drop Down Liste. Dort gibts auch "Manage Configs...".

gruß cyblord

von Marcel K. (viewer)


Lesenswert?

Hallo zusammen,

@cycyblord __
Also das mit den Configurations ist echt super. Ich habe ein Projekt in 
dem ich sowohl den Master als auch den Slave programmiere. Da muss ich 
hin und wieder mal zwischen den zwei Decvices wechseln. Jetzt kann ich 
einfach die Konfiguration umstellen und den Progammer umstecken und das 
ganze läuft. Jetzt wird nicht mehr der ganze Code kompiliert und muss 
nicht mehr zwischen zwei Projekten wechseln. Der gesamte Code hält sich 
jetzt auch in Grenzen.
Was mich etwas stört, ist dass die Anzeige ob etwas definiert ist oder 
nicht, oft nicht stimmt. Wenn etwas nicht definiert ist, dann wird das 
ganze ja „eingegraut“. Jetzt ist z.B. „MASTER“ definiert, aber Master 
ist „eingegraut“ und SLAVE nicht. Wenn ich aber Müll innerhalb von 
MASTER schreibe, (also in das „eingegraute“ dann bekomme ich eine 
Fehlermeldung. Das heißt, es ist das richtige definiert aber das falsche 
„eingegraut“. Naja, damit muss ich halt leben...

Vielen Dank für den Tip und Grüße,

Marcel(",)

von Peter D. (peda)


Lesenswert?

Marcel K. schrieb:
> Leider benutze ich kein "Makefile"

Ich auch nicht.

Beitrag "Re: AVR Studio schon soweit?"


Peter

von Cyblord -. (cyblord)


Lesenswert?

Marcel K. schrieb:

> Also das mit den Configurations ist echt super.

Die ganze Eclipse IDE ist super. Mir ist bisher noch keine IDE 
untergekommen die der das Wasser reichen kann. Ich arbeite auch viel mit 
MS Visual Studio 2010 Professional, ist ja ne sauteure Geschichte aber 
die Features der IDE sind gegenüber Eclipse richtig ärmlich. Leider 
arbeiten viele damit ohne das Potential auch nur halbwegs auszunutzen.

> Was mich etwas stört, ist dass die Anzeige ob etwas definiert ist oder
> nicht, oft nicht stimmt. Wenn etwas nicht definiert ist, dann wird das
> ganze ja „eingegraut“. Jetzt ist z.B. „MASTER“ definiert, aber Master
> ist „eingegraut“ und SLAVE nicht. Wenn ich aber Müll innerhalb von
> MASTER schreibe, (also in das „eingegraute“ dann bekomme ich eine
> Fehlermeldung. Das heißt, es ist das richtige definiert aber das falsche
> „eingegraut“. Naja, damit muss ich halt leben...

Dieses Verhalten konnte ich bisher noch nicht feststellen. Eigentlich 
kann Eclipse das mit den #defines schon richt handlen. Benutzt du eine 
aktuelle Eclipse Version? Das muss irgendeinen Grund haben, als Bug 
scheint mir das etwas plump zu sein als das es einfach so ungefixt drinn 
sein soll.

gruß cyblord

von Peter D. (pdiener) Benutzerseite


Lesenswert?


von Marcel K. (viewer)


Lesenswert?

Hallo zusammen,

@cyblord __
also ich hatte Helius und bin jetzt auf indigo. Naja da ist mir 
plötzlich der Rechner abgeschmiert. Habe jetzt die Projekt-Arbeit von 
den letzten zwei Tagen verloren da mein Repository im Moment nicht 
funktioniert. SCHEI** Naja es hilft nicht über vergossen Milch zu 
weinen!! Werd es hoffentlich wieder auf einen vernünftigen Stand 
bringen.

@Peter Diener
Danke für den Link. Den habe ich auch schon gefunden. Leider scheitert 
das ganze daran, das ich nicht weiß wo ich "-ffunction-sections 
-fdata-sections" eintragen muss. Solche Optionseinstellungen habe ich 
schon öfters im Netz gesehen aber keiner Erklärt wo man das ganze 
eintragen muss. Ich konnte auch keine Infos oder How-To's im Netz finden 
:o(

Grüße,
Marcel (",)

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Die Einstellungen müssten hier sein:

Project / Properties -> C/C++ Build / ToolSettings -> GCC-C-Compiler -> 
Command

bzw. für den Linker:

Project / Properties -> C/C++ Build / ToolSettings -> GCC-C-Linker -> 
Miscellaneous: Linker Flags

Quelle zum Nachlesen:
http://www.mikrocontroller.net/articles/AVR_Eclipse

Ich habe gerade kein Eclipse hier, kann das daher nicht testen. Aber 
prinzipiell muss man einfach nur dafür sorgen, dass die entsprechenden 
Parameter in dem Compiler- und Linkeraufruf übergeben werden.

Grüße,

Peter

von Marcel K. (viewer)


Lesenswert?

Hallo zusammen,
ich habe jetzt einige Stunden damit verbracht das ganze so hin zu 
bekommen, dass nur der Code im Projekt kompiliert wird, der auch 
benötigt wird. Mit Hilfe dieses Forums habe ich es auch hin bekommen. 
Damit jeder etwas davon hat, erkläre ich gerne was ich gemacht habe.

Erst habe ich folgende programmiert, damit ich es auch testen kann ob es 
wirklich funktioniert. (nur Beispielhaft, daher stark vereinfacht)

#ifdef MASTER
Void  init_master(void)
{…}
#endif

#ifdef SLAVE
Void  init_slave(void)
{…}
#endif

Void main(void)
{
#define MASTER


#ifdef MASTER
init_master();
#endif

#ifdef SLAVE
init_slave();
#endif

}

Am Anfang war es so,  dass ja SLAVE nicht definiert war. Also wurde auch 
oben die Fkt. "init_slave()" nicht erzeugt. Allerdings bekam ich in der 
main eine Fehlermeldung, dass die Fkt. "init_slave()" nicht existiert. 
Ich bin halt davon ausgegangen, dass wenn SLAVE nicht definiert ist, es 
auch egal ist was innerhalb dieser ifdef steht.

Jetzt habe ich folgende Einstellungen gemacht!

Unter:

Projekt/Properties/C/C++ Build/Settings/AVR Compiler/Miscellaneous/Other 
flags

-ffunction-sections -fdata-sections

eingetragen.

Und unter:

Projekt/Properties/C/C++ Build/Settings/AVR C Linker/General/Other 
Arguments

-Wl,--gc-sections

eingetragen.

Dabei habe ich mich an den folgenden Link gehalten:

http://www.mikrocontroller.net/articles/GCC:_unbenutzte_Funktionen_entfernen

Jetzt wird das ganze ohne Fehler kompiliert und mein Projekt hat jetzt 
auch weniger Platzbedarf. Allerdings konnte ich das ganze noch nicht auf 
Herz und Nieren zu testen. Bis jetzt sieht es aber gut aus.

Viele Grüße und Danke an alle die mir in diesem Beitrag geantwortet 
haben!!!

Marcel(",)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.