假设有以下目录结构:
projects
|
+--lib1
| |
| +-CMakeFiles.txt
|
+--lib2
| |
| +-CMakeFiles.txt
|
+--test
|
+-CMakeFiles.txt
lib1/CMakeFiles.txt:
cmake_minimum_required(VERSION 2.0)
add_library(lib1 STATIC lib1.cpp)
lib2/CMakeFiles.txt:
cmake_minimum_required(VERSION 2.0)
add_subdirectory(../lib1 ${CMAKE_CURRENT_BINARY_DIR}/lib1)
add_library(lib2 STATIC lib2.cpp)
target_link_libraries(lib2 lib1)
test/CMakeFiles.txt:
cmake_minimum_required(VERSION 2.0)
project(test)
add_subdirectory(../lib1 ${CMAKE_CURRENT_BINARY_DIR}/lib1)
add_subdirectory(../lib2 ${CMAKE_CURRENT_BINARY_DIR}/lib2)
add_executable(test main.cpp)
target_link_libraries(test lib1 lib2)
即 lib2
取决于lib1
,test
取决于两者。(我知道技术上静态库不会"链接",但这只是一个示例。
问题是在当前设置下,lib1 编译两次 - 第一次在"test"构建目录中,第二次在"test/build_directory/lib2/build_directory"中。我想避免这种情况。
我希望能够将 lib1、lib2 或两者(使用 add_subdirectory(的依赖项添加到位于其他地方的任何项目中。因此,移动CMakeFiles不是一种选择。我还想避免多次编译任何库。
我该怎么做?
平台:CMake v. 2.8.4 和 Windows XP SP3
顶级 CMakeLists.txt 文件不是一个选项,因为我想保持一个干净的顶级目录,并能够在其他项目中包含可以位于其他地方的库。因为它是Windows,所以我不能"在系统范围内安装软件包" - 我不想失去即时切换编译器的能力。使用不同编译器构建的实用程序库将使用不同的 C 运行时库/ABI,因此将不兼容。
另一种解决方案是在子目录CMakeLists的顶部添加一个保护.txt:
if(TARGET targetname)
return()
endif(TARGET targetname)
这将导致 cmake 在第二次添加子目录时不执行任何操作(当然,如果在该文件中定义了 targetname(。
这将导致lib beeing构建在build/树中的任意位置(取决于哪个模块首先添加它(,但它只会构建一次并链接到任何地方。
在您的示例中,您将添加
if(TARGET lib1)
return()
endif(TARGET lib1)
在lib1/CMakeFiles的顶部.txt
使用 CMake,库依赖项是可传递的,因此您不应该在 test/CMakeFiles.txt
中调用 add_subdirectory
两次(也不需要将lib1
列为test
的依赖项,因为它已经是 lib2
的依赖项(。
因此,您可以将test
的CMakeFiles.txt修改为:
cmake_minimum_required(VERSION 2.8.7) # Prefer the most current version possible
project(test)
add_subdirectory(../lib2 ${CMAKE_CURRENT_BINARY_DIR}/lib2)
add_executable(test main.cpp)
target_link_libraries(test lib2)
此外,您可能应该从非项目 CMakeFiles .txt 文件(lib 文件(中删除 cmake_minimum_required
调用。 有关详细信息,请运行:
cmake --help-policy CMP0000
如果您添加类似的 test2 子目录和项目,这取决于 lib1
和 lib2
,此设置仍会导致所有库被重新编译。 如果您真的不想在 projects/
中拥有顶级 CMakeFiles.txt,那么您将坚持您正在做的事情,或者您可以使用 export
或 install
命令。
export
将创建一个文件,该文件可由其他项目include
,并将目标导入调用include
的项目。
install
可以将库安装到projects/
的另一个公共子目录中。 根据您的源目录结构,这样做的好处是仅使预期的库 API 标头可供依赖项目使用。
但是,这两个选项都需要在修改依赖库项目时重新生成(并安装它们(,而当前设置包括项目中的所有依赖目标,因此对依赖库中源文件的任何更改都将导致test
目标过期。
有关export
和install
的更多详细信息,请运行:
cmake --help-command export
cmake --help-command install
也许在你的项目目录中添加一个顶级CMakeLists.txt像这样:
project( YourProjects )
add_subdirectory( lib1 )
add_subdirectory( lib2 )
add_subdirectory( test )
这应该足够了,并且会在顶级构建目录中为您提供解决方案文件或生成文件。然后,您应该从 lib1 和 lib2 项目中删除add_subdirectory( ../lib1 ...
,而只需链接到它们。CMake 在编译测试时会知道如何找到 lib1 和 lib2。
即在 lib2 中:
project( lib2)
add_library(lib2 STATIC lib2.cpp)
target_link_libraries(lib2 lib1)
并在测试中:
project( test )
add_executable(test main.cpp)
target_link_libraries(test lib1 lib2)
额外的好处:您将在lib2目录中获得用于构建lib2(使用依赖lib1(的makefiles/解决方案文件...