让我们说以下目录结构:
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)
测试/ 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-2.8.4 winxp sp3
- EDIT-- 顶级cmakelists不是一个选项,因为我想保持干净的顶级目录,并能够将库包含在可以位于其他地方的其他项目中。因为它是windows,我不能在全系统安装软件包" - 我不想失去动态切换编译器的能力。使用不同编译器构建的实用程序库将使用不同的C运行时库/ ABI,因此将不兼容。
答案 0 :(得分:12)
另一个解决方案是在子目录-CMakeLists.txt的顶部添加一个防护:
if(TARGET targetname)
return()
endif(TARGET targetname)
这将导致cmake在第二次添加子目录时不执行任何操作(当然,如果在该文件中定义了targetname)。
这将导致lib beeing构建在构建/树中的任意位置(取决于首先添加它的模块),但它将只构建一次并在任何地方链接。
在您的示例中,您将添加
if(TARGET lib1)
return()
endif(TARGET lib1)
位于lib1 / CMakeFiles.txt
的顶部答案 1 :(得分:4)
使用CMake,库依赖项是可传递的,因此您不应在add_subdirectory
中调用test/CMakeFiles.txt
两次(也不需要将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
或{{1命令。
install
会创建一个文件,该文件可能由其他项目export
组成,并将目标导入到调用include
的项目中。
include
可以将库安装到另一个公共子目录install
。根据您的源目录结构,这可能只有使目标库API头可用于依赖项目。
但是,这两个选项都需要重建(并安装)依赖库项目(如果它们被修改),而当前设置包括项目中的所有依赖目标,因此对依赖库中的源文件进行任何更改会导致projects/
目标过期。
有关test
和export
的详细信息,请运行:
install
答案 2 :(得分:0)
也许在项目目录中添加顶级CMakeLists.txt。类似的东西:
project( YourProjects )
add_subdirectory( lib1 )
add_subdirectory( lib2 )
add_subdirectory( test )
这应该足够了,并且会在顶级build-dir中为您提供解决方案文件或makefile。然后,您应该从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)的makefile / solutionfiles ...