开发者

CMake: ordering of include directories (How to mix system- and user-based include paths?)

开发者 https://www.devze.com 2023-04-12 22:32 出处:网络
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 locat

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 wh开发者_如何学运维ile 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?


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


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.


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.


For me this worked fine:

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

精彩评论

暂无评论...
验证码 换一张
取 消