CMake:包含目录的排序(如何混合基于系统和用户的包含路径?)

发布于 2024-12-09 09:00:57 字数 1293 浏览 0 评论 0原文

我有一个 CMake 项目,其中包含并链接两个库,例如 AB (实际上它不止两个,其中一个是 boost 的东西,但这并不这里并不重要)。两者都通过 FindSomething.cmake 脚本定位,这些脚本(正确地)填充标准 CMake 变量,以便通过添加包含目录

INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})

并稍后通过完成链接

TARGET_LINK_LIBRARIES(mytarget ${A_LIBRARIES} ${B_LIBRARIES})

现在,问题是这两个库都可以驻留在基于用户的位置或系统目录(顺便说一下,我在 Linux 上,CMake 2.8.2) - 或两者兼而有之。假设 A 仅在 $HOME/usr/include$HOME/usr/lib 中,而 B ( boost 在我的例子中)驻留在系统路径(/usr/include/usr/lib)和基于用户的路径中 - 在不同的版本中。可以使用查找脚本来查找系统或基于用户的库 B,这是可行的。

当我想从系统路径链接 B 时,麻烦就开始了。${B_INCLUDE_DIRS}${B_LIBRARIES} 正确指向系统标头和库的范围位置。但仍然有 ${A_INCLUDE_DIRS} 指向非系统包含目录,最终库 B 的标头也从此位置获取,而 B 的链接code>B 使用系统路径中的版本(通过 ${B_LIBRARIES}),这会导致冲突,即链接错误。

更改 INCLUDE_DIRECTORIES 语句的顺序似乎没有改变任何内容。我通过目标文件上的 nm --line-numbers 检查了导致链接错误的符号的来源。

我能做些什么?是否有一个技巧可以

  • 强制包含目录的排序(即使这意味着优先考虑系统路径,尽管还指定了基于用户的位置)?
  • 告诉 CMake 对 A 中的所有标头使用 ${A_INCLUDE_DIRS} ,对 B 中的所有标头使用 ${B_INCLUDE_DIRS} >?

I've got a CMake project that includes and links against two libraries, say A and B (actually it's more than two and one of them is boost stuff, but that doesn't really matter here). Both are located via FindSomething.cmake scripts that (correctly) populate the standard CMake variables such that include directories are added via

INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})

and linking is later done via

TARGET_LINK_LIBRARIES(mytarget ${A_LIBRARIES} ${B_LIBRARIES})

