前言

本文基于 RK3588 + Buildroot 编写.
在RK3588开发板环境下,开发者通常利用Buildroot来定制适合RK3588芯片特性的嵌入式Linux系统。通过Buildroot,开发者能够根据实际需求裁剪系统组件、添加特定驱动、配置内核特性,并集成用户应用程序,最终生成最小化且高效的Bootloader、Linux内核镜像、根文件系统镜像(例如rootfs.ext2或 squashfs格式)以及其他必要的启动和系统配置文件。

结合RK3588芯片的强大功能与Buildroot的高度灵活性,开发者能够快速实现针对RK3588平台的嵌入式Linux系统的定制开发,确保系统不仅满足性能要求,还能达到资源占用小、启动速度快、稳定性高的目标,广泛应用于各种工业控制、智能家居、物联网终端等应用场景。
在这里插入图片描述

目标:

在这里插入图片描述

  1. 增加自定义软件模块(模块使用Cmake + C/C++, 源文件基于本地)
  2. 模块单独编译并支持配置默认编译

1. 增加自定义软件模块(模块使用Cmake + C/C++, 源文件基于本地)

增加模块配置:

buildroot/package/test_app/
├── Config.in
└── test.mk

package/test_app/Config.in

config BR2_PACKAGE_TEST_APP
bool "TestApp build!"
help
Add add app for test!

package/test_app/test.mk

TEST_APP_SITE = $(TOPDIR)/test_app
TEST_APP_SITE_METHOD = local
TEST_APP_INSTALL_STAGING = YES
#TEST_APP_CONF_OPTS = -DBUILD_DEMOS=ON
$(eval $(cmake-package))

模块C和CMakeLists源码

buildroot/test_app/
├── CMakeLists.txt
└── main.c

test_app/CMakeLists.txt

cmake_minimum_required(VERSION 3.1.0)
set(CMAKE_CXX_STANDARD 11)
project(test_app)
include_directories(inc)
set(SOURCES main.c)
add_executable(${PROJECT_NAME} ${SOURCES})
install(TARGETS test_app DESTINATION bin)

test_app/main.c

#include <stdio.h>

int main()
{
   printf("Test App by add new package!\n");
   return 0;
}

2. 模块单独编译并支持配置默认编译

参考: The Buildroot user manual:Understanding how to rebuild packages 和RK的SDK文档.

## 切换到buildroot目录下.
source build/envsetup.sh (config_name)
## 编译模块和系统
#选好编译平台,接下来就可以编译每⼀个package,它主要是config、build、install三部分组成
make <package>-reconfigure
make <package>-rebuild
make <package>-reinstall

#清理包命令如下:
make <package>-dirclean

# 其他的一些编译命令:
make <package>-<target>
Package-specific:
  <pkg>                  - Build and install <pkg> and all its dependencies
  <pkg>-source           - Only download the source files for <pkg>
  <pkg>-extract          - Extract <pkg> sources
  <pkg>-patch            - Apply patches to <pkg>
  <pkg>-depends          - Build <pkg>'s dependencies
  <pkg>-configure        - Build <pkg> up to the configure step
  <pkg>-build            - Build <pkg> up to the build step
  <pkg>-graph-depends    - Generate a graph of <pkg>'s dependencies
  <pkg>-dirclean         - Remove <pkg> build directory
  <pkg>-reconfigure      - Restart the build from the configure step
  <pkg>-rebuild          - Restart the build from the build step

