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?
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
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()
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
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
.
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)
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()
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
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
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()
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