@@ -20,30 +20,36 @@ SCons construction environment can be customized in sconscript.local script.
20
20
"""
21
21
22
22
import os
23
+ from os .path import join as pjoin
23
24
import re
24
25
import subprocess
25
26
import platform
26
27
28
+
27
29
def subdictionary (d , keyset ):
28
30
return dict (kv for kv in d .items () if kv [0 ] in keyset )
29
31
32
+
30
33
def getsyspaths (* names ):
31
34
pall = sum ((os .environ .get (n , '' ).split (os .pathsep ) for n in names ), [])
32
35
rv = [p for p in pall if os .path .exists (p )]
33
36
return rv
34
37
38
+
35
39
def pyoutput (cmd ):
36
40
proc = subprocess .Popen ([env ['python' ], '-c' , cmd ],
37
41
stdout = subprocess .PIPE ,
38
42
universal_newlines = True )
39
43
out = proc .communicate ()[0 ]
40
44
return out .rstrip ()
41
45
46
+
42
47
def pyconfigvar (name ):
43
48
cmd = ('from distutils.sysconfig import get_config_var\n '
44
49
'print(get_config_var(%r))\n ' ) % name
45
50
return pyoutput (cmd )
46
51
52
+
47
53
# copy system environment variables related to compilation
48
54
DefaultEnvironment (ENV = subdictionary (os .environ , '''
49
55
PATH PYTHONPATH GIT_DIR
@@ -53,7 +59,7 @@ DefaultEnvironment(ENV=subdictionary(os.environ, '''
53
59
_PYTHON_SYSCONFIGDATA_NAME
54
60
_CONDA_PYTHON_SYSCONFIGDATA_NAME
55
61
''' .split ())
56
- )
62
+ )
57
63
58
64
# Create construction environment
59
65
env = DefaultEnvironment ().Clone ()
@@ -64,18 +70,35 @@ env.EnsureSConsVersion(0, 98)
64
70
# Customizable compile variables
65
71
vars = Variables ('sconsvars.py' )
66
72
67
- vars .Add (PathVariable ('prefix' ,
68
- 'installation prefix directory' , None ))
73
+ # Set PREFIX for installation and linking
74
+ # TODO: also amend paths when VIRTUAL_ENV variable exists ?
75
+ if 'PREFIX' in os .environ :
76
+ # building with a set prefix
77
+ vars .Add (PathVariable (
78
+ 'prefix' ,
79
+ 'installation prefix directory' ,
80
+ os .environ ['PREFIX' ]))
81
+ elif 'CONDA_PREFIX' in os .environ :
82
+ # building for a conda environment
83
+ vars .Add (PathVariable (
84
+ 'prefix' ,
85
+ 'installation prefix directory' ,
86
+ os .environ ['CONDA_PREFIX' ]))
87
+ else :
88
+ vars .Add (PathVariable ('prefix' ,
89
+ 'installation prefix directory' , None ))
90
+ vars .Update (env )
91
+
69
92
vars .Add (EnumVariable ('build' ,
70
- 'compiler settings' , 'fast' ,
71
- allowed_values = ('debug' , 'fast' )))
93
+ 'compiler settings' , 'fast' ,
94
+ allowed_values = ('debug' , 'fast' )))
72
95
vars .Add (EnumVariable ('tool' ,
73
- 'C++ compiler toolkit to be used' , 'default' ,
74
- allowed_values = ('default' , 'intelc' )))
96
+ 'C++ compiler toolkit to be used' , 'default' ,
97
+ allowed_values = ('default' , 'intelc' , 'clang' , 'clangxx ' )))
75
98
vars .Add (BoolVariable ('profile' ,
76
- 'build with profiling information' , False ))
99
+ 'build with profiling information' , False ))
77
100
vars .Add ('python' ,
78
- 'Python executable to use for installation.' , 'python' )
101
+ 'Python executable to use for installation.' , 'python' )
79
102
vars .Update (env )
80
103
env .Help (MY_SCONS_HELP % vars .GenerateHelpText (env ))
81
104
@@ -89,78 +112,120 @@ if env['tool'] == 'intelc':
89
112
env .Tool ('intelc' , topdir = icpc [:icpc .rfind ('/bin' )])
90
113
91
114
# Figure out compilation switches, filter away C-related items.
92
- good_python_flag = lambda n : (
93
- not isinstance (n , str ) or
94
- not re .match (r'(-g|-Wstrict-prototypes|-O\d|-fPIC)$' , n ))
115
+ good_python_flag = lambda n : (
116
+ not isinstance (n , str ) or
117
+ not re .match (r'(-g|-Wstrict-prototypes|-O\d|-fPIC)$' , n ))
95
118
96
119
# Determine python-config script name.
97
- pyversion = pyoutput ('import sys; print("%i.%i" % sys.version_info[:2])' )
98
- pycfgname = 'python%s-config' % (pyversion if pyversion [0 ] == '3' else '' )
99
- # realpath gets the real path if exec is a link (e.g. in a python environment)
100
- xpython = os .path .realpath (env .WhereIs (env ['python' ]))
101
- pybindir = os .path .dirname (xpython )
102
- pythonconfig = os .path .join (pybindir , pycfgname )
103
-
104
- # Verify python-config comes from the same path as the target python.
105
- xpythonconfig = env .WhereIs (pythonconfig )
106
- if os .path .dirname (xpython ) != os .path .dirname (xpythonconfig ):
107
- print ("Inconsistent paths of %r and %r" % (xpython , xpythonconfig ))
108
- Exit (1 )
109
- # Process the python-config flags here.
110
- env .ParseConfig (pythonconfig + " --cflags" )
111
- env .Replace (CCFLAGS = [f for f in env ['CCFLAGS' ] if good_python_flag (f )])
112
- env .Replace (CPPDEFINES = 'BOOST_ERROR_CODE_HEADER_ONLY' )
113
- # the CPPPATH directories are checked by scons dependency scanner
114
- cpppath = getsyspaths ('CPLUS_INCLUDE_PATH' , 'CPATH' )
115
- env .AppendUnique (CPPPATH = cpppath )
116
- # Insert LIBRARY_PATH explicitly because some compilers
117
- # ignore it in the system environment.
118
- env .PrependUnique (LIBPATH = getsyspaths ('LIBRARY_PATH' ))
119
- # Add shared libraries.
120
- # Note: ObjCryst and boost_python are added from SConscript.configure.
121
-
122
- fast_linkflags = ['-s' ]
123
- fast_shlinkflags = pyconfigvar ('LDSHARED' ).split ()[1 :]
124
-
125
- # Specify minimum C++ standard. Allow later standard from sconscript.local.
126
- # In case of multiple `-std` options the last option holds.
127
- env .PrependUnique (CXXFLAGS = '-std=c++11' , delete_existing = 1 )
128
-
129
- # Need this to avoid missing symbol with boost<1.66
130
- env .PrependUnique (CXXFLAGS = ['-DBOOST_ERROR_CODE_HEADER_ONLY' ])
131
-
132
- # Platform specific intricacies.
133
- if env ['PLATFORM' ] == 'darwin' :
134
- darwin_shlinkflags = [n for n in env ['SHLINKFLAGS' ]
135
- if n != '-dynamiclib' ]
136
- env .Replace (SHLINKFLAGS = darwin_shlinkflags )
137
- env .AppendUnique (SHLINKFLAGS = ['-bundle' ])
138
- env .AppendUnique (SHLINKFLAGS = ['-undefined' , 'dynamic_lookup' ])
139
- fast_linkflags [:] = []
140
-
141
- # Compiler specific options
142
- if icpc :
143
- # options for Intel C++ compiler on hpc dev-intel07
144
- env .AppendUnique (CCFLAGS = ['-w1' , '-fp-model' , 'precise' ])
145
- env .PrependUnique (LIBS = ['imf' ])
146
- fast_optimflags = ['-fast' , '-no-ipo' ]
120
+ if 'PY_VER' in os .environ :
121
+ pyversion = os .environ ['PY_VER' ]
122
+ else :
123
+ pyversion = pyoutput ('import sys; print("%i.%i" % sys.version_info[:2])' )
124
+
125
+ if 'CONDA_BUILD' in os .environ and 'PY_VER' in os .environ :
126
+ # Messy: if CONDA_BUILD and PY_VER are in the path, we are building a conda package
127
+ # using several environment. Make sure python3.X-config points to the destination
128
+ # (host) environment
129
+ pythonconfig = pjoin (os .environ ['PREFIX' ], 'bin' , 'python%s-config' % os .environ ['PY_VER' ])
130
+ print ("Using $PREFIX and $PY_VER to determine python-config pth: %s" % pythonconfig )
131
+ xpython = pjoin (os .environ ['PREFIX' ], 'bin' , 'python' )
132
+ pyversion = os .environ ['PY_VER' ]
133
+ else :
134
+ pycfgname = 'python%s-config' % (pyversion if pyversion [0 ] == '3' else '' )
135
+ # realpath gets the real path if exec is a link (e.g. in a python environment)
136
+ xpython = os .path .realpath (env .WhereIs (env ['python' ]))
137
+ pybindir = os .path .dirname (xpython )
138
+ pythonconfig = pjoin (pybindir , pycfgname )
139
+
140
+ # for k in sorted(os.environ.keys()):
141
+ # print(" ", k, os.environ[k])
142
+
143
+ if platform .system ().lower () == "windows" :
144
+ # See https://scons.org/faq.html#Linking_on_Windows_gives_me_an_error
145
+ env ['ENV' ]['TMP' ] = os .environ ['TMP' ]
146
+ # the CPPPATH directories are checked by scons dependency scanner
147
+ cpppath = getsyspaths ('CPLUS_INCLUDE_PATH' , 'CPATH' )
148
+ env .AppendUnique (CPPPATH = cpppath )
149
+ # Insert LIBRARY_PATH explicitly because some compilers
150
+ # ignore it in the system environment.
151
+ env .PrependUnique (LIBPATH = getsyspaths ('LIBRARY_PATH' ))
152
+ if env ['prefix' ] is not None :
153
+ env .Append (CPPPATH = [pjoin (env ['prefix' ], 'include' )])
154
+ env .Append (CPPPATH = [pjoin (env ['prefix' ], 'Library' , 'include' )])
155
+ # Windows conda library paths are a MESS ('lib', 'libs', 'Library\lib'...)
156
+ env .Append (LIBPATH = [pjoin (env ['prefix' ], 'Library' , 'lib' )])
157
+ env .Append (LIBPATH = [pjoin (env ['prefix' ], 'libs' )])
158
+ # This disable automated versioned named e.g. libboost_date_time-vc142-mt-s-x64-1_73.lib
159
+ # so we can use conda-installed libraries
160
+ env .AppendUnique (CPPDEFINES = 'BOOST_ALL_NO_LIB' )
161
+ # Prevent the generation of an import lib (.lib) in addition to the dll
162
+ # env.AppendUnique(no_import_lib=1)
163
+ env .PrependUnique (CCFLAGS = ['/Ox' , '/EHsc' , '/MD' ])
164
+ env .AppendUnique (CPPDEFINES = {'NDEBUG' : None })
147
165
else :
148
- # g++ options
149
- env .AppendUnique (CCFLAGS = ['-Wall' ])
150
- fast_optimflags = ['-ffast-math' ]
151
-
152
- # Configure build variants
153
- if env ['build' ] == 'debug' :
154
- env .AppendUnique (CCFLAGS = '-g' )
155
- elif env ['build' ] == 'fast' :
156
- env .AppendUnique (CCFLAGS = ['-O3' ] + fast_optimflags )
157
- env .AppendUnique (CPPDEFINES = 'NDEBUG' )
158
- env .AppendUnique (LINKFLAGS = fast_linkflags )
159
- env .AppendUnique (SHLINKFLAGS = fast_shlinkflags )
160
-
161
- if env ['profile' ]:
162
- env .AppendUnique (CCFLAGS = '-pg' )
163
- env .AppendUnique (LINKFLAGS = '-pg' )
166
+ if 'CONDA_BUILD' not in os .environ :
167
+ # Verify python-config comes from the same path as the target python.
168
+ xpythonconfig = env .WhereIs (pythonconfig )
169
+ if os .path .dirname (xpython ) != os .path .dirname (xpythonconfig ):
170
+ print ("Inconsistent paths of %r and %r" % (xpython , xpythonconfig ))
171
+ Exit (1 )
172
+ # Process the python-config flags here.
173
+ env .ParseConfig (pythonconfig + " --cflags" )
174
+ env .Replace (CCFLAGS = [f for f in env ['CCFLAGS' ] if good_python_flag (f )])
175
+ env .Replace (CPPDEFINES = 'BOOST_ERROR_CODE_HEADER_ONLY' )
176
+ # the CPPPATH directories are checked by scons dependency scanner
177
+ cpppath = getsyspaths ('CPLUS_INCLUDE_PATH' , 'CPATH' )
178
+ env .AppendUnique (CPPPATH = cpppath )
179
+ # Insert LIBRARY_PATH explicitly because some compilers
180
+ # ignore it in the system environment.
181
+ env .PrependUnique (LIBPATH = getsyspaths ('LIBRARY_PATH' ))
182
+ # Add shared libraries.
183
+ # Note: ObjCryst and boost_python are added from SConscript.configure.
184
+
185
+ fast_linkflags = ['-s' ]
186
+ fast_shlinkflags = pyconfigvar ('LDSHARED' ).split ()[1 :]
187
+
188
+ # Specify minimum C++ standard. Allow later standard from sconscript.local.
189
+ # In case of multiple `-std` options the last option holds.
190
+ env .PrependUnique (CXXFLAGS = '-std=c++11' , delete_existing = 1 )
191
+
192
+ # Need this to avoid missing symbol with boost<1.66
193
+ env .PrependUnique (CXXFLAGS = ['-DBOOST_ERROR_CODE_HEADER_ONLY' ])
194
+
195
+ # Platform specific intricacies.
196
+ if env ['PLATFORM' ] == 'darwin' :
197
+ darwin_shlinkflags = [n for n in env ['SHLINKFLAGS' ] if n != '-dynamiclib' ]
198
+ env .Replace (SHLINKFLAGS = darwin_shlinkflags )
199
+ env .AppendUnique (SHLINKFLAGS = ['-bundle' ])
200
+ env .AppendUnique (SHLINKFLAGS = ['-undefined' , 'dynamic_lookup' ])
201
+ fast_linkflags [:] = []
202
+
203
+ # Compiler specific options
204
+ if icpc :
205
+ # options for Intel C++ compiler on hpc dev-intel07
206
+ env .AppendUnique (CCFLAGS = ['-w1' , '-fp-model' , 'precise' ])
207
+ env .PrependUnique (LIBS = ['imf' ])
208
+ fast_optimflags = ['-fast' , '-no-ipo' ]
209
+ else :
210
+ # g++ options
211
+ env .AppendUnique (CCFLAGS = ['-Wall' , '-fno-strict-aliasing' ])
212
+ fast_optimflags = ['-ffast-math' ]
213
+
214
+ # Configure build variants
215
+ if env ['build' ] == 'debug' :
216
+ env .AppendUnique (CCFLAGS = '-g' )
217
+ elif env ['build' ] == 'fast' :
218
+ env .AppendUnique (CCFLAGS = ['-O3' ] + fast_optimflags )
219
+ env .AppendUnique (CPPDEFINES = 'NDEBUG' )
220
+ env .AppendUnique (LINKFLAGS = fast_linkflags )
221
+ env .AppendUnique (SHLINKFLAGS = fast_shlinkflags )
222
+
223
+ if env ['profile' ]:
224
+ env .AppendUnique (CCFLAGS = '-pg' )
225
+ env .AppendUnique (LINKFLAGS = '-pg' )
226
+
227
+ env .Append (CPPPATH = [pjoin (env ['prefix' ], 'include' )])
228
+ env .Append (LIBPATH = [pjoin (env ['prefix' ], 'lib' )])
164
229
165
230
builddir = env .Dir ('build/%s-%s' % (env ['build' ], platform .machine ()))
166
231
0 commit comments