让编译器找到Cmake创建的文件
我正在使用Cmake中的configure_file
命令进行function可用性检查,如本页所述 。 该页面建议使用如下命令:
configure_file(config.h.in config.h)
这会将${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
为${CMAKE_CURRENT_BINARY_DIR}/config.h
。 但是当我编译程序时,编译器只在${CMAKE_CURRENT_SOURCE_DIR}
查找标题(例如config.h
),而不是${CMAKE_CURRENT_BINARY_DIR}
。 很自然地,编译器找不到生成它的config.h
,并且构建失败。
解决此问题的标准方法是什么? 我应该更改CMakeLists.txt
以便在源目录config.h
创建config.h
吗? 或者我应该更改它以将构建目录添加到包含路径? (实际上,为什么我必须手动处理这个问题?[半修辞问题])
这个问题涉及类似的问题,但建议两种方案作为可能的解决方案; 我想知道是否有一个标准的做法,或者这是否表明我错过了一些关于如何使用Cmake的内容。
保持你的源代码树’原始’是正确的,如果你想做多个不同的构建,或者如果你想通过rm的构建目录来清理构建,那么不这样做是’错误的’如果您正在为源代码生成内容,那就足够了。
在构建目录中生成它并添加包含路径。
设置变量
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
使每个源目录的相应构建目录自动添加,并使其成为其他目标的传递行为(例如, foo
不必显式添加bar
的构建目录)。
我认为没有一种标准的方法可以解决这个问题,但从我自己对其他项目的有限看法来看,似乎并不是绝大多数都是这样或那样的。 如果我猜测,我认为将生成的文件放在构建树而不是源树中更常见。
为了清楚起见,我自己的偏好是将它放在像${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仅由库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设置为代价保持你的源树原始状态。