【发布时间】:2019-10-24 12:11:50
【问题描述】:
我们正在尝试交叉编译某个软件,并且在大多数情况下它一直在工作。但是,包含文件被拆分为多个目录,如果该目录位于 sysroot 树之外,有时 CMake 会决定不将其添加到 Makefile 的包含列表中。
工具链是:
- 适用于 ARM 的 GCC 4.4.1(Windows 可执行文件)
- MinGW Make(无 MSYS)
CMake 调用如下:
cmake -G"MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-vde.cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=C:\vf-install ..
toolchain-vde.cmake 文件是:
# 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}")
注意最后一行,INCLUDE_DIRECTORIES("${VF_ADK_INCLUDE}") 这个目录,VF_ADK_INCLUDE,如果存在,在构建过程中会被忽略。这意味着 make 调用将没有 -IC:\VDE\ADKs\default\vos\include 参数,但如果目录不存在,则生成文件将具有正确的 -I[...] 参数。
如果我添加INCLUDE_DIRECTORIES 如:
INCLUDE_DIRECTORIES(
"X:\\"
"C:\\VDE\\ADKs\\default\\vos\\include"
"Y:\\"
)
X: 和 Y: 都将在编译器调用中显示为-IX:\ -IY:\,但不知何故中间包含丢失。奇怪的是,如果我在配置期间重命名包含目录(因此 cmake 找不到它),然后在编译期间将其重命名,CMake 已经添加了正确的 -I[...] 参数并且程序编译得很好。
作为一种解决方法,我现在正在对 CMAKE_C_FLAGS 和 CMAKE_CXX_FLAGS 变量的 -I[...] 参数进行硬编码,但这个解决方案远非正确。
edit:MESSAGE 调用在 CMake 配置期间显示正确的路径/值。所以它不应该是“变量未定义”的问题。
从本质上讲,为了使这个问题成为一个正确的问题:
为什么 CMake 会删除或忽略来自 INCLUDE_DIRECTORIES 调用的包含路径?
【问题讨论】:
-
工具链是丑陋的专有解决方案的一部分,因此标头在系统根目录内外的许多目录中拆分(这是首选的习惯用法 AFAIK),因此工具链上的
include_directories有被使用,因为所有进一步执行的 CMakeLists.txt 将继承这些包含。不确定这样做的“正确”方式是什么。 -
显然 CMake 有一些内部“排除列表”,这些目录在存在时会以某种方式被排除。参考来自:gitlab.kitware.com/cmake/cmake/issues/17966 如果没有合适的解决方案出现,我会选择这个,因为“它有效”
-
是的,我做到了。同时使用
include_directories和target_include_directories并且路径也被排除在外。很可能在编译器检测期间,它认为编译器“知道”该路径不正确,因此禁用排除(丑陋的黑客攻击)起作用的原因。 -
CMake 实际上删除了被编译器视为 implicit 的包含路径。这样做是有充分理由的(据我记得,如果显式添加系统包含目录,系统标头中的
#include_next指令可能会被破坏)。但是除非 CMake 检测失败,或者您的程序要求此类包含目录是明确的,否则此类删除不应破坏。
标签: c++ c cmake include cross-compiling