我正在Cmake中使用configure_file
命令进行功能可用性检查,如本页所述。该页面建议使用以下命令:
configure_file(config.h.in config.h)
其将CCD_ 2翻译成CCD_。但当我编译程序时,编译器只在${CMAKE_CURRENT_SOURCE_DIR}
中查找头(例如config.h
),而不在${CMAKE_CURRENT_BINARY_DIR}
中查找。因此,编译器很自然地找不到生成config.h
的位置,因此构建失败。
解决这个问题的标准方法是什么?我应该更改CMakeLists.txt
以便在源目录中创建config.h
吗?或者我应该更改它以将构建目录添加到include路径中?(真的,为什么我必须手动处理这个问题?[半反问])
这个问题涉及一个类似的问题,但这两种选择都是可能的解决方案;我想知道是否有一个标准的做法,或者这是否表明我错过了关于如何使用Cmake的一些东西。
保持源树"原始"是正确的,如果你想进行多个不同的构建,或者如果你想通过rm'ing构建目录来清理构建,那么不这样做是错误的(如果你正在向源目录生成内容,那就不够了)。
在构建目录中生成它,并添加include路径。
设置变量
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-规格和使用要求
我不认为有一种标准的方法来处理这个问题,但从我自己对其他项目的有限看法来看,似乎并没有绝大多数的方法。如果我猜测的话,我认为将生成的文件放在构建树中比放在源树中更常见。
为了清楚起见,我自己更喜欢把它放在${CMAKE_CURRENT_BINARY_DIR}/GeneratedFiles/config.h
这样的子目录中。这避免了${CMAKE_CURRENT_BINARY_DIR}
的所有子目录出现在IDE(如Visual Studio)的自动完成列表中。它还可以让您的构建根更加干净,特别是当您最终生成了几个文件时。您必须首先创建目录:
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仅由库MyLib
内部使用,则可以执行以下操作:
add_library(MyLib ${ConfigFile} ... other sources ...)
target_include_directories(MyLib
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${GeneratedFilesDir}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
与使用include_directories
不同,这避免了将${GeneratedFilesDir}
作为包含路径的所有目标。
当生成的文件需要作为公共头公开或添加到install
命令中时,问题变得更加有争议。最终,我认为这里没有"错误"的选择。归根结底,你是否觉得以更复杂的CMake设置为代价来保持源树的原始状态更好。