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
${A_INCLUDE_DIRS}
for all headers from A
and ${B_INCLUDE_DIRS}
for all headers from B
?First, you use include_directories() to tell CMake to add the directory as -I to the compilation command line. Second, you list the headers in your add_executable() or add_library() call.
cmake is searched first in CMAKE_MODULE_PATH , then in the CMake module directory. There is one exception to this: if the file which calls include() is located itself in the CMake builtin module directory, then first the CMake builtin module directory is searched and CMAKE_MODULE_PATH afterwards.
include_directories(x/y) affects directory scope. All targets in this CMakeList, as well as those in all subdirectories added after the point of its call, will have the path x/y added to their include path. target_include_directories(t x/y) has target scope—it adds x/y to the include path for target t .
By convention, the contents of the include directory are the headers exposed for public consumption. The source directory may have headers for internal use, but those are not meant to be distributed with the compiled library.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With