您可以将修订指示器嵌入到由已编译源代码生成的对象中的方法在很大程度上取决于您用于编译源代码的工具,当然也取决于您用于包含哪些源代码控制系统来源。前者决定了您可以做什么以及如何运行命令。后者决定了哪些信息是重要的,哪些命令提取了该信息,以及——在某种程度上——如何将这些信息嵌入到源文件中,如果可以直接完成的话。
由于您专门询问了 Git,这里有几点:
分支名称本质上是不相关的。 Git 分支名称几乎没有任何意义:今天可以通过bleek 命名的提交,明天可能通过pribble 命名。
-
git describe 的输出更有趣,因为它不太可能改变,包括附近的带注释标签——标签本身从不应该改变,尽管这要求制作标签的用户表现自己——并为您提供方便的“与标签的距离”的线性计数,加上一个后缀,即使没有其余信息,通常也能精确定位特定的提交:
v2.12.0-190-ge0688e9
例如,对于 ID 以 e0688e9 开头且“附近标签”为 v2.12.0 (在某种意义上是 190 次提交)的提交来说,这是一个可读性最强的名称。
完整的原始提交 ID 本身唯一标识提交。
可以使用ident 属性作为过滤器——参见the gitattributes documentation——将原始提交ID 嵌入到源文件中。我自己会避免这种方法,除非构建系统太原始而无法运行git describe。
[编辑:稍微修复一下 - 你不想将版本文件“导入”为 Python 文件,因为这是在运行时完成的!]
根据您的构建系统,您可以让您的构建器执行,例如:
echo 'DESCRIBE = "' $(git describe --dirty) '"' > gitignored.pyx
然后构建文件。文件本身根本不应该提交到存储库中,而是每次都构建(它总是需要重新生成)。
同样的方法适用于大多数编译语言,当然要定义的变量的形式以及字符串和源文件的语法各不相同。
直接在 Cython 中执行此操作,无需辅助文件
特别是对于 Cython,如果您使用 setup.py,则可以在 Python 代码中提取 Git 版本,并在编译期间将其作为 -D 参数传递。这是一个实际的工作示例,它修改了基本的setup.py 来执行此操作,格式为 Git 提交。 hello.pyx 和 setup.py 文件几乎直接来自 initial Cython compilation example。
commit c1a008c1555be451047ff9869abe30c753cfc15d
Author: Chris Torek <chris.torek@gmail.com>
Date: Wed Mar 15 02:03:41 2017 -0700
build in Git version at compile time
diff --git a/hello.pyx b/hello.pyx
index da1b827..e3efef9 100644
--- a/hello.pyx
+++ b/hello.pyx
@@ -1,2 +1,7 @@
def say_hello_to(name):
print("Hello %s!" % name)
+
+cdef extern from *:
+ char *BUILD_VERSION
+
+version = BUILD_VERSION
diff --git a/setup.py b/setup.py
index 6e6bc70..7c6d07c 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,23 @@
from distutils.core import setup
from Cython.Build import cythonize
+from Cython.Distutils.extension import Extension
+from Cython.Distutils import build_ext
+
+import subprocess
+import sys
+
+proc = subprocess.Popen(['git', 'describe', '--dirty'], stdout=subprocess.PIPE)
+GIT_VERSION = proc.stdout.read().rstrip().encode('utf-8')
+if proc.wait():
+ sys.exit('git describe --dirty failed: exit code {}'.format(proc.wait()))
+
+extensions = [
+ Extension('hello', ['hello.pyx'],
+ extra_compile_args=['-D', 'BUILD_VERSION="{}"'.format(GIT_VERSION)]),
+]
setup(
name='Hello world app',
- ext_modules=cythonize("hello.pyx"),
+ cmdclass={'build_ext': build_ext},
+ ext_modules=extensions
)