1

我一直在研究一个包含大量文件的 Python 扩展模块。在一台机器上构建时,python setup.py build会很高兴地检测到更改的文件,只构建那些文件,并将整个东西链接在一起,就像 make 一样。然而,在另一台机器上,对任何文件的一次更改都会触发所有源的重新编译。

只是要清楚。两台机器都检测到软件包何时是最新的并且不会做任何事情。只有当单个文件发生更改时,它们的行为才会出现分歧。

为什么第二台机器会这样做?

机器 1(对每个文件进行适当的依赖检查和构建。)

Python 2.6.4 (r264:75706, Feb 15 2010, 17:06:03) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.

setuptools-0.6c11-py2.6

LSB Version: :core-3.1-amd64:core-3.1-ia32:core-3.1-noarch:graphics-3.1-amd64:graphics-3.1-ia32:graphics-3.1-noarch
Distributor ID: CentOS
Description: CentOS release 5.4 (Final)
Release: 5.4
Codename: Final

机器 2(当单个源文件更改时重建所有内容。)

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.

setuptools-0.6c11-py2.6

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 10.04 LTS
Release: 10.04
Codename: lucid
4

2 回答 2

2

我查看了 Mercurial 存储库,发现了这个变化:

问题 #5372:在 Distutils 的 ccompiler 中删除 .o 文件的重用(因为扩展额外选项可能会在不更改 .c 文件的情况下更改输出)。

IOW,这是一个被删除的简单优化。

于 2011-10-10T16:17:08.240 回答
1

我已经追踪到 Python 2.6.4 和 Python 2.6.5 之间 distutils 的变化。中的两个方法distutils.ccompiler.CCompiler,即_setup_compile_prep_compile,删除了相同的代码块:

if self.force:
    skip_source = {}            # rebuild everything
    for source in sources:
        skip_source[source] = 0
elif depends is None:
    # If depends is None, figure out which source files we
    # have to recompile according to a simplistic check. We
    # just compare the source and object file, no deep
    # dependency checking involving header files.
    skip_source = {}            # rebuild everything
    for source in sources:      # no wait, rebuild nothing
        skip_source[source] = 1

    n_sources, n_objects = newer_pairwise(sources, objects)
    for source in n_sources:    # no really, only rebuild what's
        skip_source[source] = 0 # out-of-date
else:
    # If depends is a list of files, then do a different
    # simplistic check.  Assume that each object depends on
    # its source and all files in the depends list.
    skip_source = {}
    # L contains all the depends plus a spot at the end for a
    # particular source file
    L = depends[:] + [None]
    for i in range(len(objects)):
        source = sources[i]
        L[-1] = source
        if newer_group(L, objects[i]):
            skip_source[source] = 0
        else:
            skip_source[source] = 1

此代码根据其目标对象检查每个源文件,如果它比目标更旧,则将其标记为跳过。我不知道为什么它被删除,但它解释了差异。当我把它作为测试放回去时,编译器会恢复到每个源的依赖分析。

于 2010-06-30T07:16:53.540 回答