Считать номер версии из файла в configure.ac - PullRequest
11 голосов
/ 19 декабря 2011

Я по некоторым причинам определяю номер версии своего проекта в текстовом файле вместо configure.ac. Я хотел бы создать оператор, который будет читать номер версии и сохранять его во время компиляции.

Прямо сейчас мой файл configure.ac выглядит следующим образом:

AC_INIT([my program],[999.9.9])

Я бы хотел что-то вроде:

AC_INIT([my program],[ $(cat VERSION) ])

Это не сработает, конечно. В чем тут подвох? (Я знаю, что теряю некоторую мобильность - мне сейчас все равно). Спасибо!

Ответы [ 2 ]

22 голосов
/ 20 декабря 2011

Попробуйте:

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])])
1 голос
/ 30 марта 2019

Вы можете просто использовать собственный макрос 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]))
...