Now, the problem is that both libraries can either reside in a user based location or in the system directories (I'm on linux by the way, CMake 2.8.2) - or in both. Let's say A is only in $HOME/usr/include and $HOME/usr/lib while B (boost in my case) resides in both the system paths (/usr/include and /usr/lib) AND in the user based paths - in different versions. The find scripts can be made to find either the system or the user-based library B, this works.

The trouble starts when I want to link against B from the system paths.${B_INCLUDE_DIRS} and ${B_LIBRARIES} correctly point to the system-wide locations of the headers and libraries. But there is still ${A_INCLUDE_DIRS} that points to a non-system include directory and ultimately also the headers for library B are taken from this location, while the linking for B uses the version from the system paths (via ${B_LIBRARIES}) which leads to conflicts, i.e. linking errors.

Changing the order of the INCLUDE_DIRECTORIES statements does not seem to change anything. I checked the origin of the symbols that cause the linking errors via nm --line-numbers on the object files.

What can I do? Is there a trick to

  • force the ordering of the include directories (even if this would mean to give precedence to a system path although there is also a user-based location specified)?
  • tell CMake to use ${A_INCLUDE_DIRS} for all headers from A and ${B_INCLUDE_DIRS} for all headers from B?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小情绪 2024-12-16 09:00:57

以下是 CMake 关于 include_directories() 的说法:

include_directories ([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

您可以指定在您告知系统包含目录之前或之后搜索包含目录那些目录。

您还可以特定于目标:

target_include_directories(target [系统] [之前] [items1...] [ [items2...] ...])

Here's what CMake says about include_directories():

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

You can specify that you want to have include directories searched before or after the system include directories at the time that you tell it about those directories.

You may also be specific to a target:

target_include_directories(target [SYSTEM] [BEFORE] [items1...] [ [items2...] ...])

柏拉图鍀咏恒 2024-12-16 09:00:57

如果 AB 是包含不同头文件和路径的不同库,那么执行您现在正在执行的操作应该没有问题。

话虽这么说,如果 AB 是相似的库,在同一位置包含相同名称的头文件,那就有问题了。在这种情况下,include_directory() 调用的顺序很重要。我进行了一个小测试,其中有一个头文件的三个副本。第一个副本位于我的系统路径中(例如 /usr/include)。其他副本位于两个用户定义的位置(例如 /tmp/include1/tmp/include2)。如果我按以下顺序调用 include_directory() ,则首先找到并使用 /tmp/include1 中的文件:

include_directory("/tmp/include1")
include_directory("/tmp/include2")

/tmp/include2< 中的文件如果我按以下顺序调用 include_directory() ,则首先找到并使用 /code>:

include_directory("/tmp/include2")
include_directory("/tmp/include1")

如果我没有放置 include_directory() 语句,则系统中的标头找到并使用路径。

您可能需要重新检查 FindSomething.cmake 的编写方式。 find_*() CMake 命令的搜索顺序可以在 CMake 文档

据我所知,现在有一种方法可以告诉 CMake 对来自的所有标头使用 ${A_INCLUDE_DIRS} A${B_INCLUDE_DIRS} 用于 B 中的所有标头(如果可以在两个位置找到头文件)。这完全取决于 include_directory() 调用的顺序。如果 FindSomething.cmake 编写正确,如果 CMAKE_MODULE_PATH (这是 CMake 查找 Find*.cmake 文件的位置)设置正确并且所有路径都良好,那么您应该可以开始了。如果没有,我将需要有关您当前的 CMake/库设置的更多信息。

If A and B are different libraries containing different header files and paths, there should be no problem doing what you are doing right now.

That being said, if A and B are similar libraries containing header files of the same name at the same location, that is problematic. In that case, the order of the include_directory() call is important. I ran a little test where I had three copies of a header file. The first copy is located in my system path (say /usr/include). The other copies are located in two user-defined locations (say /tmp/include1 and /tmp/include2). The file in /tmp/include1 is found and used first if I put the include_directory() call in the following order:

include_directory("/tmp/include1")
include_directory("/tmp/include2")

The file in /tmp/include2 is found and used first if I put the include_directory() call in the following order:

include_directory("/tmp/include2")
include_directory("/tmp/include1")

If I put no include_directory() statement, then the header in the system path is found and used.

You may want to re-check how your FindSomething.cmake are written. The search order of the find_*() CMake commands can be found in the CMake documentation,

As far as I can remember, there is now way of telling CMake to use ${A_INCLUDE_DIRS} for all headers from A and ${B_INCLUDE_DIRS} for all headers from B if the header file can be found in both location. It all depends in what order the include_directory() call are made. If the FindSomething.cmake are written properly, if the CMAKE_MODULE_PATH (this is the location where CMake will look for the Find*.cmake files) is set properly and all the paths are good, then you should be good to go. If not, I will need more information on your current CMake/library setup.

追星践月 2024-12-16 09:00:57

当使用第三方库时,我总是会这样做

Library A + B 头文件:

third_party/include/libA_name/ <-- put header files in

therethird_party/include/libB_name/ <-- put header files in there

在源代码中文件,你总是这样使用它

#include "libA_name/file.h" <-- no ambiguity possible

#include "libB_name/file.h" <-- no ambiguity possible

然后你仍然可以使用 -I“third_party/include”作为包含文件夹,并且源文件中不会发生排序歧义。

这也消除了自定义头文件与系统头文件的歧义,系统头文件可能会不时与第 3 方库发生冲突。

When using third party libraries, I would always do this

Library A + B header files:

third_party/include/libA_name/ <-- put header files in there

third_party/include/libB_name/ <-- put header files in there

In source files you would always use it like this

#include "libA_name/file.h" <-- no ambiguity possible

#include "libB_name/file.h" <-- no ambiguity possible

Then you can still use -I "third_party/include" as the include folder and no ambiguity in ordering will happen in source files.

This also disambiguates custom header files from system header files which could clash from time to time from 3rd party libs.

梦晓ヶ微光ヅ倾城 2024-12-16 09:00:57

对我来说这效果很好:

INCLUDE_DIRECTORIES(BEFORE ${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})

For me this worked fine:

INCLUDE_DIRECTORIES(BEFORE ${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文