author: hjjdebugdate: 2026年 06月 12日 星期五 19:54:58 CSTdescrip: buildroot 入门介绍文章目录1. buildroot 是什么?1.1 下载地址: https://buildroot.org1.2 你怎么做到这块板子编一套bsp, 那块板子编另一套bsp,不同的板子编出不同的bsp?1.3 菜单项那么多内容,不知道怎么点怎么办?1.4 我怎么知道内置了哪些模板呢? 哪个适合我呢?2. buildroot 深层解析.2.1 make list-defconfigs 命令解析2.1.1 先解释第一条命令: \$(call ...)2.1.2 再解释第二条命令: $(foreach ...)2.2 make qemu_x86_64_defconfig 命令解释2.3 make menuconfig 命令解释2.4 make 命令解释1. buildroot 是什么?它是一个软件, 它是一个工具软件,它用来方便的构建嵌入式系统板载软件.包括bootloader,内核,跟文件系统,应用. 以及交叉构建工具的生成.1.1 下载地址: https://buildroot.org目前长期稳定最新版本为buildroot-2025.02.14.tar.xz大小5.7M 很小.设想一下,当今嵌入式系统横行天下, 天上飞的:卫星,飞行器,地上跑的:汽车,手机家里用得:电视,空调 等等,等等.这些设备其中都有一块电路板, 而单纯的板子是没有任何作用的,需要软件支撑才能工作.而你说, 我能一键编出它们用的软件, 让这些硬件工作起来,你是不是很牛!buildroot 就能做到一个make, 等待若干时间后, 完整的板级支持包(BSP)已经生成.1.2 你怎么做到这块板子编一套bsp, 那块板子编另一套bsp,不同的板子编出不同的bsp?那只需要 make menuconfig会出来一个菜单,不过是字符界面形势的菜单,你只要点菜就行了, 要这个,不要那个, 等等…最后你点的会保留在.config 文件中, 再执行make就出对应的bsp了.1.3 菜单项那么多内容,不知道怎么点怎么办?开发人员为我们想好了,里面有套餐,你点套餐就可以了.点了套餐,再用make menuconfig 调整几项(如果需要的话)来匹配你的板子. 再make就可以了.例如:make qemu_x86_64_defconfig (选中内置的模板项)make menuconfig (可忽略,如果不需要调整config 项的话)make1.4 我怎么知道内置了哪些模板呢? 哪个适合我呢?这点开发人员也替我们考虑到了.make list-defconfigs就能输出所有的内置模板名称.2. buildroot 深层解析.3 条命令就想走遍天下? 想的还是太简单了. 至少也要把3条命令的底层工作原理搞清楚吧.否则你怎么灵活运用它呢? 你怎么剪裁菜单呢? 你怎么调整里边的细节呢? 例如代码下载不下来,能不能换的网站呢? 能不能手工下载放到指定目录呢? 等等问题.make 是由Makefile 支撑的, Makefile 是make 的脚本语言. 它指示的make 先构建这,在构建那.Makefile 是知道构建流程的.作为第一步, make help 显然应该作为起点. 不过这只是一个帮助信息.90% 是简单的字符串照印. 不过有一个foreach 语句循环,后面再分析.现在我们就倒序的来深挖一下make的过程2.1 make list-defconfigs 命令解析list-defconfigs:$(call list-defconfigs,$(TOPDIR))$(foreach name,$(BR2_EXTERNAL_NAMES),\ $(call list-defconfigs,$(BR2_EXTERNAL_$(name)_PATH),\ $(BR2_EXTERNAL_$(name)_DESC))$(sep))就这么短,但是能看的懂吗?2.1.1 先解释第一条命令: $(call …)list-defconfig 是一个自定义命令,其第1参数 TOPDIR : $(CURDIR)而CURDIR 是makefile 的内置变量,是make启动时的目录名称第2参数为空自定义函数的模板时这样的. 这是Makefile 被读进去保留在数据库中的样子.#List the defconfig files# $(1):base directory # $(2):br2-external name,emptyforbundled define list-defconfigs firsttrue;\fordefconfig in $$([-d $(1)/configs]find $(1)/configs-name*_defconfig|sort);do\[-f$${defconfig}]||continue;\if$${first};then \if[$(2)];then \ printfExternal configs in %s:\n$(call qstrip,$(2));\else\ printfBuilt-in configs:\n;\ fi;\ firstfalse;\ fi;\ defconfig$${defconfig#$(1)/configs/};\ printf %-35s - Build for %s\n$${defconfig}$${defconfig%_defconfig};\ done;\ $${first}||printf\nendef当被call 调用,并代入$(1),$(2) 参数时,它会被展开成字符串. 借助remake实时跟踪可以知道##firsttrue;fordefconfig in $([-d/home/hjj/source/arm64/buildroot/configs]find/home/hjj/source/arm64/buildroot/configs-name*_defconfig|sort);do[-f${defconfig}]||continue;if${first};thenif[];then printfExternal configs in %s:\n;elseprintfBuilt-in configs:\n;fi;firstfalse;fi;defconfig${defconfig#/home/hjj/source/arm64/buildroot/configs/};printf %-35s - Build for %s\n${defconfig}${defconfig%_defconfig};done;${first}||printf\n##这些被展开的字符串,将作为shell 脚本被执行,因为它们就处在构建目标的位置上.而这段shell 脚本的功能,我来简单分析一下.做一个for 循化.如果./configs 目录存在,找到该目录下*_defconfig 文件并排序,依次处理如果它(defconfig变量)是一个文件,不是文件继续下一个.由于first 为真,打印一条Build-in configs, 然后把first置为假防止循环打印.把文件名去除目录.用printf 打印文件名 Build for 文件名去掉右部_defconfig2.1.2 再解释第二条命令: $(foreach …)\$(foreach name,$(BR2_EXTERNAL_NAMES),\由于 $(BR2_EXTERNAL_NAMES) 为空, 直接退出该语句2.2 make qemu_x86_64_defconfig 命令解释1042%_defconfig:$(BUILD_DIR)/buildroot-config/conf outputmakefile1043defconfig$(or\1044$(firstword \1045$(foreach d,\1046$(call reverse,$(TOPDIR)$(BR2_EXTERNAL_DIRS)),\1047$(wildcard $(d)/configs/$)\1048)\1049),\1050$(errorCant find $)\1051);\1052$(COMMON_CONFIG_ENV)BR2_DEFCONFIG$${defconfig}\1053$--defconfig$${defconfig}$(CONFIG_CONFIG_IN)这段代码非常的难读,前面设置了一堆环境变量之后,调用了output/build/buildroot-config/conf Config.inconf 是一个执行程序, Config.in 就是根目录下的Config.in, 1千多行配置输入.因为脚本及参数可能都是不变的,而变化是环境变量(例如设置了输入文件名称等)这其中处理细节我没有搞清楚,不过不影响理解.总之conf处理完之后写入了.config 文件2.3 make menuconfig 命令解释1010menuconfig:$(BUILD_DIR)/buildroot-config/mconf outputmakefile1011$(COMMON_CONFIG_ENV)$$(CONFIG_CONFIG_IN)BR2_DEFCONFIGKCONFIG_AUTOCONFIG/home/hjj/source/buildroot-2025.02.14/output/build/buildroot-config/auto.conf KCONFIG_AUTOHEADER/home/hjj/sou\ rce/buildroot-2025.02.14/output/build/buildroot-config/autoconf.h KCONFIG_TRISTATE/home/hjj/source/buildroot-2025.02.14/output/build/buildroot-co\ nfig/tristate.config BR2_CONFIG/home/hjj/source/buildroot-2025.02.14/.config HOST_GCC_VERSION15BASE_DIR/home/hjj/source/buildroot-2025.02.14\/output SKIP_LEGACY/home/hjj/source/buildroot-2025.02.14/output/build/buildroot-config/mconf Config.in其展开后前面是一堆变量设置,再调用mconf 程序, 输入参数还是Config.in这样在mconf 程序控制下,在命令行界面选择菜单, 最后保存文件到.config2.4 make 命令解释敲make, 它就干起来了, 到底它是怎样干的,这些细节还是需要了解一下. 因为有时候我们也想手工控制一下.也应该有个目标, 搞清楚目录级别的流程就可以了, 再搞清楚下载是怎样进行的.make 默认的目标就是all了这里边内容太多, 我解释不了太细致了. 来个小实验吧. 跑通了这个小实验,自己琢磨.再package/下见demo 目录, 再创建demo.mk, 内容如下::~/source/buildroot-2025.02.14/package/demo$ lsdemo.mk$ cat demo.mk#package/demo/demo.mkDEMO_VERSION1.0.0DEMO_SITEhttps://example.com/demoDEMO_SOURCEdemo-$(DEMO_VERSION).tar.gz HOST_DEMO_DEPENDENCIEShost-m4 HOST_DEMO_CONF_OPTS--enable-sharedno # 核心调用主机autotools模板自动生成全套规则 $(eval $(host-autotools-package));关键是那个宏定义,是下面这个文件../package/pkg-autotools.mk319:host-autotools-package$(call inner-autotools-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host)然后你执行 make host-demo你看到它真的会从https://example.com/demo 网站下载文件, 当然是不可能下载成功的.为了跳过下载, 我们在./dl 目录添加demo-1.0.0.tar.gz 文件 .如果你给一个假文件,它会说格式不对.没法解压缩给它一个真正的.tar.gz, 解开口,他说没法configure.给它一个真正的autotools 打包的文件. 带./configure, 可make 的那一种.敲make host-demo, 它真的调用configure, make, gcc 给出了正确的编译结果,其中gcc 带一大堆参数.这一下对Makefile 的运行就很有内容要研究了首先: demo.mk 是怎样被顶层Makefile 包含进来的?顶层Makefile 543 行有包含543 include $(sort $(wildcard package//.mk))host-autotools-package 宏展开是pkgname 是怎样赋值的?没看清楚! 对demo.mk 而言, 它的pkgnamedemohost-autotools-package 被展开成了什么?可能被展开动态生成了几百条规则,文件越复杂生成的规则越复杂, 我没看懂,以后再研究吧.先到这里吧.再重复看make 的过程,可以先clean, 再make, 生成的log 如下:hjjhjj-JIAOLONG-Series:~/source/buildroot-2025.02.14$ make host-demo-dirclean rm-Rf/home/hjj/source/buildroot-2025.02.14/output/build/host-demo-1.0.0hjjhjj-JIAOLONG-Series:~/source/buildroot-2025.02.14$ make host-demo WARNING:no hash filefordemo-1.0.0.tar.gzhost-demo1.0.0Extracting gzip-d-c/home/hjj/source/buildroot-2025.02.14/dl/demo/demo-1.0.0.tar.gz|tar--strip-components1-C/home/hjj/source/buildroot-2025.02.14/output/build/host-demo-1.0.0-xf-host-demo1.0.0Patchinghost-demo1.0.0Updating config.subandconfig.guessforfile in config.guess config.sub;dofori in $(find/home/hjj/source/buildroot-2025.02.14/output/build/host-demo-1.0.0-name $file);docp support/gnuconfig/$file $i;done;donehost-demo1.0.0Patching libtoolhost-demo1.0.0Configuring(cd/home/hjj/source/buildroot-2025.02.14/output/build/host-demo-1.0.0/rm-rf config.cache;GIT_DIR.PATH/home/hjj/source/buildroot-2025.02.14/output/host/bin:/home/hjj/source/buildroot-2025.02.14/output/host/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binPKG_CONFIG/home/hjj/source/buildroot-2025.02.14/output/host/bin/pkg-configPKG_CONFIG_SYSROOT_DIR/PKG_CONFIG_ALLOW_SYSTEM_CFLAGS1PKG_CONFIG_ALLOW_SYSTEM_LIBS1PKG_CONFIG_LIBDIR/home/hjj/source/buildroot-2025.02.14/output/host/lib/pkgconfig:/home/hjj/source/buildroot-2025.02.14/output/host/share/pkgconfigAR/usr/bin/arAS/usr/bin/asLD/usr/bin/ldNM/usr/bin/nmCC/usr/bin/gccGCC/usr/bin/gccCXX/usr/bin/gCPP/usr/bin/cppOBJCOPY/usr/bin/objcopyRANLIB/usr/bin/ranlibCPPFLAGS-I/home/hjj/source/buildroot-2025.02.14/output/host/includeCFLAGS-O2 -I/home/hjj/source/buildroot-2025.02.14/output/host/includeCXXFLAGS-O2 -I/home/hjj/source/buildroot-2025.02.14/output/host/includeLDFLAGS-L/home/hjj/source/buildroot-2025.02.14/output/host/lib -Wl,-rpath,/home/hjj/source/buildroot-2025.02.14/output/host/libINTLTOOL_PERL/usr/bin/perl CONFIG_SITE/dev/null./configure--prefix/home/hjj/source/buildroot-2025.02.14/output/host--sysconfdir/home/hjj/source/buildroot-2025.02.14/output/host/etc--localstatedir/home/hjj/source/buildroot-2025.02.14/output/host/var--enable-shared--disable-static--disable-gtk-doc--disable-gtk-doc-html--disable-doc--disable-docs--disable-documentation--disable-debug--with-xmltono--with-fopno--disable-nls--disable-dependency-tracking--enable-sharedno)configure:WARNING:unrecognized options:--enable-shared,--disable-static,--disable-gtk-doc,--disable-gtk-doc-html,--disable-doc,--disable-docs,--disable-documentation,--disable-debug,--with-xmlto,--with-fop,--disable-nls,--enable-shared checkingfora BSD-compatible install.../usr/bin/install-c checking whether sleep supports fractional seconds...yes checking filesystem timestamp resolution...0.01checking whether build environment is sane...yes checkingfora race-free mkdir-p.../usr/bin/mkdir-p checkingforgawk...gawk checking whether make sets $(MAKE)...yes checking whether make supports nested variables...yes checking xargs-n works...yes checking whether UID1000is supported by ustar format...yes checking whether GID1000is supported by ustar format...yes checking how to create a ustar tar archive...gnutar checkingforgcc.../usr/bin/gcc checking whether the C compiler works...yes checkingforC compilerdefaultoutput file name...a.out checkingforsuffix of executables...checking whether we are cross compiling...no checkingforsuffix of object files...o checking whether the compiler supports GNU C...yes checking whether/usr/bin/gcc accepts-g...yes checkingfor/usr/bin/gcc option to enable C11 features...none needed checking whether/usr/bin/gcc understands-cand-o together...yes checking whether make supports the include directive...yes(GNU style)checking dependency style of/usr/bin/gcc...none checking that generated files are newer than configure...done configure:creating./config.status config.status:creating Makefile config.status:executing depfiles commands configure:WARNING:unrecognized options:--enable-shared,--disable-static,--disable-gtk-doc,--disable-gtk-doc-html,--disable-doc,--disable-docs,--disable-documentation,--disable-debug,--with-xmlto,--with-fop,--disable-nls,--enable-sharedhost-demo1.0.0Building GIT_DIR.PATH/home/hjj/source/buildroot-2025.02.14/output/host/bin:/home/hjj/source/buildroot-2025.02.14/output/host/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binPKG_CONFIG/home/hjj/source/buildroot-2025.02.14/output/host/bin/pkg-configPKG_CONFIG_SYSROOT_DIR/PKG_CONFIG_ALLOW_SYSTEM_CFLAGS1PKG_CONFIG_ALLOW_SYSTEM_LIBS1PKG_CONFIG_LIBDIR/home/hjj/source/buildroot-2025.02.14/output/host/lib/pkgconfig:/home/hjj/source/buildroot-2025.02.14/output/host/share/pkgconfig/usr/bin/make-j33-C/home/hjj/source/buildroot-2025.02.14/output/build/host-demo-1.0.0/make[2]:Nothing to be doneforall.host-demo1.0.0Installing to host directory GIT_DIR.PATH/home/hjj/source/buildroot-2025.02.14/output/host/bin:/home/hjj/source/buildroot-2025.02.14/output/host/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binPKG_CONFIG/home/hjj/source/buildroot-2025.02.14/output/host/bin/pkg-configPKG_CONFIG_SYSROOT_DIR/PKG_CONFIG_ALLOW_SYSTEM_CFLAGS1PKG_CONFIG_ALLOW_SYSTEM_LIBS1PKG_CONFIG_LIBDIR/home/hjj/source/buildroot-2025.02.14/output/host/lib/pkgconfig:/home/hjj/source/buildroot-2025.02.14/output/host/share/pkgconfig/usr/bin/make-j33 install-C/home/hjj/source/buildroot-2025.02.14/output/build/host-demo-1.0.0/make[3]:Nothing to be doneforinstall-data-am./usr/bin/mkdir-p /home/hjj/source/buildroot-2025.02.14/output/host/bin/usr/bin/install-c demo /home/hjj/source/buildroot-2025.02.14/output/host/bin总之,buildroot 依据一个复杂的Makefile, 能把各种可剪裁的功能模块文件集中在一起, 你可以方便的配置,组装它们.形成不同的板级支持包