Вы можете просто использовать собственный макрос m4_include()
(вместо вызова tr
или cat
через m4_esyscmd_s()
, как предложено ldav1s ),
AC_INIT([foo], m4_normalize(m4_include([VERSION])))
, которыйэто также то, что официальный справочник GNU M4 предлагает для подобных случаев:
$ cat examples/incl.m4
⇒Include file start
⇒foo
⇒Include file end
[…]
Тот факт, чтоinclude
и sinclude
раскрыть содержимое файла можно использовать для определения макросов, которые работают с целыми файлами.Вот пример, который определяет 'bar
' для расширения до содержания incl.m4
:
$ m4 -I examples
define(`bar', include(`incl.m4'))
⇒
This is `bar': >>bar<<
⇒This is bar: >>Include file start
⇒foo
⇒Include file end
⇒<<
GNU M4 предлагает также поддержку для обычноговыражений , поэтому, если вы хотите убедиться, что строка версии всегда следует определенному шаблону - или если файл VERSION
содержит больше текста, чем просто строка версии - вы можете использовать m4_bregexp()
, чтобы найти то, что вы ищетеfor:
AC_INIT([foo], m4_bregexp(m4_include([VERSION]), [[0-9]+\.[0-9]+\.[0-9]+], [\&]))
Это также самый безопасный подход, поскольку если регулярное выражение, указанное выше, не может быть найдено в файле VERSION
, второй аргумент AC_INIT()
просто раскрывается в пустую строку и следующая ошибка Autoconf выдает сообщение:
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_
в имени макроса NA_DEFINE_SUBSTRINGS_AS()
означает « N ot A utotools».
Если приведенное выше регулярное выражение не может бытьнайденный в файле 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)
Примечание: * .json
файлы могут содержать запятые и квадратные скобки (которые не очень удобны дляGNU m4-ish ), и их необходимо удалить / заменить перед обработкой строки 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()
как:
AC_INIT([foo], m4_bregexp(m4_join([|], m4_unquote(m4_include([package.json]))), ["?version"?:\s*"?\s*\([0-9]+\.[0-9]+\.[0-9]+\)\s*"?], [\1]))