C++ CMake:当我尝试添加源目录本身或其子目录之一时,target_include_directories() 会打印错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25676277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CMake: target_include_directories() prints an error when I try to add the source directory itself, or one of its subdirectories
提问by JPNotADragon
I am writing a C++ library (header-only) and am using CMake to generate my (Visual Studio) project and solution files. I'm also writing a test suite, which is part of the same CMake project.
我正在编写一个 C++ 库(仅限头文件)并使用 CMake 生成我的(Visual Studio)项目和解决方案文件。我也在编写一个测试套件,它是同一个 CMake 项目的一部分。
My problem occurs when I call target_include_directories() on the target that represents my header-only library, so that consumers of my library may find its header files. I get the following error message (even though generation is NOT aborted).
当我在代表我的仅标头库的目标上调用 target_include_directories() 时会出现我的问题,以便我的库的使用者可以找到它的头文件。我收到以下错误消息(即使生成没有中止)。
CMake Error in CMakeLists.txt:
Target "Fonts" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"D:/Projects/GPC/fonts/include"
which is prefixed in the source directory.
(D:/Projects/GPC/Fonts being the top-level directory of my library project. Btw the problem remains if I move my header files to the top directory.)
(D:/Projects/GPC/Fonts 是我的库项目的顶级目录。顺便说一句,如果我将头文件移动到顶级目录,问题仍然存在。)
The offending line in my CMakeLists.txt is this (adapted for simplicity):
我的 CMakeLists.txt 中的违规行是这样的(为简单起见进行了改编):
target_include_directories(Fonts INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
I do not understand what I'm doing wrong. Without target_include_directories(), code of consumer projects simply can't include my header files (unless in installed form, but I haven't gotten to that yet, and in any case I want to be able to use my library from its build tree, without installation.)
我不明白我做错了什么。如果没有 target_include_directories(),消费者项目的代码根本无法包含我的头文件(除非以安装形式存在,但我还没有做到这一点,无论如何我希望能够从它的构建树中使用我的库,无需安装。)
I feel like I'm missing something basic here; yet I've searched for hours without finding a solution or explanation.
我觉得我在这里缺少一些基本的东西;但我已经搜索了几个小时没有找到解决方案或解释。
回答by ComicSansMS
The origin of the problem is not the target_include_directories
command itself, but the attempt to install
a target that has a public or interface include directory prefixed in the source path.
问题的根源不是target_include_directories
命令本身,而是对install
具有公共或接口的目标的尝试,包括源路径中带有前缀的目录。
While it is perfectly fine and desirable to use absolute paths when building the library from scratch, a third party library that pulls in a prebuilt version of that library will probably want to use a different include path. After all, you do not want all of your users to mirror the directory structure of your build machine, just to end up in the right include path.
虽然在从头开始构建库时使用绝对路径是非常好的和可取的,但引入该库的预构建版本的第三方库可能希望使用不同的包含路径。毕竟,您不希望所有用户都镜像构建机器的目录结构,只是为了在正确的包含路径中结束。
CMake's packaging mechanismprovides support for both of these use cases: You may pull in a library directly from the build tree (that is, check out the source, build it, and point find_package()
to the directory), or from an install directory (run make INSTALL
to copy built stuff to the install directory and point find_package()
to thatdirectory). The latter approach needs to be relocatable (that is, I build and install on my machine, send you the resulting directory and you will be able to use it on your machine from a different directory structure), while the former is not.
CMake 的打包机制为这两种用例提供支持:您可以直接从构建树(即,检出源代码、构建它并指向find_package()
目录)或从安装目录(运行make INSTALL
到内置的东西复制到安装目录,并点find_package()
到该目录)。后一种方法需要可重定位(即,我在我的机器上构建和安装,将结果目录发送给您,您将能够在您的机器上从不同的目录结构使用它),而前者则不是。
This is a very neat feature, but you have to account for it when setting up the include directories. Quoting the manual for target_include_directories
:
这是一个非常巧妙的功能,但是您必须在设置包含目录时考虑到它。引用手册target_include_directories
:
Include directories usage requirements commonly differ between the build-tree and the install-tree. The
BUILD_INTERFACE
andINSTALL_INTERFACE
generator expressions can be used to describe separate usage requirements based on the usage location. Relative paths are allowed within theINSTALL_INTERFACE
expression and are interpreted relative to the installation prefix. For example:target_include_directories(mylib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib> $<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib )
包含目录的使用要求通常在构建树和安装树之间有所不同。的
BUILD_INTERFACE
和INSTALL_INTERFACE
发电机表达式可以用于描述基于所述使用位置分开的使用要求。INSTALL_INTERFACE
表达式中允许使用相对路径,并相对于安装前缀进行解释。例如:target_include_directories(mylib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib> $<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib )
The BUILD_INTERFACE
and INSTALL_INTERFACE
generator expressionsdo all the magic:
在BUILD_INTERFACE
和INSTALL_INTERFACE
发电机表达式做所有的魔法:
$<INSTALL_INTERFACE:...>
Content of
...
when the property is exported usinginstall(EXPORT)
, and empty otherwise.
$<BUILD_INTERFACE:...>
Content of
...
when the property is exported usingexport()
, or when the target is used by another target in the same buildsystem. Expands to the empty string otherwise.
$<INSTALL_INTERFACE:...>
...
使用 导出属性时的内容,install(EXPORT)
否则为空。
$<BUILD_INTERFACE:...>
...
使用 导出属性时的内容export()
,或同一构建系统中的另一个目标使用该目标时的内容。否则扩展为空字符串。