物联网

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

2021-02-22  本文已影响0人  PIBOT导航机器人

1.环境

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. 测试

// main.c
#include <stdio.h>

int main()
{
  printf("hello pibot\n");
  return 0;
}
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, 下面我们看看如何编译上面的测试程序

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
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

可以看到详细的编译信息

上一篇下一篇

猜你喜欢

热点阅读