Binärdatei in Bibliothek linken.



  • Hi, ich möchte eine Binärdatei in eine Lib .so .a linken. Dazu hatte ich unter Linux bislang den Aufruf wie unten zu sehen:

    COMMAND ${CMAKE_LINKER} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o "${outputFile}" "${inputFile}"
    ld: error: target emulation unknown: -m or at least one .o file required
    

    Leider - ihr seht es an der Fehlermeldung - funktioniert das so mit Android's lld nicht mehr. Dieser möchte unbedingt einen emulation mode Parameter haben. Leider ist dieser völlig undokumentiert und kein Mensch weis was man dort zu übergeben hat. Außerdem will ich dafür jetzt nicht auch noch irgedwelche Sonderlogiken pflegen müssen.

    Darum möchte ich den "ld" Aufruf durch einen "clang" Aufruf ersetzen, der dann den Linker mit allen Parametern füttert:

    COMMAND ${CMAKE_CXX_COMPILER} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o "${outputFile}" "${inputFile}"
    

    Leider bekomme ich nun Fehlermeldungen der Art:

    ld: error: duplicate symbol: _binary__usr_lib_gcc_x86_64_redhat_linux_11_libgcc_s_so_start
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc_s.so:(.data+0x0)
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc_s.so:(.data+0x0)
    
    ld: error: duplicate symbol: _binary__usr_lib_gcc_x86_64_redhat_linux_11_libgcc_s_so_end
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc_s.so:(.data+0xC3)
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc_s.so:(.data+0xC3)
    
    ld: error: duplicate symbol: _binary__usr_lib_gcc_x86_64_redhat_linux_11_libgcc_a_start
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc.a:(.data+0x0)
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc.a:(.data+0x0)
    
    ld: error: duplicate symbol: _binary__usr_lib_gcc_x86_64_redhat_linux_11_libgcc_a_end
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc.a:(.data+0x2FCE56)
    >>> defined at /usr/lib/gcc/x86_64-redhat-linux/11/libgcc.a:(.data+0x2FCE56)
    clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
    

    Weis jemand was hier falsch läuft. Muss ich dem clang Compiler noch andere Parameter übergeben bzw. wenn ich versuche die CMAKE_CXX_FLAGS mit zu übergeben

    COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o "${outputFile}" "${inputFile}"
    

    kommt die Fehlermeldung:

    clang-12: error: unknown argument: '-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong
    

    Scheinbar erkennt clang, die ganzen Argumente als ein einzelnes. Keine Ahnung warum.



  • Wäre nicht schlecht den vollständigen (relevanten) CMake Code zu haben. Denke man das wird ja vermutlich ein add_custom_command sein?
    Ist schon relevant, das bestimmt schließlich wie die Syntax auszusehen hat 😉



  • @Enumerator sagte in Binärdatei in Bibliothek linken.:

    COMMAND ${CMAKE_LINKER} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o "${outputFile}" "${inputFile}"
    ld: error: target emulation unknown: -m or at least one .o file required
    

    Diese Fehlermeldung hört sich für eher so an als ob hier kein Objekt-File zum linken angegeben wurde. Möglichwerweise ist hier ${inputFile} in einem oder mehreren Fällen leer.

    Die -m-Flags sind meines wissens für maschinenspezifische Einstellungen wie Aktivierung von hard-floats, zu verwendende Endianess, Aktivierung/Deaktivierung von Befehlssatzerweiterungen (NEON, SSE, AVC) und dergleichen. Auch wenn diese fehlen oder inkorrekt für die Zielarchitektur sind, sollte der Linker hier zumindest nicht meckern und dennoch eine Binary generieren (auch wenn diese dann möglicherweise nicht lauffähig ist, weil z.B. von der Ziel-CPU nicht unterstützte Instruktionen erzeugt wurden).

    Ich vermute das hier folgendes passiert: Sind keine -m-Flags angegeben, leitet der Linker diese aus den gelinkten Objektdateien ab. Da aber keine .o-Files angegeben sind kann der Linker das jedoch nicht machen und es kommt zu dieser missverständlichen Meldung. Eine bessere Fehlermeldung wäre wahrscheinlich "error: Keine .o-Files angegeben! Was zum Henker soll ich eigentlich linken?"

    ... so zumindest meine Spekulation.



  • @Enumerator sagte in Binärdatei in Bibliothek linken.:

    clang-12: error: unknown argument: '-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong
    

    Scheinbar erkennt clang, die ganzen Argumente als ein einzelnes. Keine Ahnung warum.

    Noch eine Anmerkung hierzu: Stell sicher, dass die Argumente im Build-Script nicht alle zusammen in einem einzigen String zwischen Anführungszeichen angegeben sind bzw. in add_custom_command nicht alle im COMMAND-Argument:

    add_custom_command(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o "${outputFile}" "${inputFile}")
    

    sondern dass du stattdessen das ARGS-Argument verwendest (siehe Doku):

    add_custom_command(COMMAND ${CMAKE_CXX_COMPILER} ARGS ${CMAKE_CXX_FLAGS} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o "${outputFile}" "${inputFile}")
    

    Ich hab das jetzt nicht ausprobiert, aber ich denke CMake gibt sich schon Mühe, dass alles was zwischen COMMAND und ARGS steht, als ein einzelner, zusammenhängender Shell-Befehl interpretiert und in den generierten Makefliles dann auch entsprechend escaped wird. Pfade zu (ausführbaren) Dateien können ja durchaus auch Leerzeichen beinhalten - auch wenn viele Build-Systeme damit überhaupt nicht klarkommen (vor allem die auf Autotools basierenden).

    Edit: Vielleicht hätte ich die Doku mal selbst lesen sollen 😉 ... ARGS ist offenbar "deprecated", also eigentlich sollten die übergebenen Argumente auch als einzelne Kommandozeilen-Argumente generiert werden. Ist es eventuell möglich, dass du die Argumente alle in einem einzigen String stehen hast? Irgendwie sowas in die Richtung:

    add_custom_command(COMMAND "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} -Wl,--relocatable -Wl,--format=binary -z noexecstack -o ${outputFile} ${inputFile}")
    

    ? ... oder dass du die irgendwie programmatisch zusammensetzt z.B. via string(APPEND)? In dem Fall besser via LIST(APPEND) zusammensetzen und ohne Anführungsstriche übergeben (add_custom_command(COMMAND "${CMAKE_CXX_COMPILER}" ${argument_list})), damit daraus auch separate Argumente werden und nicht nur ein einziger (im Listen-Fall semikolon-separierter) String.



  • Ich baue mir zunächste eine "MY_CXX_FLAGS" Lsite mittels "LIST(APPEND)" zusammen. Im letzten Schritt wird dieses dann mittels "set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MY_CXX_FLAGS}")" verheiratet. Das scheint leider nicht anders zu funktionieren. Mache ich hier auch ein LIST(APPEND) fliegt mir alles um die Ohren. Auch z.B. die android.toolchain.cmake wo ich mir das im wesentlichen abgeschaut habe wird es genauso gehandhabt. Das "ARGS" wenn auch deprecated hat leider auch nicht funktioniert.

    Das mit dem nicht angegebenem Object File habe ich nicht ganz verstanden. Mittels des "ld --relocatable --format=binary -z noexecstack -o "outputFile""{outputFile}" "{inputFile}"" Aufrufs soll ja das Object File erzeugt werden. Dann kann ich es ja schlecht angeben. Oder ist gemeint, dass man dem ld zusätzlich ein beliebiges schon existierendes "Dummy" .o File angeben kann damit er sich von diesem den -m Parameter bzw. target emulation ermitteln kann? Wenn ja wie gebe ich dem ld das "Dummy" .o File an? Gibt es da ein Parameter für? Die Input/Output Pfade stimmen auch.

    Ein Tipp war auch gar nicht direkt das ld zu verwenden sondern über den clang zu gehen und diesem die Linker Parameter mittel -Wl, durchzureichen, weil clang dann den emulation mode usw. für den ld Aufruf anwenden würde. Aber ich habe das auch nicht über clang hinbekommen. Jemand eine Idee wie man ein Binärdatei oder Textdatei mittels "clang" Aufruf linken kann?


Log in to reply