4

現在、CMakeを使用してプロジェクトをビルドし、CppUnitを使用してテストしています。私のCMakeファイルで2つの実行可能ファイルを作成します。sampleコンパイルされたソース自体です。そして、sample_test私はテストを実行します。irの場合

ここに私の一部CMakeLists.txt

SET(SAMPLE_ROOT_PATH ${PROJECT_BINARY_DIR})
SET(SAMPLE_SOURCE_PATH ${SAMPLE_ROOT_PATH}/src)
SET(SAMPLE_TEST_SOURCE_PATH ${SAMPLE_ROOT_PATH}/test)
SET(SAMPLE_BIN_PATH ${SAMPLE_ROOT_PATH}/bin)
SET(SAMPLE_EXEC_NAME sample)
SET(SAMPLE_TEST_EXEC_NAME sample_test)

SET(EXECUTABLE_OUTPUT_PATH ${SAMPLE_BIN_PATH})

FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp)
FILE(GLOB_RECURSE SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_PATH}/*.cpp)
SET(SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_FILES} ${SAMPLE_SOURCE_FILES}
)
LIST(REMOVE_ITEM SAMPLE_TEST_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/main.cpp)

SET(CMAKE_CXX_FLAGS "-g -Wall")

ADD_EXECUTABLE(${SAMPLE_EXEC_NAME} ${SAMPLE_SOURCE_FILES})
ADD_EXECUTABLE(${SAMPLE_TEST_EXEC_NAME} ${SAMPLE_TEST_SOURCE_FILES})

これはの出力ですmake

[  8%] Building CXX object CMakeFiles/sample.dir/src/KeyBuffer.cpp.obj
[ 12%] Building CXX object CMakeFiles/sample.dir/src/main.cpp.obj
[ 20%] Building CXX object CMakeFiles/sample.dir/src/Object.cpp.obj
[ 45%] Building CXX object CMakeFiles/sample.dir/src/World.cpp.obj
Linking CXX executable bin/sample.exe
[ 45%] Built target sample
[ 50%] Building CXX object CMakeFiles/sample_test.dir/test/KeyBufferTest.cpp.obj

[ 54%] Building CXX object CMakeFiles/sample_test.dir/test/ObjectTest.cpp.obj
[ 66%] Building CXX object CMakeFiles/sample_test.dir/src/KeyBuffer.cpp.obj
[ 75%] Building CXX object CMakeFiles/sample_test.dir/src/Object.cpp.obj
[100%] Building CXX object CMakeFiles/sample_test.dir/src/World.cpp.obj
Linking CXX executable bin/sample_test.exe

ご覧Object.cppのとおり、2回コンパイルされますWorld.cppKeyBuffer.cppどうすればそれを防ぐことができますか?または、CMakeを使用してCppUnitテストを処理するためのより良い方法はありますか?

4

2 に答える 2

4

ターゲットごとに異なるコンパイラフラグが設定されている可能性があるため、1つのソースファイルを2つのターゲットに追加する場合は、両方のターゲットについて、この1つのソースファイルから個別のオブジェクトファイルを作成する必要があります。

通常の解決策は、共有ソースファイルを静的ライブラリにコンパイルしてから、両方のアプリケーションターゲットにリンクすることです。

add_library(base STATIC ${shared_SOURCES}) # except e.g. foo_main.cpp

add_executable(foo ${foo_only_SOURCES})
target_link_libraries(foo base)

add_executable(bar ${bar_only_SOURCES})
target_link_libraries(bar base)
于 2012-08-07T13:52:51.913 に答える
4

概念的には、CMakeは各ターゲット(つまり、実行可能ファイルまたはライブラリ)を個別のビルドユニットとして扱います。生成されたビルドシステムは、ターゲットに属するソースファイルごとにオブジェクトファイルを生成します。デフォルトでは、コンパイル設定(コンパイルフラグ、プリプロセッサ定義など)がまったく同じであっても、CMakeは複数のターゲットで使用されるソースファイルの冗長なコンパイルを回避しません。

CMake 2.8.8は、冗長なコンパイルを回避する問題に対処するために、targetと呼ばれる新機能を導入しました。OBJECT_LIBRARY

オブジェクトライブラリを生成するには、次を使用しますadd_library

FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp)
ADD_LIBRARY(sample_objects OBJECT EXCLUDE_FROM_ALL ${SAMPLE_SOURCE_FILES})

次の形式の式を使用してオブジェクトによって作成された、add_libraryまたはオブジェクトを参照する可能性のある他のターゲット:add_executable$<TARGET_OBJECTS:objlib>

ADD_EXECUTABLE(${SAMPLE_EXEC_NAME} $<TARGET_OBJECTS:sample_objects>)

FILE(GLOB_RECURSE SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_PATH}/*.cpp)
ADD_EXECUTABLE(${SAMPLE_TEST_EXEC_NAME} $<TARGET_OBJECTS:sample_objects> ${SAMPLE_TEST_SOURCE_FILES})

冗長なコンパイルを回避するために通常の静的ライブラリを使用する場合と比較して、オブジェクトライブラリには、リンクする必要がないという利点があります。その上、インポート、エクスポート、またはインストールすることはできません。

于 2012-08-07T14:14:20.480 に答える