0

マクロを使用して、cmakeプロジェクトのプリコンパイル済みヘッダーを作成しています。gccの場合、このマクロはadd_custom_commandを使用して* .h.gchファイルを作成します。このファイルは、add_executable/add_libraryを使用して他のソースファイルと一緒にターゲットに追加できます。問題は、一部のライブラリが静的ライブラリと動的ライブラリの両方として構築されているため、同じ*.h.gchファイルが2つの異なるターゲットに使用される場合があることです。

MSVC / Xcodeの場合、PCHの使用/コンパイルを有効にするためにターゲットのプロパティを調整する必要があるため、各add_library呼び出しの後にマクロを呼び出す必要があります。ただし、gccの場合、ビルドルール(.gch)が既に含まれている出力でadd_custom_commandを使用しようとすると、エラーが発生します。現在、名前に「Static」が含まれているターゲットのadd_custom_commandをスキップすることで、このエラーを回避しています。これは、プロジェクト内のすべての静的ライブラリに「Static」の接尾辞があるために機能しますが、明らかにあまり洗練されたソリューションではありません。 。

ターゲットにすでにビルドルールがあるかどうかをcmakeに確認する方法はありますか、あるいは、エラーを発生させずにadd_custom_commandをサイレントに失敗させる方法はありますか?または、問題を完全に回避できるようにデザインを変更する方法はありますか?1つの「解決策」は、各CMakeListに条件付きチェックを追加することだと思いますが、実際にはそうしたくありません。

これは私が現在使用しているコードです:

マクロ:

macro(SET_PRECOMPILED_HEADER targetName PCHFile)
if(MSVC)
# PCH for MSVC
elseif(${CMAKE_GENERATOR} MATCHES "Xcode")
# PCH for Xcode
else() #gcc
if(NOT ${targetName} MATCHES "Static") ## <-- this is bad
    ## set the correct "compilerArgs"
    add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PCHFile}.gch
        COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${compilerArgs}
        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PCHFile}
    )
endif()
endmacro(SET_PRECOMPILED_HEADER targetName PCHFile)

...次に、CMakeListsで、次のようになります。

# Dynamic version:
set(MODULE_NAME MyLib)
project(${MODULE_NAME})

## set ${sources}

add_library(${MODULE_NAME} SHARED ${sources} "src/precompiled.h.${PCH_EXT}")

set_target_properties(${MODULE_NAME} PROPERTIES COMPILE_DEFINITIONS MY_DLL_DEFINITION)

SET_PRECOMPILED_HEADER(${MODULE_NAME} "src/precompiled.h")

# Static version:
set(MODULE_NAME MyLibStatic)
project(${MODULE_NAME})

add_library(${MODULE_NAME} ${sources} "src/precompiled.h.${PCH_EXT}")

set_target_properties(${MODULE_NAME} PROPERTIES COMPILE_DEFINITIONS MY_STATIC_DEFINITION)

SET_PRECOMPILED_HEADER(${MODULE_NAME} "src/precompiled.h")

ご協力いただきありがとうございます!これが重複している場合は申し訳ありません。add_custom_commandにはすでにいくつかの質問がありますが、どれも私が求めているものに完全に対応しているようには見えません。

4

1 に答える 1

1

まず、各 PCH のターゲットを作成し、新しいターゲットを宣言する前にこれを使用できます。

if(TARGET ${PCHFile}.gch)

別の方法:

ルート CMakeLists.txt で:

set(PRECOMPILED_HEADERS "" CACHE INTERNAL "")

マクロでは:

list(FIND PRECOMPILED_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PCHFile}.gch res)
if(NOT res EQUAL -1)
  add_custom_command(
          OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PCHFile}.gch
          COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${compilerArgs}
          DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PCHFile}
      )
  list(APPEND PRECOMPILED_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PCHFile}.gch)
endif()
于 2012-08-22T16:24:42.173 に答える