我如何优雅地更新 autoconf 中的版本字符串,例如手册页和其他非源文档?
How can I elegantly update the version string from autoconf in things like the man page and other non-source documents?
随着xnec2c项目的发展,似乎需要修改越来越多的文件来更新它的版本。目前它看起来像这样:
- 更新 AC_INIT 版本
- 更新 doc/xnec2c.1 中的手册页版本
- 为 RPM 构建更新打包的 .spec 文件中的版本
- 使用变更日志和注释更新 doc/xnec2c。html。
- 带有发布消息和版本信息的最终发布提交
- 将标签推送到 github
- 利润。 (好吧,真的是劳动或爱情,收益是开发的乐趣!)
我可以编写一个 shell 脚本来破解这些每次我修改版本时的问题,但肯定这之前已经解决了!
有没有更优雅的方式?
您可以编写制作方法(基本上是 shell 脚本),通过调用或多或少常用的工具从可用信息构建所需的文件。
让我们从简单的内容开始,例如手册页中的版本号。
dnl configure.ac snippet
AC_PROG_SED
您将手册页文件 doc/xnec2c.1
重命名为 doc/xnec2c.1in
,以便 运行ning make 可以构建一个 doc/xnec2c.1
手册页,并将正确的版本号替换为:
.\" doc/xnec2c.1in man page snippet
This is the man page for xnec2c version @PACKAGE_VERSION@.
dnl Makefile.am or Makefile-files snippet
EXTRA_DIST += doc/xnec2c.1in
CLEANFILES += doc/xnec2c.1
man1_DATA += doc/xnec2c.1
SED_REPLACEMENTS += -e 's|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g'
.1in.1:
@$(MKDIR_P) $(@D) ||:
$(SED) $(SED_REPLACEMENTS) < $< > $@
这是入门的基本方法。它仍然存在的一些问题:
您需要先在代码段上方的某处定义变量,然后才能 +=
添加到它们(CLEANFILES =
,等等)。我非常喜欢 +=
定义变量的方式,因为这使得添加或删除诸如从 doc/xnec2c.1in
生成 doc/xnec2c.1
之类的东西的差异更容易阅读。
当您将无效的 sed 命令放入 SED_REPLACEMENTS
时,运行ning sed 将失败并留下一个空的 doc/xnec2c.1
文件。下一个 make 运行 然后看到比 doc/xnec2c.1in
更新的空文件,跳过重建 doc/xnec2c.1
,导致明显成功的构建将一个空文件作为手册页发送。
生成的文件可能包含您忘记添加到 SED_REPLACMENTS
变量的 @FOOBAR@
模式,您可以使用 grep 和适当的正则表达式检测到它。
您可能希望使用更通用的后缀模式进行替换以允许例如将 *.1.in
替换为 *.1
,将 *.spec.in
替换为 *.spec
,等等。使用类似 %: %.in
的模式用于 GNU make 在这里可以工作,但不是可移植的 make。 (我不记得 .in:
是否是为所有可能情况编写 %: %.in
的可移植方式。)
然后就是要不要对生成的文件进行版本控制的问题。对于可以通过非常标准的工具(如 sed)完成的简单替换,您可以期望用户可以使用该工具并进行构建。您可能不想要求您的用户需要一个很少使用的工具,因此选择将构建的结果置于版本控制之下。我通常在用户系统上需要工具方面犯错误,因此告诉我的版本控制系统忽略生成的文件,因为我不想处理由于我编辑另一个源代码控制文件而导致的源代码控制文件更改。
# .gitignore snippet
/doc/xnec2c.1
所以,现在我们开始将变更日志替换为 HTML 文件。这现在变得任意复杂,具体取决于您的更改日志的格式和存储位置,以及您希望如何将其转换为 HTML.
我个人喜欢将 README
之类的文本文档编写为 README.md
markdown 文件,因为 github.com 可以很好地呈现 HTML,所以我将更改日志保存在一个 NEWS.md
文件。 NEWS.md
文件的(部分)可以替换为从 doc/xnec2c.md.in
生成的 doc/xnec2c.md
文件,然后使用 .md
转换为 .html
markdown
工具.
然后您需要 configure.ac
检查是否存在并要求用户安装 markdown
,或者将生成的 doc/xnec2c.md
文件添加到 git 索引,然后处理 git 突然注意到更改的文件只是因为您更改了 AC_INIT
.
中的版本号
您还可以依赖 git 标签的版本信息,并使用 shell 脚本从 git 标签生成 AC_INIT
版本号,方法是使用 m4_esyscmd
m4宏。然而,这带来了它自己的一系列优点和缺点,并且可能有点超出了这个问题的范围。不过,最后 some 文件毕竟应该直接包含版本号,例如一个 NEWS
或 NEWS.md
文件,详细说明与上一版本相比用户可见的更改,因为您希望该文件在 github.com 和 dist tarball 中显示正确的信息。所以总会有 some 工作来更新 some 文件中的版本号。
自动一致性检查在这里很有用,可以连接到 all-local
或 check-local
目标,或者作为单独的 shell 脚本编写,添加到 TESTS
。
在我在 github.com 上的几个项目中,我使用 markdown 格式的用户更新日志 NEWS.md
的第一部分作为 github 发行说明,通常没有更改。
可能有更优雅的方法,但在类似情况下,有一些方法对我有用。但是,有些东西 总是 有用:记录发布过程中的每个步骤,以便您下次需要时只需阅读步骤列表,而无需记住其中的所有细节你的头。
我希望这会有所帮助,即使它在所有方面可能都不是非常普遍的最佳实践。
随着xnec2c项目的发展,似乎需要修改越来越多的文件来更新它的版本。目前它看起来像这样:
- 更新 AC_INIT 版本
- 更新 doc/xnec2c.1 中的手册页版本
- 为 RPM 构建更新打包的 .spec 文件中的版本
- 使用变更日志和注释更新 doc/xnec2c。html。
- 带有发布消息和版本信息的最终发布提交
- 将标签推送到 github
- 利润。 (好吧,真的是劳动或爱情,收益是开发的乐趣!)
我可以编写一个 shell 脚本来破解这些每次我修改版本时的问题,但肯定这之前已经解决了!
有没有更优雅的方式?
您可以编写制作方法(基本上是 shell 脚本),通过调用或多或少常用的工具从可用信息构建所需的文件。
让我们从简单的内容开始,例如手册页中的版本号。
dnl configure.ac snippet
AC_PROG_SED
您将手册页文件 doc/xnec2c.1
重命名为 doc/xnec2c.1in
,以便 运行ning make 可以构建一个 doc/xnec2c.1
手册页,并将正确的版本号替换为:
.\" doc/xnec2c.1in man page snippet
This is the man page for xnec2c version @PACKAGE_VERSION@.
dnl Makefile.am or Makefile-files snippet
EXTRA_DIST += doc/xnec2c.1in
CLEANFILES += doc/xnec2c.1
man1_DATA += doc/xnec2c.1
SED_REPLACEMENTS += -e 's|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g'
.1in.1:
@$(MKDIR_P) $(@D) ||:
$(SED) $(SED_REPLACEMENTS) < $< > $@
这是入门的基本方法。它仍然存在的一些问题:
您需要先在代码段上方的某处定义变量,然后才能
+=
添加到它们(CLEANFILES =
,等等)。我非常喜欢+=
定义变量的方式,因为这使得添加或删除诸如从doc/xnec2c.1in
生成doc/xnec2c.1
之类的东西的差异更容易阅读。当您将无效的 sed 命令放入
SED_REPLACEMENTS
时,运行ning sed 将失败并留下一个空的doc/xnec2c.1
文件。下一个 make 运行 然后看到比doc/xnec2c.1in
更新的空文件,跳过重建doc/xnec2c.1
,导致明显成功的构建将一个空文件作为手册页发送。生成的文件可能包含您忘记添加到
SED_REPLACMENTS
变量的@FOOBAR@
模式,您可以使用 grep 和适当的正则表达式检测到它。您可能希望使用更通用的后缀模式进行替换以允许例如将
*.1.in
替换为*.1
,将*.spec.in
替换为*.spec
,等等。使用类似%: %.in
的模式用于 GNU make 在这里可以工作,但不是可移植的 make。 (我不记得.in:
是否是为所有可能情况编写%: %.in
的可移植方式。)
然后就是要不要对生成的文件进行版本控制的问题。对于可以通过非常标准的工具(如 sed)完成的简单替换,您可以期望用户可以使用该工具并进行构建。您可能不想要求您的用户需要一个很少使用的工具,因此选择将构建的结果置于版本控制之下。我通常在用户系统上需要工具方面犯错误,因此告诉我的版本控制系统忽略生成的文件,因为我不想处理由于我编辑另一个源代码控制文件而导致的源代码控制文件更改。
# .gitignore snippet
/doc/xnec2c.1
所以,现在我们开始将变更日志替换为 HTML 文件。这现在变得任意复杂,具体取决于您的更改日志的格式和存储位置,以及您希望如何将其转换为 HTML.
我个人喜欢将 README
之类的文本文档编写为 README.md
markdown 文件,因为 github.com 可以很好地呈现 HTML,所以我将更改日志保存在一个 NEWS.md
文件。 NEWS.md
文件的(部分)可以替换为从 doc/xnec2c.md.in
生成的 doc/xnec2c.md
文件,然后使用 .md
转换为 .html
markdown
工具.
然后您需要 configure.ac
检查是否存在并要求用户安装 markdown
,或者将生成的 doc/xnec2c.md
文件添加到 git 索引,然后处理 git 突然注意到更改的文件只是因为您更改了 AC_INIT
.
您还可以依赖 git 标签的版本信息,并使用 shell 脚本从 git 标签生成 AC_INIT
版本号,方法是使用 m4_esyscmd
m4宏。然而,这带来了它自己的一系列优点和缺点,并且可能有点超出了这个问题的范围。不过,最后 some 文件毕竟应该直接包含版本号,例如一个 NEWS
或 NEWS.md
文件,详细说明与上一版本相比用户可见的更改,因为您希望该文件在 github.com 和 dist tarball 中显示正确的信息。所以总会有 some 工作来更新 some 文件中的版本号。
自动一致性检查在这里很有用,可以连接到 all-local
或 check-local
目标,或者作为单独的 shell 脚本编写,添加到 TESTS
。
在我在 github.com 上的几个项目中,我使用 markdown 格式的用户更新日志 NEWS.md
的第一部分作为 github 发行说明,通常没有更改。
可能有更优雅的方法,但在类似情况下,有一些方法对我有用。但是,有些东西 总是 有用:记录发布过程中的每个步骤,以便您下次需要时只需阅读步骤列表,而无需记住其中的所有细节你的头。
我希望这会有所帮助,即使它在所有方面可能都不是非常普遍的最佳实践。