26

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

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

#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プリプロセッサのコマンドラインに表示されません。

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

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

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

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

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

アップデート

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

私が配置した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
4

4 に答える 4

52

ダミーターゲットの作成や構成ファイルの削除を回避することで、作業を簡素化できます。代わりに、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_Aその結果、プリプロセッサ定義としてビルドに ON追加されます。コードで定義されていません。USE_FEATURE_AUSE_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変数( 1つWITH_FEATURE...)とプリプロセッサ定義(1つ)を混同しているよう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()

于 2013-03-04T23:07:18.653 に答える
6

私はこの質問に出くわし、別のオプションを共有していると思いましTARGET_COMPILE_DEFINITIONSた。CMakeLists.txtファイルに2つのターゲット(構成ごとに1つ)を含めることができ、次のようになります。

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)

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

make versionA
make versionB
于 2017-02-01T21:57:46.207 に答える
4

オプション間の関係を紹介したいようです。ステップを分けると、これは簡単になります。最初に関係を解決し、次に結果に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()
于 2013-03-05T16:36:58.860 に答える
0

configure_fileこれに使用できます。たとえば、CMakeLists.txt

if(WITH_FEATURE_A)
    set(USE_FEATURE_A 1)
    # Feature A should enable feature B
    set(WITH_FEATURE_B ON)
endif()

if(WITH_FEATURE_B)
    set(USE_FEATURE_B 1)
    # Feature B should enable feature D
    set(WITH_FEATURE_D ON)
endif()

if(WITH_FEATURE_C)
    set(USE_FEATURE_C 1)
    # Feature C should enable feature D, too
    set(WITH_FEATURE_D ON)
endif()

if(WITH_FEATURE_D)
    set(USE_FEATURE_D 1)
endif()

configure_file(config.h.in config.h)

ではconfig.h.in、CMake変数を次のように定義するように変換できます。

#cmakedefine USE_FEATURE_A 1
#cmakedefine USE_FEATURE_B 1
#cmakedefine USE_FEATURE_C 1

/* You can use the values of the cmake variables too, using @<var>@. Ex: */
#cmakedefine USE_FEATURE_D @USE_FEATURE_D@

を実行するcmake -DWITH_FEATURE_A=1と、結果のconfig.hは次のようになります。

#define USE_FEATURE_A 1
#define USE_FEATURE_B 1
/* #undef USE_FEATURE_C */

/* You can use the values of the cmake variables too, using @<var>@: */
#define USE_FEATURE_D 1

参照:

于 2021-04-06T21:17:17.370 に答える