web-dev-qa-db-ja.com

CMakeを使用してターゲットアーキテクチャを検出する方法

私は多くの研究を行ったが、これに対する答えを見つけることができませんでした... CMakeを使用して、コンパイルするターゲットアーキテクチャを確実に見つけるにはどうすればよいですか?基本的に、qmakeのQMAKE_TARGET.Archと同等です。

ほとんどのソースはCMAKE_SYSTEM_PROCESSORを提案しているようですが、i386、x86_64、ppc、ppc64のいずれでコンパイルしていても、OS Xでは常にi386を返すため、これは悪い解決策です。

同様に、CMAKE_SIZEOF_VOID_Pは、ターゲットではなくsystemのポインターサイズを示します。

CMAKE_OSX_ARCHITECTURESがあることを理解していますが、これは設定されていない場合は空になる可能性があります。その場合、システムで可能なすべてがデフォルトになっているようです。それでは、ターゲットアーキテクチャ情報をどのように見つけることができますか?

また、特にOS Xでは、32、64、およびIntel Universalをどのように区別できますか?

40
Jake Petroules

そこで、私は自分の問題に対してかなり創造的な解決策を考案しました... CMakeにはターゲットアーキテクチャをまったく検出する機能がないようです。

これで、__i386____x86_64__などは、環境に応じて定義されます。さいわい、CMakeにはtry_run関数があり、configureステージで任意のCソースコードファイルをコンパイルして実行します。

その後、多数のifdefを使用し、アーキテクチャ名を文字列としてコンソールに書き込む小さなプログラムを作成できます。唯一の問題は、ホストとターゲットシステムが同じ場合にのみ機能することです。バイナリをコンパイルすることはできますが、出力を確認するために実行できないため、クロスコンパイル中は機能しません。

ここからがおもしろいところです。壊れたCプログラムを意図的に記述することにより、Cプリプロセッサを利用して必要な情報を取得できます... ifdefに基づいてコンソールにアーキテクチャ名を書き込むという元の概念を使用しますが、その代わりに、単に#を配置しますprintf呼び出しの代わりにエラープリプロセッサディレクティブ。

CMakeのtry_run関数がCファイルをコンパイルすると、コンパイルは常に失敗しますが、#errorディレクティブに配置したメッセージはすべてコンパイラーのエラー出力に表示され、try_runが返します。

したがって、CMake文字列コマンドを使用してコンパイラのエラー出力からアーキテクチャ名を解析するだけで、クロスコンパイル時でもターゲットアーキテクチャを取得できます。

コードのOS X固有部分は、主にCMAKE_OSX_ARCHITECTURESを使用してターゲットアーキテクチャを決定しますが、指定されていない場合、他のシステムと同じコードを使用し、x86_64(コンパイラのデフォルトである最新のシステムの場合)またはi386を正しく返します(Leopardなどの古いOS Xシステムの場合)。

Visual Studio 9および10ジェネレーター(x86、x86_64、ia64)、Xcode、NMake、MSYS Makefile、Unix Makefileを使用して、Windows、OS X、Linuxでこれが動作することをテストおよび検証しました。毎回正しい結果が返されます。

注意:コンパイラに-m32または-m64を渡すなど、ターゲットアーキテクチャに影響を与える可能性のある他のフラグを意図的に実行すると、このソリューションは失敗する可能性があります(すべての環境設定をtry_runに渡す方法はありますか?);これは私がテストしたものではありません。ジェネレーターのデフォルト設定を使用しており、すべてのターゲットが同じアーキテクチャー用にコンパイルされている限り、問題ありません。

私のソリューションの完全なソースコードはGitHubにあります。 https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake

34
Jake Petroules

ホストとターゲットシステムが同じである場合のソリューションがあります。

まず、「マシンハードウェア名」を取得するために「uname -m」を呼び出す必要があります。その後、末尾の「Carriage Return」を切り取って、指定された変数に実際の値を戻す必要があります。

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

これで、変数$ {ARCHITECTURE}を印刷できます。

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

または、いくつかの正規化を行ってマッピングします。 「x86_64」、「AMD64」、...など「64ビット」。 32ビットについても同様です。これにより、次のようなアーキテクチャ依存コンパイルを実行できます。

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

Android ${Android_ABI}

${Android_ABI}変数は、arm64-v8ax86_64などの値を想定するAndroidでの使用方法です。

公式のNDKライブラリの例で使用されています: https://github.com/googlesamples/Android-ndk/blob/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/app/src/main/cpp/CMakeLists.txt #L25

その例については、さらにコメントしました: NDK:アーキテクチャに関係なく、事前構築済みの共有ライブラリを含める方法

ビルドプロセスに複数のターゲットが関係している場合、CMake know Arch/toolchainのビルド対象とする方が良いでしょう。 instructions に従ってCMakeクロスコンパイルを行うことができます。これにより、使用するツールチェーン/コンパイラを選択できるツールチェーンCMakeファイルを作成できます。

ARMプロセッサ用のC++ Linuxアプリケーションを作成するために作成し、_toolchain-arm.cmake_という名前を付けました。

set(CMAKE_SYSTEM_PROCESSOR arm)が含まれます。

次に、CMakeを次のように実行しました。

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

プロジェクトのCMakeList.txt内で、CMAKE_SYSTEM_PROCESSORを自由に参照できます。

X86用にビルドする場合、-DCMAKE_TOOLCHAIN_FILEへの参照を含めず、CMAKE_SYSTEM_PROCESSORを未定義のままにするか、少なくともarmとして定義しません。

これが私の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

この投稿は古いので、ここで死者を復活させれば申し訳ありませんが、私が作った解決策を共有すると思っただけです。

外部アプリケーションを使いたくなかったのですが、残念ながら、使用しているtoolchain.cmakeファイルには別の変数にArchが設定されていないので、CMAKE_C_FLAGSCMAKE_CXX_FLAGSを見てそれを検出しますGCCへの-march引数を探す変数。存在しない場合は、CMAKE_Host_SYSTEM_PROCESSORにフォールバックします。

Clangのドキュメントをざっと見てみると、これはそれでは機能しないが、期待される引数と一致するために2番目の正規表現ステップが必要なだけであると思われます。

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

現時点では、ターゲットアーキテクチャを決定するためのハックは必要ありません。ターゲットごとの変数OSX_ARCHITECTURESがcmakeに追加され、目的に使用できます。 http://public.kitware.com/Bug/view。 php?id = 8725

0
slashdot