Kompilierfehler, Ideen?



  • @SeppJ sagte in Kompilierfehler, Ideen?:

    Das hat so absolut überhaupt nix mit dem Fehler zu tun.

    Ein aktueller GCC wirft Dir exakt diesen Fehler, wenn Du gets verwendest. Include und Linker Probleme kannst Du erst dann angehen, wenn das gets Problem gelöst ist.

    Ergänzung Beispiel:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        char buffer[4096];
        char* p = gets(&buffer);
    
        return EXIT_FAILURE;
    }
    

    Das liefert die folgende Fehlermeldung

    gcc gets.c -o gets
    gets.c: In function ‘main’:
    gets.c:6:19: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
        6 |         char* p = gets(&buffer);
          |                   ^~~~
          |                   fgets
    gets.c:6:19: warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
    /usr/bin/ld: /tmp/ccuYnOwB.o: in function `main':
    gets.c:(.text+0x37): Warnung: the `gets' function is dangerous and should not be used.
    

  • Mod

    Liest du hier überhaupt irgendwas? Oder Beißreflex, weil gets im Text? Das ist nicht einmal ein Fehler...

    Du weißt doch sonst eigentlich ganz gut was los ist, und wie Dinge funktionieren.



  • @SeppJ sagte in Kompilierfehler, Ideen?:

    Liest du hier überhaupt irgendwas?

    Anscheinend verstehst Du das Problem nicht. Solange gets verwendet wird, wird ein aktueller Compiler immer Fehler werfen und das Übersetzen wird scheitern. Und das siehst so aus als ob man ein Include bzw. ein Linker Problem hat. D.h. Du musst zuerst das gets Problem lösen, und danach kannst Du Dich um die anderen Probleme kümmern.


  • Mod

    @john-0 sagte in Kompilierfehler, Ideen?:

    @SeppJ sagte in Kompilierfehler, Ideen?:

    Liest du hier überhaupt irgendwas?

    Anscheinend verstehst Du das Problem nicht.

    Nein! Nein! Nein! Nimm mal Abstand, atme tief durch, dann lies den gesamten Thread noch einmal gründlich und unvoreingenommen durch. Ohne reflexartig auf das Wort gets zu reagieren. Warum hat der Threadersteller wohl wonach gefragt? Warum hat er diese vollständige Fehlermeldung gepostet, und nicht nur die Zeile mit gets? Warum haben andere Poster in diesem Thread ganz andere Antworten gegeben als du, auf die der Threadersteller auch einging, und was war wohl deren Absicht? Willst du dann wirklich noch anderen sagen, sie hätten das Problem nicht verstanden?



  • @Timo_R sagte in Kompilierfehler, Ideen?:

    @SeppJ
    eingebundene Header: stdio.h und stdlib.h
    zeigt:

    /usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/lib/thumb/v7e-m/nofp/libc.a(lib_a-exit.o): in function `exit':
    /home/pere/src/newlib-salsa/build/arm-none-eabi/thumb/v7e-m/nofp/newlib/libc/stdlib/../../../../../../../../newlib/libc/stdlib/exit.c:64: undefined reference to `_exit'
    

    Vielleicht erzählst du uns etwas genauer, was du da gerade machst und was du vorhast, dann können wir dir eventuell besser helfen. arm-none-eabi ist wie schon erwähnt wurde ein Baremetal-Compiler, der keine libc-Implementierung mitbringt. Und selbst wenn eine solche dabei wäre, wird sie mit -nostdlib explizit nicht dazu gelinkt.

    Ich sehe in den Fehlermeldungen aber auch eine libc arm-none-eabi/lib/thumb/v7e-m/nofp/libc.a und die Pfade (newlib-salsa) sprechen dafür, dass da irgendwo eine Newlib-basierte libc gelinkt wird. Das muss entweder über die Kommandozeile geschehen (sehe ich dort nicht), über das Linker-Skript linker_script.ld oder die ist in dem Compiler "eingebettet" via einkompiliertem GCC-SPEC (sollte bei einem unmodifizierten arm-none-eabi-GCC aber eigentlich nicht der Fall sein).

    Die in deiner zweiten geposteten Fehlermeldung aufgelisteten Funktionen _exit, _sbrk, _write, etc. sind auch alles diejenigen Funktionen, die man bei einer Newlib-basierten libc normalerweise selbst implementieren muss, wenn das nicht schon jemand für deine Zielplattform getan hat. Da ist also irgendwas falsch konfiguriert. Z.B. könnte eine Bibliothek oder Objektdatei mit den Implementierungen für _exit, _sbrk, _write, etc. nicht dazu gelinkt werden oder sie wird es, aber in der falschen Reihenfolge (muss in der Kommandozeile denke ich nach der libc gelinkt werden). Oder aber es gibt irgendwo einen Widerspruch, wie die Funktionen heißen. Ich kenne diese selbst implementierten Funktionen beispielsweise nur in der Variante ohne Unterstrich, also lediglich exit, sbrk, write, etc. Es gibt je nach Zielplattform Unterschiede, wie GCC Compiler und Assembler die Funktionssymbole benennen. Manchmal wird da intern ein Unterstrich vorangestellt (also das Symbol einer C-Funktion meine_funktion heisst dann in der Objektdatei _meine_funktion). Wenn die libc.a z.B. die Funktionen mit Unterstrich referenziert, aber dein Compiler die Symbole ohne Unterstrich erzeugt, dann könnte das auch zu solchen Fehlern führen. Leider wiess ich gerade nicht aus dem Kopf ob arm-none-eabi mit Unterstich-Präfix ist.

    Auch auffällig ist das undefined reference to __bss_start__. Ich würde erwarten, dass es Aufgabe des Linker-Skripts ist, dieses Symbol zu erzeugen und dass das immer geschieht, auch bei einer leeren BSS-Section. Hier könnte auch die Fehlerursache liegen, dass das Linker-Skript nicht zu dem Rest deines Setup passt.

    Wie gesagt: Beschreib mal genau was du vorhast und wie du da rangegangen bist. Vielleicht liegt es ja an etwas offensichtlichem und wir können weiter helfen. Aus eigener Erfahrung weiß ich aber auch, dass diese Probleme ganz schön fummelig sein können bei so einem Baremetal-Setup. Also ohne Garantie 😁


  • Mod

    @Finnegan sagte in Kompilierfehler, Ideen?:

    Die in deiner zweiten geposteten Fehlermeldung aufgelisteten Funktionen _exit, _sbrk, _write, etc. sind auch alles diejenigen Funktionen, die man bei einer Newlib-basierten libc normalerweise selbst implementieren muss, wenn das nicht schon jemand für deine Zielplattform getan hat. Da ist also irgendwas falsch konfiguriert. Z.B. könnte eine Bibliothek oder Objektdatei mit den Implementierungen für _exit, _sbrk, _write, etc. nicht dazu gelinkt werden oder sie wird es, aber in der falschen Reihenfolge (muss in der Kommandozeile denke ich nach der libc gelinkt werden). Oder aber es gibt irgendwo einen Widerspruch, wie die Funktionen heißen. Ich kenne diese selbst implementierten Funktionen beispielsweise nur in der Variante ohne Unterstrich, also lediglich exit, sbrk, write, etc. Es gibt je nach Zielplattform Unterschiede, wie GCC Compiler und Assembler die Funktionssymbole benennen. Manchmal wird da intern ein Unterstrich vorangestellt (also das Symbol einer C-Funktion meine_funktion heisst dann in der Objektdatei _meine_funktion). Wenn die libc.a z.B. die Funktionen mit Unterstrich referenziert, aber dein Compiler die Symbole ohne Unterstrich erzeugt, dann könnte das auch zu solchen Fehlern führen. Leider wiess ich gerade nicht aus dem Kopf ob arm-none-eabi mit Unterstich-Präfix ist.

    Da gab es, wenn ich mich recht erinnere, auch wilde Schalter, damit für diese Funktionen leere Platzhalter erzeugt werden (mit dem passenden Namen), wenn diese auf der Plattform denn Sinn ergeben (z.B. wenn man nirgendwohin exiten kann, weil kein Betriebssystem). Aber erst einmal gilt es herauszufinden, was hier mit der erwarteten aber fehlenden Standardbibliothek los ist. Ich denke, da brauchen wir eine Antwort von @Timo_R , um weiter zu kommen.



  • @Finnegan

    Dank für Ihre Antwort.
    Wir nutzen die arm-none-eabi eigentlich als ungesehenes Kompilierwerkzeug.
    Mehrere Fragen tun sich natürlich hier auch auf, ich arbeite derzeit auf einem 32-bit Intel Atom und benötige - wie es bis dato scheint - dennoch dieses Werkzeug zum Kompilieren um ein Programm einem Cortex-M4 zur Verfügung zu stellen.

    Jedoch:
    Ihr zweiter Absatz ist interessant - newlib-basierte libc Linkung und das linken über die Kommandozeile, wie mache ich das? Das ist es eigentlich m. E. "schon"...
    Kurze prägnante Quellen würden reichen.

    Wir benutzen die arm-none-eabi also obwohl "Kreuz-Kompilierer" auf einem 32 bit System, weil wir nicht soviel Ahnung genau vom kompilieren haben.

    In diesem Fall für eine U(S)ART-Schnittstelle.



  • @Timo_R sagte in Kompilierfehler, Ideen?:

    @Finnegan

    Dank für Ihre Antwort.
    Wir nutzen die arm-none-eabi eigentlich als ungesehenes Kompilierwerkzeug.

    "Ungesehen" heißt hier es arbeitet im Hintergrund einer IDE oder sowas?

    Mich interessiert hier vor allem folgendes:

    Wo stammt der Compiler her? Ist der Teil eines SDK? Gibt es dazu eine Dokumentation und vielleicht sogar einen Support, der wahrscheinlich zielgerichteter helfen könnte als wir hier?

    Mehrere Fragen tun sich natürlich hier auch auf, ich arbeite derzeit auf einem 32-bit Intel Atom und benötige - wie es bis dato scheint - dennoch dieses Werkzeug zum Kompilieren um ein Programm einem Cortex-M4 zur Verfügung zu stellen.

    Das ist sehr unspezifisch formuliert 😉 ... was ist das denn für ein Maschinchen, in dem der Cortex-M4 steckt? Ein "Computer" ist ja nicht nur die CPU, sondern auch die ganze Hardware drumherum, und eine libc-Unterstützung ohne OS muss eben gerade diese Hardware kennen und korrekt ansprechen. Ein printf muss z.B. wissen, wie man Text auf dem "Terminal" ausgibt. Das kann z.B. über eine BIOS/Firmware-Funktion geschehen, oder man schreibt die Zeichen irgendwo in einen in den Adressraum gemappten Text-Videospeicher. Oder man muss den Text über den seriellen Port oder irgendeine andere Hardware ausgeben. Das kann in allen Fällen ein Cortex-M4 sein, aber wie die Grundfunktionen der libc implementiert sein müssen, ist primär davon abhängig, wie und mit welchen Chips die CPU zu einem "Computer" verlötet wurde 😁

    Jedoch:
    Ihr zweiter Absatz ist interessant - newlib-basierte libc Linkung und das linken über die Kommandozeile, wie mache ich das? Das ist es eigentlich m. E. "schon"...
    Kurze prägnante Quellen würden reichen.

    newlib an sich ist keine fertige Lösung, sondern eine libc-Implementierung, die sich relativ leicht auf neue (oft selbst entwickelte, "embedded") Systeme portieren lässt, indem man lediglich ein paar lowlevel-Grundfunktionen für das System implementiert. Sowas selbst zu machen erfordert detailliertes Wissen über die Ziel-Hardware und über die Funktionsweise von Compiler und Linker. Davon würde ich vorerst abraten, besonders wenn Compiler und Linker über die Kommandozeile zu bedienen noch neu für dich ist. Neben Kenntnissen über die Hardware sollte man mindestens in der Lage sein, sich eine GCC-Toolchain mit libc selbst zu bauen, bevor man damit anfängt.

    Aber du arbeitest ja offenbar schon mit einer newlib-basierten libc, so wie die Pfade in deiner zweiten Fehlermeldung aussehen: ../newlib/libc/stdlib/exit.c. Wo stammt die denn her? Ich denke die ist einfach nur falsch konfiguriert oder nicht richtig eingebunden.

    Wir benutzen die arm-none-eabi also obwohl "Kreuz-Kompilierer" auf einem 32 bit System, weil wir nicht soviel Ahnung genau vom kompilieren haben.

    In diesem Fall für eine U(S)ART-Schnittstelle.

    Wie gesagt. Sehr unspezifisch. Das System, auf dem der Compiler läuft, ist hier auch m.E. nicht das Problem.
    Bitte um mehr Infos woher der Compiler kommt (die Toolchain muss ja irgendjemand für eure Ziel-Hardware zusammengestellt haben) und was das für ein System ist, auf dem die damit gebauten Programme laufen sollen.



  • @SeppJ sagte in Kompilierfehler, Ideen?:

    Nein! Nein! Nein! Nimm mal Abstand, atme tief durch,

    Mein lieber SeppJ Du textest hier jemanden ohne fundierte C Kenntnisse mit Detailwissen zu, dass zu diesem Zeitpunkt ohnehin nicht verstanden wird. Denn wer im Jahre 2024 C Source Code mit gets Aufrufen versucht zu übersetzen, der irrlichtert vollkommen planlos durch die C Welt.

    Es geht darum heraus zu finden, was wirklich gemacht werden soll, und dann eine Hilfestellung zu geben.

    @Timo_R
    Nach der ersten Fehlermeldung habt ihr von STMicroelectronics eine STM32MCU Entwicklungsplattform. Von STM gibt es die STM32CubeIDE, diese muss korrekt installiert sein. Nutzt ihr diese? Lässt sich ein Projekt wie in der Dokumentation beschrieben aus der IDE erfolgreich übersetzen? Falls ja, folge der Dokumentation für die Kommandozeile, um erfolgreich darüber ein Projekt zu übersetzen. Gelingt das nicht, wendet Euch am besten an die STM Community, da dürfte mehr Fachwissen zu dieser speziellen Toolchain vorhanden sein.



  • @john-0 sagte in Kompilierfehler, Ideen?:

    Denn wer im Jahre 2024 C Source Code mit gets Aufrufen versucht zu übersetzen, der irrlichtert vollkommen planlos durch die C Welt.

    Wir reden hier aber von Embedded C und nicht von Standard C. Und Embedded C verhält sich gerne mal anders als der Standard.

    Warum z.B. funktioniert der folgende Code nicht?

    sprintf(s, "%f", 2.34);

    Problem: Die Unterstützung für Gleitkommazahlen wurde ausgeschaltet um Programmspeicher zu sparen. Die Zielplatform hat IOT Eigenschaften. Die Stückzahlen sind größer als 100k, die Software darf nicht viel Strom verbrauchen und beim Einkaufspreis zählt jeder zehntel Cent.

    Da sind 129 kByte Flash und 24 kByte RAM purer Luxus. Standard sind eher 32 kByte Flash.

    Davon mal angesehen. Was ist eigentlich stdin auf der Embedded Welt?

    • Nichts ?
    • Uart ?
    • Uart Extended mit Easy DMA ?
    • Bluetooth Profil ?
    • SPI ?
    • PWM ?

    Da kann sich ein gets komplett anders verhalten, als auf der PC Welt.


    Dem Threadersteller @Timo_R würde ich erst einmal empfehlen uns weitere Informationen zu seiner IDE zu geben. Dort kann man ggf. einen Hinweis auf die Standard Lib oder das Board geben.

    Ein Beispiel zu suchen und anzupassen ist aber sicherlich auch eine Option.



  • @Quiche-Lorraine sagte in Kompilierfehler, Ideen?:

    Wir reden hier aber von Embedded C und nicht von Standard C. Und Embedded C verhält sich gerne mal anders als der Standard.

    Wir reden von C bei dem die gets Funktion seit ANSI C 1989 als veraltet markiert wurde, und seit C2011 aus der Sprache komplett entfernt wurde.

    Erschreckend ist, dass Du hier so einen Sermon schreibst, und das nicht weißt.



  • @john-0 sagte in Kompilierfehler, Ideen?:

    @Quiche-Lorraine sagte in Kompilierfehler, Ideen?:

    Wir reden hier aber von Embedded C und nicht von Standard C. Und Embedded C verhält sich gerne mal anders als der Standard.

    Wir reden von C bei dem die gets Funktion seit ANSI C 1989 als veraltet markiert wurde, und seit C2011 aus der Sprache komplett entfernt wurde.

    Erschreckend ist, dass Du hier so einen Sermon schreibst, und das nicht weißt.

    Das ist ja schon richtig, aber hier nicht das primäre Problem. Daher kann man das mal nebenher erwähnen, muss es aber nicht unbedingt so in den Vordergrund rücken. Konträr zu deiner vorherigen Empfehlung bin ich nämlich der Meinung, dass das Programm erstmal überhaupt kompilierbar sein sollte, bevor man solche deprecated-Funktionen ersetzt. Schließlich will man ja auch testen, ob die Alternative überhaupt ordentlich funktioniert - sonst müsste man das ja blind machen.

    Und ja, ich denke es kann im Embedded-Kontext durchaus Situationen geben, in denen gets unproblematisch ist - je nach dem was stdin auf diesem System überhaupt ist. Z.B. wenn der Mechanismus dahinter eine feste Länge garantiert. Das muss nicht immer beliebiger User-Input sein, das kann auch von einem abgeschlossenen System stammen, das wohldefinierte Daten weiterleitet. Z.B. zwei Prozesse, bei denen das stdout des einen in das stdin des anderen geht. Wenn da immer nur exakt 1KiB-Strings kommen können, wäre ein gets durchaus vertretbar. Das mit dem UART klingt jedenfalls nach irgendeiner Hardware, die da über eine serielle Schnittstelle angesprochen wird. Vielleicht sendet die ja per Spezifikation nur Daten mit einer bekannten Maximallänge?


  • Mod

    @john-0 sagte in Kompilierfehler, Ideen?:

    @Quiche-Lorraine sagte in Kompilierfehler, Ideen?:

    Wir reden hier aber von Embedded C und nicht von Standard C. Und Embedded C verhält sich gerne mal anders als der Standard.

    Wir reden von C bei dem die gets Funktion seit ANSI C 1989 als veraltet markiert wurde, und seit C2011 aus der Sprache komplett entfernt wurde.

    Erschreckend ist, dass Du hier so einen Sermon schreibst, und das nicht weißt.

    @john-0 :Wir wissen das alle! Wir sind bloß klug genug zu verstehen, dass es völlig egal ist, wenn der Scheibenwischerwasserstand niedrig ist, während das Licht für Motorschaden leuchtet. Und wenn da dauernd der Praktikant um das Auto tanzt und schreit "Meister! Meister! Der Scheibenwischerwasserstand ist niedrig! Da dran liegt es! Das müssen wir sofort beheben! Das ist wichtig! Die anderen Gesellen haben offensichtlich alle keine Ahnung, wenn sie dies nicht sehen!", dann nervt das einfach nur. Vor allem, wenn der Praktikant auch noch keinen Wink mit egal wie dickem Zaunpfahl verstehen möchte.


Anmelden zum Antworten