一、测试环境

  • 开发板:rv1126

  • buildroot版本:2018.02-rc3

二、.mk规则

  • PKG_NAME:定义软件包的名称。通常与软件包源代码的目录名相同。

  • PKG_VERSION:定义软件包的版本号。

  • PKG_SOURCE:定义软件包源代码的下载链接或路径。可以是远程 URL 或本地路径。

  • PKG_HASH:定义软件包源代码的哈希值,用于验证下载文件的完整性。通常使用 MD5 或 SHA256 算法计算。

  • PKG_LICENSE:定义软件包的许可证类型。可以是单个许可证或多个许可证的组合。

  • PKG_BUILD_DIR:定义软件包构建过程中的临时目录。通常是 ${BUILD_DIR}/${PKG_NAME}-${PKG_VERSION}。

  • PKG_INSTALL_DIR:定义软件包安装到目标系统的目录。通常是 ${TARGET_DIR}。

  • PKG_CONFIG_DEPENDS:定义软件包构建过程中依赖的其他软件包。这些依赖将被自动解析和构建。

  • PKG_BUILD_CMDS结尾的变量会在 buildroot 框架编译的时候执行,用于给源码的 Makefile 传递编译选项和链接选项,调用源码的Makefile。

  • PKG_INSTALL_TARGET_CMDS结尾的变量是在编译完之后,自动安装执行,一般是让 buildroot 把编译出来的的 bin 或 lib 拷贝到指定目录。

  • $(eval $(autotools-package)):使用 Autotools 构建系统的软件包规则。适用于使用 configure 脚本的软件包。

  • $(eval $(cmake-package)):使用 CMake 构建系统的软件包规则。适用于使用 CMakeLists.txt 的软件包。

  • $(eval $(generic-package)):通用的软件包规则,适用于没有特定构建系统的软件包。需要手动定义构建和安装过程。

  • $(eval $(host-generic-package)):适用于主机(开发机)上构建的通用软件包规则。与目标系统无关。

  • $(eval $(python-package)):适用于 Python 软件包的规则。用于构建和安装 Python 模块。

三、创建自定义软件包

对 buildroot 目录还不熟的小伙伴可以看我之前的笔记【Buildroot】使用记录

3.1 Makefile

  1. 创建 Buildroot 项目

    在 SDK/app 目录下创建 app_demo 文件,并在文件中创建 test.c 和 Makefile 文件,内容如下

    文件目录

    app_demo
    ├── test.c
    └── Makefile

    Makefile 文件

    OPT = -O2
    DEBUG = -g
    OTHER = -Wall -Wno-deprecated
    CFLAGS = $(OPT) $(OTHER)
    INCDIR = -I
    LIBDIR = -L
    LIBS =
    APP=app_demo
    SRCS=test.c .PHONY: all
    all:
    $(CC) -o $(APP) $(SRCS) $(CFLAGS) $(LIBDIR) $(INCDIR) $(LIBS) .PHONY: clean
    clean:
    rm -f *.o *~ $(APP) .PHONY: install
    install:
    cp -f $(APP) $(TARGET_DIR)/../oem .PHONY: uninstall
    uninstall:
    rm -f $(TARGET_DIR)/../oem/$(APP)

    test.c 文件

    #include <stdio.h>
    
    int main()
    {
    printf("buildroot helloworld\n");
    return 0;
    }
  2. APP 的版本和编译规则

    在 Buildroot/package 目录下创建 app_demo 目录,并在目录中创建 app_demo.mk 和 Config.in 文件,内容如下

    文件目录

    app_demo
    ├── app_demo.mk
    └── Config.in

    app_demo.mk 文件

    ##################################################
    #
    # app_demo.mk
    #
    ################################################## ifeq ($(BR2_PACKAGE_APP_DEMO), y) APP_DEMO_VERSION:=1.0.0
    APP_DEMO_SITE=$(TOPDIR)/../app/app_demo
    APP_DEMO_SITE_METHOD=local
    #APP_INSTALL_TARGET:=YES define APP_DEMO_BUILD_CMDS
    $(TARGET_MAKE_ENV) $(MAKE) CC=$(TARGET_CC) CXX=$(TARGET_CXX) -C $(@D)
    endef define APP_DEMO_CLEAN_CMDS
    $(TARGET_MAKE_ENV) $(MAKE) -C $(@D) clean
    endef define APP_DEMO_INSTALL_TARGET_CMDS
    $(TARGET_MAKE_ENV) $(MAKE) -C $(@D) install
    endef define APP_DEMO_UNINSTALL_TARGET_CMDS
    $(TARGET_MAKE_ENV) $(MAKE) -C $(@D) uninstall
    endef $(eval $(generic-package))
    endif

    Config.in 文件

    config BR2_PACKAGE_APP_DEMO
    bool "app_demo"
    help
    This is a demo to add app_demo.
  3. 加到 menuconfig 配置中

    打开“buildroot/package/Config.in”文件。跳转到最后一个“endmenu”下添加如下示例代码(注意:必须在此文件的最后一个 endmenu 前添加)。代码如下所示:

    menu "app_demo"
    source "package/app_demo/Config.in"
    endmenu

  4. 在 menuconfig 打开项目

    这里需要注意的是,需要编译项目时,在 menuconfig 中配置完成后,需要使用命令 make savedefconfig 保存配置。打开项目如下图所示:

  5. 编译项目

    每次编译完成后都会在 output/build 目录下生成对应的包

    # 编译项目
    make app_demo # 清除项目
    make app_demo-dirclean