相关package的开发,可以参考 /buildroot/package/* , 其中package/rockchip是Rockchip开发的相关package


添加后模块不会参与编译, 增加配置项到构建系统也很简单:

buildroot/package/Config.in

diff --git a/buildroot/package/Config.in b/buildroot/package/Config.in
index 75cfa5799..e593037ca 100755
--- a/buildroot/package/Config.in
+++ b/buildroot/package/Config.in
@@ -2601,4 +2601,8 @@ menu "Text editors and viewers"
       source "package/vim/Config.in"
endmenu

+menu "Customize Packages"
+       source "package/test_app/Config.in"
+endmenu
+
endmenu

在文件末尾增加模块的Config.in
运行 make menuconfig 进入 Target packages
在这里插入图片描述
可以看到增加的菜单, 进入后可以看到并选中菜单.
在这里插入图片描述
保存配置后, 重新make即可.

编译完成后可以看到:
在这里插入图片描述

一些问题记录

  1. No rule to make target ‘test_app’. Stop
$ make test_app
/xxx/...../buildroot/../prebuilts/gcc/linux-x86/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf GCC10 
arm64 arm64 arm64
arm64
make[1]: *** No rule to make target 'test_app'.  Stop.
make: *** [Makefile:88: _all] Error 2

test_app 实际上是模块的文件夹名称, 如: package/test_app, 写成*package/testapp 会报这个问题

  1. package/test_app/test_app.mk中 test_app.mk 的文件名没有限定, 也可以存在多个, 只要内容定义不冲突
    比如, 前面的代码用的文件名是: test.mk
  2. does not appear to contain CMakeLists.txt.
buildroot/../prebuilts/gcc/linux-x86/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf GCC10 
arm64 arm64 arm64
arm64
>>> test_app  Extracting
>>> test_app  Patching
>>> test_app  Configuring
(mkdir -p /buildroot/output/rockchip_rk3588/build/test_app/ && cd /buildroot/output/rockchip_rk3588/build/test_app/ && rm -f CMakeCache.txt && sed -e 's#@@STAGING_SUBDIR@@#aarch64-buildroot-linux-gnu/sysroot#' -e 's#@@RELOCATED_HOST_DIR@@#/buildroot/output/rockchip_rk3588/host/share/buildroot/#' -e 's#@@TARGET_CFLAGS@@#-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1#' -e 's#@@TARGET_CXXFLAGS@@#-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1#' -e 's#@@TARGET_FCFLAGS@@#-Os -g0#' -e 's#@@TARGET_LDFLAGS@@##' -e 's#@@TARGET_CC@@#bin/aarch64-buildroot-linux-gnu-gcc#' -e 's#@@TARGET_CXX@@#bin/aarch64-buildroot-linux-gnu-g++#' -e 's#@@TARGET_AR@@#bin/aarch64-buildroot-linux-gnu-ar#' -e 's#@@TARGET_AS@@#bin/aarch64-buildroot-linux-gnu-as#' -e 's#@@TARGET_LD@@#bin/aarch64-buildroot-linux-gnu-ld#' -e 's#@@TARGET_NM@@#bin/aarch64-buildroot-linux-gnu-nm#' -e 's#@@TARGET_RANLIB@@#bin/aarch64-buildroot-linux-gnu-ranlib#' -e 's#@@TARGET_READELF@@#bin/aarch64-buildroot-linux-gnu-readelf#' -e 's#@@TARGET_STRIP@@#bin/aarch64-buildroot-linux-gnu-strip#' -e 's#@@TARGET_OBJCOPY@@#bin/aarch64-buildroot-linux-gnu-objcopy#' -e 's#@@TARGET_OBJDUMP@@#bin/aarch64-buildroot-linux-gnu-objdump#' -e 's#@@TARGET_FC@@#bin/aarch64-buildroot-linux-gnu-gfortran#' -e 's#@@CMAKE_SYSTEM_PROCESSOR@@#aarch64#' -e 's#@@TOOLCHAIN_HAS_CXX@@#1#' -e 's#@@TOOLCHAIN_HAS_FORTRAN@@#0#' -e 's#@@CMAKE_BUILD_TYPE@@#Release#' /buildroot/support/misc/toolchainfile.cmake.in > /buildroot/output/rockchip_rk3588/build/test_app//toolchainfile.cmake && PATH="/buildroot/output/rockchip_rk3588/host/bin:/buildroot/output/rockchip_rk3588/host/sbin:/home/anson/.local/bin:/home/anson/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"  /usr/bin/cmake /buildroot/output/rockchip_rk3588/build/test_app/ -DCMAKE_TOOLCHAIN_FILE="/buildroot/output/rockchip_rk3588/build/test_app//toolchainfile.cmake" -DCMAKE_INSTALL_PREFIX="/usr" -DCMAKE_COLOR_MAKEFILE=OFF -DBUILD_DOC=OFF -DBUILD_DOCS=OFF -DBUILD_EXAMPLE=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TEST=OFF -DBUILD_TESTS=OFF -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON   )
CMake Error: The source directory "/buildroot/output/rockchip_rk3588/build/test_app" does not appear to contain CMakeLists.txt.
Specify --help for usage, or press the help button on the CMake GUI.
make[1]: *** [package/pkg-generic.mk:287: /buildroot/output/rockchip_rk3588/build/test_app/.stamp_configured] Error 1
make: *** [Makefile:88: _all] Error 2

出现这个问题的原因是test.mk中的配置问题:

TESTAPP_SITE = $(TOPDIR)/work/test_app
TESTAPP_SITE_METHOD = local
TESTAPP_INSTALL_STAGING = YES
$(eval $(cmake-package))

TESTAPP 名称需要与编译模块对应, 假如是make test_app, 对应应该是TEST_APP_*
所以, 正确的配置是:

TEST_APP_SITE = $(TOPDIR)/work/test_app
TEST_APP_SITE_METHOD = local
TEST_APP_INSTALL_STAGING = YES
$(eval $(cmake-package))
  1. 关于MK文件(内容来自Google bard)
# 模块源码的路径
TEST_APP_SITE = $(TOPDIR)/work/test_app
# 
TEST_APP_SITE_METHOD = local
TEST_APP_INSTALL_STAGING = YES

TEST_APP_SITE 变量定义测试应用程序的源代码目录。在本例中,它位于 $(TOPDIR)/work/test_app

TEST_APP_SITE_METHOD 变量定义测试应用程序的获取方式。在本例中,它设置为 local,表示应用程序源代码已存在于本地目录 $(TEST_APP_SITE) 中。

TEST_APP_INSTALL_STAGING 变量定义是否将测试应用程序安装到暂存目录。在本例中,它设置为 YES,表示应用程序将安装到 $(STAGING_DIR) 目录。

以下是这段代码的详细解释:

  • TEST_APP_SITE 变量:
    • 该变量定义测试应用程序的源代码目录。
    • 可以使用绝对路径或相对路径。
    • 如果使用相对路径,则相对于 $(TOPDIR) 目录。
  • TEST_APP_SITE_METHOD 变量:
    • 该变量定义测试应用程序的获取方式。
    • 可以设置以下值:
      • local:表示应用程序源代码已存在于本地目录 $(TEST_APP_SITE) 中。
      • git:表示应用程序源代码将从 Git 仓库克隆。
      • svn:表示应用程序源代码将从 SVN 仓库检出。
      • http:表示应用程序源代码将从 HTTP 服务器下载。
      • ftp:表示应用程序源代码将从 FTP 服务器下载。
  • TEST_APP_INSTALL_STAGING 变量:
    • 该变量定义是否将测试应用程序安装到暂存目录。
    • 可以设置以下值:
      • YES:表示应用程序将安装到 $(STAGING_DIR) 目录。
      • NO:表示应用程序不会安装到暂存目录。

示例

假设 TEST_APP_SITE 设置为 $(TOPDIR)/work/test_appTEST_APP_SITE_METHOD 设置为 localTEST_APP_INSTALL_STAGING 设置为 YES

在这种情况下,Buildroot 将执行以下操作:

  1. $(TOPDIR)/work/test_app 目录获取测试应用程序源代码。
  2. 编译测试应用程序。
  3. 将测试应用程序安装到 $(STAGING_DIR) 目录。

注意

  • 如果 TEST_APP_SITE_METHOD 设置为 gitsvnhttpftp,则 Buildroot 将自动下载应用程序源代码。
  • 如果 TEST_APP_INSTALL_STAGING 设置为 NO,则 Buildroot 将只编译测试应用程序,不会将其安装到暂存目录。

参考

[ 编译篇 ] Buildroot Add Package的一些坑
嵌入式Linux构建框架Buildroot创建自己的软件包(基于传统makefile和cmake)(篇二)
buildroot中配置自定义APP

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