target_include_directories behavior with empty value

I’ve already left a comment in commit which was ensuring clean INTERFACE_INCLUDE_DIRECTORIES:
https://gitlab.kitware.com/cmake/cmake/-/commit/af81a3c31b206633742eb13d41c54a9bc807ffea

That it doesn’t seem to work right when the value added with target_include_directories is actually empty it ends exporting PROJECT_SOURCE_DIR.

Recently I’ve noticed this in CMakeLists.txt: don't include CERES_INCLUDE_DIRS if it's empty or not set by shr-project · Pull Request #1808 · cartographer-project/cartographer · GitHub

When variable used in target_include_directories is empty or unset:

target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC "${SOME_UNDEFINED_OR_EMPTY_VARIABLE}")

the PROJECT_SOURCE_DIR ends in INTERFACE_INCLUDE_DIRECTORIES/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES.

Is this correct behavior?

The target_include_directories command documents that the specified paths must be either absolute or relative paths. If given a relative path, target_include_directories interprets it with respect to the current source directory. The code here determines that an empty string is not an absolute path, and so converts it to an absolute path by prefixing it with the current source directory.

In your use case, the variable reference should not be quoted. CMake’s language does not require quoting variable references to handle spaces in the path. An unquoted variable reference will expand to zero or more non-empty arguments by splitting on ;. See documentation on lists.

The code here determines that an empty string is not an absolute path, and so converts it to an absolute path by prefixing it with the current source directory.

Then why doesn’t it trigger an error like when you add e.g. ‘.’ as relative path?

target_include_directories(Tutorial PUBLIC ".")
CMake Error in CMakeLists.txt:
  Target "Tutorial" INTERFACE_INCLUDE_DIRECTORIES property contains path:

    "/OE/projects/cmake/Help/guide/tutorial/Step2/."

  which is prefixed in the source directory.

similarly

target_include_directories(Tutorial PUBLIC "..")

triggers the same error (except the shown path), but

target_include_directories(Tutorial PUBLIC "")

doesn’t trigger any error nor any warning about unnecessary quotes.

The lack of diagnostic on install(EXPORT) for this case is a bug. I’ve opened CMake Issue 21879 for this.

1 Like