3.2 cmake

不论是使用 make 构建还是使用 cmake 构建,所操作的流程都是一样的,只是编译规则有一点区别,所以这里就不描述具体的流程了,只将不同的文件贴上即可,其他流程是一样的

  1. 在 SDK/app/app_demo 文件中创建 CMakeLists.txt 文件,内容如下

    cmake_minimum_required(VERSION 3.1.0)
    set(CMAKE_CXX_STANDARD 11) project(app_demo1) set(SOURCES test.c) add_executable(${PROJECT_NAME} ${SOURCES}) install(TARGETS ${PROJECT_NAME} DESTINATION ../../oem)

    注意:install 默认安装的位置是 $(TARGET_DIR)/usr 目录下

  2. 将 Buildroot/package/app_demo 目录下的 app_demo.mk 文件内容更改成以下内容

    ##################################################
    #
    # app_demo.mk
    #
    ################################################## ifeq ($(BR2_PACKAGE_APP_DEMO), y) APP_DEMO_VERSION:=1.0.0
    APP_DEMO_SITE=$(TOPDIR)/../app/app_demo
    APP_DEMO_SITE_METHOD=local
    #UVC_APP_DEPENDENCIES = libdrm mpp $(eval $(cmake-package))
    endif
  3. 编译结果如下所示

四、修改软件版本

完成上面操作后,应给会发现,软件包不只是自定义的,也有从线上下载的。有时候需要更改线上包的版本,情况稍微有一点不一样,所以这里记录了一下。

可能会有小伙伴和我做同样的尝试,上一篇笔记中有提到软件包下载的目录在 Buildroot/dl 下,所以就将需要的版本软件下载到 dl 目录下,便会发现这样的操作是不可行的,需要更改一下配置文件,这里以 iperf3 为例,流程如下:

  1. 进入 buildroot/package/iperf3/ 目录,如下图所示

  2. 重要文件

    图中的文件中,有三个比较重要的文件,分别是:

    • Config.in 相当于内核的 Kconfig;
    • iperf3.hash 软件包的校验码;
    • iperf3.mk 相对于内核的 Makefile;
  3. 修改软件版本

    打开 iperf3.mk 文件,可以看到包的下载地址和版本号(有时候下载地址在 Config.in 里),进入下载网站后,可以找到自己需要的版本,然后修改文件,如下图所示:

  4. 下载测试

    使用命令 make iperf3-source 可以进行下载,如下图所示

  5. 生成源码的 hash 值

    sha256sum buildroot/dl/iperf-3.9.tar.gz

  6. 修改 iperf3.hash 文件



    注意:因为 3.9 版本没有补丁文件的,所以将对应的补丁文件删除即可

五、开机自启

开机时启动自己的应用程序有两种办法,一种是进入文件系统后,在 /etc/init.d/ 目录添加自己的启动脚本;另一种将脚本放在 buildroot 中,在编译的时候,自动放在 /etc/init.d/ 目录下。

