【问题标题】:CMake include_directories vs file GLOBCMake include_directories 与文件 GLOB
【发布时间】:2016-02-19 03:34:13
【问题描述】:

我一直在尝试将项目从 VS 迁移到 CMake,但我不确定我的项目结构是否适合简单的迁移:

project/
|- CMakeLists.txt
|- build/
    |- (cmake stuff)
|- src/
    |- main.cpp
    |- tests.cpp // also contains a main()
    |- class1.hpp
    |- class1.cpp
    |- class2.hpp
    |- class2.cpp
    |- ...
|- included/
    | - (external libs)

到目前为止,我的 CMakeLists.txt 尝试是:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)

add_executable(webnectar src/main.cpp
                         src/test.cpp)

enable_testing()
add_test(tests project)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/included)

但是我在自己的类中出现链接错误。我不明白为什么。

在其他几个 SO 问题中,我看到人们使用文件 GLOB 来包含子文件夹中的所有源,我想这将是一个解决方案。不过,我希望我能理解为什么 include_directories 还不够,以及为什么(如果可以的话)文件 GLOB 是可以的。

另外,使用文件 GLOB 会弄乱我的构建,因为 test.cpp 和 main.cpp 都有一个 main 函数。

虽然它看起来是另一回事(对于不同的问题),但请考虑这个问题更笼统,因为我如何使用 CMake 语法或更合适的文件结构来解决所有这些问题。

【问题讨论】:

标签: cmake


【解决方案1】:
  1. 关于include_directories 该指令对应于-I 编译器标志,允许编译器查找header 文件,即那些包含在#include ... 中的文件。
  2. 您应该在add_executable 的参数中提及您的所有源文件。这是不可避免的。

您可以使用FILE(GLOB..) 形成完整的来源列表:

FILE(GLOB webnectar_SOURCES RELATIVE src/ *.cpp)

然后在add_executable(webnectar ${webnectar_SOURCES})中使用它。

但是,这不是最好和最安全的选择,因为它包含一个重大缺陷。文件列表是在构建过程的“配置”阶段形成的(例如cmake -D<....> -D<.....> .),然后在与 CMake 相关的文件(CMakeLists.txt、CMakeCache.txt 等)发生某种变化之前,它永远不会被重建。所以如果你先运行cmake...,然后添加一个新文件,就不会被注意到,而且Makefiles也不会被重新生成。

此外,如果一些额外的文件(例如,在中断合并后留下的文件)适合掩码,您会得到一些非常意想不到的结果。

因此,形成和维护一个明确的来源列表会更安全,即

set(webnectar_SOURCES
  src/main.cpp
  src/class1.cpp
  src/class2.cpp
  ...
)

然后在add_executable(webnectar ${webnectar_SOURCES}) 中使用它。变量的名称可以是任何名称,但某些 IDE(如 KDevelop)更喜欢标准命名 <artifact>_SOURCES,因此它们可以为您自动维护列表(或至少尝试维护 :))

【讨论】:

  • 我想这是一个解决方案,但是手动添加每个源文件会很烦人。这是大多数人实际工作的方式,还是他们一开始就不会将来源与标题分开?
  • 其实这个问题好像是跟古人一模一样:stackoverflow.com/questions/1027247/…从那以后利弊没变。
  • 哦,谢谢。我没找到那个。我希望重新排列文件夹结构可以有所帮助,或者除了文件 glob 和手动列出文件之外的任何其他解决方案。
  • 不,重新排列文件夹无济于事。任何构建系统(不一定是 CMake,还包括 GNU autotools 等)都必须为所有文件生成构建规则。它们都生成每个文件的规则(不是像 Makefiles 中的 .c.o: 这样的通配符规则),因此它们必须知道源文件的确切列表。所以你必须提供文件列表。而且,如果您提供使用 globbing 制作的文件列表,那么您将遇到上述所有问题
猜你喜欢
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
  • 2015-01-12
相关资源
最近更新 更多