2

I'm using the configure_file command in Cmake in a feature availability check as described on this page. That page suggests using the command like this:

configure_file(config.h.in config.h)

which will translate ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in to ${CMAKE_CURRENT_BINARY_DIR}/config.h. But when I compile my program, the compiler only looks in ${CMAKE_CURRENT_SOURCE_DIR} for headers (e.g. config.h), not in ${CMAKE_CURRENT_BINARY_DIR}. So naturally, the compiler doesn't find config.h where it was generated, and the build fails.

What's the standard way to resolve this issue? Should I change CMakeLists.txt so that config.h gets created in the source directory? Or should I change it to add the build directory to the include path? (And really, why do I have to manually deal with this at all? [semi-rhetorical question])

This question concerns a similar issue but both options are suggested as possible solutions; I want to know if there's a standard practice, or if this indicates that I'm missing something about how Cmake is meant to be used.

4

2 回答 2

6

保持源代码树“原始”是正确的,如果您想进行多个不同的构建,或者如果您希望能够通过 rm'ing 构建目录来清理构建(不是如果您正在为源目录生成东西就足够了)。

在构建目录中生成它并添加包含路径。

设置变量

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

使每个源目录的相应构建目录自动添加,并使其成为其他目标使用的传递行为(例如,foo不必bar显式添加构建目录)。

http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#build-specification-and-usage-requirements

于 2014-09-25T05:52:24.163 回答
3

我不认为有一个标准的方法来处理这个问题,但从我自己对其他项目的有限看法来看,似乎并没有一种方法占绝大多数。如果我猜的话,我认为将生成的文件放在构建树而不是源树中更为常见。

为了清楚起见,我自己的偏好是将它放在一个子目录${CMAKE_CURRENT_BINARY_DIR}/GeneratedFiles/config.h中。这避免了所有子目录${CMAKE_CURRENT_BINARY_DIR}出现在像 Visual Studio 这样的 IDE 的自动完成列表中。它还可以使您的构建根目录更加干净,特别是在您最终生成多个文件的情况下。您必须先创建目录:

set(GeneratedFilesDir "${CMAKE_CURRENT_BINARY_DIR}/GeneratedFiles")
file(MAKE_DIRECTORY ${GeneratedFilesDir})

set(ConfigFile "${GeneratedFilesDir}/config.h")
configure_file(config.h.in ${ConfigFile})


然后,您也许可以通过使用target_include_directories而不是include_directories. 例如,如果 config.h 仅由 library 内部使用MyLib,您可以执行以下操作:

add_library(MyLib ${ConfigFile} ... other sources ...)
target_include_directories(MyLib
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${GeneratedFilesDir}
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

与 using 不同include_directories,这避免了所有具有${GeneratedFilesDir}包含路径的目标。


当生成的文件需要作为公共标头公开或添加到install命令时,事情变得更有争议。最终,我认为这里没有“错误”的选择。归结为您是否觉得以更复杂的 CMake 设置为代价来保持源代码树的原始状态更好。

于 2014-09-25T03:43:54.007 回答