CMake: organizing included directories (how to mix system and user included paths?)

I have a CMake project, which includes links to two libraries, say A and B (in fact, it is more than two, and one of them is forced material, but it does not really matter here). Both of them are located through FindSomething.cmake scripts that (correctly) populate standard CMake variables, such as added directories, through

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

and communication is later done through

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

Now the problem is that both libraries can either be in the user location or in the system directories (I am on Linux, by the way, CMake 2.8.2) - or both. Let's say A is located only in $HOME/usr/include and $HOME/usr/lib , and B (boost in my case) is located both on the system paths ( /usr/include and on /usr/lib ) And in user paths - in different versions, Search scripts can be found to find either system or user library B , this works.

The problem starts when I want to associate B with system paths. ${B_INCLUDE_DIRS} and ${B_LIBRARIES} correctly point to system-wide locations of headers and libraries. But there’s still ${A_INCLUDE_DIRS} that points to a non-system directory, and ultimately, headers for library B are taken from this place, and the link for B uses the version from the system paths (via ${B_LIBRARIES} ), leading to conflicts, i.e. error binding.

Reordering the INCLUDE_DIRECTORIES statements does not seem to change anything. I checked the origin of the characters that cause binding errors via nm --line-numbers in object files.

What can I do? Is there a trick for

  • forcibly organizes include directories (even if it means it will take precedence over the system path, although there is also a user-defined location)?
  • tell CMake to use ${A_INCLUDE_DIRS} for all the headers from A and ${B_INCLUDE_DIRS} for all the headers from B ?
+6
source share
3 answers

When using third-party libraries, I will always do this

Library A + B Header Files:

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

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

In the source files you will 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 there will be no ambiguity in the source files for ordering.

It also removes the ambiguity of custom header files from system header files that may occasionally arise from third-party libraries.

+3
source

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

If it is said that A and B are similar libraries containing header files with the same name in one place, this is problematic. In this case, the order of the call to include_directory() important. I did a little testing where I had three copies of the header file. The first copy is in my system path (say /usr/include ). Other copies are in two user places (say /tmp/include1 and /tmp/include2 ). The file in /tmp/include1 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 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 did not put the include_directory() operator, then the header will be found and used in the system path.

You might want to double-check how your FindSomething.cmake . The search order for find_*() CMake commands can be found in the CMake documentation ,

As far as I remember, there is now a way to tell CMake to use ${A_INCLUDE_DIRS} for all the headers from A and ${B_INCLUDE_DIRS} for all the headers from B , if the header file can be found in both places. It all depends on the order in which include_directory() is called include_directory() . If FindSomething.cmake spelled correctly, if CMAKE_MODULE_PATH (this is the place where CMake will look for Find*.cmake ) will be installed correctly, and all paths will be good, then you should be good to go. If not, I will need more information about the current configuration of CMake / library.

+2
source

Here CMake talks about include_directories() :

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

You can specify that you want to include directories that you searched for before or after the system included directories while you were talking about these directories.

You can also indicate the goal:

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

+2
source

Source: https://habr.com/ru/post/899207/


All Articles