John Rocha
John Rocha

Reputation: 1705

How to force CMake's target_include_directories() to use absolute path

How do I force CMake's function target_include_directories() to treat the value as an absolute path?

For example, I want this line of code:

target_include_directories(foobar  PRIVATE   "%FOOBAR_INCLUDE%")

to simply add %FOOBAR_INCLUDE% to the list of include directories.

However, what we actually get is c:\path\to\foobar\%FOOBAR_INCLUDE%.

I know that I could do

target_include_directories(foobar  PRIVATE   "$ENV{FOOBAR_INCLUDE}")

but that's not what I want. That would expand the value of the environment variable and insert the current setting of the FOOBAR_INCLUDE value.

We need for it to simply push the environment variable, and then during development the developers will change the value of FOOBAR_INCLUDE manually without having to re-run CMake each time.

Upvotes: 3

Views: 5715

Answers (2)

Kevin
Kevin

Reputation: 18243

It is not possible to add something that looks like a relative directory (i.e. "%FOOBAR_INCLUDE%") to the include directories this way. CMake will always try to manipulate these into absolute paths. This is more-or-less stated in the include_directories documentation:

Relative paths are interpreted as relative to the current source directory.

but applies to the target_include_directories() command as well.

Even if you try to circumvent this, and set the INCLUDE_DIRECTORIES property of the target manually:

set_target_properties(foobar PROPERTIES
    INCLUDE_DIRECTORIES "%FOOBAR_INCLUDE%"
)

CMake will throw an error during the generation stage:

CMake Error in CMakeLists.txt:
  Found relative path while evaluating include directories of "foobar":

    "%FOOBAR_INCLUDE%"

You could compromise, providing a full path, but allowing the %FOOBAR_INCLUDE% variable to stay:

target_include_directories(foobar PRIVATE "C:/%FOOBAR_INCLUDE%")

but this ties you and your fellow developers to the C: drive.


I would recommend following the approach you suggested, using an environment variable:

target_include_directories(foobar  PRIVATE   "$ENV{FOOBAR_INCLUDE}")

or creating a FOOBAR_INCLUDE CMake cache variable that can be populated by each developer before they re-run CMake. If each developer's environment is different, CMake should be re-configured to match that environment.

Upvotes: 2

micha
micha

Reputation: 1085

You can trick CMake into accepting literal values through generator expressions

target_include_directories(foobar PRIVATE $<1:%FOOBAR_INCLUDE%>)

This, however, won't work as CMake will generate an error about the path not being absolute.

Luckily its an include directory, so therefore you can try to add the include flag manually:

target_compile_definitions(foobar PRIVATE -I%FOOBAR_INCLUDE%)

Upvotes: 1

Related Questions