【龙芯久久派新世界】3.交叉编译链文件(CMakeLists.txt)
本文介绍了如何配置交叉编译工具链文件(cross.cmake)和使用CMake构建项目的方法。主要内容包括: 交叉编译配置: 设置目标系统(Linux)和处理器架构(loongarch64) 指定交叉编译器路径(loongarch64工具链) 配置sysroot路径和目标系统根文件系统 控制资源查找路径模式 CMakeLists.txt文件: 包含交叉编译配置 设置编译标准和选项 查找OpenCV
编写交叉编译链文件
交叉编译工具链文件toolchain.cmake或者cross.cmake文件名都可以
# cross.cmake文件
# 设置为1则表示交叉编译,设置为0则表示x86 gcc编译
SET(CROSS_COMPILE 1)
IF(CROSS_COMPILE)
SET(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR loongarch64)
SET(TOOLCHAIN_DIR "/usr/local/loongson-gnu-toolchain-13.2")
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-unknown-linux-gnu-g++)
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-unknown-linux-gnu-gcc)
# 指定 Buildroot 的 sysroot 路径
set(BUILDROOT_SYSROOT "/home/robot/tspi/ABI2.0/buildroot/output/host/loongarch64-buildroot-linux-gnu/sysroot")
set(CMAKE_SYSROOT ${BUILDROOT_SYSROOT})
# 告诉 CMake 在 sysroot 中查找库和头文件
set(CMAKE_FIND_ROOT_PATH ${BUILDROOT_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
ENDIF(CROSS_COMPILE)
第6行:目标系统类型
SET(CMAKE_SYSTEM_NAME Linux)
-
作用:指定目标平台的操作系统是 Linux。
-
为什么重要:这是 CMake 识别开始交叉编译的最关键变量之一。设置这个变量会告诉 CMake:"现在开始交叉编译,目标系统不是当前主机系统"。
第7行:目标处理器架构
set(CMAKE_SYSTEM_PROCESSOR loongarch64)
-
作用:指定目标平台的 CPU 架构是龙芯 LoongArch 64 位。
-
为什么重要:帮助 CMake 了解目标硬件架构,某些自动检测的功能可能会基于此做出决策。
第8-10行:编译器路径设置
SET(TOOLCHAIN_DIR "/usr/local/loongson-gnu-toolchain-13.2")
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-unknown-linux-gnu-g++)
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-unknown-linux-gnu-gcc)
-
作用:明确指定交叉编译器的完整路径。
-
设计思路:避免依赖系统 PATH 环境变量,确保使用正确的工具链。
-
为什么重要:这是交叉编译的核心,告诉 CMake 使用哪个编译器来生成目标平台的代码。
第13-14行:Sysroot 设置
set(BUILDROOT_SYSROOT "/home/robot/tspi/ABI2.0/buildroot/output/host/loongarch64-buildroot-linux-gnu/sysroot")
set(CMAKE_SYSROOT ${BUILDROOT_SYSROOT})
-
作用:指定目标系统的根文件系统在开发主机上的位置。
-
设计思路:创建一个"虚拟的目标系统环境",所有库和头文件都从这里获取。
-
为什么重要:这是最关键的设置!它确保:
-
编译时找到的是目标平台的库文件(龙架构的
.so文件),不是主机平台的(x86_64 的.so文件) -
头文件来自目标系统的版本,避免因版本不一致导致的编译错误
-
第17-21行:查找路径控制
set(CMAKE_FIND_ROOT_PATH ${BUILDROOT_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
-
作用:精细控制 CMake 在哪些位置查找各种资源。
-
设计思路:实施严格的隔离策略,防止意外找到主机系统的资源。
详细解释每个模式:
| 模式 | 设置 | 含义 | 为什么这样设置 |
|---|---|---|---|
| PROGRAM | NEVER |
永远不要在 sysroot 中查找可执行程序 |
因为目标平台的程序无法在主机上运行,我们需要使用主机上的交叉编译工具 |
| LIBRARY | ONLY |
只在 sysroot 中查找库文件 |
确保链接的是目标平台的库,避免链接到错误架构的主机库 |
| INCLUDE | ONLY |
只在 sysroot 中查找头文件 |
确保使用目标平台兼容的头文件 |
| PACKAGE | ONLY |
只在 sysroot 中查找包配置 |
确保 find_package() 找到的是目标平台的 |
编写CMakeLists.txt文件
# 包含交叉编译工具链
include(cross.cmake)
# 设置CMake的最低版本要求
cmake_minimum_required(VERSION 3.5.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -pthread -Wall -lrt -lpthread") # 对于 C++ 编译器
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall -lrt -lpthread" ) # 对于 C 编译器
# 获取当前 CMakeLists.txt 文件所在目录的完整路径
set(CURRENT_DIR ${CMAKE_CURRENT_LIST_DIR})
# 获取上上级目录的完整路径
get_filename_component(PARENT_PARENT_DIR ${CURRENT_DIR}/.. ABSOLUTE)
# 从完整路径中提取文件夹名称
get_filename_component(PARENT_PARENT_FOLDER_NAME ${PARENT_PARENT_DIR} NAME)
# 打印上上级文件夹名称
message("Parent parent folder name: ${PARENT_PARENT_FOLDER_NAME}")
# 定义项目名称和版本,并指定使用C和C++语言
project(${PARENT_PARENT_FOLDER_NAME} VERSION 0.1.0 LANGUAGES C CXX)
# 设置OpenCV的安装路径(用于本地编译而非交叉编译时指明路径)
# set(CMAKE_PREFIX_PATH "/opt/opencv_4_10_build")
# 查找OpenCV库,确保安装了所需的依赖
find_package(OpenCV REQUIRED)
# 包含OpenCV的头文件路径
include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}")
message(STATUS "OpenCV_LIBS: ${OpenCV_LIBS}")
# 包含项目的自定义库路径
include_directories(../user)
include_directories(../code)
# 从目录下查找C/C++文件
aux_source_directory(../user DIR_SRCS)
aux_source_directory(../code DIR_SRCS)
# 创建可执行文件,使用项目名称作为目标名称
add_executable(${PROJECT_NAME} ${DIR_SRCS})
# 链接OpenCV库到可执行文件
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
编写build.sh文件
将上面两个文件放在user文件夹下,在user同级文件夹out下编写build.sh文件内容:
cd ../out
# 检查 cd 命令是否执行成功
if [ $? -ne 0 ]; then
echo "无法进入 ./project/out 目录,请检查目录是否存在。"
exit 1
fi
find . -mindepth 1 ! -name "本文件夹作用.txt" -exec rm -rf {} +
# 检查 cd 命令是否执行成功
if [ $? -ne 0 ]; then
echo "无法进入 ./project/out 目录,请检查目录是否存在。"
exit 1
fi
cmake ../user
# 检查 cmake 命令是否执行成功
if [ $? -ne 0 ]; then
echo "cmake 命令执行失败。"
exit 1
fi
echo "cmake 命令执行成功。"
make -j4
echo "生成可执行文件"
# cmake --build .
# 获取上级目录的名称
# parent_dir_name=$(basename $(dirname $(pwd)))
# 使用获取到的上级目录名称进行 scp 操作
# scp -O $parent_dir_name root@192.168.2.61:/home/root/
# echo "传输完成"
第1行:Shebang
#!/bin/bash
-
作用:指定这个脚本使用 Bash shell 来执行。
第3行:切换目录
cd ../out
-
作用:切换到上级目录下的
out目录。 -
设计意图:通常
out或build目录用于存放编译生成的文件,与源代码分离。
第5-9行:检查目录切换是否成功
if [ $? -ne 0 ]; then
echo "无法进入 ./project/out 目录,请检查目录是否存在。"
exit 1
fi
-
作用:检查上一条
cd命令的返回值($?),如果非零(表示失败),则输出错误信息并退出脚本。 -
设计意图:增加脚本的健壮性,避免在错误目录中执行后续命令。
第11行:清理目录(核心命令)
find . -mindepth 1 ! -name "本文件夹作用.txt" -exec rm -rf {} +
-
作用:删除当前目录(
out)下的所有文件和子目录,但保留名为"本文件夹作用.txt"的文件。 -
分解说明:
-
find .:在当前目录查找 -
-mindepth 1:不包括当前目录本身(.) -
! -name "本文件夹作用.txt":排除名为"本文件夹作用.txt"的文件 -
-exec rm -rf {} +:对找到的所有文件执行rm -rf(强制删除)
-
第13-17行:再次检查目录状态
if [ $? -ne 0 ]; then
echo "无法进入 ./project/out 目录,请检查目录是否存在。"
exit 1
fi
-
注意:这里的检查逻辑上有问题,因为它检查的是上一条
find命令的返回值,而不是cd命令。应该是多余的代码。
第19行:运行 CMake
cmake ../user
-
作用:在
out目录中运行 CMake,指定源代码目录为../user。 -
设计意图:执行"外部构建",在单独的目录中生成构建文件。
第21-25行:检查 CMake 是否成功
if [ $? -ne 0 ]; then
echo "cmake 命令执行失败。"
exit 1
fi
-
作用:检查 CMake 命令是否执行成功,失败则退出。
第27行:输出成功信息
echo "cmake 命令执行成功。"
第28行:执行编译
make -j4
-
作用:使用 4 个并行任务(
-j4)执行编译,加速构建过程。
cmake --build . 统一的参数接口
cmake --build . 提供标准化的参数,无论底层是什么构建工具:
# 指定并行编译(所有平台通用)
cmake --build . --parallel 4
cmake --build . -j 4
# 指定构建目标
cmake --build . --target my_app
# 清理构建
cmake --build . --target clean
# 详细输出
cmake --build . --verbose
# 只编译不链接
cmake --build . --target my_app_obj
现代方式(跨平台)
# 所有平台使用相同的命令
cmake --build . --parallel 4
# 如果需要指定构建类型
cmake --build . --config Release --parallel 4
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)