forked from schrodinger/pymol-open-source
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonkeypatch_distutils.py
147 lines (121 loc) · 4.34 KB
/
monkeypatch_distutils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'''
Enhances distutils with:
- better C++ support
- incremental builds (w/o header dependency handling)
- parallel builds
'''
import os
import sys
import distutils.sysconfig
import distutils.unixccompiler
# threaded parallel map (optional)
pmap = map
try:
import _osx_support
_osx_support._UNIVERSAL_CONFIG_VARS += ('CXXFLAGS', 'LDCXXSHARED',)
_osx_support._COMPILER_CONFIG_VARS += ('LDCXXSHARED',)
except ImportError:
_osx_support = None
distutils.unixccompiler.UnixCCompiler.executables.update({
'compiler_cxx' : ["c++"],
'compiler_so_cxx' : ["c++"],
'linker_so_cxx' : ["c++", "-shared"],
'linker_exe_cxx' : ["c++"],
})
def set_parallel_jobs(N):
'''
Set the number of parallel build jobs.
N=1 : single threaded
N=0 : use number of CPUs
'''
global pmap
if N == 1:
pmap = map
else:
from multiprocessing import pool
pmap = pool.ThreadPool(N or None).map
def monkeypatch(parent, name):
'''
Decorator to replace a function or class method. Makes the
unpatched function available as <patchedfunction>._super
'''
def wrapper(func):
orig = getattr(parent, name)
func._super = orig
func.__name__ = name
setattr(parent, name, func)
return func
return wrapper
@monkeypatch(distutils.sysconfig, 'customize_compiler')
def customize_compiler(compiler):
# remove problematic flags
if sys.platform == 'linux' and (
'clang' in os.getenv('CC', '') or
'clang' in os.getenv('LD', '')):
import re
re_flto = re.compile(r'-flto\S*')
config_vars = distutils.sysconfig.get_config_vars()
for (key, value) in config_vars.items():
if re_flto.search(str(value)) is not None:
config_vars[key] = re_flto.sub('', value)
customize_compiler._super(compiler)
if compiler.compiler_type != "unix":
return
(cxx, ccshared, ldcxxshared) = \
distutils.sysconfig.get_config_vars('CXX', 'CCSHARED', 'LDCXXSHARED')
cxx = os.environ.get('CXX') or cxx
cxxflags = os.environ.get('CXXFLAGS', '') + ' ' + os.environ.get('CPPFLAGS', '')
ldcxxshared = os.environ.get('LDCXXSHARED', ldcxxshared or '') + \
' ' + os.environ.get('LDFLAGS', '') + \
' ' + os.environ.get('CXXFLAGS', '') + \
' ' + os.environ.get('CPPFLAGS', '')
cxx_cmd = cxx + ' ' + cxxflags
# C++11 by default
if '-std=' not in cxx_cmd:
cxx_cmd += ' -std=c++11'
compiler.set_executables(
compiler_cxx=cxx_cmd,
compiler_so_cxx=cxx_cmd + ' ' + ccshared,
linker_so_cxx=ldcxxshared,
linker_exe_cxx=cxx)
@monkeypatch(distutils.unixccompiler.UnixCCompiler, 'compile')
def compile(self, sources, output_dir=None, macros=None,
include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None,
depends=None):
'''
Enable parallel and incremental build.
To do a clean build, please remove the "build" directory.
'''
if os.getenv('DEBUG', ''):
debug = 1
macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
output_dir, macros, include_dirs, sources, depends, extra_postargs)
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
compiler_so = self.compiler_so
compiler_so_cxx = self.compiler_so_cxx
if sys.platform == 'darwin' and _osx_support is not None:
compiler_so = _osx_support.compiler_fixup(compiler_so, cc_args + extra_postargs)
compiler_so_cxx = _osx_support.compiler_fixup(compiler_so_cxx, cc_args + extra_postargs)
def _single_compile(obj):
try:
src, ext = build[obj]
except KeyError:
return
try:
if not self.force and \
os.path.getmtime(obj) > \
os.path.getmtime(src):
return
except OSError:
pass
# _compile
compiler = compiler_so_cxx \
if self.detect_language(src) == 'c++' \
else compiler_so
try:
self.spawn(compiler + cc_args + [src, '-o', obj] + extra_postargs)
except distutils.errors.DistutilsExecError as msg:
raise distutils.errors.CompileError(msg)
for _ in pmap(_single_compile, objects):
pass
return objects