it-swarm.com.de

Wie kann die Zielarchitektur mit CMake erkannt werden?

Ich habe viel recherchiert und konnte keine Antwort darauf finden. Wie kann ich mit CMake zuverlässig die Zielarchitektur finden, für die ich kompiliere? Im Grunde das Äquivalent zu QMAKE_TARGET.Arch in qmake.

Die meisten Quellen scheinen CMAKE_SYSTEM_PROCESSOR zu suggerieren. Dies ist jedoch eine schlechte Lösung, da i386 unter OS X immer zurückgegeben wird, egal ob Sie für i386, x86_64, ppc oder ppc64 kompilieren.

In ähnlicher Weise gibt CMAKE_SIZEOF_VOID_P die Zeigergröße des Systems an, nicht das Ziel.

Ich verstehe, dass es CMAKE_OSX_ARCHITECTURES gibt, aber dies kann leer sein, wenn es nicht gesetzt ist. In diesem Fall scheint es, dass standardmäßig alles verwendet wird, wozu das System in der Lage ist. Wie kann ich die Zielarchitekturinformationen finden?

Und wie kann ich speziell für OS X zwischen 32, 64 und Intel Universal unterscheiden?

35
Jake Petroules

Also habe ich eine ziemlich kreative Lösung für mein Problem gefunden ... Es scheint, dass CMake keine Funktionalität hat, um die Zielarchitektur zu erkennen.

Jetzt wissen wir, dass wir dies in C problemlos tun können, da Symbole wie __i386__, __x86_64__ usw. abhängig von Ihrer Umgebung definiert werden. Glücklicherweise verfügt CMake über eine try_run-Funktion, die während der Konfigurationsphase eine beliebige C-Quellcodedatei kompiliert und ausführt.

Wir könnten dann ein kleines Programm schreiben, das eine Reihe von ifdefs verwendet und den Architekturnamen als String in die Konsole schreibt. Das einzige Problem ist, dass dies nur funktioniert, wenn der Host und das Zielsystem identisch sind. Während der Cross-Kompilierung kann dies nicht funktionieren, da Sie zwar die Binärdatei kompilieren können, aber nicht ausgeführt werden können, um die Ausgabe anzuzeigen.

Hier werden die Dinge interessant. Wir können den C-Präprozessor ausnutzen, um die notwendigen Informationen zu erhalten, indem wir absichtlich ein defektes C-Programm schreiben. Wir verwenden das ursprüngliche Konzept, den Architekturnamen auf der Basis der ifdefs in die Konsole zu schreiben. Stattdessen setzen wir einfach ein #. Fehler-Präprozessoranweisung anstelle eines printf-Aufrufs.

Wenn die Try_run-Funktion von CMake die C-Datei kompiliert, schlägt die Kompilierung immer fehl. Welche Meldung wir jedoch in die # Fehler-Direktive einfügen, wird in der Fehlerausgabe des Compilers angezeigt, die try_run an uns zurückgibt.

Daher müssen wir nur den Namen der Architektur aus der Fehlerausgabe des Compilers mit einigen CMake-Stringbefehlen analysieren und die Zielarchitektur abrufen, selbst wenn überkompiliert wird.

Der OS X-spezifische Teil des Codes verwendet meist CMAKE_OSX_ARCHITECTURES, um die Zielarchitektur zu bestimmen. Wenn er jedoch nicht angegeben ist, wird er denselben Code wie andere Systeme verwenden und x86_64 (für moderne Systeme, auf denen dies standardmäßig der Compiler ist) oder i386 zurückgeben (für ältere OS X-Systeme wie Leopard).

Ich habe diese Funktion unter Windows, OS X und Linux unter Verwendung der Generatoren Visual Studio 9 und 10 (x86, x86_64, ia64), Xcode, NMake, MSYS Makefiles und Unix Makefiles getestet und überprüft. Das korrekte Ergebnis wird jedes Mal zurückgegeben.

Notice: Diese Lösung kann fehlschlagen, wenn Sie vorsätzlich Dinge wie -m32 oder -m64 an Ihren Compiler übergeben oder andere Flags, die sich auf die Zielarchitektur auswirken können (gibt es eine Möglichkeit, alle Umgebungseinstellungen an try_run zu übergeben?) ; Das habe ich nicht getestet. Solange Sie die Standardeinstellungen für Ihren Generator verwenden und alle Ziele für dieselbe Architektur kompiliert werden, sollten Sie OK sein.

Den vollständigen Quellcode für meine Lösung finden Sie unter GitHub: https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake

32
Jake Petroules

Ich habe eine Lösung für den Fall, dass Host und Zielsystem identisch sind.

