Buildroot构建host-systemd报__VA_OPT__语法错误的修复方案问询
Buildroot编译host-systemd时__VA_OPT__语法报错修复
问题现象
使用Buildroot为i386目标平台构建搭载SystemD的根文件系统时,目标端systemd包可正常完成编译,但host-systemd编译失败,报错信息如下:
../src/udev/udev-event.c:1047:9: note: in expansion of macro ‘DEVICE_TRACE_POINT’ DEVICE_TRACE_POINT(rules_finished, dev); ^~~~~~~~~~~~~~~~~~ ../src/shared/udev-util.h:81:81: error: expected ‘)’ before ‘__VA_OPT__’ STAP_PROBEV(udev, name, device_action_to_string(_a), _n, _p, _s __VA_OPT__(,) __VA_ARGS__);\
已知排查结论:
- host端与目标端的systemd使用完全相同的源码构建,仅编译配置选项存在差异,调整host端已有配置选项无法解决该报错
- 本次编译面向5.15版本内核,i386默认配置、x86_64架构配置均可复现问题
- 差异点定位:编译host-systemd时构建选项
HAVE_SYS_SDT_H为启用状态,编译目标端systemd时该选项未启用;手动在host-systemd的meson.build第700行插入conf.set10('HAVE_SYS_SDT_H',false)可解决问题,但该修改方式侵入源码,不够规范。
当前使用的编译配置如下:
目标端systemd配置:
SYSTEMD_CONF_OPTS += \ -Ddefault-hierarchy=unified \ -Didn=true \ -Dima=false \ -Dkexec-path=/usr/sbin/kexec \ -Dkmod-path=/usr/bin/kmod \ -Dldconfig=false \ -Dlink-boot-shared=true \ -Dloadkeys-path=/usr/bin/loadkeys \ -Dman=false \ -Dmount-path=/usr/bin/mount \ -Dmode=release \ -Dnss-systemd=true \ -Dquotacheck-path=/usr/sbin/quotacheck \ -Dquotaon-path=/usr/sbin/quotaon \ -Drootlibdir='/usr/lib' \ -Dsetfont-path=/usr/bin/setfont \ -Dsplit-bin=true \ -Dsplit-usr=false \ -Dsulogin-path=/usr/sbin/sulogin \ -Dsystem-gid-max=999 \ -Dsystem-uid-max=999 \ -Dsysvinit-path= \ -Dsysvrcnd-path= \ -Dtelinit-path= \ -Dtests=false \ -Dtmpfiles=true \ -Dumount-path=/usr/bin/umount \ -Dutmp=false
host端systemd配置:
# We need a very minimal host variant, so we disable as much as possible. HOST_SYSTEMD_CONF_OPTS = \ -Dsplit-bin=true \ -Dsplit-usr=false \ --prefix=/usr \ --libdir=lib \ --sysconfdir=/etc \ --localstatedir=/var \ -Dmode=release \ -Dutmp=false \ -Dhibernate=false \ -Dldconfig=false \ -Dresolve=false \ -Defi=false \ -Dtpm=false \ -Denvironment-d=false \ -Dbinfmt=false \ -Drepart=false \ -Dcoredump=false \ -Dpstore=false \ -Doomd=false \ -Dlogind=false \ -Dhostnamed=false \ -Dlocaled=false \ -Dmachined=false \ -Dportabled=false \ -Dsysext=false \ -Duserdb=false \ -Dhomed=false \ -Dnetworkd=false \ -Dtimedated=false \ -Dtimesyncd=false \ -Dremote=false \ -Dcreate-log-dirs=false \ -Dnss-myhostname=false \ -Dnss-mymachines=false \ -Dnss-resolve=false \ -Dnss-systemd=false \ -Dfirstboot=false \ -Drandomseed=false \ -Dbacklight=false \ -Dvconsole=false \ -Dquotacheck=false \ -Dsysusers=false \ -Dtmpfiles=true \ -Dimportd=false \ -Dhwdb=false \ -Drfkill=false \ -Dman=false \ -Dhtml=false \ -Dsmack=false \ -Dpolkit=false \ -Dblkid=false \ -Didn=false \ -Dadm-group=false \ -Dwheel-group=false \ -Dzlib=false \ -Dgshadow=false \ -Dima=false \ -Dtests=false \ -Dglib=false \ -Dacl=false \ -Dsysvinit-path='' \ -Dinitrd=false \ -Dxdg-autostart=false \ -Dkernel-install=false \ -Danalyze=false \ -Dlibcryptsetup=false \ -Daudit=false \ -Dzstd=false
根因分析
报错的核心原因是:__VA_OPT__是C23/C++20标准才正式引入的可变参数宏语法,host编译时自动检测到宿主机存在<sys/sdt.h>(SystemTap静态探针头文件),因此启用了HAVE_SYS_SDT_H宏,但是宿主机安装的sdt头文件版本过旧,内部的STAP_PROBEV宏没有兼容__VA_OPT__的语法逻辑,导致预编译阶段抛出语法错误。
交叉编译目标端systemd时,构建系统不会拾取宿主机的sdt头文件,HAVE_SYS_SDT_H自动检测为关闭状态,因此不会触发该报错。
规范修复方案
不需要修改systemd源码,直接通过meson构建参数即可解决:
- 推荐方案:在
HOST_SYSTEMD_CONF_OPTS配置块末尾追加-Dhave-sys-sdt-h=false,显式告诉meson构建系统关闭sys/sdt.h探针支持,跳过自动检测逻辑。该参数是systemd meson构建系统原生支持的标准配置项,效果和手动修改meson.build强制赋值完全一致,属于配置层面的合法修改,没有源码侵入性,后续Buildroot版本升级时维护成本极低。 - 备选方案:升级宿主机的sdt开发包(Debian/Ubuntu系安装/升级
systemtap-sdt-dev,CentOS/RHEL系安装/升级systemtap-sdt-devel)到新版本,让头文件兼容__VA_OPT__语法。但该方案依赖宿主机发行版的包版本,不同构建环境下一致性差,不推荐用于自动化构建场景。
修改完成后清理Buildroot的host-systemd构建缓存,重新编译即可正常通过。
内容的提问来源于stack exchange,提问作者Denis Stepanenko
相关产品推荐
相关产品推荐

