NeonMan
NeonMan

Reputation: 663

Why is CMake removing some include directories from INCLUDE_DIRECTORIES() calls?

We are trying to cross compile a certain piece of software and for most cases it has been working. However, the include files are split over multiple directories and, if the directorie lies outside the sysroot tree, sometimes CMake decides not to add it to the include list on Makefiles.

The toolchain is:

The CMake call is as follows:

cmake -G"MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-vde.cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=C:\vf-install ..

The toolchain-vde.cmake file is:

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)

# which compilers to use for C and C++
include(CMakeForceCompiler)
#Use 8.1 names if path has spaces since it will break on paths with spaces
set(CMAKE_C_COMPILER "C:/VDE/toolchains/windows/vos/arm-vf-linux-gnueabi/bin/arm-vf-linux-gnueabi-gcc.exe")
set(CMAKE_CXX_COMPILER "C:/VDE/toolchains/windows/vos/arm-vf-linux-gnueabi/bin/arm-vf-linux-gnueabi-g++.exe")

# here is the target environment located
SET(VF_SYSROOT "C:/VDE/SDKs/vos/default")


#Vf includes and libs
#Declared as variables for compatibility and usage by CMake scripts down the line
SET(VF_ADK_INCLUDE       "C:\\VDE\\ADKs\\default\\vos\\include")
SET(VF_ADK_LIB           "C:/VDE/ADKs/default/vos/lib")
SET(VF_SDK_USR_LIB       "${VF_SYSROOT}/usr/lib")
SET(VF_SDK_USR_LOCAL_LIB "${VF_SYSROOT}/usr/local/lib")
SET(VF_SDK_USR           "${VF_SDK_USR_LIB}") #<-- Compatibility with old Vf detection
SET(VF_SVCMGR            "${VF_SYSROOT}/usr/local/lib/svcmgr")

MESSAGE("debug1: --- ${VF_ADK_INCLUDE} --- ${VF_SYSROOT} ---")

SET(CMAKE_SYSROOT "${VF_SYSROOT}")

#Define variables for compiler and CMAKE scripts
set(VF_UX_410 TRUE)
add_definitions(-DVF_UX_410="${VF_UX_410}")

LINK_DIRECTORIES("${CMAKE_INSTALL_PREFIX}/lib")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lrt --std=gnu99")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrt")

LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}")
INCLUDE_DIRECTORIES("${CMAKE_INSTALL_PREFIX}/include")
INCLUDE_DIRECTORIES("${VF_ADK_INCLUDE}")

Notice the last line, INCLUDE_DIRECTORIES("${VF_ADK_INCLUDE}") this directory, VF_ADK_INCLUDE, if it exists, will be ignored during build. Meaning that the make call will not have the -IC:\VDE\ADKs\default\vos\include argument but if the directory is not there, the makefiles will have the proper -I[...] argument.

If I add the INCLUDE_DIRECTORIES such as:

INCLUDE_DIRECTORIES(
  "X:\\"
  "C:\\VDE\\ADKs\\default\\vos\\include"
  "Y:\\"
)

Both X: and Y: will appear on the compiler call as -IX:\ -IY:\ but somehow the middle include is missing. Doubly Oddly, if I rename the include directory during config (so cmake cannot find it), then rename it back during compilation, CMake has added the correct -I[...] argument and the program compiles just fine.

As a workaround, right now I'm hardcoding the -I[...] argument on the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS variables but this solution is far, far, far from correct.

edit: the MESSAGE call shows the correct path/value during CMake configuration. So it shouldn't be a "variable is not defined" issue.

In essence and to make this a proper question:
Why does CMake remove or ignore include paths from INCLUDE_DIRECTORIES calls?

Upvotes: 5

Views: 2529

Answers (1)

NeonMan
NeonMan

Reputation: 663

After a few days I couldn't find a better answer so I'll post this answer-to-self since it works.

During the compiler detection, CMake will extract a series of implicit include paths which usually are always available and, if added to include paths, might break the compilation process (Thanks to @Tsyvarev for the caveat). However, if this path gets incorrectly added to the excluded paths, the only way I could find to override this is removing the exclusion list alltogether using:

unset(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES)
unset(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)

As described on https://gitlab.kitware.com/cmake/cmake/issues/17966 but this solution is using CMake internals so it may do or break depending on your compiler or environment. In this particular case the fix worked.

On a similar situation, again with a proprietary + ancient gcc toolchain, simply updating to the latest CMake version worked, apparently due to better compiler detection.

Upvotes: 6

Related Questions