Zuerst müssen Sie "uname -m" aufrufen, um den " machine hardware name " zu erhalten. Danach müssen Sie das nachfolgende " Carriage Return " abschneiden, um den tatsächlichen Wert wieder in die bereitgestellte Variable zu bringen.

EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE )

Nun können Sie die Variable $ {ARCHITECTURE} ausdrucken:

message( STATUS "Architecture: ${ARCHITECTURE}" )

oder machen Sie eine Canonisierung, z. "x86_64", "AMD64", ... bis z.B. "64Bit". Gleiches gilt für 32Bit . Damit können Sie eine artekturabhängige Kompilierung wie folgt ausführen:

if( ${ARCHITECTURE} STREQUAL "64Bit" )
    set( BLA_LIBRARY "/opt/lib/libBla.so" )
else()
    set( BLA_LIBRARY "/opt/lib32/libBla.so" )
endif()
14
Angstgeist

Android ${Android_ABI}

Die Variable ${Android_ABI} Ist die Methode in Android, bei der Werte wie arm64-v8a, x86_64 Usw. angenommen werden.

Es wird im Beispiel der offiziellen NDK-Bibliothek verwendet: https://github.com/googlesamples/Android-ndk/blob/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/app/src/main/cpp/CMakeLists # L25

Ich habe dieses Beispiel unter folgendem Link weiter kommentiert: NDK: Einbinden einer vorgefertigten gemeinsam genutzten Bibliothek unabhängig von der Architektur

Wenn Ihr Build-Prozess mehr als ein Ziel umfasste, ist es besser, CMake mitzuteilen , gegen welchen Arch/welche Toolchain es erstellt. Sie können der Anleitung für die CMake-Cross-Kompilierung folgen, die Sie zum Erstellen einer CMake-Toolchain-Datei auffordert, in der Sie die verwendete Toolchain/den verwendeten Compiler auswählen können.

Ich habe eine für die Erstellung meiner C++ Linux-Anwendung für den Arm-Prozessor erstellt und sie toolchain-arm.cmake Genannt.

Es enthält set(CMAKE_SYSTEM_PROCESSOR arm).

Ich habe dann CMake so ausgeführt:

cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE={my toolchain cmake path}/toolchain-arm.cmake {my source path}

in der CMakeList.txt meines Projekts kann ich auf beliebige Weise auf CMAKE_SYSTEM_PROCESSOR verweisen.

Beim Erstellen für X86 füge ich keinen Verweis auf -DCMAKE_TOOLCHAIN_FILE ein, wodurch CMAKE_SYSTEM_PROCESSOR undefiniert bleibt oder zumindest nicht als arm definiert wird.

Hier ist mein Toolchain-Arm.cmake

SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR arm)

# specify the cross compiler
SET(ENV{TOOLCHAIN_ROOT} /home/user/toolchain/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin )
SET(CMAKE_C_COMPILER   $ENV{TOOLCHAIN_ROOT}/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN_ROOT}/arm-linux-gnueabihf-gcc)

# search for programs in the build Host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
5

Dieser Beitrag ist alt, es tut mir leid, die Toten hier wiederzubeleben, aber ich dachte nur, ich würde meine Lösung teilen.

Ich wollte keine externe Anwendung verwenden, und leider hat die von uns verwendete toolchain.cmake-Datei den Arch nicht in einer anderen Variablen festgelegt. Daher erkenne ich sie, indem ich CMAKE_C_FLAGS und CMAKE_CXX_FLAGS betrachte. Variablen, die nach dem Argument -march für GCC suchen. Wenn es keine gibt, fällt es auf CMAKE_Host_SYSTEM_PROCESSOR zurück.

Ein kurzer Blick auf die Clang-Dokumentation scheint zu zeigen, dass dies für diese nicht funktionieren würde, aber es würde nur einen zweiten Regex-Schritt benötigen, um das erwartete Argument zu finden.

set(TARGET_Arch_REGEX "^.*-march[= ]([^ ]+).*$")
string(REGEX MATCH "${TARGET_Arch_REGEX}" TARGET_Arch_MATCH ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS})
if (TARGET_Arch_MATCH)
    string(REGEX REPLACE "${TARGET_Arch_REGEX}" "\\1" TARGET_Arch ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS})
else()
    set(TARGET_Arch ${CMAKE_Host_SYSTEM_PROCESSOR})
endif()
1
Joe Balough

Zur Zeit benötigen Sie keine Hacks zum Bestimmen der Zielarchitektur: Die pro-Ziel-Variable OSX_ARCHITECTURES wurde zu cmake hinzugefügt und kann für Ihre Zwecke verwendet werden: http://public.kitware.com/Bug/view .php? id = 8725

0
slashdot