在 AC_OUTPUT() 的参数中使用 PACKAGE_VERSION

Use PACKAGE_VERSION in the argument of AC_OUTPUT()

对于我缺乏使用 m4sh 的经验,我提前表示歉意。

我有一个包含以下行的 configure.ac 文件:

AC_INIT([libhelloworld], [2.5])

...

AC_OUTPUT([
Makefile
src/helloworld-${PACKAGE_VERSION}.pc
src/Makefile
])

AC_OUTPUT() 论点背后的原因是我想避免在每次更新时在多个地方复制和粘贴我的程序的新版本。因此我决定利用 PACKAGE_VERSION 宏,它在 configure.ac.

开头调用 AC_INIT() 时自动定义

src/helloworld-${PACKAGE_VERSION}.pc 然后正确地扩展为 src/helloworld-2.5.pc 并且一切似乎都工作正常。但是我有几个问题。

  1. 我用${PACKAGE_VERSION}作为一个shell变量,但是PACKAGE_VERSION本身就是一个m4宏。我可以相信这会一直有效吗?调用 AC_OUTPUT() 时是否总是这样定义?
  2. 有没有其他方法可以在configure.ac中获取PACKAGE_VERSION的值?例如,如果我在 Makefile.am 中而不是 configure.ac,我将不会使用大括号,而是使用命令评估语法,如 $(PACKAGE_VERSION) 中那样。 configure.ac 内做我想做的事情的正确方法是什么

AC_INIT 的文档指出 PACKAGE_VERSION 是一个 "output variable",这意味着当您调用 AC_INIT 时,将执行如下操作:

AC_SUBST([PACKAGE_VERSION], [2.5])

这允许 Makefile.in(从 Makefile.am 生成)等输入文件的配置依赖于这些文件中的 @PACKAGE_VERSION@2.5 替换。

如果您的方法有效,则没有任何问题,但您可以考虑使用 AS_VAR_SET([hello_version], [AC_PACKAGE_VERSION]) 在 Autoconf 输入中设置 hello_version shell 变量和 src/helloworld-${hello_version}.pc。这样,即使 Autoconf 在将来的某个版本中不再公开 PACKAGE_VERSION shell 变量,您的代码也不会中断,因为您将依赖自己的 hello_version 变量。


顺便说一句,当 helloworld 版本为 1.0 或更高版本时(即 API 稳定),使用 helloworld-2.5.pc 有点不正常。看到 helloworld.pc 很常见,除了当你发布 3.0 并将安装的 2.x 版本的 helloworld.pc 替换为 3.0 版本时会发生什么问题:假设你正在使用语义版本控制, 3.0 与 2.x 不兼容,任何依赖于 pkg-config --libs helloworld 之类的代码都会中断。

然后您可以考虑使用 helloworld-2.pc 代替,当您发布 3.0 时,您将使用 helloworld-3.pc 来避免您的库的用户链接 incorrect/incompatible 库(并且还允许用户可以选择按照自己的节奏迁移到新版本);也可以在 Automake 中将此想法应用于特定版本的头目录:

## SOURCE PATH     => INSTALL PATH
## include/hello.h => $(includedir)/helloworld-2/hello.h
helloincludedir = @includedir@/helloworld-@hello_major@
helloinclude_HEADERS = include/hello.h

Autoconf 还允许您指定输出文件的输入,因此可以从源目录中的 src/helloworld.pc.in 生成构建目录中的输出文件 src/helloworld-${hello_major}.pc,而无需更新 src/helloworld.pc.in 从 2.x 移动到 3.0 时的文件名;如果您对宏没问题,这也可以与 AC_INIT 一起使用,允许您在一个中心位置控制版本信息:

m4_define([hello_version_major], [2]) dnl
m4_define([hello_version_minor], [5]) dnl
m4_define([hello_version], [hello_version_major[.]hello_version_minor]) dnl
AC_PREREQ([2.69])
AC_INIT([libhelloworld], [hello_version])
AS_VAR_SET([hello_major], [hello_version_major])
AS_VAR_SET([hello_minor], [hello_version_minor])
# For automake and configuration of pkg-config file
AC_SUBST([hello_major])
AC_SUBST([hello_minor])
AC_SUBST([hello_version])
...
AC_CONFIG_FILES([
    Makefile
    src/Makefile
    src/helloworld-]hello_version_major[.pc:src/helloworld.pc.in
])
AC_OUTPUT

我意识到它看起来比人们想象的要复杂得多,但这就是适合您的 Autoconf。请注意,我不得不在 AC_CONFIG_FILES 中使用一些奇怪的引号来使用宏。使用

src/helloworld-${hello_major}.pc:src/helloworld.pc.in

而不是宏导致在 Autoconf 2.69 中生成了一个残缺的 config.status 文件(尝试不带参数的 config.status,然后 config.status src/helloworld-2.pc 以查看问题);我没有测试过任何其他版本。我已经报告了这个错误,但宏在下一个版本之前一直有效。