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/"
相关推荐
一叶飘零_sweeeet1 小时前
Codex 与 Claude Code 深度拆解:两代 AI 编程智能体的技术本质与 Java 实战指南
java·ai·codex·claude code
Listen·Rain2 小时前
提示词和提示词模板
java·人工智能·spring boot
wuqingshun3141592 小时前
重写equals而不重写hashCode,会出什么问题?
java·开发语言
我今晚不熬夜2 小时前
Java语言实现Modbus协议通过用串口读取数据(以RTU为例)
java·网络协议
小锋java12343 小时前
Maven 4 要来了:15 年后,Java 构建工具迎来"彻底重构"
java·maven
卓怡学长3 小时前
w269基于spring boot + vue 候鸟监测数据管理系统
java·数据库·spring boot·spring·intellij-idea
孫治AllenSun4 小时前
【MDC】使用 MDC 封装一个 LogMdcUtil 工具类
java·spring boot·后端
济*沧*海4 小时前
BaseMapper的介绍
java·windows·tomcat
plainGeekDev4 小时前
依赖管理 → Version Catalog
android·java·kotlin