美文网首页物联网
使用CMake搭建树莓派交叉编译环境

使用CMake搭建树莓派交叉编译环境

作者: PIBOT导航机器人 | 来源:发表于2021-02-22 19:16 被阅读0次

    1.环境

    • PC
      Ubuntu 16.04
    • Raspberry PI4B
      Ubuntu 18.04

    2.交叉工具链接

    cd ~
    mkdir -p toolchain/raspberrypi
    git clone git://github.com/raspberrypi/tools.git
    cd tools/arm-bcm2708
    ls -al
    

    可以看到有几套工具链

    arm-bcm2708hardfp-linux-gnueabi
    arm-bcm2708-linux-gnueabi
    arm-linux-gnueabihf -> arm-rpi-4.9.3-linux-gnueabihf
    arm-rpi-4.9.3-linux-gnueabihf
    gcc-linaro-arm-linux-gnueabihf-raspbian
    gcc-linaro-arm-linux-gnueabihf-raspbian-x64
    

    在这里我们使用的是 arm-linux-gnueabihf 版本

    3.安装cmake

    sudo apt-get install cmake
    cmake --version
    

    如需升级cmake可以自行查找升级方法

    4. 配置toolchain

    复制下面文件保存至toolchain/raspberrypi_32.cmake

    set(CMAKE_SYSTEM_NAME Linux)
    
    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)
    
    set(LINUX_COMPILER_FLAGS)
    set(LINUX_COMPILER_FLAGS_CXX)
    set(LINUX_COMPILER_FLAGS_DEBUG)
    set(LINUX_COMPILER_FLAGS_RELEASE)
    set(LINUX_LINKER_FLAGS)
    set(LINUX_LINKER_FLAGS_EXE)
    
    # STL.
    set(LINUX_TOOLCHAIN_PATH $ENV{RASPBERRYPI_32_TOOLCHAIN})
    list(APPEND CMAKE_FIND_ROOT_PATH "${LINUX_TOOLCHAIN_PATH}")
    
    # Sysroot.
    set(CMAKE_SYSROOT ${LINUX_TOOLCHAIN_PATH}/arm-linux-gnueabihf/sysroot)
    
    # Toolchain.
    set(LINUX_C_COMPILER   "${LINUX_TOOLCHAIN_PATH}/bin/arm-linux-gnueabihf-gcc")
    set(LINUX_CXX_COMPILER "${LINUX_TOOLCHAIN_PATH}/bin/arm-linux-gnueabihf-g++")
    set(LINUX_ASM_COMPILER "${LINUX_TOOLCHAIN_PATH}/bin/arm-linux-gnueabihf-as")
    
    set(CMAKE_C_COMPILER_ID_RUN TRUE)
    set(CMAKE_CXX_COMPILER_ID_RUN TRUE)
    set(CMAKE_C_COMPILER_ID Clang)
    set(CMAKE_CXX_COMPILER_ID Clang)
    set(CMAKE_C_COMPILER_VERSION 3.8)
    set(CMAKE_CXX_COMPILER_VERSION 3.8)
    set(CMAKE_C_STANDARD_COMPUTED_DEFAULT 11)
    set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT 98)
    set(CMAKE_CXX_STANDARD 11)
    # Generic flags.
    list(APPEND LINUX_COMPILER_FLAGS
        -DLINUX
        -ffunction-sections
        -funwind-tables
        -fstack-protector-strong
        -no-canonical-prefixes)
    list(APPEND LINUX_LINKER_FLAGS
        -Wl,--build-id
        -Wl,--warn-shared-textrel
        -Wl,--fatal-warnings)
    list(APPEND LINUX_LINKER_FLAGS_EXE
        -Wl,--gc-sections
        -Wl,-z,nocopyreloc)
    
    # Debug and release flags.
    list(APPEND LINUX_COMPILER_FLAGS_DEBUG
        -g
        -O0)
    
    list(APPEND LINUX_COMPILER_FLAGS_RELEASE
        -O2)
    
    list(APPEND LINUX_COMPILER_FLAGS_RELEASE
        -DNDEBUG)
        
    # Toolchain and ABI specific flags.
    # Configuration specific flags.
    # if(LINUX_PIE)
    set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
    list(APPEND LINUX_LINKER_FLAGS_EXE
        -pie
        -fPIE)
    # endif()
    
    list(APPEND LINUX_LINKER_FLAGS
    -Wl,--no-undefined)
    
    # Convert these lists into strings.
    string(REPLACE ";" " " LINUX_COMPILER_FLAGS         "${LINUX_COMPILER_FLAGS}")
    string(REPLACE ";" " " LINUX_COMPILER_FLAGS_CXX     "${LINUX_COMPILER_FLAGS_CXX}")
    string(REPLACE ";" " " LINUX_COMPILER_FLAGS_DEBUG   "${LINUX_COMPILER_FLAGS_DEBUG}")
    string(REPLACE ";" " " LINUX_COMPILER_FLAGS_RELEASE "${LINUX_COMPILER_FLAGS_RELEASE}")
    string(REPLACE ";" " " LINUX_LINKER_FLAGS           "${LINUX_LINKER_FLAGS}")
    string(REPLACE ";" " " LINUX_LINKER_FLAGS_EXE       "${LINUX_LINKER_FLAGS_EXE}")
    
    set(CMAKE_C_COMPILER        "${LINUX_C_COMPILER}")
    set(CMAKE_CXX_COMPILER      "${LINUX_CXX_COMPILER}")
    
    # Set or retrieve the cached flags.
    # This is necessary in case the user sets/changes flags in subsequent
    # configures. If we included the Android flags in here, they would get
    # overwritten.
    set(CMAKE_C_FLAGS ""
        CACHE STRING "Flags used by the compiler during all build types.")
    set(CMAKE_CXX_FLAGS ""
        CACHE STRING "Flags used by the compiler during all build types.")
    set(CMAKE_ASM_FLAGS ""
        CACHE STRING "Flags used by the compiler during all build types.")
    set(CMAKE_C_FLAGS_DEBUG ""
        CACHE STRING "Flags used by the compiler during debug builds.")
    set(CMAKE_CXX_FLAGS_DEBUG ""
        CACHE STRING "Flags used by the compiler during debug builds.")
    set(CMAKE_ASM_FLAGS_DEBUG ""
        CACHE STRING "Flags used by the compiler during debug builds.")
    set(CMAKE_C_FLAGS_RELEASE ""
        CACHE STRING "Flags used by the compiler during release builds.")
    set(CMAKE_CXX_FLAGS_RELEASE ""
        CACHE STRING "Flags used by the compiler during release builds.")
    set(CMAKE_ASM_FLAGS_RELEASE ""
        CACHE STRING "Flags used by the compiler during release builds.")
    set(CMAKE_MODULE_LINKER_FLAGS ""
        CACHE STRING "Flags used by the linker during the creation of modules.")
    set(CMAKE_SHARED_LINKER_FLAGS ""
        CACHE STRING "Flags used by the linker during the creation of dll's.")
    set(CMAKE_EXE_LINKER_FLAGS ""
        CACHE STRING "Flags used by the linker.")
    
    set(CMAKE_C_FLAGS             "${LINUX_COMPILER_FLAGS} ${CMAKE_C_FLAGS}")
    set(CMAKE_CXX_FLAGS           "${LINUX_COMPILER_FLAGS} ${LINUX_COMPILER_FLAGS_CXX} ${CMAKE_CXX_FLAGS}")
    set(CMAKE_ASM_FLAGS           "${LINUX_COMPILER_FLAGS} ${CMAKE_ASM_FLAGS}")
    set(CMAKE_C_FLAGS_DEBUG       "${LINUX_COMPILER_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}")
    set(CMAKE_CXX_FLAGS_DEBUG     "${LINUX_COMPILER_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}")
    set(CMAKE_ASM_FLAGS_DEBUG     "${LINUX_COMPILER_FLAGS_DEBUG} ${CMAKE_ASM_FLAGS_DEBUG}")
    set(CMAKE_C_FLAGS_RELEASE     "${LINUX_COMPILER_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}")
    set(CMAKE_CXX_FLAGS_RELEASE   "${LINUX_COMPILER_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}")
    set(CMAKE_ASM_FLAGS_RELEASE   "${LINUX_COMPILER_FLAGS_RELEASE} ${CMAKE_ASM_FLAGS_RELEASE}")
    set(CMAKE_SHARED_LINKER_FLAGS "${LINUX_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
    set(CMAKE_MODULE_LINKER_FLAGS "${LINUX_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
    set(CMAKE_EXE_LINKER_FLAGS    "${LINUX_LINKER_FLAGS} ${LINUX_LINKER_FLAGS_EXE} ${CMAKE_EXE_LINKER_FLAGS}")
    
    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
    
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"./$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"./$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
    

    5. 测试

    • ~/test/main.c
    // main.c
    #include <stdio.h>
    
    int main()
    {
      printf("hello pibot\n");
      return 0;
    }
    
    • ~/test/CMakeList.txt
    add_executable(test main.c)
    

    本机测试

    编译本机PC执行程序只需要直接执行cmake即可,如下

    cd ~/test
    rm -rf build
    mkdir build
    cd build
    cmake ..
    make
    

    交叉编译

    export RASPBERRYPI_32_TOOLCHAIN=$HOME/toolchains/raspberrypi/tools/arm-bcm2708/arm-linux-gnueabihf
    cd ~/test/
    rm -rf build
    mkdir build
    cd build
    cmake ..  -DCMAKE_TOOLCHAIN_FILE=${HOME}/toolchains/raspberrypi_32.cmake
    make
    

    6. 扩展

    可以看到我们只需要编写CMAKE_TOOLCHAIN_FILE就可以完成,对于其他平台也是类似
    下面介绍下Android平台下用NDK如何编译

    NDK的cmake交叉环境配置

    首先下在ndk环境, 这里我们使用的android-ndk-r14b具体
    可以发现android-ndk-r14b/build/cmake命令中已经有配置好的CMAKE_TOOLCHAIN_FILE文件, 打开该文件可以看到可以支持gcc/clang, 支持不同的Android Platform, 下面我们看看如何编译上面的测试程序

    • 使用gcc编译32的版本
    cd ${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
    ln -sf /opt/android-ndk-r14b/platforms/android-22/arch-arm sysroot
    cd ~/test/
    rm -rf build
    mkdir build
    cd build
    cmake  ..    -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
                        -DANDROID_TOOLCHAIN=gcc \
                        -DANDROID_ABI=armeabi-v7a \
                        -DANDROID_UNIFIED_HEADERS=1 \
                        -DANDROID_PLATFORM=android-21 \
                        -DCMAKE_ANDROID_STANDALONE_TOOLCHAIN=${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 \
                        -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=gcc
    make
    
    • 使用clang编译64的版本
    cd ~/test/
    rm -rf build
    mkdir build
    cd build
    cmake  .. -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
                    -DANDROID_TOOLCHAIN=clang \
                    -DANDROID_ABI=arm64-v8a \
                    -DANDROID_PLATFORM=android-21 \
                    -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
                    -DANDROID_STL=c++_static
    make
    

    可以使用make VERBOSE=1查看是否使用指定编译器编译, 例如

    [ 50%] Building C object CMakeFiles/test.dir/main.c.o
    /opt/android-ndk-r14b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=aarch64-none-linux-android --gcc-toolchain=/opt/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 --sysroot=/opt/android-ndk-r14b/platforms/android-21/arch-arm64  -isystem /opt/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include -isystem /opt/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include/aarch64-linux-android  -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fno-limit-debug-info -O0 -fno-limit-debug-info  -fPIE   -o CMakeFiles/test.dir/main.c.o   -c /home/david/test/main.c
    [100%] Linking C executable test
    /opt/clion-2018.3.4/bin/cmake/linux/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
    /opt/android-ndk-r14b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=aarch64-none-linux-android --gcc-toolchain=/opt/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 --sysroot=/opt/android-ndk-r14b/platforms/android-21/arch-arm64 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fno-limit-debug-info -O0 -fno-limit-debug-info   -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -L/opt/android-ndk-r14b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -Wl,--gc-sections -Wl,-z,nocopyreloc -pie -fPIE -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -L/opt/android-ndk-r14b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -Wl,--gc-sections -Wl,-z,nocopyreloc -pie -fPIE  CMakeFiles/test.dir/main.c.o  -o test -lm 
    make[2]: Leaving directory '/home/david/test/build'
    [100%] Built target test
    make[1]: Leaving directory '/home/david/test/build'
    /opt/clion-2018.3.4/bin/cmake/linux/bin/cmake -E cmake_progress_start /home/david/test/build/CMakeFiles 0
    

    可以看到详细的编译信息

    相关文章

      网友评论

        本文标题:使用CMake搭建树莓派交叉编译环境

        本文链接:https://www.haomeiwen.com/subject/loukfltx.html