Jak wykryć docelową architekturę za pomocą CMake?

Zrobiłem wiele badań i nie byłem w stanie znaleźć odpowiedzi na to... Jak mogę niezawodnie znaleźć docelową architekturę, dla której kompiluję, używając CMake? Zasadniczo odpowiednik QMAKE_TARGET.łuk w qmake.

Większość źródeł wydaje się sugerować CMAKE_SYSTEM_PROCESSOR, ale jest to złe rozwiązanie, ponieważ zawsze zwróci i386 na przykład w OS X, bez względu na to, czy kompilujesz dla i386, x86_64, ppc lub ppc64.

Podobnie, CMAKE_SIZEOF_VOID_P daje wielkość wskaźnika systemu, a nie cel.

Rozumiem, że istnieje CMAKE_OSX_ARCHITECTURES, ale może to być puste, jeśli nie jest ustawione, w takim przypadku wydaje się domyślne dla tego, do czego system jest zdolny. Jak mogę znaleźć informacje o docelowej architekturze?

A konkretnie dla OS X, Jak mogę odróżnić 32, 64 i Intel Universal?

Author: Jake Petroules, 2012-08-14

8 answers

Więc wymyśliłem dość kreatywne rozwiązanie mojego problemu... wydaje się, że CMake nie ma żadnej funkcjonalności do wykrywania docelowej architektury.

Teraz wiemy, że możemy to łatwo zrobić w C, ponieważ symbole takie jak __i386__, __x86_64__, itd., zostanie zdefiniowany w zależności od środowiska. Na szczęście CMake posiada funkcję try_run, która kompiluje i uruchamia dowolny plik kodu źródłowego C podczas etapu konfiguracji.

Możemy wtedy napisać mały program, który wykorzystuje kilka ifdefs i zapisuje nazwę architektury do konsoli jako ciąg znaków. Jedynym problemem jest to, że działa to tylko wtedy, gdy host i system docelowy są takie same... nie może działać podczas kompilacji krzyżowej, ponieważ podczas kompilacji binarnej nie można go uruchomić, aby zobaczyć jego wynik.

Tutaj robi się ciekawie. Możemy wykorzystać preprocesor C do uzyskania niezbędnych informacji, celowo pisząc zepsuty program C... wykorzystujemy oryginalną koncepcję zapisu nazwy architektury do konsola oparta na ifdefs, ale zamiast tego, umieścimy po prostu dyrektywę preprocesora #error zamiast wywołania printf.

Gdy funkcja CMake ' a try_run skompiluje plik C, kompilacja zawsze się nie powiedzie, ale jakikolwiek komunikat, który umieściliśmy w dyrektywie # error, pojawi się w wyjściu kompilatora błędu, który try_run nam zwróci.

W związku z tym, wszystko co musimy zrobić, to przeanalizować nazwę architektury z wyjścia błędu kompilatora za pomocą niektórych poleceń CMake string, a my może odzyskać docelową architekturę... nawet przy kompilacji krzyżowej.

Specyficzna dla OS X część kodu używa głównie CMAKE_OSX_ARCHITECTURES do określenia docelowej architektury, ale w przypadku nieokreślonym użyje tego samego kodu co inne systemy i poprawnie zwróci x86_64 (dla nowoczesnych systemów, na których jest to domyślne kompilator) lub i386 (dla starszych systemów OS X, takich jak Leopard).

Przetestowałem i zweryfikowałem to działa na Windows, OS X i Linux przy użyciu Visual Studio 9 i 10 generatorów (x86, x86_64, ia64), Xcode, NMake, MSYS Makefiles i Unix Makefiles. Poprawny wynik jest zwracany za każdym razem.

Notice: To rozwiązanie może się nie udać, jeśli celowo wykonasz takie rzeczy jak pass-M32 lub-M64 do kompilatora lub inne flagi, które mogą mieć wpływ na docelową architekturę (czy istnieje sposób, aby przekazać wszystkie ustawienia środowiska do try_run?); to nie jest coś, co testowałem. Tak długo, jak używasz domyślnych ustawień dla swojego generatora i wszystkich celów są kompilowane dla tej samej architektury powinno być OK.

Pełny kod źródłowy mojego rozwiązania można znaleźć na GitHub: https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake

 40
Author: Jake Petroules,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-15 01:58:15

Mam rozwiązanie dla Przypadku, Gdy Host i system docelowy są takie same.

Najpierw musisz wywołać "uname-m", aby uzyskać " Nazwa sprzętu maszynowego ". Następnie musisz odciąć końcowy " carriage Return", aby uzyskać rzeczywistą wartość z powrotem do podanej zmiennej.

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

