如何将git版本信息添加到cython构建的.so文件中?

时间:2017-03-15 02:42:16

标签: python c++ git compilation cython

我想将我的git提交信息(分支信息和sha1信息)添加到我的cython已编译的.so文件中。

例如,我有一个.pyx文件,我将其编译为.so模块。但问题来了,当我需要调试它时,我无法找到它确实来的哪个提交。我需要做些什么来支持./demo.so --gitinfo之类的某些操作才能获得类似Branch: master, Commit: *******的内容?

我通过使用cmake搜索了一些关于c / c ++可执行文件和git commit info的网页。

以下是一些网页相关:
Stackoverflow link
Github repo about git info

非常感谢!

1 个答案:

答案 0 :(得分:1)

将修订指示符嵌入到由编译源生成的对象中的方法在很大程度上取决于用于编译源的工具,当然还包括用于包含哪些源代码控制系统的方法来源。前者决定了你可以做什么以及如何运行命令。后者确定信息是重要的,哪些命令提取该信息,以及 - 在某种程度上 - 如何将该信息嵌入源文件中,如果可以直接完成的话。

既然你专门询问了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.pyxsetup.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
 )