【问题标题】:How can I use AC_REVISION with Git?如何在 Git 中使用 AC_REVISION?
【发布时间】:2012-01-03 04:28:31
【问题描述】:

在使用Subversion 管理的项目中使用Autoconf 时,我会将这段代码放在configure.ac 中:

AC_REVISION($Revision: 1234 $)

对于svn:keywords RevisionAC_REVISION 会将configure.ac 的修订号插入到生成的configure 脚本中。

如何在使用Git 管理的项目中做类似的事情?

Git 没有像$Revision$ 这样的关键字,也没有这样的修订号。但它确实有用于提交的 SHA1 和 git describe。我只是不确定如何将其合并到configure.ac

【问题讨论】:

  • 如果您使用的是类 unix 系统,您可以编写一个 git-hook 来执行 sed -i 's/\$Revision/$REVISION/g' configure.ac(只是一个示例)。如果您愿意,$REVISION 变量可能包含git describe 的结果。听起来有道理?否则,您可能会使用$Id:$,它将被替换为 blob 的 sha1(而不是提交)。请参阅[此问题] (stackoverflow.com/questions/384108/…)。
  • 使用分布式 SCM 时另请阅读 why this is not a good idea
  • @jweyrich, AC_REVISION 是一个仅供内部使用的版本字符串(即它出现在生成的configure 脚本的源代码中,但不会显示给用户)。为此使用提交的 SHA1 没有任何问题。

标签: git autoconf


【解决方案1】:

当 Autoconf 运行时,您实际上可以使用 M4 执行任何命令。因此,也许你想要这样的东西:

AC_REVISION([m4_esyscmd_s([git describe --always])])

请注意,与$Revision$ 字符串不同,您的configure.ac 不会在您每次更新树时更改。因此configure 不会在每次更新后重新生成,而放入configure 的修订版将只是生成configure 的最后一个版本。

