web-dev-qa-db-ja.com

CMake条件付きプリプロセッサはコードで定義します

MakefileプロジェクトをCMakeに移行しています。 makefileを初めて作成した人は、インクルードファイルに特定の値を書き込むためのモジュールを作成していました。

Config_in.hを含むメインのconfig.hファイルがあります。 config.hファイルには次のようなものが含まれています。

_#ifndef USE_FEATURE_A
#define USE_FEATURE_A 0
#endif

#ifndef USE_FEATURE_B
#define USE_FEATURE_B 0
#endif
_

Makefileには、config_in.hに書き込む_with_feature_a_のような偽のターゲットがあります。

_#define USE_FEATURE_A 1
_

このようにして、誰かがタイプすることができます

_make with_feature_a
make
_

適切なビルドを取得します。

このコードベースを使用して、CMakeを使用してこのようなものを複製したいと思います。ネットで提案されているいくつかのアプローチを試してみましたが、うまくいきませんでした。

_set_target_properties(with_feature_a PROPERTIES COMPILE_DEFINITIONS 
    "WITH_FEATURE_A=1"
)
_

これは機能しません

_make with_feature_a
_

プリプロセッサのコマンドラインに_with_feature_a_がありません。

2番目の試みは、コンテンツを好きなように設定してファイルを直接書き込むことですが、file()コマンドをターゲットに接続する方法がわかりませんでした。

これをCMakeLists.txtに配置しました

_file(WRITE 
local/config_in.h 
    "#define WITH_FEATURE_A 1"
)
_

しかし、これは毎回実行されるわけではなく、単一のターゲットに設定する方法がわかりません。

どんな助けでもありがたいです。このすべてを読んでいただきありがとうございます。長い話でごめんなさい:)

更新

提供されるソリューション here は、ソリューションへの道のりを大きく強化します。問題は、再帰的な定義を許可しないことです。例を示します:

私が置いたCMakeLists.txtで:

_if (WITH_FEATURE_A)
MESSAGE(STATUS "WITH_FEATURE_A")
add_definitions(-DUSE_FEATURE_A=1)
    add_definitions(-DWITH_FEABURE_B=1)
endif()

if (WITH_FEABURE_B)
MESSAGE(STATUS "WITH_FEATURE_B")
add_definitions(-DUSE_FEATURE_D=1)
endif()


if (WITH_FEABURE_C)
MESSAGE(STATUS "WITH_FEATURE_C")
add_definitions(-DUSE_FEATURE_D=1)
endif()


if (WITH_FEABURE_D)
MESSAGE(STATUS "WITH_FEATURE_D")
endif()
_

この場合、-DWITH_FEATURE_A = 1を指定してcmakeを実行すると、出力が表示されます。

_WITH_FEATURE_A
WITH_FEATURE_B
WITH_FEATURE_D
_

実際にはこのコードはちょうど印刷します

_WITH_FEATURE_A
_
23
andyinno

ダミーのターゲットを作成したり、設定ファイルを削除したりすることで、物事を簡素化できます。代わりに、CMakeを呼び出すときにコマンドラインを介して(またはCMake GUIを介して)要件を渡すと、makeを1回だけ実行できます。

たとえば、CMakeLists.txtに以下を追加できます。

option(WITH_FEATURE_A "Option description" ON)
option(WITH_FEATURE_B "Option description" OFF)

if(WITH_FEATURE_A)
  add_definitions(-DUSE_FEATURE_A)
endif()
if(WITH_FEATURE_B)
  add_definitions(-DUSE_FEATURE_B)
endif()

デフォルトでは、CMakeを実行すると、CMake変数WITH_FEATURE_AONに設定され、その結果、プリプロセッサ定義としてUSE_FEATURE_Aがビルドに追加されます。 USE_FEATURE_Bはコードで定義されていません。

これは、コードで#define USE_FEATURE_Aを実行することと同じです。


同等のものが本当に必要な場合

#define USE_FEATURE_A 1
#define USE_FEATURE_B 0

次に、CMakeLists.txtで次のことができます。

option(WITH_FEATURE_A "Option description" ON)
option(WITH_FEATURE_B "Option description" OFF)

if(WITH_FEATURE_A)
  add_definitions(-DUSE_FEATURE_A=1)
