یکی از مشکلات برنامهنویسی پروژهها روی چیپهای اقتصادی و نهفتهی دستگاهها مانند نانوپای یا Luckfox Pico، این است که کامپایل برنامهها روی آنها بسیار طولانی و زمانبر است. در این مواقع امکان کامپایل میان-پردازندهای (Cross-Compile) موجب افزایش سرعت بیلد و توسعهی پروژه میگردد.
در این آموزش کوتاه یاد میگیریم که چگونه روی Debian (من به صورت WSL روی یک رایانه x64 نصب کردهام) برنامهی C یا C++ را برای لینوکس armhf کامپایل کنیم.
1- ایجاد sysroot مخصوص Armhf با افزودن معماری Armhf به دبیان
|
1 |
sudo dpkg --add-architecture armhf |
2- نصب برنامهها و کتابخانههای موردنیاز روی دبیان (نسخهی مخصوص armhf به کمک علامت «:»)
|
1 |
sudo apt update |
|
1 2 3 4 |
sudo apt update sudo apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \ pkg-config qemu-user-static |
3- تنظیم CMake
حالا CMakeLists.txt را به نحوی تنظیم میکنیم تا تنظیمات کلی و بدون مشکل برای معماریهای مختلف در آن قرار گیرد:
|
1 2 3 4 5 6 7 8 |
cmake_minimum_required(VERSION 3.16) # Minimum required CMake version project(PROJECT_NAME) # Set your project name here add_compile_options(-s -flto=auto ${TARGET_COMPILE_OPTIONS}) add_compile_options(-O3 -Wall -Wextra) add_compile_options(-mfpu=neon -mfloat-abi=hard -march=armv7-a -mtune=cortex-a7) ... |
و تنظیمات وابسته به بیلد armhf در cmake/Toolchain-armhf.cmake قرار میگیرد:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# cmake/Toolchain-armhf.cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) # or armv7 # Cross compilers set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) # Avoid try-run during checks set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_SYSROOT "/") # Tell find_* and pkg-config to search the ARM sysroot first set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # build tools from host set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # libraries from target set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # headers from target set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # packages from target # Use the host pkg-config binary but point it at the ARM pc files: if(NOT DEFINED ENV{PKG_CONFIG_SYSROOT_DIR}) set(ENV{PKG_CONFIG_SYSROOT_DIR} "${CMAKE_SYSROOT}") endif() set(_pc_paths "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig" "${CMAKE_SYSROOT}/usr/lib/pkgconfig" "${CMAKE_SYSROOT}/usr/share/pkgconfig" "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf/glib-2.0/pkgconfig" "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig" ) string(JOIN ":" _pc_joined ${_pc_paths}) set(ENV{PKG_CONFIG_LIBDIR} "${_pc_joined}") find_program(CMAKE_AR arm-linux-gnueabihf-gcc-ar) find_program(CMAKE_RANLIB arm-linux-gnueabihf-gcc-ranlib) find_program(CMAKE_NM arm-linux-gnueabihf-gcc-nm) |
4- تنظیم Toolchain، نوع کامپایل، پوشههای سورس و خروجی و در نهایت، بیلد
|
1 2 3 |
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-armhf.cmake \ cmake --build build -j |
برای مطمئن شدن از نوع معماری خروجی کامپایل، میتوانید از دستور file استفاده کنید.