C/C++ 交叉编译方法

文章目录

本机是 x86_64 架构的,使用 Ubuntu 22.04.4 LTS 作为 WSL 虚拟机

Update APT

开启 universe 源,

bash 复制代码
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update

x86

Toolchain

bash 复制代码
sudo apt install gcc-multilib g++-multilib
sudo apt install linux-libc-dev-i386-cross libc6-dev-i386

toolchain-x86-linux.cmake

cmake 复制代码
# 指定交叉编译工具链
set(TARGET_TRIPLE x86_64-linux-gnu)
set(TOOLCHAIN_BIN /usr/bin)
set(CMAKE_C_COMPILER   ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-gcc        CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-g++        CACHE FILEPATH "" FORCE)
set(CMAKE_AR           ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ar         CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB       ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ranlib     CACHE FILEPATH "" FORCE)

# 指定目标 OS 和 CPU
set(CMAKE_CROSSCOMPILING ON CACHE BOOL "" FORCE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR i686)

# 告知 CMake 交叉搜索根目录
include_directories(SYSTEM /usr/i686-linux-gnu/include)
set(CMAKE_FIND_ROOT_PATH /usr/lib32)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 编译目标 32-bit
add_compile_options(-m32 -maes -mavx -mavx2)
add_link_options(-m32)

# 指定产物的输出目录
set(ARCH_OUTPUT_NAME "x86")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/lib
    CACHE PATH "" FORCE
)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/
    CACHE PATH "" FORCE
)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/bin
    CACHE PATH "" FORCE
)

x86_64

Toolchain

bash 复制代码
sudo apt install gcc g++ make cmake

toolchain-x86_64-linux.cmake

cmake 复制代码
# 指定交叉编译工具链
set(TARGET_TRIPLE x86_64-linux-gnu)
set(TOOLCHAIN_BIN /usr/bin)
set(CMAKE_C_COMPILER   ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-gcc        CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-g++        CACHE FILEPATH "" FORCE)
set(CMAKE_AR           ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ar         CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB       ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ranlib     CACHE FILEPATH "" FORCE)

# 指定目标 OS 和 CPU
set(CMAKE_CROSSCOMPILING ON CACHE BOOL "" FORCE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)

# 告知 CMake 交叉搜索根目录
include_directories(SYSTEM /usr/include)
set(CMAKE_FIND_ROOT_PATH /usr/lib64)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 编译目标 64-bit
add_compile_options(-m64 -maes -mavx -mavx2)
add_link_options(-m64)

# 指定产物的输出目录
set(ARCH_OUTPUT_NAME "x86_64")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/lib
    CACHE PATH "" FORCE
)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/
    CACHE PATH "" FORCE
)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/bin
    CACHE PATH "" FORCE
)

ARMv7

Toolchain

bash 复制代码
sudo apt install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
sudo apt install linux-libc-dev-armel-cross

sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
sudo apt install linux-libc-dev-armhf-cross

toolchain-armv7abi-linux.cmake

cmake 复制代码
# 指定交叉编译工具链
set(TARGET_TRIPLE arm-linux-gnueabi)
set(TOOLCHAIN_BIN /usr/bin)
set(CMAKE_C_COMPILER   ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-gcc        CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-g++        CACHE FILEPATH "" FORCE)
set(CMAKE_AR           ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ar         CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB       ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ranlib     CACHE FILEPATH "" FORCE)

# 指定目标 OS 和 CPU
set(CMAKE_CROSSCOMPILING ON CACHE BOOL "" FORCE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# 告知 CMake 交叉搜索根目录
set(CMAKE_FIND_ROOT_PATH /usr/${TARGET_TRIPLE})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 指定目标架构为 ARMv7-a, 采用软浮点 ABI
add_compile_options(-march=armv7-a)

# 指定产物的输出目录
set(ARCH_OUTPUT_NAME "armv7abi")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/lib
    CACHE PATH "" FORCE
)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/
    CACHE PATH "" FORCE
)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/bin
    CACHE PATH "" FORCE
)

toolchain-armv7abihf-linux.cmake

cmake 复制代码
# 指定交叉编译工具链
set(TARGET_TRIPLE arm-linux-gnueabihf)
set(TOOLCHAIN_BIN /usr/bin)
set(CMAKE_C_COMPILER   ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-gcc        CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-g++        CACHE FILEPATH "" FORCE)
set(CMAKE_AR           ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ar         CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB       ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ranlib     CACHE FILEPATH "" FORCE)

# 指定目标 OS 和 CPU
set(CMAKE_CROSSCOMPILING ON CACHE BOOL "" FORCE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# 告知 CMake 交叉搜索根目录
set(CMAKE_FIND_ROOT_PATH /usr/${TARGET_TRIPLE})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 指定目标架构为 ARMv7-a, 适配带 NEON 浮点的硬件
add_compile_options(-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard)

# 指定产物的输出目录
set(ARCH_OUTPUT_NAME "armv7abihf")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/lib
    CACHE PATH "" FORCE
)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/
    CACHE PATH "" FORCE
)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/bin
    CACHE PATH "" FORCE
)

ARMv8

Toolchain

bash 复制代码
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
sudo apt install linux-libc-dev-arm64-cross

toolchain-armv8a-linux.cmake

cmake 复制代码
# 指定交叉编译工具链
set(TARGET_TRIPLE aarch64-linux-gnu)
set(TOOLCHAIN_BIN /usr/bin)
set(CMAKE_C_COMPILER   ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-gcc        CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-g++        CACHE FILEPATH "" FORCE)
set(CMAKE_AR           ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ar         CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB       ${TOOLCHAIN_BIN}/${TARGET_TRIPLE}-ranlib     CACHE FILEPATH "" FORCE)

