13

假设有以下目录结构:

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 v. 2.8.4 和 Windows XP SP3

顶级 CMakeLists.txt 文件不是一个选项,因为我想保持一个干净的顶级目录,并能够在其他项目中包含可以位于其他地方的库。因为它是 Windows,所以我不能“在系统范围内安装包”——我不想失去即时切换编译器的能力。使用不同编译器构建的实用程序库将使用不同的 C 运行时库/ABI,因此将不兼容。

4

3 回答 3

15

另一种解决方案是在子目录-CMakeLists.txt 的顶部添加一个守卫:

if(TARGET targetname)
    return()
endif(TARGET targetname)

这将导致 cmake 在第二次添加子目录时不执行任何操作(当然,如果在该文件中定义了 targetname)。

这将导致 libbeeing 在 build/ 树中的任意位置(取决于首先添加它的模块)中构建,但它只会构建一次并链接到任何地方。

在您的示例中,您将添加

if(TARGET lib1)
    return()
endif(TARGET lib1)

在 lib1/CMakeFiles.txt 的顶部

于 2012-10-29T20:05:23.790 回答
7

使用 CMake,库依赖项是可传递的,因此您不应调用add_subdirectory两次test/CMakeFiles.txt(也不需要将其lib1列为依赖项,test因为它已经是lib2's 的依赖项)。

因此,您可以将test's 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)

此外,您可能应该cmake_minimum_required从非项目 CMakeFiles.txt 文件(lib 文件)中删除调用。有关更多信息,请运行:

cmake --help-policy CMP0000


lib1如果您添加一个类似的 test2 子目录和依赖于and 的项目,此设置仍将导致重新编译所有库lib2。如果您真的不想在 中包含顶级 CMakeFiles.txt projects/,那么您将无法解决您正在做的事情,或者您可以使用exportorinstall命令。

export将创建一个文件,该文件include可由其他项目 d 并将目标导入到调用include.

install可以将库安装到projects/. 根据您的源目录结构,这可能具有仅使预期的库 API 标头可用于依赖项目的好处。

但是,如果修改了这两个选项,则需要重新构建(和安装)依赖库项目,而您当前的设置包括项目中的所有依赖目标,因此对依赖库中源文件的任何更改都会导致您test目标过时。

有关 and 的更多详细信息export,请install运行:

cmake --help-command export
cmake --help-command install
于 2012-04-04T20:05:51.670 回答
0

也许在您的项目目录中添加一个顶级 CMakeLists.txt。就像是:

project( YourProjects )

add_subdirectory( lib1 )
add_subdirectory( lib2 )
add_subdirectory( test )

这应该足够了,并且会在您的顶级构建目录中为您提供解决方案文件或生成文件。然后,您应该add_subdirectory( ../lib1 ...从您的 lib1 和 lib2 项目中删除 ,而只需链接到它们。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/解决方案文件...

于 2012-04-04T14:15:55.850 回答