使用CMake搭建树莓派交叉编译环境
2021-02-22 本文已影响0人
PIBOT导航机器人
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
可以看到详细的编译信息