# 指定目标 OS 和 CPU
set(CMAKE_CROSSCOMPILING ON CACHE BOOL "" FORCE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

# 告知 CMake 交叉搜索根目录
set(CMAKE_FIND_ROOT_PATH /usr/${TARGET_TRIPLE})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 指定目标架构为 ARMv8-a
add_compile_options(-march=armv8-a)

# 指定产物的输出目录
set(ARCH_OUTPUT_NAME "armv8a")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/lib
    CACHE PATH "" FORCE
)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/
    CACHE PATH "" FORCE
)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
    ${CMAKE_SOURCE_DIR}/build_out/${ARCH_OUTPUT_NAME}/bin
    CACHE PATH "" FORCE
)

build

CMakeLists.txt

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(MULTI_TOOLCHAIN VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# 检查工具链情况
message(">>> CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
message(">>> CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
message(">>> CMAKE_CXX_FLAGS_DEBUG = ${CMAKE_CXX_FLAGS_DEBUG}")
message(">>> CMAKE_CXX_FLAGS_RELEASE = ${CMAKE_CXX_FLAGS_RELEASE}")
message(">>> COMPILE_OPTIONS GLOBAL = ${CMAKE_CURRENT_LIST_DIR} : ${CMAKE_COMPILE_OPTIONS}")

# 指定头文件目录
include_directories(
    ${PROJECT_SOURCE_DIR}/include
)

# 编译子目录
add_subdirectory(src)

build.sh

bash 复制代码
#!/bin/bash

set -euo pipefail

# 项目根目录(脚本所在目录)
PROJ_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# 并发线程数
BUILD_JOBS=$(nproc)

# 格式: 工具链配置文件; 构建目录; 产物输出目录 (在各个 toolchain-xxx.cmake 中定义)
ARCH_LIST=(
    "toolchain-x86-linux.cmake;build_x86;x86"
    "toolchain-x86_64-linux.cmake;build_x86_64;x86_64"
    "toolchain-armv7abi-linux.cmake;build_armv7abi;armv7abi"
    "toolchain-armv7abihf-linux.cmake;build_armv7abihf;armv7abihf"
    "toolchain-armv8a-linux.cmake;build_armv8a;armv8"
)

# 循环遍历所有架构
for entry in "${ARCH_LIST[@]}"; do
    IFS=';' read -r TC_FILE BUILD_DIR ARCH_OUT <<< "$entry"

    FULL_TC_PATH="${PROJ_ROOT}/cmake/${TC_FILE}"
    FULL_BUILD_PATH="${PROJ_ROOT}/${BUILD_DIR}"

    echo "========================================"
    echo "Start build arch: ${ARCH_OUT}"
    echo "Toolchain file:  ${FULL_TC_PATH}"
    echo "Build directory: ${FULL_BUILD_PATH}"
    echo "========================================"

    # 0. 安全清理旧数据
    # if [[ -z "${FULL_BUILD_PATH}" ]]; then
    #     exit 1
    # fi

    # if [[ "${FULL_BUILD_PATH}" == "/" ]]; then
    #     exit 1
    # fi

    # if [[ "${FULL_BUILD_PATH}" != "${PROJ_ROOT}/"* ]]; then
    #     exit 1
    # fi

    # if [[ -d "${FULL_BUILD_PATH}" ]]; then
    #     echo "Clean old build dir: ${FULL_BUILD_PATH}"
    #     rm -rf "${FULL_BUILD_PATH}"
    # fi

    # 1. 创建构建目录
    mkdir -p "${PROJ_ROOT}/build_out"
    mkdir -p "${FULL_BUILD_PATH}"

    # 2. 加载工具链
    cmake -C "${FULL_TC_PATH}" -S "${PROJ_ROOT}" -B "${FULL_BUILD_PATH}" 
    
    # 3. 并发编译
    cmake --build "${FULL_BUILD_PATH}" -j"${BUILD_JOBS}"

    echo "==== Finish ${ARCH_OUT} ===="
    echo ""
done

echo "All architectures compile finished!"
echo "Output dir: ${PROJ_ROOT}/build_out/"
相关推荐
IKUN家族5 小时前
Spring MVC(一)
java·spring·mvc
code_pgf7 小时前
C++11 / C++14 / C++17 / C++20 新特性总结
c++·c++20
老马识途2.07 小时前
关于跨域问题的总结
java·前端
都叫我大帅哥7 小时前
Java日期时间三十年战争:从Date考古到LocalDateTime革命,以及数据库与前端的那点事儿
java
Muscleheng8 小时前
SpringBoot 集成 DeepSeek 实现 RAG 文档问答
java·spring boot·ai·springai
2501_936415698 小时前
可变参数&综合练习&斗地主游戏
java·windows·游戏
麻瓜老宋8 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十二步,分号赋值链式修复、TOKEN_ASSIGN
c语言·开发语言·atomcode
极客先躯9 小时前
高级java每日一道面试题-2026年05月03日-实战篇[Docker]-如何实现容器化环境的数据加密?
java·运维·docker·容器·金融·加解密·高级面试
xqqxqxxq10 小时前
Java Socket 多人聊天室(私聊+群聊)技术笔记(V4版本)
java·网络·笔记
wang090710 小时前
自己动手写一个spring之aop_1
java·后端·spring