Teraz możesz wydrukować zmienną ${Architektura}:

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

Albo zrobić jakąś kanonizację do mapowania, np. "x86_64", "amd64",... do np. "64Bit". To samo dotyczy 32Bit. Z tym możesz wykonać kompilację archtecture dependend jak:

if( ${ARCHITECTURE} STREQUAL "64Bit" )
    set( BLA_LIBRARY "/opt/lib/libBla.so" )
else()
    set( BLA_LIBRARY "/opt/lib32/libBla.so" )
endif()
 19
Author: Angstgeist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-11 09:03:12

Android ${ANDROID_ABI}

Zmienna ${ANDROID_ABI} jest sposobem na Androida, gdzie przyjmuje wartości takie jak arm64-v8a, x86_64 i tak dalej.

Jest używany na oficjalnym przykładzie biblioteki NDK: https://github.com/googlesamples/android-ndk/blob/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/app/src/main/cpp/CMakeLists.txt#L25

Skomentowałem ten przykład pod adresem: NDK: jak włączyć wstępnie zbudowaną bibliotekę współdzieloną niezależnie od architektury

 11
Author: Ciro Santilli TRUMP BAN IS BAD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 10:30:27

Jeśli twój proces budowania obejmował więcej niż 1 Cel, lepiej niech CMake wie na czym opiera się ARCH/toolchain. Możesz postępować zgodnie z instrukcją dla kompilacji krzyżowej CMake, która zachęca do utworzenia pliku Toolchain CMake, który pozwala wybrać używany zestaw narzędzi/kompilator.

Stworzyłem jedną do budowania mojej aplikacji C++ Linux dla procesora arm i nazwałem ją toolchain-arm.cmake.

Obejmuje set(CMAKE_SYSTEM_PROCESSOR arm).

I wtedy wykonanie CMake tak:

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

W ramach CMakeList mojego projektu.txt mogę odwoływać się do CMAKE_SYSTEM_PROCESSOR w dowolny sposób.

Podczas budowania dla X86, nie podaję odniesienia do-DCMAKE_TOOLCHAIN_FILE, pozostawiając cmake_system_processor niezdefiniowany, lub przynajmniej nie zdefiniowany jako arm.

Oto mój łańcuch narzędzi.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)
 6
Author: Parallel Universe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-13 06:29:33

Ten post jest stary, więc przepraszam, jeśli wskrzeszenie zmarłych tutaj, ale pomyślałem, że podzielę się rozwiązaniem, które zrobiłem.

Nie chciałem używać żadnej zewnętrznej aplikacji i niestety toolchain.plik cmake, którego używamy nie ma ustawionego łuku w innej zmiennej, więc wykrywam go patrząc na zmienne CMAKE_C_FLAGS i CMAKE_CXX_FLAGS szukając argumentu -march do GCC. Jeśli go nie ma, wraca do CMAKE_HOST_SYSTEM_PROCESSOR.

Szybkie spojrzenie na dokumentację Clang wydaje się wskazywać, że to to nie zadziała, ale wystarczy drugi krok regex, aby dopasować oczekiwany argument.

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()
 2
Author: Joe Balough,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 16:42:43

Na razie nie potrzebujesz żadnych hacków do określenia docelowej architektury: zmienna OSX_ARCHITECTURES została dodana do cmake i może być używana do tego celu: http://public.kitware.com/Bug/view.php?id=8725

 0
Author: slashdot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-24 09:25:18

Myślę, że najprostszym i najbardziej niezawodnym rozwiązaniem jest ręczne określenie architektury dla platformy, na której budujesz (możesz użyć cmake . -DMY_ARCHITECTURE=x86 lub czegoś podobnego). Przynajmniej to robimy w naszych projektach, z powodu tych samych problemów, które opisałeś powyżej

 -1
Author: Unknown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-14 11:50:04

Jest to dobrze przetestowany sposób poznania architektury hosta:

# Store in CMAKE_DEB_HOST_ARCH var the current build architecture
execute_process(COMMAND
  dpkg-architecture
    -qDEB_HOST_ARCH
  OUTPUT_VARIABLE
    CMAKE_DEB_HOST_ARCH
  OUTPUT_STRIP_TRAILING_WHITESPACE
)

I użyj tych informacji później w CMakeLists, jak potrzebujesz

if(${CMAKE_DEB_HOST_ARCH} MATCHES "armhf")
  ...
elseif(${CMAKE_DEB_HOST_ARCH} MATCHES "i386")
  ...
else()
  ...
endif()
 -3
Author: Roberto Mier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 10:04:13