You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake交叉编译时头文件找不到问题求助

CMake交叉编译头文件查找问题排查

原项目结构

- myproject/
|- toolchain.cmake
|- tmproot/
|- app/
 |- myapp/
  |- CMakeLists.txt
|- lib/
 |- mylib1/
  |- CMakeLists.txt
 |- mylib2/
  |- CMakeLists.txt
 |- mylib3/
  |- CMakeLists.txt
 |- spdlog/
  |- CMakeLists.txt
 |- json/
  |- CMakeLists.txt

工具链配置(toolchain.cmake)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
 
SET(CMAKE_FIND_ROOT_PATH  <path to myproject>/tmproot) 

set(CMAKE_C_COMPILER            $ENV{XILINX_VITIS}/gnu/aarch64/lin/aarch64-linux/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER          $ENV{XILINX_VITIS}/gnu/aarch64/lin/aarch64-linux/bin/aarch64-linux-gnu-g++)

set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

编译安装流程

编译并安装所有库的命令:

/usr/bin/cmake $PWD -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="../../toolchain.cmake"
make DESTDIR="$PWD/../../tmproot" install

安装后,库文件位于<path to myproject>/tmproot/usr/local/lib,头文件位于<path to myproject>/tmproot/usr/local/include/<lib_name>。编译库时编译器自动添加-isystem <path to myproject>/tmproot/usr/local/include参数,可正常找到头文件,但编译依赖这些库的应用时无该参数,报头文件缺失。


最小复现示例

项目结构

- myproject/
|- toolchain.cmake
|- tmproot/
|- app/
 |- app1/
  |- CMakeLists.txt
  |- app1.cpp
|- lib/
 |- lib1/
  |- CMakeLists.txt
  |- lib1.cpp
  |- lib1.h
 |- lib2/
  |- CMakeLists.txt
  |- lib2.cpp
  |- lib2.h

lib1相关文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(lib1 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_STATIC_LIBRARY_PREFIX "")
add_library (lib1 lib1.cpp lib1.h)
install(FILES lib1.h DESTINATION include/lib1 COMPONENT Development)
install (TARGETS lib1
    RUNTIME DESTINATION ${BINDIR} COMPONENT Applications
    LIBRARY DESTINATION ${LIBDIR} COMPONENT Libraries
)

lib1.h

#ifndef LIB1_H
#define LIB1_H
int lib1_func(int param);
#endif

lib1.cpp

int lib1_func(int param)
{
    return param+42;
}

lib2相关文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(lib2 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(CMAKE_STATIC_LIBRARY_PREFIX "")

add_library (lib2 lib2.cpp lib2.h)

target_link_libraries (lib2 PUBLIC lib1)

install(FILES lib2.h DESTINATION include/lib2 COMPONENT Development)
install (TARGETS lib2
    RUNTIME DESTINATION ${BINDIR} COMPONENT Applications
    LIBRARY DESTINATION ${LIBDIR} COMPONENT Libraries
)

lib2.h

#ifndef LIB2_H
#define LIB2_H
int lib2_func(int param);
#endif 

lib2.cpp

#include "lib1/lib1.h"
int lib2_func(int param)
{
    return param+lib1_func(param);
}

app1相关文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(app1 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

add_executable (app1 "app1.cpp")
target_link_libraries(app1 PUBLIC lib1 PUBLIC lib2)

app1.cpp

#include "lib1/lib1.h"
#include "lib2/lib2.h"

int main()
{
    return lib1_func(1) + lib2_func(2);
}

复现步骤及报错

cd lib/lib1
/usr/bin/cmake $PWD -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="../../toolchain.cmake"
make DESTDIR="$PWD/../../tmproot" install
cd ../lib2
/usr/bin/cmake $PWD -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="../../toolchain.cmake"
make

报错信息:

fatal error: lib1/lib1.h: No such file or directory
    1 | #include "lib1/lib1.h"
      |          ^~~~~~~~~~~~~

确认头文件已存在:

ls ../../tmproot/usr/local/include/lib1/
lib1.h

问题原因分析

  1. CMake未自动识别安装的lib1:编译lib2时,CMake不知道lib1已安装在tmproot中,仅用target_link_libraries链接静态库无法自动传递头文件路径,必须通过包查找机制导入依赖的完整配置。
  2. lib1未导出CMake配置文件:安装lib1时未生成lib1Config.cmake等配置文件,导致后续项目无法通过CMake的包查找功能定位到lib1的头文件和库路径。
  3. 包查找路径未明确:虽然CMAKE_FIND_ROOT_PATH指向了tmproot,但CMake默认不会自动遍历其子目录查找配置文件,需要显式指定包的查找路径或配置CMAKE_PREFIX_PATH。

解决方案

步骤1:修改lib1的CMakeLists.txt,添加配置导出

更新lib1的CMakeLists.txt,让CMake生成并导出配置文件,方便后续项目导入:

cmake_minimum_required(VERSION 3.5)
project(lib1 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_STATIC_LIBRARY_PREFIX "")

add_library (lib1 lib1.cpp lib1.h)

# 设置头文件路径,让依赖项自动继承
target_include_directories(lib1 PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:include/lib1>
)

# 导出目标和配置文件
install(TARGETS lib1
    EXPORT lib1Targets
    RUNTIME DESTINATION bin COMPONENT Applications
    LIBRARY DESTINATION lib COMPONENT Libraries
    ARCHIVE DESTINATION lib COMPONENT Libraries
)

install(EXPORT lib1Targets
    FILE lib1Targets.cmake
    NAMESPACE lib1::
    DESTINATION lib/cmake/lib1
)

install(FILES lib1.h DESTINATION include/lib1 COMPONENT Development)

# 生成Config.cmake文件
include(CMakePackageConfigHelpers)
configure_package_config_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/lib1Config.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/lib1Config.cmake"
    INSTALL_DESTINATION lib/cmake/lib1
)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib1Config.cmake"
    DESTINATION lib/cmake/lib1
)