【讨论】:

    【解决方案2】:

    adl's answer 不是我想要的,但它为我指明了正确的方向。这是我想出的:

    把这个放到configure.ac:

    AC_REVISION([m4_esyscmd([./tools/configure.commit])])
    

    将其保存为tools/configure.commit(并使其可执行):

    #! /bin/sh
    # Display the SHA1 of the commit in which configure.ac was last modified.
    # If it's not checked in yet, use the SHA1 of HEAD plus -dirty.
    
    if [ ! -d .git ] ; then
      # if no .git directory, assume they're not using Git
      printf 'unknown commit'
    elif git diff --quiet HEAD -- configure.ac ; then
      # configure.ac is not modified
      printf 'commit %s' `git rev-list --max-count=1 HEAD -- configure.ac`
    else # configure.ac is modified
      printf 'commit %s-dirty' `git rev-parse HEAD`
    fi
    

    该组合会将上次修改configure.ac 的提交的SHA-1 放入configure,这正是我要寻找的。但是有一个问题。 Git 在提交文件时不会触及文件的修改时间。这意味着configure 将继续包含OLDSHA-dirty 值而不是被更新,因为autoconf 不会意识到它已经过时了。

    您可以使用 post-commit 挂钩来解决这个问题。将此保存为.git/hooks/post-commit(并确保您将chmod 设置为可执行文件,否则将无法运行):

    #!/bin/sh
    #
    # Copy this to .git/hooks/post-commit
    
    # If configure.ac was just checked in, touch it,
    # so that configure will be regenerated and
    # AC_REVISION will reflect the new commit.
    #
    # For some reason, --quiet isn't actually quiet,
    # so redirect output to /dev/null
    
    git diff-tree --quiet HEAD -- configure.ac >/dev/null \
     || touch -c configure.ac
    

    【讨论】:

      【解决方案3】:

      我试图实现与 OP 类似的东西;我想在 Postgres 版本字符串中嵌入 Git commit-id。 Postgres 的 configure.in 中的代码,在我打算修改的同一行中,已经有一个示例。

      它的要点是您可以将 shell sn-p 嵌入到 configure.in 的字符串文字中,并且生成的 configure 文件(实际上是执行 shell 脚本的 shell)将始终执行该 shell sn-p 到构建结果字符串。

      请参阅patch。以下是 configure.in 的补丁程序以及生成的 configure 文件中的相关部分。

      AC_DEFINE_UNQUOTED(PG_VERSION_STR,
      -                   ["PostgreSQL $PACKAGE_VERSION on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"],
      +                   ["PostgreSQL $PACKAGE_VERSION (commit `cd $srcdir && git log -1 --format=format:%h`) on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"],
                          [A string containing the version number, platform, and C compiler])
      

      生成的configure 代码:

       cat >>confdefs.h <<_ACEOF
      -#define PG_VERSION_STR "PostgreSQL $PACKAGE_VERSION on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"
      +#define PG_VERSION_STR "PostgreSQL $PACKAGE_VERSION (commit `cd $srcdir && git log -1 --format=format:%h`) on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"
       _ACEOF
      

      补丁前后的Postgres版本字符串:

      PostgreSQL 9.3.0 on x86_64-unknown-linux-gnu, compiled by  ...
      PostgreSQL 9.3.0 (commit 2cf9dac) on x86_64-unknown-linux-gnu, compiled by ...
      

      【讨论】:

      • 这个补丁的最大问题是你不能再make dist,因为你的configure脚本假设它在一个Git repo中运行。如果有人解压压缩包并运行./configure,他们会得到一个看起来很奇怪的版本字符串。
      • 一般方法可以工作,但您需要更复杂的 shell 代码来处理“不是 Git repo”的情况。我建议让make dist 在压缩包中生成一个 gitrevision 文件,如果$srcdir/.git 不存在,则从中读取提交。
      • 附带说明,这并不能解决完全相同的问题。我正在尝试记录configure 脚本的版本,而您正在尝试记录正在配置的代码的版本。这就是为什么我的解决方案在autoconf 时间运行,而你的解决方案在configure 时间运行。
      • 我同意这个嵌入式脚本需要更多的爱来涵盖所有情况(脏树、Git 存储库信息不可用等)。请注意,当前目录中没有 .git 目录。 Git 命令遍历目录树,直到找到一个;因此,如果项目代码被提取到 Git 管理的 $HOME 中,那么git log 将返回该上层目录的信息(另一种情况是我的迷你补丁无法解决,这在您的提案中不是问题)。我想以这个补丁的形式记录它,以便人们可以在它适用于他们的情况下使用这种技术。
      【解决方案4】:

      已建立的 git autoconf 解决方案是使用build-aux/git-version-gen, 见例如。 https://github.com/kergoth/autoconf/blob/master/build-aux/git-version-gen

      然后您只需要确保您的标签使用与版本相同的前缀(即v)。

      AC_INIT([GNU project], m4_esyscmd([build-aux/git-version-gen .tarball-version]), [bug-project@example])

      这适用于 git 和非 git 版本,其中.version 跟踪 .git 开发版本,.tarball-version 跟踪非 git 版本。

      【讨论】:

      • 我只能在第一次使用时让它工作......在干净的结帐时效果很好,但我找不到一致的方法来在每次提交时更新它。即使触摸 configure.ac 并手动重新运行 ./configure 也不会更新。
      • 我应该将git-version-gen 的副本提交到我的存储库中,还是应该添加某种提供此文件的构建时间依赖项?
      【解决方案5】:

      Git 有类似的东西,但你必须通过.gitattributes 文件为相关路径专门启用它。

         ident
             When the attribute ident is set for a path, git replaces $Id$ in
             the blob object with $Id:, followed by the 40-character hexadecimal
             blob object name, followed by a dollar sign $ upon checkout. Any
             byte sequence that begins with $Id: and ends with $ in the worktree
             file is replaced with $Id$ upon check-in.
      

      【讨论】:

      • 我不确定 blob 的 SHA1 会有多大用处。给定 blob 的 SHA1,如何找到包含它的提交?我更喜欢git describe
      【解决方案6】:

      【讨论】:

        猜你喜欢
        • 2011-09-06
        • 2011-07-04
        • 1970-01-01
        • 2014-08-31
        • 2021-01-30
        • 2011-12-08
        • 2012-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多