如何从CMakeLists.txt文件设置include_directories?

15

使用CMake的include_directories()命令设置包含路径(-I)好像有些麻烦。我的项目目录如下:

Root
| - CMakeLists.txt
| - libs
| - | - CMakeLists.txt
| - | - inc
| - | - | - // lib specific includes
| - | - src
| - | - | - // lib specific sources
| - proj1
| - | - CMakeLists.txt
| - | - inc
| - | - | - // proj1 specific includes
| - | - src
| - | - | - // proj1 specific sources

根目录下的 CMakeLists.txt 文件如下:

project(ROOT)
add_subdirectory(libs)
add_subdirectory(proj1)

libs目录下的CMakeLists.txt文件:

project(lib)
add_library(lib STATIC ${lib_hdrs} ${lib_srcs}) // for conciseness, omitted set() 

最后是在proj1下的CMakeLists.txt文件:

project(proj1)

include_directories("${ROOT_SOURCE_DIR}/lib/inc") # <- problem line?

add_executable(proj1 ${proj1_srcs})
target_link_libraries(proj1 lib)

目标是从libs中的源文件和头文件创建库,然后链接到proj1生成的可执行文件。Proj1有一些包含在libs中的东西,所以我需要添加用-I使用的目录。根据文档,这就是include_directories()应该做的事情。但是,尽管明确设置了这一点,并在其后跟随一个调试message(${INCLUDE_DIRECTORIES}),但INCLUDE_DIRECTORIES变量是一个空字符串,并且没有指定任何目录用于包含路径,因此我的proj1编译失败。

我还尝试删除${ROOT_SOURCE_DIR}/inc周围的引号,看看是否有帮助,但没有成功。


2
笔误?你写的是 include_directories("${ROOT_SOURCE_DIR}/lib/inc"),但应该是 libs 而不是 lib。而且调用 CMake 函数 include_directories 并不会实际填充名为 INCLUDE_DIRECTORIES 的变量。 - Fraser
抱歉,那只是问题中的一个打字错误。 - HD_Mouse
1个回答

19

include_directories()会填充一个名为INCLUDE_DIRECTORIES的目录属性:

http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_dir:INCLUDE_DIRECTORIES

请注意,CMake 2.8.11学习了target_include_directories命令,该命令会填充INCLUDE_DIRECTORIES目标属性。 http://www.cmake.org/cmake/help/v2.8.12/cmake.html#command:target_include_directories

还要注意,您可以使用target_include_directoriesPUBLIC关键字将“编译针对lib目标的头文件需要包含目录lib/inc”的事实编码到lib目标本身中。

add_library(lib STATIC ${lib_hdrs} ${lib_srcs}) # Why do you list the headers?
target_include_directories(lib PUBLIC "${ROOT_SOURCE_DIR}/lib/inc")

此外,我假设您不会安装lib库供他人使用。在这种情况下,您需要为构建位置和安装位置指定不同的头文件目录。

target_include_directories(lib
  PUBLIC
    # Headers used from source/build location:
    "$<BUILD_INTERFACE:${ROOT_SOURCE_DIR}/lib/inc>"
    # Headers used from installed location:
    "$<INSTALL_INTERFACE:include>"     
)

不管怎样,只有在你安装 lib 供他人使用时才很重要。

在上面的 target_include_directories(lib ...) 之后,您不需要其他的 include_directories() 调用。 lib 目标“告诉” proj1 它需要使用的包含目录。

另请参见 target_compile_defintions()target_compile_options()


这就是PUBLIC的作用。文档上并没有很清楚地说明。 - JAB
JAB: http://www.cmake.org/cmake/help/v3.2/manual/cmake-buildsystem.7.html#build-specification-and-usage-requirements - steveire
target_include_directories(<your_lib> PUBLIC <dir1_with_path> <dir2_path>)是我一直在寻找的内容。这可以帮助指定“仅针对指定目标的包含文件路径”。 - parasrish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接