
构建工具【免费下载链接】mesonThe Meson Build System项目地址https://gitcode.com/gh_mirrors/me/meson点击查看免费下载本篇指南以 AppStream-glib 这类典型项目包含库、GObject Introspection 数据、测试、man 页、i18n、bash-completion以及可选的构建开关为样例系统讲解如何把一套成熟的 Autotools 构建体系configure.acMakefile.am逐行迁移到 Meson。读完本篇你将掌握 Meson 自带的ac_converter辅助脚本用法、configure.ac各关键宏与meson.build的对照写法以及Makefile.am中库、资源、测试、GIR、GSettings、gettext 等机制的完整替代方案可直接照搬到自己的项目迁移工作中。迁移概览为什么 Meson 能替代 AutotoolsAutotools 项目通常由两类文件驱动configure.ac生成 configure 脚本并探测系统与Makefile.am描述编译规则。Meson 将二者统一为一个声明式的meson.build文件配合可选的meson.options旧版本为meson_options.txt描述构建选项。在动手前Meson 仓库自带了辅助脚本 tools/ac_converter.py可自动转换configure.ac中基础的 autoconf 探测逻辑。其用法说明写在该脚本的help_message中Usage: ac_converter config.h.meson脚本读取config.h.meson查找其中的头文件/函数检查并输出对应的 Meson 声明。使用方式为把config.h.in复制为config.h.meson将#undef替换为#mesondefine后运行。之所以不能全自动完成是因为部分 configure 脚本中的#undef语句与 configure 检查无关见 tools/ac_converter.py。从脚本源码可以看到它实际能转换三类检查tools/ac_converter.py头文件检查凡以#mesondefine开头且以_H结尾的行会被推断为头文件最终生成check_headers列表并用cc.has_header()逐项探测函数检查脚本内置了一张function_data表将常见的HAVE_XXX宏映射到函数名, 头文件二元组如HAVE_MMAP→mmapsys/mman.h输出为check_functions列表并用cc.has_function()验证未收录的HAVE_宏则以注释# check token输出留待手工处理sizeof 检查SIZEOF_前缀的条目会被转换为cc.sizeof()调用如SIZEOF_SIZE_T→cdata.set(SIZEOF_SIZE_T, cc.sizeof(size_t))。脚本最终还会自动生成configure_file(input : config.h.meson, output : config.h, configuration : cdata)与下面手写版完全一致。Configure.ac 到 meson.build探测与宏的一一对应版本声明忽略 AC_PREREQ用 project() 承载版本AC_PREREQ(2.63)只是声明 autoconf 的最低版本要求Meson 没有对应函数直接忽略即可。版本变量的定义在 Autotools 中用 m4 宏m4_define([as_major_version], [0]) m4_define([as_minor_version], [3]) m4_define([as_micro_version], [6]) m4_define([as_version], [as_major_version.as_minor_version.as_micro_version])Meson 中版本号统一在project()里声明再用字符串的split(.)方法拆出主/次/微版本as_version meson.project_version() # set in project() below ver_arr as_version.split(.) as_major_version ver_arr[0] as_minor_version ver_arr[1] as_micro_version ver_arr[2]项目初始化与编译器选择AC_INIT([appstream-glib],[as_version]) AC_PROG_CC对应 Mesonproject(appstream-glib, c, version : 0.3.6)注意这必须是meson.build文件的第一行。project()的声明在解释器中的实现位于 mesonbuild/interpreter/interpreter.py它负责初始化项目名、语言、版本等核心元数据。Meson 没有AC_PROG_CC之类的手动编译器选择——声明了语言Meson 会在配置阶段自动探测对应编译器。AC_SUBST 与自动头文件AC_SUBST的作用是把变量注入 Makefile 模板Meson 中完全不需要因为它只有一种构建描述文件meson.build不存在 Makefile/configure 两类模板文件的分裂。Autotools 的AC_CONFIG_HEADERS([config.h])会自动生成配置头文件Meson 不支持这种自动头文件需要手工指定要写入的内容。做法是先构造configuration_data()对象再用configure_file()生成conf configuration_data() # Surround the version in quotes to make it a C string conf.set_quoted(VERSION, as_version) configure_file(output : config.h, configuration : conf)其中set_quoted会把值加上引号生成合法的 C 字符串宏。configure_file()还支持SOME_VAR形式的变量替换细节参见 配置页面。该函数在解释器中的实现位于 mesonbuild/interpreter/interpreter.py。程序探测AC_PATH_PROG → find_programAutotools 用AC_PATH_PROG探测外部程序并配合AC_DEFINE和AM_CONDITIONAL做条件编译AC_PATH_PROG(GPERF, [gperf], [no]) if test x$GPERF ! xno ; then AC_DEFINE(HAVE_GPERF,[1], [Use gperf]) fi AM_CONDITIONAL(HAVE_GPERF, [test x$GPERF ! xno])Meson 的find_program()返回一个可判断found()的程序对象天然支持可选依赖gperf find_program(gperf, required : false) if gperf.found() conf.set(HAVE_GPERF, 1) endifrequired : false表示找不到也不报错随后用gperf.found()判断是否可用。该函数由 mesonbuild/interpreter/interpreter.py 实现返回的ExternalProgram对象可直接作为custom_target()的command使用。pkg-config 依赖PKG_CHECK_MODULES → dependencyPKG_CHECK_MODULES(SOUP, libsoup-2.4 2.24)对应soup dependency(libsoup-2.4, version : 2.24)dependency()是 Meson 依赖系统的统一入口不仅支持 pkg-config还支持 CMake 模块、系统内置依赖等自动完成探测、版本校验与编译/链接参数收集。可选功能开关AC_ARG_ENABLE → get_optionAutotools 用AC_ARG_ENABLE声明--enable-dep11之类的开关并在启用时检查头文件、添加库和宏定义AC_ARG_ENABLE(dep11, AS_HELP_STRING([--enable-dep11],[enable DEP-11]), enable_dep11$enableval,enable_dep11yes) AM_CONDITIONAL(HAVE_DEP11, test x$enable_dep11 xyes) if test x$enable_dep11 xyes; then AC_CHECK_HEADER(yaml.h, [], [AC_MSG_ERROR([No yaml.h])]) YAML_LIBS-lyaml AC_SUBST(YAML_LIBS) AC_DEFINE(AS_BUILD_DEP11,1,[Build DEP-11 code]) fiMeson 把选项声明与使用分离选项在meson.options中声明构建脚本里用get_option()读取if get_option(enable-dep11) yaml dependency(yaml-0.1) conf.set(AS_BUILD_DEP11, 1) else yaml dependency(yaml-0.1, required : false) endifmeson.optionsoption(enable-dep11, type : boolean, value : true, description : enable DEP-11)对比可见Meson 将AC_ARG_ENABLE的声明帮助文本、默认值和使用条件逻辑彻底解耦默认值true相当于 Autotools 示例中的enable_dep11yes启用时用dependency(yaml-0.1)默认 required找不到会报错未启用时则改成required : false以避免无谓报错。Makefile.am 到 meson.build构建规则的同构迁移在 Meson 中不需要单独的 Makefile 类文件所有规则仍写在meson.build中。子目录SUBDIRS → subdirSUBDIRS \ libappstream-glib对应subdir(libappstream-glib)清理与分发文件*CLEANFILES 与 EXTRA_DIST 均可省去Autotools 需要DISTCLEANFILES、MAINTAINERCLEANFILES等清理规则以及EXTRA_DIST分发清单DISTCLEANFILES \ appstream-glib-*.tar.xz MAINTAINERCLEANFILES \ *~ \ ABOUT-NLS \ aclocal.m4 \ ChangeLog \ compile \ config.guess \ config.h.* \ config.rpath EXTRA_DIST \ COPYING \ MAINTAINERS \ AUTHORS \ README.md \ NEWS \ autogen.sh \ config.hMeson 中两者都不需要清理Meson 强制在临时目录通常叫build中构建产物与源码隔离删除整个 build 目录即完成清理无需维护*CLEANFILES清单分发打包 tarball 时用git archive或类似工具基于版本控制生成无需维护EXTRA_DIST。glib-compile-resourcesMakefile 规则 → gnome.compile_resourcesAutotools 中用带依赖的生成规则手工调用glib-compile-resources生成.c和.h并维护BUILT_SOURCESas-resources.c: appstream-glib.gresource.xml \ as-stock-icons.txt \ ... $(AM_V_GEN) \ glib-compile-resources \ --sourcedir$(srcdir) \ --sourcedir$(top_builddir)/data \ --target$ \ --generate-source \ --c-name as \ $(srcdir)/appstream-glib.gresource.xml as-resources.h: ... $(AM_V_GEN) \ glib-compile-resources ... --generate-header --c-name as ...Meson 通过gnome模块一行搞定自动生成源与头文件、自动跟踪资源依赖asresources gnome.compile_resources( as-resources, appstream-glib.gresource.xml, source_dir : ., c_name : as)compile_resources的实现位于 mesonbuild/modules/gnome.py从源码可以看出其内部行为自动查找glib-compile-resources工具把source_dir依次转为--sourcedir参数并去重c_name对应--c-name然后统一追加--generate --target OUTPUT。新版 glib 下还会扫描 gresource XML 解析出依赖文件列表使资源文件的变更能正确触发重建。返回的对象可直接作为库/可执行程序的源码。头文件安装include_HEADERS → install_headerslibappstream_glib_includedir $(includedir)/libappstream-glib libappstream_glib_include_HEADERS \ appstream-glib.h \ as-app.h \ ...Meson 用数组 install_headers()headers [ appstream-glib.h, as-app.h, as-bundle.h, as-enums.h, as-icon.h, as-image.h, as-inf.h, as-node.h, as-problem.h, as-provide.h, as-release.h, as-screenshot.h, as-store.h, as-tag.h, as-utils.h, as-version.h] install_headers(headers, subdir : libappstream-glib)subdir参数对应$(includedir)/libappstream-glib的安装子目录。共享库lib_LTLIBRARIES → shared_libraryAutotools 中lib_LTLIBRARIES定义库目标SOURCES/LIBADD/LDFLAGS分别描述源码、链接依赖与链接选项符号导出靠-export-symbols-regexlib_LTLIBRARIES \ libappstream-glib.la libappstream_glib_la_SOURCES ...大量 .c/.h 列表 libappstream_glib_la_LIBADD \ $(GLIB_LIBS) $(GDKPIXBUF_LIBS) $(LIBARCHIVE_LIBS) $(SOUP_LIBS) $(YAML_LIBS) libappstream_glib_la_LDFLAGS \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -export-dynamic \ -no-undefined \ -export-symbols-regex ^as_.*Meson 的对应写法源码列表可直接把之前生成的asresources拼入sources数组依赖用dependencies数组统一管理符号导出改用版本脚本version scriptappstream-glib.mapsources [ as-app.c, as-app-desktop.c, as-app-inf.c, as-app-private.h, as-app-validate.c, as-bundle.c, as-bundle-private.h, as-cleanup.h, as-enums.c, as-icon.c, as-icon-private.h, as-image.c, as-image-private.h, as-inf.c, as-inf.h, as-node.c, as-node-private.h, as-problem.c, as-problem.h, as-provide.c, as-provide-private.h, as-release.c, as-release-private.h, asresources, as-screenshot.c, as-screenshot-private.h, as-store.c, as-tag.c, as-utils.c, as-utils-private.h, as-version.h, as-yaml.c, as-yaml.h] deps [glib, gdkpixbuf, libarchive, soup, yaml] mapfile appstream-glib.map vflag -Wl,--version-script,0/1.format(meson.current_source_dir(), mapfile) asglib shared_library( appstream-glib, sources, soversion : lt_current, version : lt_version, dependencies : deps, include_directories : include_directories(0/...format(meson.current_build_dir())), link_args : [-Wl,--no-undefined, vflag], link_depends : mapfile, install : true)appstream-glib.map内容为{ global: as_*; local: *; };各关键字与 Autotools 的对应关系soversion/version取代-version-infolink_args中的-Wl,--no-undefined取代-no-undefinedlink_depends : mapfile保证版本脚本变化时重新链接install : true相当于注册进lib_LTLIBRARIES。自定义目标gperf 规则 → custom_targetAutotools 用带if的生成规则调用 gperf 并追加到BUILT_SOURCESif HAVE_GPERF as-tag-private.h: as-tag.gperf $(AM_V_GEN) gperf $ $ libappstream_glib_la_SOURCES as-tag-private.h BUILT_SOURCES as-tag-private.h endifMeson 的custom_target()把命令、输入输出显式化并支持条件拼接if gperf.found() astagpriv custom_target(gperf as-tag, output : as-tag-private.h, input : as-tag.gperf, command : [gperf, INPUT, --output-file, OUTPUT]) sources sources [astagpriv] endifcommand中INPUT/OUTPUT自动展开为输入输出文件路径sources sources [astagpriv]把生成的头文件加入库源码列表与BUILT_SOURCES 等价。全局编译参数AM_CPPFLAGS → add_project_argumentsAM_CPPFLAGS \ -DAS_COMPILATION \ -DLOCALSTATEDIR\$(localstatedir)\ \ -DG_LOG_DOMAIN\As\Meson 的add_project_arguments()需要指定语言且字符串引用需按 Meson 语法书写add_project_arguments(-DG_LOG_DOMAINAs, language : c) add_project_arguments(-DAS_COMPILATION, language : c) add_project_arguments(-DLOCALSTATEDIR/var, language : c)注意LOCALSTATEDIR原本由 Autotools 从$(localstatedir)注入通常是/var迁移时需按目标系统显式确认该路径。测试check_PROGRAMS → executable testAutotools 中check_PROGRAMS声明测试程序、TESTS声明要运行的测试check_PROGRAMS \ as-self-test as_self_test_SOURCES \ as-self-test.c as_self_test_LDADD ...各依赖与库 as_self_test_CFLAGS -DTESTDATADIR\$(top_srcdir)/data/tests\ TESTS as-self-testMeson 先构建可执行文件链接被测库、注入测试数据目录宏再注册测试selftest executable( as-self-test, as-self-test.c, include_directories : include_directories(0/...format(meson.current_build_dir())), dependencies : deps, c_args : -DTESTDATADIR0/../data/tests.format(meson.current_source_dir()), link_with : asglib) test(as-self-test, selftest)test()注册后meson test命令即可运行全部测试c_args用meson.current_source_dir()动态拼接源码树下的测试数据路径替代$(top_srcdir)。GObject Introspection手写 GIR 规则 → gnome.generate_girAutotools 下 GObject Introspection 需要大量样板规则定义introspection_sources、AppStreamGlib-1.0.gir依赖、gir_INCLUDES/gir_CFLAGS/gir_SCANNERFLAGS/gir_EXPORT_PACKAGES等一堆变量还要手动把 gir/typelib 装到对应目录introspection_sources ....c/.h 列表 AppStreamGlib-1.0.gir: libappstream-glib.la AppStreamGlib_1_0_gir_INCLUDES GObject-2.0 Gio-2.0 GdkPixbuf-2.0 AppStreamGlib_1_0_gir_SCANNERFLAGS --identifier-prefixAs \ --symbol-prefixas_ \ --warn-all \ --add-include-path$(srcdir) AppStreamGlib_1_0_gir_EXPORT_PACKAGES appstream-glib ... gir_DATA $(INTROSPECTION_GIRS) typelib_DATA $(INTROSPECTION_GIRS:.gir.typelib)Meson 的gnome.generate_gir()封装了 scanner 与 typelib 编译器introspection_sources [ as-app.c, as-app-validate.c, as-app.h, as-bundle.c, as-bundle.h, as-enums.c, as-enums.h, as-icon.c, as-icon.h, as-image.c, as-image.h, as-inf.c, as-inf.h, as-node.c, as-node.h, as-problem.c, as-problem.h, as-provide.c, as-provide.h, as-release.c, as-release.h, as-screenshot.c, as-screenshot.h, as-store.c, as-store.h, as-tag.c, as-tag.h, as-utils.c, as-utils.h, as-version.h] gnome.generate_gir(asglib, sources : introspection_sources, nsversion : 1.0, namespace : AppStreamGlib, symbol_prefix : as_, identifier_prefix : As, export_packages : appstream-glib, includes : [GObject-2.0, Gio-2.0, GdkPixbuf-2.0], install : true )generate_gir的实现在 mesonbuild/modules/gnome.py从源码可见其自动完成为项目补 C 编译器、查找g-ir-scanner与g-ir-compiler、把namespace/nsversion拼为--namespace/--nsversion、symbol_prefix/identifier_prefix/export_packages分别对应 scanner 的三个标志includes负责解析依赖 GIR 的搜索路径。相比 Autotools 手写的十余行模板Meson 一次调用同时产出.gir与.typelib并处理安装。GSettingsGSETTINGS_RULES → install_data 安装脚本Autotools 中先要在configure.ac调用GLIB_GSETTINGS再在Makefile.am用GSETTINGS_RULES模板展开 schema 的编译与安装规则GLIB_GSETTINGSgsettings_SCHEMAS foo.gschema.xml GSETTINGS_RULESMeson 的做法更直接把 schema 当作普通数据安装再用add_install_script()挂一个安装后脚本执行glib-compile-schemasinstall_data(foo.gschema.xml, install_dir: get_option(datadir) / glib-2.0 / schemas) meson.add_install_script(meson_post_install.py)meson_post_install.py#!/usr/bin/env python3 import os import subprocess schemadir os.path.join(os.environ[MESON_INSTALL_PREFIX], share, glib-2.0, schemas) if not os.environ.get(DESTDIR): print(Compiling gsettings schemas...) subprocess.call([glib-compile-schemas, schemadir])脚本中通过MESON_INSTALL_PREFIX环境变量定位安装前缀并用DESTDIR判断是否处于打包阶段打包时不编译 schema避免污染暂存目录。除了这种手写方式gnome模块也提供compile_schemas()封装见 mesonbuild/modules/gnome.py作为替代。gettext / i18nmsgfmt 规则 → i18n 模块本例不涉及intltool用法。Autotools 侧需要AM_GNU_GETTEXT、GETTEXT_PACKAGE宏、po/Makevars中一堆XGETTEXT_OPTIONS以及Makefile.am里%.desktop、%.appdata.xml两条调用MSGFMT的模式规则AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.19.7]) GETTEXT_PACKAGEfoo AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, $GETTEXT_PACKAGE, [The prefix for our gettext translation domains.])XGETTEXT_OPTIONS --from-codeUTF-8 --keyword_ --keywordN_ --keywordC_:1c,2 --keywordNC_:1c,2 --keywordg_dngettext:2,3 --add-comments%.desktop: %.desktop.in $(AM_V_GEN)$(MSGFMT) --desktop --template $ -d $(top_srcdir)/po -o $ %.appdata.xml: %.appdata.xml.in $(AM_V_GEN)$(MSGFMT) --xml --template $ -d $(top_srcdir)/po -o $Meson 用i18n模块统一处理。先在顶层meson.build导入模块、定义包名、声明宏并进入po子目录然后对每个需要翻译合并的文件调用i18n.merge_file()i18n import(i18n) gettext_package foo add_project_arguments(-DGETTEXT_PACKAGE gettext_package, language: c) subdir(po) i18n.merge_file( input: foo.desktop.in, output: foo.desktop, type: desktop, po_dir: po, install: true, install_dir: get_option(datadir) / applications ) i18n.merge_file( input: foo.appdata.xml.in, output: foo.appdata.xml, po_dir: po, install: true, install_dir: get_option(datadir) / appdata )po/meson.build中则声明 POT 生成与更新规则i18n.gettext(gettext_package, preset: glib)merge_file与gettext的实现位于 mesonbuild/modules/i18n.py 与 mesonbuild/modules/i18n.py。从源码可以确认type参数决定底层调用msgfmt --desktop还是msgfmt --xml对应 Autotools 的两条模式规则gettext()的preset参数如glib会从预置表展开一组常用的 xgettext 参数再与用户传入的extra_args合并去重见 mesonbuild/modules/i18n.py替代po/Makevars中的XGETTEXT_OPTIONS。迁移要点速查Autotools 机制Meson 对应写法备注AC_PREREQ忽略无对应概念AC_INITAC_PROG_CCproject()首行声明编译器自动探测AC_SUBST不需要单一构建描述文件AC_CONFIG_HEADERSconfiguration_data()configure_file()需手工conf.set*()AC_PATH_PROGfind_program(..., required : false)配合found()条件PKG_CHECK_MODULESdependency()统一依赖入口AC_ARG_ENABLEmeson.options声明 get_option()声明与使用解耦SUBDIRSsubdir()*CLEANFILES/EXTRA_DIST不需要build 目录隔离、git archive打包glib-compile-resources规则gnome.compile_resources()自动跟踪依赖include_HEADERSinstall_headers(headers, subdir : ...)lib_LTLIBRARIES全家桶shared_library() 版本脚本soversion/version/link_argsif HAVE_XXX生成规则custom_target() 条件拼接INPUT/OUTPUT展开AM_CPPFLAGSadd_project_arguments(..., language : ...)需逐语言声明check_PROGRAMSTESTSexecutable()test()meson test运行GIR/typelib 模板规则gnome.generate_gir()一次调用完成扫描与编译GLIB_GSETTINGSGSETTINGS_RULESinstall_data()add_install_script()或gnome.compile_schemas()AM_GNU_GETTEXTMSGFMT规则i18n模块merge_file/gettextpreset: glib覆盖常用参数结语从configure.ac的探测逻辑到Makefile.am的构建规则本指南以 AppStream-glib 为完整样例给出了逐条对照。整体思路可以概括为探测逻辑头文件、函数、程序、依赖、选项收敛到find_program()/dependency()/get_option()等少数统一 API生成规则资源、gperf、GIR、翻译文件由各功能模块gnome、i18n封装清理与分发则借助 build 目录隔离和版本控制天然消除。迁移前先用 tools/ac_converter.py 处理config.h.meson中的基础探测再按本对照表逐节替换configure.ac与Makefile.am即可得到一份声明式、可读性更高的 Meson 构建系统。赞分享构建工具【免费下载链接】mesonThe Meson Build System项目地址https://gitcode.com/gh_mirrors/me/meson点击查看免费下载相关推荐VLC 构建系统指南从 Autotools 到 Meson 迁移的完整实战解析VLC 构建系统指南从 Autotools 到 Meson 迁移的完整实战解析 VLCVideoLAN Client是一个庞大的多媒体项目其构建系统同时音视频Meson 构建系统转换器实战从 CMake 与 Autotools 平滑迁移到 MesonMeson 构建系统转换器实战从 CMake 与 Autotools 平滑迁移到 Meson 本文聚焦 Meson 源码树中自带的两个构建系统转换脚本——面向构建工具Kata Containers 配置迁移实战从 Go Runtime 到 runtime-rs 的 QEMU 配置完整对照与移植指南Kata Containers 配置迁移实战从 Go Runtime 到 runtime rs 的 QEMU 配置完整对照与移植指南 Kata Contain云原生容器运行时上一篇S905L3设备Armbian启动失败深度解析三阶段修复法解决电视盒子启动故障下一篇如何高效处理Zotero条目的Extra字段ExtraField工具模块深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考