Я определяю номер своей версии проекта в текстовом файле вместо configure.ac по некоторым причинам. Я хотел бы создать инструкцию, которая будет читать номер версии и хранить ее во время компиляции.
Конечно, эта работа не будет. Что это за трюк? (Я знаю, что теряю некоторую мобильность - на данный момент меня это не волнует). Спасибо!
Ответ 2
Вы можете просто использовать собственный макрос m4_include()
(вместо того, чтобы m4_esyscmd_s()
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()
чтобы найти то, что вы ищем:
AC_INIT([foo], m4_bregexp(m4_include([VERSION]), [[0-9]+\.[0-9]+\.[0-9]+], [\&]))
Это также самый безопасный подход, поскольку если регулярное выражение выше не может быть найдено в файле VERSION
второй аргумент AC_INIT()
просто раскрывается в пустую строку, и 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([email protected]))))])
])
])
который можно использовать для выполнения:
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()
макроса NA_DEFINE_SUBSTRINGS_AS()
означает " N o 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
могут содержать запятые и квадратные скобки (которые не очень .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
, вы можете избавиться от некоторых скобок в регулярном выражении, описанном выше, как 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]))