CMake:target_include_directories()打印一个错误,当我尝试添加源目录本身或其中一个子目录 [英] CMake: target_include_directories() prints an error when I try to add the source directory itself, or one of its subdirectories

查看:5248
本文介绍了CMake:target_include_directories()打印一个错误,当我尝试添加源目录本身或其中一个子目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个C ++库(仅头),并使用CMake生成我的(Visual Studio)项目和解决方案文件。我也编写了一个测试套件,它是同一个CMake项目的一部分。



我的问题发生在当我调用target_include_directories()只有库,所以我的库的消费者可能会找到它的头文件。我收到以下错误消息(即使生成未中止)。

  CMakeLists.txt中的CMake错误:
目标字体INTERFACE_INCLUDE_DIRECTORIES属性包含路径:

D:/ Projects / GPC / fonts / include

其在源目录中为前缀。

(D:/ Projects / GPC / Fonts是我的库项目的顶级目录Btw )



我的CMakeLists.txt中的违规行是这样的(为了简单起见):

  target_include_directories(Fonts INTERFACE$ {CMAKE_CURRENT_SOURCE_DIR} / include)

我不明白我做错了什么。没有target_include_directories(),消费者项目的代码根本不能包括我的头文件(除非在已安装的形式,但我还没有得到,但在任何情况下,我想能够使用我的库从其构建树,没有安装。)



我觉得我在这里缺少一些基本的东西;

解决方案

问题的根源不是 target_include_directories 命令本身,但试图 install 具有在源路径中以公共或接口包含目录为前缀的目标。



完全精细和理想的使用绝对路径,当从头开始构建库,第三方库,拉入一个预建版本的库可能会想使用一个不同的包含路径。毕竟,你不希望所有的用户都镜像你的构建机器的目录结构,只是到了正确的包含路径。



CMC的包装机制为这两种用例提供​​支持:您可以直接从构建树(即,检出源,构建它,并将 find_package()指向该目录)或从安装目录(运行 make INSTALL 将内部文件复制到安装目录,并将 find_package()指向目录)。后一种方法需要可重定位(也就是说,我在我的机器上构建和安装,向您发送生成的目录,您将能够在不同的目录结构中在您的机器上使用它),而前者不是。 p>

这是一个非常整洁的功能,但是你必须在设置include目录时考虑它。引用 target_include_directories


包括目录使用要求通常在
构建树和安装树之间不同。可以使用 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


< blockquote>

BUILD_INTERFACE INSTALL_INTERFACE 生成器表达式执行所有的魔法:


$< INSTALL_INTERFACE:...>


$ b b

当使用 install(EXPORT)导出属性时, ... 的内容,否则为空。



$< BUILD_INTERFACE:...>



当使用 export()导出属性时或使用目标时, ... 的内容由同一构建系统中的另一个目标。
否则扩展为空字符串。



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.

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).

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.)

The offending line in my CMakeLists.txt is this (adapted for simplicity):

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.)

I feel like I'm missing something basic here; yet I've searched for hours without finding a solution or explanation.

解决方案

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.

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 mechanism provides 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 that directory). 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.

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:

Include directories usage requirements commonly differ between the build-tree and the install-tree. The BUILD_INTERFACE and INSTALL_INTERFACE generator expressions can be used to describe separate usage requirements based on the usage location. Relative paths are allowed within the INSTALL_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
)

The BUILD_INTERFACE and INSTALL_INTERFACE generator expressions do all the magic:

$<INSTALL_INTERFACE:...>

Content of ... when the property is exported using install(EXPORT), and empty otherwise.

$<BUILD_INTERFACE:...>

Content of ... when the property is exported using export(), or when the target is used by another target in the same buildsystem. Expands to the empty string otherwise.

这篇关于CMake:target_include_directories()打印一个错误,当我尝试添加源目录本身或其中一个子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