由于在 /etc/init.d/ 目录下创建脚本的方式比较简单,这里就不介绍了,主要分析方式二,将启动脚本放在 buildroot 中进行替换。

在操作之前,先来科普一些东西,在 buildroot 编译完成后,有一个最终确定目标的过程,在配置选项中预留了几个接口,如下:

  • BR2_ROOTFS_OVERLAY:指向一个目录,此目录下的所有文件将会覆盖到output/target下。比如一些配置文件,或者预编译的库等可以在此阶段处理。

  • BR2_ROOTFS_POST_BUILD_SCRIPT:一个脚本,更加复杂的对文件进行删除、重命名、strip等等功能。

  • BR2_ROOTFS_POST_IMAGE_SCRIPT:对最终生成的images进行打包处理等。

注意: 配置文件在 Buildroot/configs 目录下。可以通过命令 make menuconfig 进行配置和查看,如下图所示:

  1. fs overlay

    buildroot 会将 BR2_ROOTFS_OVERLAY 配置路径的文件替换到 buildroot/output/xxx/build/target/ 目录下存在或不存在的文件,所以只需要将脚本放在 BR2_ROOTFS_OVERLAY 中对应的目录下即可

  2. 通过脚本操作

    除了fs overlay这种方式,buildroot还提供了一个脚本进行更加复杂的处理。可以进行文件删除、重命名,甚至对带调试信息的文件进行strip等。

    @$(foreach s, $(call qstrip,$(BR2_ROOTFS_POST_BUILD_SCRIPT)), \
    $(call MESSAGE,"Executing post-build script $(s)"); \
    $(EXTRA_ENV) $(s) $(TARGET_DIR) $(call qstrip,$(BR2_ROOTFS_POST_SCRIPT_ARGS))$(sep))

  3. 脚本打包

    除了上面两种方式进行替换之外,还可以在脚本打包的环节进行替换,这个方式我没有研究过,有需要的小伙伴可以自行尝试一下。

常见问题

  1. tar: ./usr/bin/pkg:警告:无法 stat: 没有那个文件或目录

    当安装包的路径变动时,可能会出现这个警告,只需要将 output/build 路径下的 packages-file-list.txt 中的路径给删除即可,如下图所示:

参考资料

buildroot/packages/app/的.mk规则的详细解释:https://blog.csdn.net/benco1986/article/details/131455637

嵌入式Linux构建框架Buildroot创建自己的软件包(基于传统makefile和cmake):https://zhuanlan.zhihu.com/p/451071335

【Buildroot】基础知识:目录、根文件系统目录覆盖、编译性能分析(编译时间、目标尺寸、包依赖图):https://blog.csdn.net/qq_28877125/article/details/130347075

【Buildroot】工具包使用的更多相关文章

  1. Buildroot 用户手册 (中文)

    文章目录 I. Getting started 1. About Buildroot 2. System requirements 2.1. Mandatory packages 2.2. Optio ...

  2. 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?

    0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...

  3. 【NLP】干货!Python NLTK结合stanford NLP工具包进行文本处理

    干货!详述Python NLTK下如何使用stanford NLP工具包 作者:白宁超 2016年11月6日19:28:43 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的 ...

  4. Werkzeug工具包学习-官方例子Shortly分析

    为了学习werkzeug的wsgi框架工具,今天真对官网的例子进行调试运行.涉及到了werkzeug工具包,jinja2前端模版,以及redis内存库,之后可以灵活定制自己主页.再次,作以记录. 首先 ...

  5. Win10 UWP 开发系列:使用多语言工具包让应用支持多语言

    之前我在一篇blog中写过如何使用多语言工具包,见http://www.cnblogs.com/yanxiaodi/p/3800767.html 在WinEcos社区也发布过一篇详细的文章介绍多语言工 ...

  6. Neo4j图数据库管理系统开发笔记之一:Neo4j Java 工具包

    1 应用开发概述 基于数据传输效率以及接口自定义等特殊性需求,我们暂时放弃使用Neo4j服务器版本,而是在Neo4j嵌入式版本的基础上进行一些封装性的开发.封装的重点,是解决Neo4j嵌入式版本Emb ...

  7. 脑成像数据分析:Python工具包

    来源:SealHuang 脑成像技术已经成为认知科学和心理学研究领域中一种重要的研究手段,帮助研究者不断深入发掘我们脑中的秘密.伴随着研究的不断深入,各式各样的指标参数和分析方法也不断推陈出新,以迅雷 ...

  8. doc2vec使用说明(二)gensim工具包 LabeledSentence

    欢迎交流,转载请注明出处. 本文介绍gensim工具包中,带标签(一个或者多个)的文档的doc2vec 的向量表示. 应用场景: 当每个文档不仅可以由文本信息表示,还有别的其他标签信息时,比如,在商品 ...

  9. Cookie对象工具包,对象添加,获取,修改-亲测可用

    先来了解下Cookie 和 Session对象的概念吧. 首先,Cookie是客户端缓存技术,大小一般为4kb左右,主要存储一些比较小的信息,常用的例子有用户名和密码,且是不安全的: Session是 ...

  10. Flat UI 工具包

    Flat UI是一套精美的扁平风格 UI 工具包,基于 Twitter Bootstrap 实现.这套界面工具包含许多基本的和复杂的 UI 部件,例如按钮,输入框,组合按钮,复选框,单选按钮,标签,菜 ...

