由于某些原因,我在纯文本文件而不是configure.ac中定义项目版本号。我想创建一个语句来读取版本号并在编译期间存储它。
现在我的configure.ac看起来像这样:
AC_INIT([my program],[999.9.9])
我希望有类似的东西:
AC_INIT([my program],[ $(cat VERSION) ])
这当然不会工作。这里的诀窍是什么? (我知道我失去了一些便携性 - 我现在不在乎)。谢谢!
尝试:
AC_INIT([my program], m4_esyscmd([tr -d '\n' < VERSION]))
编辑了评论中建议的修复程序。
我还能够使用以下方法删除不可移植的tr
调用:
AC_INIT([my program], [m4_translit(m4_esyscmd([cat VERSION]),m4_newline)])
这似乎同样有效,恩里科在下面的评论中提出的解决方案也是如此:
AC_INIT([my program], [m4_esyscmd_s([cat VERSION])])
您可以简单地使用原生宏m4_include()
(而不是按照ldav1s的建议通过tr
调用cat
或m4_esyscmd_s()
),
AC_INIT([foo], m4_normalize(m4_include([VERSION])))
这也是GNU M4 qazxsw poi针对类似案例的官方指南:
suggests[…]
$ cat examples/incl.m4 ⇒Include file start ⇒foo ⇒Include file end
和include
扩展到文件内容的事实可用于定义对整个文件进行操作的宏。这是一个例子,它定义'sinclude
'以扩展到bar
的内容:incl.m4
GNU M4还提供$ m4 -I examples
define(`bar', include(`incl.m4'))
⇒
This is `bar': >>bar<<
⇒This is bar: >>Include file start
⇒foo
⇒Include file end
⇒<<
,因此如果您想确保版本字符串始终遵循特定模式 - 或者如果support for regular expressions文件包含的文本多于版本字符串 - 您可以使用VERSION
查找您要查找的内容:
m4_bregexp()
这也是最安全的方法,因为如果在AC_INIT([foo], m4_bregexp(m4_include([VERSION]), [[0-9]+\.[0-9]+\.[0-9]+], [\&]))
文件中找不到上面的正则表达式,VERSION
的第二个参数只会扩展为空字符串,并且Autoconf会抛出以下错误消息:
AC_INIT()
调用error: AC_INIT should be called with package and version arguments
来处理m4_bregexp()
文件内容有用的典型情况是,当它包含三个数字版本字符串(VERSION
)时,你只想要一个两个数字的字符串(MAJOR.MINOR.REVISION
)作为你的扩展MAJOR.MINOR
宏。
如果您熟悉正则表达式并捕获括号,并且希望能够执行更复杂的任务,那么我已经编写了这个通用的可变参数宏(您可以将其粘贴到AC_PACKAGE_VERSION
的开头),
configure.ac
可以用来做:
dnl NA_DEFINE_SUBSTRINGS_AS(string, regexp, macro0[, macro1[, ... macroN ]])
dnl ***************************************************************************
dnl
dnl Searches for the first match of `regexp` in `string`. For both the entire
dnl regular expression `regexp` (`\0`) and each sub-expression within capturing
dnl parentheses (`\1`, `\2`, `\3`, ... , `\N`) a macro expanding to the
dnl corresponding matching text will be created, named according to the
dnl argument `macroN` passed. If a `macroN` argument is omitted or empty, the
dnl corresponding parentheses in the regular expression will be considered as
dnl non-capturing. If `regexp` cannot be found in `string` no macro will be
dnl defined. If `regexp` can be found but some of its capturing parentheses
dnl cannot, the macro(s) corresponding to the latter will be defined as empty
dnl strings.
dnl
dnl Source: https://github.com/madmurphy/not-autotools
dnl
dnl ***************************************************************************
AC_DEFUN([NA_DEFINE_SUBSTRINGS_AS], [
m4_if(m4_eval([$# > 2]), [1], [
m4_if(m4_normalize(m4_argn([$#], $*)), [], [],
[m4_bregexp([$1], [$2], [m4_define(m4_normalize(m4_argn([$#], $*)), \]m4_if([$#], [3], [&], m4_eval([$# - 3]))[)])])
m4_if(m4_eval([$# > 3]), [1], [NA_DEFINE_SUBSTRINGS_AS(m4_reverse(m4_shift(m4_reverse($@))))])
])
])
所以宏NA_DEFINE_SUBSTRINGS_AS(
m4_include([VERSION]),
[\([0-9]+\)\s*\.\s*\([0-9]+\)\s*\.\s*\([0-9]+\)],
[FOO_VERSION_STRING], [FOO_VERSION_MAJOR], [FOO_VERSION_MINOR], [FOO_VERSION_REVISION]
)
AC_INIT([foo], FOO_VERSION_MAJOR[.]FOO_VERSION_MINOR[.]FOO_VERSION_REVISION)
,FOO_VERSION_MAJOR
和FOO_VERSION_MINOR
总是在FOO_VERSION_REVISION
内可用。
注意:
configure.ac
宏名称中的NA_
前缀代表“Not Autotools”。
如果在NA_DEFINE_SUBSTRINGS_AS()
文件中找不到上面的正则表达式,VERSION
安全地不会定义相应的宏名称。这允许为此特定情况生成错误(必须在NA_DEFINE_SUBSTRINGS_AS()
之后立即粘贴以下行):
AC_INIT()
因为它可以看起来像读取一个简单的m4_ifndef([FOO_VERSION_STRING], [AC_MSG_ERROR([invalid version format in `VERSION` file])])
文件一样微不足道,如果你想从VERSION
文件中检索版本字符串,事情变得更加棘手。在这里,package.json
宏可以派上用场:
NA_DEFINE_SUBSTRINGS_AS()
注意:
NA_DEFINE_SUBSTRINGS_AS( m4_join([|], m4_unquote(m4_include([package.json]))), ["?version"?:\s*"?\s*\(\([0-9]+\)\s*\.\s*\([0-9]+\)\s*\.\s*\([0-9]+\)\)\s*"?], [JSON_ENTRY], [FOO_VERSION_STRING], [FOO_VERSION_MAJOR], [FOO_VERSION_MINOR], [FOO_VERSION_REVISION] ) AC_INIT([foo], FOO_VERSION_MAJOR[.]FOO_VERSION_MINOR[.]FOO_VERSION_REVISION)
文件可能包含逗号和方括号(对GNU m4-ish不太友好),在处理JSON字符串之前需要删除/替换这些文件。在上面的代码中,宏.json
删除了m4_unquote()
中可能存在的所有第一级方括号 - 如果后者包含嵌套数组,则package.json
必须在数组嵌套的最大级别上调用多次 - 然后宏m4_unquote()
替换所有逗号与m4_join()
。
'|'
宏也接受空参数,所以如果你愿意,你可以用NA_DEFINE_SUBSTRINGS_AS()
替换[JSON_ENTRY]
参数,因为你可能永远不会使用JSON源字符串[]
。
如果您只需要从"version": "999.9.9"
文件中检索完整版本字符串,但不需要使用package.json
,FOO_VERSION_MAJOR
和FOO_VERSION_MINOR
,则可以删除上面正则表达式中的一些捕获括号,如下例所示:
FOO_VERSION_REVISION
为了完整性,由于最后一个示例只有一个要捕获的字符串,因此也可以在不使用NA_DEFINE_SUBSTRINGS_AS(
m4_join([|], m4_unquote(m4_include([package.json]))),
["?version"?:\s*"?\s*\([0-9]+\.[0-9]+\.[0-9]+\)\s*"?],
[], [FOO_VERSION_STRING]
)
AC_INIT([foo], FOO_VERSION_STRING)
的情况下重写它:
NA_DEFINE_SUBSTRINGS_AS()