一个基于cmake跨平台交叉编译项目模板

  1. 项目目录结构
    下面目录结构是一个经过实践的项目模板结构,麻雀虽小,五脏俱全。小伙伴们可以按此模板搭建自己的项目。
    ├── build.sh                        ## 构建脚本
    ├── cmake
    │   ├── config.cmake.in             ## 构建test库的cmake配置文件 
    │   ├── create-config.cmake         ## 构建test库的cmake配置文件, find_package用到的配置文件
    │   ├── hisi.toolchain.cmake		## hisi平台工具链配置文件
    │   ├── rockchip.toolchain.cmake    ## rockchip平台工具链配置文件
    │   ├── sigmastar.toolchain.cmake   ## sigmastar平台工具链配置文件
    ├── CMakeLists.txt                  ## 项目顶层CMakeLists.txt
    ├── include                         ## 库对外提供的接口头文件
    │   ├── mymath.hpp                   
    ├── src                             ## 库实现部分
    │   ├── CMakeLists.txt
    │   ├── mymath.cpp
    ├── test                            ## 库测试代码
    │   └── CMakeLists.txt
    ├── user.env                        ## 编译相关配置
    
  2. 如何交叉编译
    直接进入项目目录,运行目录下面的build.sh脚本,如下:
  • 交叉编译
    cd $project_dir
    ./build.sh
    
  • 清除编译
    ./build.sh --clean
    
  1. 如何配置不同平台的交叉编译环境
    只需要更改项目目录下的user.env文件,就可以实现不同平台的交叉编译。
  • 海思平台dv300 user.env配置如下:
    USER_TOOLCHAIN_FILE="/xxx/dv300.toolchain.cmake"  # 平台交叉编译工具链
    USER_PLATFORM_TYPE="hisi"   # 平台类型
    USER_PLATFORM_CHIP_TYPE="dv300"  # 平台芯片类型
    
  • 瑞芯微平台rv1109/rv1126 user.env配置如下:
    USER_TOOLCHAIN_FILE="/xxx/rv1109.toolchain.cmake"  # 平台交叉编译工具链
    USER_PLATFORM_TYPE="rockchip"   # 平台类型
    USER_PLATFORM_CHIP_TYPE="rv1109"  # 平台芯片类型
    
  • 星辰平台ssd222d user.env配置如下:
    USER_TOOLCHAIN_FILE="/xxx/ssd222d.toolchain.cmake"  # 平台交叉编译工具链
    USER_PLATFORM_TYPE="sigmatar"   # 平台类型
    USER_PLATFORM_CHIP_TYPE="ssd222d"  # 平台芯片类型
    
  • 公共配置
    USER_BUILD_TYPE="Release"       # 调试模式:Debug, 发布模式:Release  
    USER_CMAKE_GENERATOR="Ninja"    # 编译加速   
    USER_BUILD_SHARED_LIBS=ON       # 是否编译共享库 ON or OFF
    
  1. 项目顶层CMakeLists.txt
    ## 要求最小cmake版本
    cmake_minimum_required(VERSION 3.10)
    
    ## 看系统是否安装ccache
    find_program(CCACHE_PROGRAM ccache)
    if(CCACHE_PROGRAM)
      message(STATUS "Set up ccache ...")
      set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
      set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
    else()
      message(WARNING "ccache has not been found")
    endif()
    ## 定义项目名称
    project(
      mymath
      VERSION 0.1.0
      DESCRIPTION "mymath libraries")
      
     ## 输出编译配置相关信息
    message(STATUS "============================================================================")
    message(STATUS "set CMAKE_MAKE_PROGRAM to: ${CMAKE_MAKE_PROGRAM}")
    message(STATUS "set CMAKE_CURRENT_BINARY_DIR to: ${CMAKE_CURRENT_BINARY_DIR}")
    message(STATUS "set CMAKE_CURRENT_SOURCE_DIR to: ${CMAKE_CURRENT_SOURCE_DIR}")
    message(STATUS "set CMAKE_INSTALL_PREFIX to: ${CMAKE_INSTALL_PREFIX}")
    message(STATUS "set CMAKE_TOOLCHAIN_FILE to: ${CMAKE_TOOLCHAIN_FILE}")
    message(STATUS "set PLATFORM_TYPE to: ${PLATFORM_TYPE}")
    message(STATUS "set PLATFORM_CHIP_TYPE to: ${PLATFORM_CHIP_TYPE}")
    message(STATUS "set CMAKE_BUILD_TYPE to: ${CMAKE_BUILD_TYPE}")
    message(STATUS "set BUILD_SHARED_LIBS to: ${BUILD_SHARED_LIBS}")
    message(STATUS "set THIRD_PARTY_PREFIX to: ${THIRD_PARTY_PREFIX}")
    message(STATUS "============================================================================")
    
    ## 编译库实现代码
    add_subdirectory(src)
    
    ## 编译测试代码
    add_subdirectory(test)
    
    ## 创建库配置文件
    include(cmake/create-config.cmake)
    
    ## 安装库头文件,若要增加库暴露的头文件,需要将暴露的头文件放入include目录
    install(
      DIRECTORY include
      DESTINATION .
      FILES_MATCHING
      PATTERN "*.h" PATTERN "*.hpp")
    
  2. 编译脚本build.sh
    #!/bin/bash
    
    set -e
    source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
    
    #读取用户编译配置
    user_env_file="$source_dir/user.env"
    if [ ! -f "$user_env_file" ]; then
        echo -e "[Warning]: $user_env_file not exists, please copy $user_env_file.sample to $user_env_file and modify it"
    else
        . $user_env_file
    fi
    #编译目录
    build_root_dir="$source_dir/build"
    #安装目录
    install_dir="$source_dir/install"
    #编译类型
    build_type=${USER_BUILD_TYPE:-"Release"}
    #编译共享库
    build_shared_libs=${USER_BUILD_SHARED_LIBS:-"OFF"}
    #编译加速
    cmake_generator=${USER_CMAKE_GENERATOR:-"Unix Makefiles"}
    #工具链文件
    toolchain_file=${USER_TOOLCHAIN_FILE:-"rv1109.toolchain.cmake"}
    #平台类型
    platform_type=${USER_PLATFORM_TYPE:-"rockchip"}
    #芯片类型
    platform_chip_type=${USER_PLATFORM_CHIP_TYPE:-"rv1109"}
    
    #支持命令传参
    for i in "$@"; do
        case $i in
        --toolchain_file=*)
            toolchain_file="${i#*=}"
            shift # past argument=value
            ;;
        --clean)
            clean_build="yes"
            shift # past argument with no value
            ;;
         --ninja)
            cmake_generator="Ninja"
            shift # past argument with no value
            ;;
        *)
            # unknown option
            ;;
        esac
    done
    
    # 编译临时目录
    build_dir=$build_root_dir/$platform_type/$chip_type/$build_type
    
    mkdir -p "$build_dir" || true
    mkdir -p "$install_dir/include" || true
    mkdir -p "$install_dir/lib" || true
    
    ## 清除编译
    if [[ $clean_build == "yes" ]]; then
        echo "clean ..."
        rm $build_root_dir -rf
        rm $install_dir -rf
    else
        pushd "$build_dir"
        cmake "$source_dir" -G "$cmake_generator" \
            -DCMAKE_INSTALL_PREFIX="$install_dir" \
            -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
            -DPLATFORM_TYPE="$platform_type" \
            -DPLATFORM_CHIP_TYPE="$platform_chip_type" \
            -DCMAKE_BUILD_TYPE="$build_type" \
            -DBUILD_SHARED_LIBS="$build_shared_libs" 
            
        # 编译
        cmake --build . --parallel
        # 安装
        cmake --build . --target install
        popd
    fi
    
  3. 交叉工具链cmake文件介绍
    以下是一个通用的交叉工具链文件模板,用户一般只需要更改交叉工具链前缀、更改芯片平台架构、及更改c++相关编译配置。分别对应CROSS_PREFIX 、CROSS_COMPILATION_ARCHITECTURE 和CMAKE_CXX_FLAGS。下面是hisi dv300平台的cmake工具链文件。
    # set cross-compiled system type, it's better not use the type which cmake
    # cannot recognized.
    set(CMAKE_SYSTEM_NAME Linux)
    set(CMAKE_SYSTEM_PROCESSOR arm)
    
    # when hislicon SDK was installed, toolchain was installed in the path as below:
    # 更改工具链前缀,这里以hisi dv300 编译工具链为例子
    set(CROSS_PREFIX arm-himix200-linux-)
    set(CROSS_HOST arm-himix200-linux)
    set(CMAKE_C_COMPILER ${CROSS_PREFIX}gcc)
    set(CMAKE_CXX_COMPILER ${CROSS_PREFIX}g++)
    
    # set searching rules for cross-compiler
    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    ## 根据不同平台的芯片架构来更改,比如arm的v7,v8架构等
    set(CROSS_COMPILATION_ARCHITECTURE armv7-a)
    # 更改c++相关配置
    set(CMAKE_CXX_FLAGS
        "-fpermissive -march=armv7-a -mfloat-abi=softfp -mfpu=neon-vfpv4 -fopenmp ${CMAKE_CXX_FLAGS}"
    )
    # -fpermissive -Wno-unused-variable -Wno-unused-parameter -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4
    # other settings
    set(CMAKE_CXX_FLAGS "-DCV__EXCEPTION_PTR=0 ${CMAKE_CXX_FLAGS}")
    
  4. config.cmake.in和create-config.cmake内容介绍
    可以参考CMake调用第三方库的两种方法,这里面有相关信息介绍。
  • src/CMakeLists.txt内容介绍
#当前目录下的所有源文件存入_SRC_FILES变量
aux_source_directory(. _SRC_FILES)
#生成目标为mymath库,因为顶层项目名称为mymath
add_library(${PROJECT_NAME} ${_SRC_FILES})
#target_link_libraries(${PROJECT_NAME} PUBLIC spdlog)
# VERSION指代动态库版本,SOVERSION指代API版本
set_target_properties(
  ${PROJECT_NAME}
  PROPERTIES VERSION ${PROJECT_VERSION}
             SOVERSION ${PROJECT_VERSION_MAJOR})
target_include_directories(
  ${PROJECT_NAME}
  PUBLIC $)
#安装目标
install(
  TARGETS ${PROJECT_NAME}
  EXPORT ${PROJECT_NAME}Targets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin)

你可能感兴趣的:(技术,Cmake技术,c++,arm开发,qt,c语言,单片机,mcu,gitlab)