如何在Python 2.7中使用distutils执行增量构建?

3
我将使用Python 2.7的distutils来构建一个C++库。然而,每次我使用以下命令发出构建命令时:
python setup.py build

即使c++文件没有改变,所有目标文件都会重新构建。


我的朋友告诉我,Python 2.6不会出现这种情况。

我的问题:

  1. 有没有一种方法可以强制distutils增量地构建代码?
  2. 如果无法增量构建代码,
    2.1 是否有使用Python 2.6 distutils的方法或者
    2.2 是否可能修改Python 2.7 distuils包?

你确定它正在重新构建吗?python setup.py --help build显示有一个-f选项,用于“强制构建(忽略时间戳)”,如果这是默认行为的话,似乎不应该存在这个选项... - undefined
@mgilson 它明确地重新构建了所有内容。也许是setup.py脚本本身的某个设置?尽管如此,如果有的话我找不到它... - undefined
2个回答

2

您无法这样做。在2.7版本中,由于编译的.o文件被简单而有缺陷地重复使用,因此取消了此优化。有关详细信息,请参见http://bugs.python.org/issue5372


谢谢你的回答!但是我更希望知道如何调整Python 2.7的distutils,以覆盖默认的“非错误”方式,即重新构建所有的.o文件。是否有一个选项标志可以传递,或者我必须深入代码中去使其不重新编译所有的代码文件来创建新的.o文件? - undefined
我的观点是告诉你不能这样做,你也不应该尝试去做,因为我提到了一个问题。 - undefined

1

我不知道这是否能解决你的确切问题,但我曾经遇到过类似的问题,我通过以下方法解决:

我有一个相对较大的C++包,带有基于cython的python包装器。最终我通过使用CMake将包编译为静态库(它具有增量构建功能),然后将静态库与cython包装器链接在一起 - 这相当稳定,尽管出于安全考虑每次都会重新编译。我的setup.py被修改以接受一些标志,告诉CMake该做什么。

处理CMake部分的相关代码片段(https://github.com/CoolProp/CoolProp/blob/master/wrappers/Python/setup.py)如下:

# ******************************
#       CMAKE OPTIONS
# ******************************

# Example using CMake to build static library:
# python setup.py install --cmake-compiler vc9 --cmake-bitness 64

if '--cmake-compiler' in sys.argv:
    i = sys.argv.index('--cmake-compiler')
    sys.argv.pop(i)
    cmake_compiler = sys.argv.pop(i)
else:
    cmake_compiler = ''

if '--cmake-bitness' in sys.argv:
    i = sys.argv.index('--cmake-bitness')
    sys.argv.pop(i)
    cmake_bitness = sys.argv.pop(i)
else:
    cmake_bitness = ''

USING_CMAKE = cmake_compiler or cmake_bitness

cmake_config_args = []
cmake_build_args = ['--config','"Release"']
STATIC_LIBRARY_BUILT = False
if USING_CMAKE:

    # Always force build since any changes in the C++ files will not force a rebuild
    touch('CoolProp/CoolProp.pyx')

    if 'clean' in sys.argv:
        if os.path.exists('cmake_build'):
            print('removing cmake_build folder...')
            shutil.rmtree('cmake_build')
            print('removed.')

    if cmake_compiler == 'vc9':
        if cmake_bitness == '32':
            generator = ['-G','"Visual Studio 9 2008"']
        elif cmake_bitness == '64':
            generator = ['-G','"Visual Studio 9 2008 Win64"']
        else:
            raise ValueError('cmake_bitness must be either 32 or 64; got ' + cmake_bitness)
    elif cmake_compiler == 'vc10':
        if cmake_bitness == '32':
            generator = ['-G','"Visual Studio 10 2010"']
        elif cmake_bitness == '64':
            generator = ['-G','"Visual Studio 10 2010 Win64"']
        else:
            raise ValueError('cmake_bitness must be either 32 or 64; got ' + cmake_bitness)
    else:
        raise ValueError('cmake_compiler [' + cmake_compiler + '] is invalid')

    cmake_build_dir = os.path.join('cmake_build', '{compiler}-{bitness}bit'.format(compiler=cmake_compiler, bitness=cmake_bitness))
    if not os.path.exists(cmake_build_dir):
        os.makedirs(cmake_build_dir)
    subprocess.check_call(' '.join(['cmake','../../../..','-DCOOLPROP_STATIC_LIBRARY=ON']+generator+cmake_config_args), shell = True, stdout = sys.stdout, stderr = sys.stderr, cwd = cmake_build_dir)
    subprocess.check_call(' '.join(['cmake','--build', '.']+cmake_build_args), shell = True, stdout = sys.stdout, stderr = sys.stderr, cwd = cmake_build_dir)

    # Now find the static library that we just built
    if sys.platform == 'win32':
        static_libs = []
        for search_suffix in ['Release/*.lib','Release/*.a', 'Debug/*.lib', 'Debug/*.a']:
            static_libs += glob.glob(os.path.join(cmake_build_dir,search_suffix))

    if len(static_libs) != 1:
        raise ValueError("Found more than one static library using CMake build.  Found: "+str(static_libs))
    else:
        STATIC_LIBRARY_BUILT = True
        static_library_path = os.path.dirname(static_libs[0])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接