同时在lib1目录下创建lib1Config.cmake.in文件(内容为空即可):

# 空配置模板文件

步骤2:修改lib2的CMakeLists.txt,用find_package导入lib1

更新lib2的CMakeLists.txt,通过find_package查找并导入lib1的配置:

cmake_minimum_required(VERSION 3.5)

project(lib2 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(CMAKE_STATIC_LIBRARY_PREFIX "")

# 查找lib1,指定配置文件路径
find_package(lib1 REQUIRED PATHS ${CMAKE_FIND_ROOT_PATH}/usr/local/lib/cmake/lib1)

add_library (lib2 lib2.cpp lib2.h)

# 链接lib1的导入目标
target_link_libraries (lib2 PUBLIC lib1::lib1)

# 设置lib2的头文件路径
target_include_directories(lib2 PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:include/lib2>
)

install(FILES lib2.h DESTINATION include/lib2 COMPONENT Development)
install (TARGETS lib2
    EXPORT lib2Targets
    RUNTIME DESTINATION bin COMPONENT Applications
    LIBRARY DESTINATION lib COMPONENT Libraries
    ARCHIVE DESTINATION lib COMPONENT Libraries
)

步骤3:修改app1的CMakeLists.txt,用find_package导入依赖

更新app1的CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)

project(app1 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# 查找依赖库
find_package(lib1 REQUIRED PATHS ${CMAKE_FIND_ROOT_PATH}/usr/local/lib/cmake/lib1)
find_package(lib2 REQUIRED PATHS ${CMAKE_FIND_ROOT_PATH}/usr/local/lib/cmake/lib2)

add_executable (app1 "app1.cpp")

# 链接导入目标
target_link_libraries(app1 PUBLIC lib1::lib1 lib2::lib2)

步骤4:重新执行编译安装流程

  1. 重新编译安装lib1:
cd lib/lib1
rm -rf build && mkdir build && cd build
cmake .. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="../../toolchain.cmake"
make DESTDIR="../../../tmproot" install
  1. 编译安装lib2:
cd ../../lib2
rm -rf build && mkdir build && cd build
cmake .. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="../../toolchain.cmake"
make DESTDIR="../../../tmproot" install
  1. 编译app1:
cd ../../app/app1
rm -rf build && mkdir build && cd build
cmake .. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="../../toolchain.cmake"
make

临时快速解决方案

如果不想修改CMake配置导出,可以在lib2和app1的CMakeLists.txt中手动添加包含路径:

# 在lib2的CMakeLists.txt中添加
target_include_directories(lib2 PUBLIC ${CMAKE_FIND_ROOT_PATH}/usr/local/include)

# 在app1的CMakeLists.txt中添加
target_include_directories(app1 PUBLIC ${CMAKE_FIND_ROOT_PATH}/usr/local/include)

该方式仅适用于临时测试,推荐使用CMake的包导出机制保证依赖管理的规范性。


内容的提问来源于stack exchange,提问作者Philip Kirchhoff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:15:00