UPDATE: Korrigierte main.cpp, aber gleiches Problem (das größere Archiv ist das richtige) ------------------------------------------------- Ich scheitere aktuell an dem Versuch, ein Symbol/Objekt extern in ein avr-Programm zu linken. Da das Gesamtprojekt zu komplex ist, habe ich ein kleines Beispiel mit genau diesem Problem gestrickt, es ist komplett im zip-Archiv vorhanden. Hier das (korrigierte) Beispiel: -------------------------- #pragma GCC optimize ("0") #include "Bitmap.h" #include <avr/pgmspace.h> #include <avr/io.h> #include <stdint.h> extern Bitmap bm; extern const Bitmap cbm; extern const Bitmap PROGMEM cbmp; int main(void) { // irgendwie verwenden, ansonsten sinnlos PORTB = bm.xsize; // ok PORTC = pgm_read_byte(&(cbm.xsize)); // undefined reference to `cbm' PORTD = pgm_read_byte(&(cbmp.xsize)); // undefined reference to `cbmp' while(1) ; } // main ----------------------- Zuerst habe ich erst mal alle Optimierungen ausgeschaltet, die haben mich schon öfter gefoppt. Ansonsten simpler Code. Ich möchte eine Bitmap im Flash ablegen, und diese nicht in "main.cpp" halten, sondern in einer externen Quelle. Die Bitmap mit in main.cpp zupacken is keine Option: Im richtigen Leben handelt es sich dabei um ein paar Fonts, die selektiv zum finalen Binary gelinkt werden, was üblichweise ja auch funktioniert. Zunächst dachte ich, dass meine Migration von C nach C++ mir da einen Streich spielt, weil das 'extern' da wohl eine etwas andere Semantik hat. Deshalb habe ich es mit beiden Sprachen versucht (siehe makc und makcpp im Archiv). Aber es bleibt sich gleich. Die Dateiendung 'cpp' heißt ja nichts, es wäre sinnlos, die exakt gleiche Source noch mal als 'c' Datei beizufügen. Das kommt dabei raus: -------------------- $ avr-gcc -mmcu=atmega328p -DF_CPU=16000000UL \ -Wall -funsigned-char -save-temps -mcall-prologues \ Bitmap.cpp main.cpp --output main.elf -Wl,-Map=main.map,--cref main.o: In function `main': main.cpp:(.text+0x1e): undefined reference to `cbm' main.cpp:(.text+0x2a): undefined reference to `cbmp' collect2: error: ld returned 1 exit status Compilation exited abnormally with code 1 at Wed Nov 20 14:13:51 ---------------- Sobald ich die Bitmap 'const' oder gar const PROGMEM definiere, steigt der Linker aus. Raff ich nicht. Ich bilde mir ein, das schon etliche Male so gemacht zu haben, aber irgendwas übersehe ich wohl. Bin dankbar für jeden Hinweis. PS: Ich habs mit zwei Compiler Versionen versucht, der 7.3.0 und zuletzt der 4.9.2: $ avr-gcc --version avr-gcc (GCC) 4.9.2 $ avr-g++ --version avr-g++ (GCC) 4.9.2
:
Verschoben durch Admin
E. H. schrieb: > extern Bitmap bm; > extern const Bitmap cbm; > extern const Bitmap PROGMEM cbmp; Das sind nur Deklarationen. Wo sollen denn den die Definitionen sein. Die ODR muss schon beachtet werden.
> Wo sollen denn den die Definitionen sein.
In Bitmap.cpp. Steht mit im Compiler-Aufruf, s.o.
Siehe 'extern Bitmap bm;' Wird ja auch korrekt aufgelöst. Die
Linker-Fehler kommen nur bei den 'const' Varianten.
E. H. schrieb: > In Bitmap.cpp. Steht mit im Compiler-Aufruf, s.o. Sorry, hatte das .zip nicht gesehen. Bei C++ bedeutet const immer internal-linkage. Du musst also bei der Definition extern const schreiben.
E. H. schrieb: > Zuerst habe ich erst mal alle Optimierungen ausgeschaltet, die haben > mich schon öfter gefoppt. Wenn das passiert, hast Du versteckt in Deinem Code UB drin, sprich, Dein fehlerhaftes Programm läuft mit -O0 scheinbar korrekt. Bei -O1, ... fällt dann das UB aber auf. Es ist also nicht der Fehler des Compilers, wie Du meinst, sondern Deiner.
Hammer! Tausend Dank! Das löst zunächst mal mein Problem. :-) Was ich nicht verstehe: Das Problem besteht auch in 'C', wenn ich also mit 'gcc' kompiliere. Dabei habe ich das "schon immer" (tm) so gemacht. Dachte ich jedenfalls. Könnten aber auch elementare Typen gewesen sein, mit denen gehts auch ohne 'extern' bei der Definition. Wie auch immer: Ich kann erst mal weiter machen. Wenn es in 'C' auch das Schlüsselwort 'extern' braucht, muss ich meine Erfahrungen wohl mal überdenken. Könnte aber sein, dass ich composite-Typen (structs, Klassen et. al.) in den letzten 20 Jahren tatsächlich nie als extern-Referenz eingesetzt habe. Das 'extern' Schlüsselwort war (und ist) in den Projekten, in denen ich mitgearbeitet habe immer verpönt (Server-Anwendungen, embedded mache ich nur privat zur Entspannung). --- Zum Thema allgemein, was ich da überhaupt mache: Embedded Sachen mache ich eigentlich seit je her in 'C', zuweilen mit ein paar Schnipseln Assembler. Da fühle ich mich sicher - auch wenn mich das aktuelle Problem hier gerade doch etwas verunsichert hatte ;-). Nun kommt man ja irgendwie nicht umhin, sich mal ein eigenes Bild von C++ auf µP zu machen. Ein paar Threads hier habe ich dazu gelesen, aber ich denke, ein eigenes, etwas größeres Projekt ist der ideale Prüfungsfall. Aus diesem Grund bin ich dabei, eine gut laufende C-Bibliothek nach C++ zu migrieren. Zunächst erst mal kompilierbar zu machen (ohne 'extern "C"' Tricks), Fehler- und Warnungsfrei zu bekommen, und dann Stück für Stück die Goodies aus der C++ Welt zu verwenden. Damit meine ich Compile-Time Argumente für konstante Composite-Typen (i.e.: template-Parameter), namespaces - weil die wirklich was bringen, und sicher noch ein paar andere nützliche Dinge. Das Ziel ist, eine vernünftige, also noch lesbare Abstraktion hin zu bekommen, und so wenig wie möglich Parameter während der Laufzeit hin- und her zu schaufeln, denn vieles geht ja in C++ mit den genannten template-Parametern. Die mag ich zwar nicht, aber wenns der Lösungsfindung dient ... Das ist jedenfalls der Hintergrund. Nochmals danke für die flotte Hilfe!
E. H. schrieb: > Was ich nicht verstehe: Das Problem besteht auch in 'C', Du kompilierts bestimmt als: gcc abc.cc oder gcc abc.cpp oder? Dann aerbeitet der gcc im C++-Mode.
E. H. schrieb: > Ja stimmt, werd ich mal anders probieren. gcc -x c abc.cpp schaltet unabhängig von irgendwelchen Heuristiken C-Language ein.
Eben probiert, stimmt. Das ist wieder so ein schlauer Automatismus, wie sie mich dutzendweise nerven. Wenn ich 'gcc' aufrufe, möchte ich ein C-Programm kompilieren, egal welche Dateierweiterung das hat. Scheint wieder so eine Windows-Allüre zu sein (das ist diese komische Anwendung, die Programme am Namen '*.exe' erkennt). Was für ein Schwachfug.
E. H. schrieb: > Wenn ich 'gcc' aufrufe, möchte ich ein C-Programm kompilieren, > egal welche Dateierweiterung das hat. Scheint wieder so eine > Windows-Allüre zu sein (das ist diese komische Anwendung, die Programme > am Namen '*.exe' erkennt). Nein. Das liegt daran, dass gcc fälschlicherweise mit gnu-c-compiler assoziiert wird. Es bedeutet aber gnu-compiler-collection (c, c++, obj-c, ada, fortran, ...)
:
Bearbeitet durch User
> Das liegt daran, dass gcc fälschlicherweise mit gnu-c-compiler > assoziiert wird. Es bedeutet aber gnu-compiler-collection Das weiß ich. Dass nun aber gcc die Dateiendung zur Indentifikation seiner Aufgabe verwendet ist zumindest nicht das *ix-Paradigma, welches auf Dateinamens-Erweiterungen ja noch nie viel gegeben hat. Dafür gab es seit je her '[/usr/share/file/]magic'. Und vor allem: Wozu dann das 'g++' Kommando ? Damit kann ich doch explizit angeben, was ich möchte? Jedenfalls wäre Letzteres bei so viel Schlauheit - wenn diese denn funktionieren würde - überflüssig. Mir ist das noch nie in die Quere gekommen, weil ich meine Dateien ansonsten nach gängigen Normen benenne. Was auch gut so ist, weils andernfalls in die Hose gehen kann, wie ich mit diesem Fall hier wohl zur Kenntnis nehmen muss: Es kann nämlich durchaus sein, dass ich deshalb Stunden verplempert habe, weil ich zu Testzwecken die 'falschen' Dateinamen verwendet habe. Ja isses toll. Nur meine 2 Cent. Trotzdem wieder was gelernt. Wusste ich nicht, danke.
:
Bearbeitet durch User
E. H. schrieb: > Und vor allem: Wozu dann das 'g++' Kommando ? Damit kann ich doch > explizit angeben, was ich möchte? Jedenfalls wäre Letzteres bei so viel > Schlauheit - wenn diese denn funktionieren würde - überflüssig. Nicht ganz, weil der Aufruf desselben Executables als g++ bedeutet, dass auch die libstdc++ hinzugebunden wird, was bei gcc nicht passiert.
Beitrag #6046076 wurde von einem Moderator gelöscht.
Es lässt sich sicher ein Begründung finden. Dennoch finde ich solche Programm-Eigenmächtigkeiten ohne explizite Anweisung wenig sinnvoll, ich sehe den Mehrwert nicht. Im Gegenteil, das kann auch nett in die Hose gehen. Mich grauts vor Programmen, die "annehmen", sie wüssten, was der Nutzer will. Der einzige, der das wirklich weiß, bin (in meinem Fall) ich. Fatal vor allem, wenn man so wie ich doch tatsächlich noch dran glaubt, dass Kommandos (i.e. Programmaufrufe) unter Linux nur genau das tun, was man per Aufruf auch festlegt. Dazu gehört m.E. nicht, dass Anwendungen nun anfangen, besonders schlau zu sein. Ich wüsste nämlich z.B. nicht, dass irgendwo festgelegt wäre, mit welchen Buchstaben der Name einer Quelldateai von Tyxp 'C/C++' et.al. aufzuhören hätte. Da ist die "Annahme", es müsse sich bei bestimmten Endungen um bestimmte Programmtypen handeln durchaus kühn. Schon (und vor allem) die Unterscheidung 'c' und 'C' ist da kritisch, denn nicht alle Systeme können das überhaupt unterscheiden (div. Windows Versionen, OS400, 3270-Umgebung u.a.). Genau das macht der gcc aber, wie ich nach Deinem Hinweis vorhin mit Erstaunen nachlesen konnte. Aber auch solcher Unfug (Gross-Kleinschreibung zu ignorieren) ist ja neuerdings auf dem Weg ins Linux-Land. Spätestens dann wirds mit der "intelligenten" Unterscheidung von '*.c' und '*.C' schwierig werden. Da lach ich dann schon mal im Voraus. :-)
:
Bearbeitet durch User
E. H. schrieb: > Mich grauts vor Programmen, die "annehmen", sie wüssten, was der Nutzer > will. Dann halte dich von Apple Produkten fern.
E. H. schrieb: > Dazu gehört m.E. nicht, dass Anwendungen nun anfangen, besonders schlau > zu sein. Ich wüsste nämlich z.B. nicht, dass irgendwo festgelegt wäre, > mit welchen Buchstaben der Name einer Quelldateai von Tyxp 'C/C++' > et.al. aufzuhören hätte. Da ist die "Annahme", es müsse sich bei > bestimmten Endungen um bestimmte Programmtypen handeln durchaus kühn. Wieso hast du dann den Compiler mit Dateien gefüttert, ohne ihm zu sagen was genau das für Dateien sind? Bist du etwa davon ausgegangen, dass er magisch weiß was er damit machen soll?
E. H. schrieb: > Dennoch finde ich solche Programm-Eigenmächtigkeiten ohne explizite > Anweisung wenig sinnvoll Na ja, der gcc macht das seit Anbeginn der Zeitrechnung so, und das ganz unabhängig vom Betriebssystem, auf dem er läuft. Und ganz ohne RTFM ist die Nutzung solcher Tools halt Glückssache. Oliver
> Bist du etwa davon ausgegangen, dass er > magisch weiß was er damit machen soll? Ich bin davon ausgegangen, dass 'gcc' eine C-Quelle erwartet, und 'g++' eine C++ Quelle. So wie ich z.B. auch davon ausgehe, das 'rm' die Datei/en, die angebe, löscht. Bei 'gcc' habe ich mich getäuscht.
Oliver S. schrieb: > E. H. schrieb: >> Dennoch finde ich solche Programm-Eigenmächtigkeiten ohne explizite >> Anweisung wenig sinnvoll > > Na ja, der gcc macht das seit Anbeginn der Zeitrechnung so, und das ganz > unabhängig vom Betriebssystem, auf dem er läuft. > > Und ganz ohne RTFM ist die Nutzung solcher Tools halt Glückssache. > > Oliver Man muss nicht sehr lange in dem FM lesen. Die ersten zwei Zeilen der gcc-man-page:
1 | NAME |
2 | gcc - GNU project C and C++ compiler |
> Und ganz ohne RTFM ist die Nutzung solcher Tools halt Glückssache.
Dem stimme ich durchaus zu. Allerdings hat es auch etwas mit Gewöhnung
zu tun, und sicher z.T. auch mit Annahmen, die dann man revidieren muss.
Das stelle ich gar nicht in Abrede.
Im Übrigen bezweifle ich stark, dass sich so leicht jemand finden lässt,
der alleine die 'man' Pages von gcc wirklich durchgelesen hat. Sie
finden sich im angehängten PDF: 358 Seiten. Da kann einem so was wie
Namenssensitivität schon mal entgehen, insbesondere wenn man viele Jahre
lang mit deren Auswirkungen nicht in Berührung gekommen ist.
Das geht aber alles völlig an der Frage vorbei, ob Dateierweiterungen
ein haltbares Kriterium für deren Inhalt sind.
Ich finde nicht. Aber das ist nur meine Meinung.
:
Bearbeitet durch User
E. H. schrieb: > Ich finde nicht. Aber das ist nur meine Meinung. Das ist das schöne an Meinungen: Jeder kann problemlos beliebig viele davon haben. Oliver
E. H. schrieb: > Dafür gab es seit je her '[/usr/share/file/]magic'. Sicher. Aber wie Du sicher weißt, funktioniert das zu 100% nur bei Binärdateien, die mit einer Magic-Number beginnen. Bei Text-Files ist auch libmagic auf eine Heuristik angewiesen. Und die geht genauso oft schief, Du darfst das gerne mit dem Kommando file an Deinen C++-Quellen einmal ausprobieren. Die werden nämlich von file als C-Source erkannt. Nun haben wir also zwei Heuristiken: einmal libmagic und einmal den Namenssuffix. Der gcc benutzt die zweite Heuristik, die für solche ähnlichen bzw. identischen Dateiinhalte wie C vs C++ die bessere ist.
Oliver S. schrieb: > E. H. schrieb: >> Dennoch finde ich solche Programm-Eigenmächtigkeiten ohne explizite >> Anweisung wenig sinnvoll > > Na ja, der gcc macht das seit Anbeginn der Zeitrechnung so, und das ganz > unabhängig vom Betriebssystem, auf dem er läuft. Was einfach daran liegt, dass der Compiler-Treiber (um den handelt es sich bei "gcc", oder auch beim klassischen "cc") schon immer verschiedene Arten von Eingabedateien akzeptieren konnte: Assemblerquelldateien mit und ohne Preprocessing, C-Dateien, Objektmodule, Objekt-Bibliotheken. Die wurden seit jeher anhand der Dateinamensendung unterschieden. Also sowas wie:
1 | cc startup.S mycode.c topsecretobject.o foreignlibrary.a -o foobar -lm |
In Abhängigkeit dessen, was er zu verarbeiten hat, wirft er die einzelnen Backends an: Präprozessor (inzwischen implizit im Compiler, früher ein separates Binary), Compiler, Assembler, Linker.
:
Bearbeitet durch Moderator
> In Abhängigkeit dessen, was er zu verarbeiten hat, wirft er die > einzelnen Backends an: Präprozessor (inzwischen implizit im Compiler, > früher ein separates Binary), Compiler, Assembler, Linker. Das hat sich, wie ich vorhin beim Quer-Lesen der man-Pages feststellen musste, enorm entwickelt. In meiner DLD Zeit (Deutsche Linux Distribution, Kernel 0.99xyz, um 1990, drei oder vier Dutzend Disketten), machte ich die ersten Schritte mit gcc. Damals war das "der C-Compiler" unter Linux. Irgendwann wurde ich dann zwar schon gewahr, dass gcc tatsächlich die Gnu Compiler Collection ist, aber in meiner Praxis hatte ich immer 'gcc' für die Kompilierung von *.c Sources verwandt, und später 'g++' für die Kompilierung von '*cpp' oder '*cxx' Sources. So blieb das über die Jahre, alles andere war eher ausgeblendet (ich brauchte es nicht). So lernt man dann halt durch Erfahrung hinzu. So wie ich in diesem Fall jetzt, in dem es dann tatsächlich mal relevant wurde. Man lernt auch noch kurz vor der Rente - was ja nicht schlecht ist.
:
Bearbeitet durch User
E. H. schrieb: > Das ist wieder so ein schlauer Automatismus, wie sie mich dutzendweise > nerven. Wenn ich 'gcc' aufrufe, möchte ich ein C-Programm kompilieren, Du willst also, dass beim Aufruf gcc modul1.o modul2.o main.o -o main.elf modul1.o, modul2.o und main.o also C-Dateien interpretiert werden? Kein Problem: Verwende anstatt gcc — was ja nur ein Compiler-Treiber ist, einfach cc1 modul1.o modul2.o main.o -o main.elf Also: C-Code = cc1 C++-Code = cc1plus Assembler = as Objects = ld LTO-Code = lto1 > Was für ein Schwachfug. Nur die falschen Tools verwendet! Nimm cc1 und du wirst glücklich. Und nach 5 Minuten noch glücklicher, dass es gcc und g++ gibt ;o)
E. H. schrieb: > und später 'g++' für die Kompilierung von '*cpp' oder '*cxx' Sources. Das ist auch völlig korrekt. Es ändert nämlich insbesondere die Argumente beim Linken. Setz' ein "-v" zur Kommandozeile hinzu, und der Compiler-Treiber erzählt dir, was er im Hintergrund alles wie werkeln lässt.
E. H. schrieb: > Mir ist das noch nie in die Quere gekommen, weil ich meine Dateien > ansonsten nach gängigen Normen benenne. Was auch gut so ist, weils > andernfalls in die Hose gehen kann, wie ich mit diesem Fall hier wohl > zur Kenntnis nehmen muss: Hast du echt gedacht, dass erstmal das ganze File analysiert wird, um am Inhalt zu erkennen, ob das jetzt C oder C++ sein soll, bevor der eigentliche Compiliervorgang startet? Das wäre nicht nur langsam, sondern auch unzuverlässig. Es kann ja durchaus auch sein, dass man es am File selbst gar nicht erkennt, sondern nur an irgendeinem der eingebundenen Header. Oder daran, womit es später mal zusammengelinkt wird. Das kann also im Gegensatz zu einer Namensendung nicht sauber funktionieren.
Rolf M. schrieb: > Hast du echt gedacht, dass erstmal das ganze File analysiert wird, um am > Inhalt zu erkennen, ob das jetzt C oder C++ sein soll, bevor der > eigentliche Compiliervorgang startet? Das habe ich oben schon geschrieben. ich glaube, er hat einfach nicht bedacht, dass seine Forderung nicht erfüllbar ist. Denn C und C++ kann identischer Code sein. Er wünscht sich also ein Compiler-Frontend, dass eine Entscheidung trifft, die unmöglich ist. Bzw. die nur von außen vorgebbar ist. Zudem wusste er selbst nicht genau, wie übersetzt werden soll ... da wird es dann schwierig für das Frontend.
Hallo Johann, > Du willst also, dass beim Aufruf > gcc modul1.o modul2.o main.o -o main.elf > modul1.o, modul2.o und main.o also C-Dateien interpretiert werden? ich nehme an, dass die '*o' als Binärdateien erkannt und an ld weiter gereicht werden. Da wäre gcc dann nur eine Durchreiche. Da ich aber Deinen Hintergrund kenne, verbietet mir mein Respekt echten Widerspruch. Ich hab ja oben geschrieben, dass ich immer noch dazu lerne bzw. es zumindest versuche. Allerdings frage ich mich immer noch, ob die Endungen von Dateinamen bei der Einführung case-insensitiver Dateisysteme noch als Erkennungsmerkmal haltbar sein werden. Es sein denn, die betroffenen Tools werden für solche Konfigurationen einfach nicht freigegeben. Was ich verstehen würde.
:
Bearbeitet durch User
E. H. schrieb: > Allerdings frage ich mich immer noch, ob die Endungen von Dateinamen bei > der Einführung case-insensitiver Dateisysteme noch als Erkennungsmerkmal > haltbar sein werden. Wer will denn so einen Murks! Ich denke, gcc geht von einem Posix-konformen OS aus.
E. H. schrieb: > Allerdings frage ich mich immer noch, ob die Endungen von Dateinamen bei > der Einführung case-insensitiver Dateisysteme noch als Erkennungsmerkmal > haltbar sein werden. Welche "case-insensitiven Dateisysteme" meinst du? CP/M, RSX-11? FatFS oder NTFS sind nicht per se "case insensitive", sie sind als Dateisystem "case preserving". Nur die Windows-Systemaufrufe darüber sind case insensitive. Daher ist es unter Windows auch nicht möglich, "foobar.S" in "foobar.s" umzubenennen, denn aus Sicht der Windows-Systemaufrufe sind beides die gleiche Datei, obwohl sie dir durchaus mit der im Dateisystem gespeicherten Groß-/Kleinschreibung angezeigt werden. Aber das Dateisystem entscheidet hier sowieso nichts. Entscheidend ist lediglich, ob du dem Compiler-Treiber gegenüber auf der Kommandozeile die Datei dann "foobar.s" oder "foobar.S" nennst: im zweiten Falle würde er vor dem Asssemblerlauf noch den Präprozessor drüber schicken. Unter Windows würde er in beiden Fällen dann sowohl "foobar.s" als auch "foobar.S" als akzeptable Quelldatei finden.
E. H. schrieb: > Hallo Johann, > >> Du willst also, dass beim Aufruf >> gcc modul1.o modul2.o main.o -o main.elf >> modul1.o, modul2.o und main.o also C-Dateien interpretiert werden? > > ich nehme an, dass die '*o' als Binärdateien erkannt und an ld weiter > gereicht werden. Da wäre gcc dann nur eine Durchreiche. Im Prinzip ja. > Allerdings frage ich mich immer noch, ob die Endungen von Dateinamen bei > der Einführung case-insensitiver Dateisysteme noch als Erkennungsmerkmal > haltbar sein werden. Je nach Endung. Ein Problem wäre dort, dass .c für C-Dateien steht, .C aber für C++, oder dass .s für Assembler-Code ohne und .S für welchen mit Präprozessorlauf steht. Und es gibt noch andere Inkompatibilitäten mit bestimmten Dateisystemen, wie z.B. dass .c++ bei manchen nicht geht, weil kein + in Dateinamen erlaubt ist. Man kann's halt nicht allen recht machen. Und natürlich werden ggf Dinge wie .cPp nicht erkannt, weil es entweder .cpp oder .CPP sein muss. Jörg W. schrieb: > Nur die Windows-Systemaufrufe darüber sind case insensitive. Kann man anscheinend bei Windows 10 umschalten - lustigerweise sogar pro Verzeichnis. https://www.howtogeek.com/354220/how-to-enable-case-sensitive-folders-on-windows-10/ Offenbar wurde das für WSL eingeführt.
:
Bearbeitet durch User
Jörg W. schrieb: > Was einfach daran liegt, dass der Compiler-Treiber (um den handelt es > sich bei "gcc", oder auch beim klassischen "cc") schon immer > verschiedene Arten von Eingabedateien akzeptieren konnte: Oder anders gesagt, das ist ein Grundprinzip vom gcc (und von vielen anderen Compilern). Sich darüber aufzuregen ist einfach Realitätsverweigerung. Oliver
E. H. schrieb: >> Du willst also, dass beim Aufruf >> gcc modul1.o modul2.o main.o -o main.elf >> modul1.o, modul2.o und main.o also C-Dateien interpretiert werden? > > ich nehme an, dass die '*o' als Binärdateien erkannt und an ld weiter > gereicht werden. *.o sind hier keine Binärdateien, sondern (ELF) Object-Dateien. Als Binärdatei würde ich bezeichnen, was ohne jegliche Transformation verwendet wird, zum Beispiel per .incbin im Assembly. > Da wäre gcc dann nur eine Durchreiche. > > Ich hab ja oben geschrieben, dass ich immer noch dazu lerne bzw. es > zumindest versuche. Und es lernt sich besser, wenn man Sinn und Zweck kennt. Wie Jörg oben schieb: Gib einfach mal allen gcc/g++ Ausrufen zusätzlich -v oder noch besser -v -Wl,-v mit. Da ist schon einiges was gcc da an Optionen zusammenstöpselt. Das will man nicht händisch machen. Ein häufiger Fehler beim Linken ist zum Beispiel, dass ld direkt aufgerufen wird aber nicht mit den richtigen Optionen, etwa für Multilib-Auswahl oder Plugin-Aufrufe wie bei LTO (-flto). > Allerdings frage ich mich immer noch, ob die Endungen von Dateinamen bei > der Einführung case-insensitiver Dateisysteme noch als Erkennungsmerkmal > haltbar sein werden. Bei .c / .C und .S / .s hat man dann eine blöde Kombination von Endung und OS oder Filesystem. Also einfach von Anfang an allen Problemen aus dem Weg gehen indem man das vermeidet und C++ .cpp nennt. Und Assembly-Quellen als .sx. Ist mir 1× unter Windos passiert, dass ich im Makefile eine clean Rule hatte mit rm -f *.s um Überbleibsel von -save-temps aufzuräumen. Und *.S Assembly-Quellen. Seither verwende ich *.sx für Assembly.
Wilhelm M. schrieb: > Wer will denn so einen Murks! Tja, das dachte ich auch immer. Linux, Kernel 5.2: "Das Ext4-Dateisystem kann jetzt Groß- und Kleinschreibung ignorieren." Siehe https://www.heise.de/ct/artikel/Linux-5-4-freigegeben-exFAT-Support-und-Einschraenkungen-fuer-Root-4541639.html?seite=all. Der Wahnsinn grassiert. Dann werden Dateiendungen *.c vs. *.C für gcc auch unter Linux kein verlässliches Attribut mehr sein.
Rolf M. schrieb: > Hast du echt gedacht, dass erstmal das ganze File analysiert wird, um am > Inhalt zu erkennen, ob das jetzt C oder C++ sein soll, bevor der > eigentliche Compiliervorgang startet? Wie Du meinen Antworten entnehmen könntest, bin ich davon ausgegangen, dass 'gcc' und 'g++' zwei unterschiedliche Dateitypen erwarten. Das war ja nun keine vollkommen abwegige Annahme. Aber das ist nun geklärt. Ich lerne, wie ich ja schon geschrieben habe, immer noch dazu.
:
Bearbeitet durch User
Kleine Korrektur: Ich meinte natürlich Kernel 5.4, und der Heise-Link oben ist auch falsch. Ich meinte diesen hier (falsches Copy & Paste): https://www.heise.de/ct/artikel/Linux-5-2-freigegeben-Aenderungsrekord-und-Geschwindigkeitsverbesserungen-4424484.html
:
Bearbeitet durch User
E. H. schrieb: > Dann werden Dateiendungen *.c vs. *.C für gcc auch unter Linux kein > verlässliches Attribut mehr sein. Auch du hast noch nicht begriffen, dass das gar nicht vom Dateisystem abhängt, sondern ausschließlich davon, was du dem Compiler auf der Kommandozeile sagst. Nennst du die Datei auf der Kommandozeile foo.c, wird sie als C-Sourcecode betrachtet, nennst du sie foo.C, wird sie als C++ angesehen. Inwiefern das Dateisystem für beide Namen die gleiche Datei finden würde oder nicht, interessiert den Compiler gar nicht. Es wurde oben schon geschrieben, wirklich „interessante“ Effekte hat man dabei eher an unerwarteten Stellen: eine "clean"-Regel eingerichtet, die *.s löscht (weil dies ja sonst nur als Assembler-Zwischencode anfällt), und man hat echte Assemblerquellen wie foo.S dabei, dann räumt einem "make clean" die Assemblerquellen mit ab, wenn das Dateisystem die Namen nicht unterscheiden kann. :-o
Jörg W. schrieb: > Auch du hast noch nicht begriffen, dass das gar nicht vom Dateisystem > abhängt, sondern ausschließlich davon, was du dem Compiler auf der > Kommandozeile sagst. Ob der Compiler per default die Endung als Attribut zur Identifikation des Dateiinihaltes nimmt oder nicht, hängt ausschließlich vom Compiler ab. Was der Compiler als Kommando bekommt, ist dabei spätestens bei der Verwendung generischer Makefiles (oder scons-builds oder, oder) in größeren Projekten mit Dutzenden oder hunderten von Dateien keine Einzelentscheidung mehr, sondern eben eine generische. Im Gegensatz dazu kann natürlich jeder, der Spaß dran hat, das natürlich für jede Einzeldatei individuell angeben. Viel Spaß dabei, besonders, wenn man nicht der Einzige ist, der in so ein Repository mit vielleicht hunderten Dateien schreibt. Dass bei den erwähnten Dateien die Unterscheidung des vermuteten Inhalts nach Groß-/Kleinschreibung dann noch einen Sinn hat, bezweifle ich sehr stark. Im Übrigen verstehe ich solch trotzige Entgegnungen nicht, wo ich doch längst "zugegeben" habe, dass ich von falschen Annahmen ausgegangen bin. Deshalb ist für mich dazu eigentlich alles gesagt. Wenn auch noch nicht von Jedem.
E. H. schrieb: > Was der Compiler als Kommando bekommt, ist dabei spätestens bei der > Verwendung generischer Makefiles (oder scons-builds oder, oder) in > größeren Projekten mit Dutzenden oder hunderten von Dateien keine > Einzelentscheidung mehr, sondern eben eine generische. Da alle derzeit existierenden Dateisysteme case-preserving sind (auf CP/M oder RSX-11 arbeitet aktuell ganz sicher niemand mehr), musst du in diesem Falle einzig und allein beim Anlegen der Datei die richtige Endung vergeben. Das musst du aber letztlich sowieso, egal ob du die Datei nun .cxx oder .C nennst. ps: Generisches "make" kennt sowieso keine Wildcards als Quelldateinamen. Bei GNU make glaube ich mich zu erinnern, dass sie das pattern matching selbst machen, insofern findet dort ein "*.c" sehr wahrscheinlich kein "foo.C", sondern nur ein "foo.c" – auch unter Windows. Könnte ja mal jemand ausprobieren, wenn's ihn interessiert.
:
Bearbeitet durch Moderator
E. H. schrieb: > Was der Compiler als Kommando bekommt, Was meinst du eigentlich mit "Compiler?" gcc ist jedenfalls kein Compiler, und g++ auch nicht. Das sind wie gesagt Treiberprogramme, die selbst keine Compilierung ausführen — und auch keine Assemblierung, Linking oder Preprocessing. Der C-Compiler der GNU-Tools ist cc1; der C++-Compiler ist cc1plus.
Und wenn man die "extern x Bitmap y z;" Deklarationen nach Bitmap.h verschiebt, validiert die Fragestellung gegen Null. Dann läuft auch der gcc, egal ob mit "-x c" oder "-x c++", durch.
Johann L. schrieb: > E. H. schrieb: >> Was der Compiler als Kommando bekommt, > > Was meinst du eigentlich mit "Compiler?" > > gcc ist jedenfalls kein Compiler, und g++ auch nicht. Sie sind das Compiler-Frontend, was man im Bezug auf den Aufruf durch den Benutzer daher als "Compiler" sehen kann. So sieht es übrigens, wie schon erwähnt wurde, auch die man-Page. > Das sind wie gesagt Treiberprogramme, die selbst keine Compilierung > ausführen — und auch keine Assemblierung, Linking oder Preprocessing. "Treiberprogramme"? > Der C-Compiler der GNU-Tools ist cc1; der C++-Compiler ist cc1plus. Die ruft aber keiner direkt auf, und sie sind auch nicht dafür gedacht.
> Die ruft aber keiner direkt auf, und sie sind auch nicht dafür gedacht.
Ich weiss nicht mehr welche IDE es war. Aber diese rief mit ihrem
internen make cc1 direkt auf. Ohne gcc - Frontend.
neuer PIC Freund schrieb im Beitrag #6058206: > validiert die Fragestellung gegen Null Den Satz würde ich nochmal überdenken: https://www.duden.de/rechtschreibung/validieren
Jörg W. schrieb: > Es wurde oben schon geschrieben, wirklich „interessante“ Effekte hat man > dabei eher an unerwarteten Stellen: eine "clean"-Regel eingerichtet, die > *.s löscht (weil dies ja sonst nur als Assembler-Zwischencode anfällt), > und man hat echte Assemblerquellen wie foo.S dabei, dann räumt einem > "make clean" die Assemblerquellen mit ab, wenn das Dateisystem die Namen > nicht unterscheiden kann. :-o weswegen man immer ein Build-Verzeichnis benutzen soll, anstatt die Quelldatei-Verzeichnisse mit temporäre Dateien vollzumüllen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.