随机推荐

  1. TCP的可靠性之道:确认重传和流量控制

    TCP 全称为 Transmission Control Protocol(传输控制协议),是一种面向连接的.可靠的.基于字节流的传输层通信协议,其中可靠性是相对于其他传输协议的优势点.TCP 为了确 ...

  2. 使用 AutoGPTQ 和 transformers 让大语言模型更轻量化

    大语言模型在理解和生成人类水平的文字方面所展现出的非凡能力,正在许多领域带来应用上的革新.然而,在消费级硬件上训练和部署大语言模型的需求也变得越来越难以满足. Hugging Face 的核心使命是 ...

  3. python 面试题第一弹

    1. 如何理解Python中的深浅拷贝 浅拷贝(Shallow Copy)创建一个新的对象,该对象的内容是原始对象的引用.这意味着新对象与原始对象共享相同的内存地址,因此对于可变对象来说,如果修改了其 ...

  4. mysql关键字匹配度模糊查询

    有时候项目中需要进行模糊查询,但是要对查询出来的结果进行匹配度排序,比如搜索关键字是"北",需要把数据库中第一个字是北的排在前面,此时就可以用mysql的INSTR函数. INST ...

  5. Spring Event 观察者模式, 业务解耦神器

    观察者模式在实际开发过程中是非常常见的一种设计模式. Spring Event的原理就是观察者模式,只不过有Spring的加持,让我们更加方便的使用这一设计模式. 一.什么是观察者模式 概念: 观察者 ...

  6. PostgreSQL-分区表介绍

    一.分区简介 表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案.一般建议当单表大小超过内存就可以考虑表分区了. 表的分区就是将一个逻辑上的大表(主 ...

  7. 「repost - from Quack」Matroid.md

    拟阵?type=header 拟阵的定义与常见性质 & 拟阵交算法 拟阵的定义与常见性质 独立集系统和拟阵 定义独立集系统\(S=(E,\mathcal{I})\),\(E\)是基本元素的集合 ...

  8. 【爬虫笔记】Python爬虫简单运用爬取代理IP

    一.前言 近些年来,网络上的爬虫越来越多,很多网站都针对爬虫进行了限制,封禁了一些不规则的请求.为了实现正常的网络爬虫任务,爬虫常用代理IP来隐藏自己的真实IP,避免被服务器封禁.本文将介绍如何使用P ...

  9. math 库中常用的数学运算和常量【GO 基础】

    〇.关于 math GO 语言的 math 库是一个内置的标准库,其中包含了许多数学函数和常量,用于计算各种数学运算和统计学计算. 日常开发中,计算当然是少不了的,那么今天来梳理下备查. 一.测试示例 ...

  10. 2023-10-04:用go语言,现有一棵无向、无根的树,树中有 n 个节点,按从 0 到 n - 1 编号 给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges , 其中 edge

    2023-10-04:用go语言,现有一棵无向.无根的树,树中有 n 个节点,按从 0 到 n - 1 编号 给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges , 其中 edge ...