else()
  add_definitions(-DUSE_FEATURE_A=0)
endif()
if(WITH_FEATURE_B)
  add_definitions(-DUSE_FEATURE_B=1)
else()
  add_definitions(-DUSE_FEATURE_B=0)
endif()


コマンドラインからこれらのデフォルトを変更するには、次のようにします(例:)。

cmake . -DWITH_FEATURE_A=OFF -DWITH_FEATURE_B=ON
make

この方法でコマンドラインを介して変数が設定されると、その変数はキャッシュされ、コマンドラインで別の値で上書きされるか、ビルドルートのCMakeCache.txtファイルを削除するまで変更されません。


更新への応答:

@Peterが述べたように、CMake変数(WITH_FEATURE...のもの)とプリプロセッサ定義(USE_FEATURE...のもの)を混同しているように見えます。提案されているように、最初にオプション間のすべての依存関係を解決してから、結果のプリプロセッサ定義を設定できます。この場合、フローが非常に簡単な場合は、一度にすべてを実行します。

if(WITH_FEATURE_A)
  message(STATUS "WITH_FEATURE_A")
  add_definitions(-DUSE_FEATURE_A=1)
  set(WITH_FEATURE_B ON)
endif()

if(WITH_FEATURE_B)
  message(STATUS "WITH_FEATURE_B")
  add_definitions(-DUSE_FEATURE_B=1)
  set(WITH_FEATURE_D ON)
endif()

if(WITH_FEATURE_C)
  message(STATUS "WITH_FEATURE_C")
  add_definitions(-DUSE_FEATURE_C=1)
  set(WITH_FEATURE_D ON)
endif()

if(WITH_FEATURE_D)
  message(STATUS "WITH_FEATURE_D")
  add_definitions(-DUSE_FEATURE_D=1)
endif()


39
Fraser

オプション間の関係を紹介したいようです。これは、ステップを分けると簡単になります。最初に関係を解決し、次に結果にC定義を設定します。 WITH_FEATURE_Aはcmake変数であり、USE_FEATURE_AはADD_DEFINITIONSで設定されたCプリプロセッサ定義セットであることを忘れないでください。

# Specify the inter-feature dependencies
if (WITH_FEATURE_A)
    # A requires B because <somereason>
    set(WITH_FEATURE_B ON)
endif()

if (WITH_FEATURE_B)
    set(WITH_FEATURE_D ON)
endif()

if (WITH_FEATURE_C)
    set(WITH_FEATURE_D ON)
endif()

# Now generate the C defines for passing the options to the compiler
if (WITH_FEATURE_A)
    MESSAGE(STATUS "WITH_FEATURE_A")
    add_definitions(-DUSE_FEATURE_A=1)
endif()

if (WITH_FEATURE_B)
    MESSAGE(STATUS "WITH_FEATURE_B")
    add_definitions(-DUSE_FEATURE_B=1)
endif()

if (WITH_FEATURE_C)
    MESSAGE(STATUS "WITH_FEATURE_C")
    add_definitions(-DUSE_FEATURE_C=1)
endif()

if (WITH_FEATURE_D)
    MESSAGE(STATUS "WITH_FEATURE_D")
    add_definitions(-DUSE_FEATURE_D=1)
endif()
4
Peter

私はこの質問に遭遇し、別のオプションを共有していると思いました: TARGET_COMPILE_DEFINITIONS 。 CMakeLists.txtファイルに、構成ごとに1つずつ、2つのターゲットを設定し、次のようなものにすることができます

ADD_EXECUTABLE (versionA, ...)
TARGET_COMPILE_DEFINITIONS (versionA, PUBLIC -DWITH_FEATURE_A=1 -DWITH_FEATURE_B=0)

ADD_EXECUTABLE (versionB, ...)
TARGET_COMPILE_DEFINITIONS (versionB, PUBLIC -DWITH_FEATURE_A=0 -DWITH_FEATURE_B=1)

これは、マクロのプリプロセッサ定義を追加するようにcmakeに指示しますWITH_FEATURE_AおよびWITH_FEATURE_B(適切な値を使用)、* ppファイルで定義した場合と同じです。次に、コンパイルするバージョンをmakeに指示できます。

make versionA
make versionB
3
bartgol