如何使用CMake

时间:2018-05-16 22:04:40

标签: c++ cmake

TL; DR我基本上需要this question的模块化解决方案。它不仅包含一个解决方案,而且还包含每个可执行文件的解决方案。

在我的问题here中,我想知道如何在不同的文件夹中拆分我的CMakeLists.txt。一些文件夹包含将成为静态库的代码,一些代码将是基于这些静态库构建的可执行文件或动态库。

文件夹结构如下所示:

/path/to/base/
  CMakeLists.txt
  app1/
    <src files for app1>
    CMakeLists.txt
  app2/
    <src files for app2>
    CMakeLists.txt
  lib/
    <src files for lib>
    CMakeLists.txt

如果我采用在父文件夹中有CMakeLists.txt的方法来处理我的所有库和可执行文件,并且从包含所有目录,我遇到的问题是当我生成VS项目/解决方案时我的项目target包含所有项目 - 不仅是我预期目标所必需的项目。

基础文件夹中CMakeLists.txt的内容:

cmake_minimum_required(VERSION 3.1)

add_subdirectory(lib)
add_subdirectory(app1)
add_subdirectory(app2)

和app1文件夹中的CMakeLists.txt(app2等效)

cmake_minimum_required(VERSION 3.1)

project(app1)

add_executable(app1 <src of app1>)

target_link_libraries(app1 lib)
lib的

CMakeLists.txt

add_library(lib <src of lib>)

如果我在CMakeLists.txt基础上运行cmake,则解决方案包含所有项目。即使我只打开其中一个项目;它还包含一切。 app1的VS项目也构建app2 - 我不想要。

如果我只在app1的CMakeLists.txt上运行cmake,我会得到一个不包含app2的解决方案,但它也不包含lib,因为只提到了在cmake文件中的链接,而不是目标(它在基础文件中)

1 个答案:

答案 0 :(得分:1)

CMake将为每个project调用创建一个解决方案,然后包含当前目录及其子目录的所有目标(无论它们是在实际调用project之前还是之后定义的。 )。

这是一个表现良好的CMake脚本应该做什么:您希望能够在较大项目中充当其自己的子树的根的每个CMakeLists应该以{{1​​}}开头呼叫,然后是cmake_minimum_required电话。在CMakeLists中编写project基本上意味着:这是一个完全独立的组件,可以独立构建,即使您从其父目录中删除所有文件也是如此。因此,为每个project提供单独的解决方案是有意义的。

考虑到这一点,我们可以看到为什么这在您的情况下不起作用:您的应用程序不是完全自包含的,它们依赖于 lib 。解决方案是为应用程序编写构建脚本,就好像 lib 是作为第三方组件提供的,具有project个调用和所有内容。 在复合构建中,您已经有 lib 的目标,因此find_package调用调用的脚本应该短路到使用该目标并且实际上只是清理系统如果它找不到现有的目标。

另请阅读CMake's packaging system的工作原理,它提供了一些非常优雅地处理此类案例的自动化。