-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathSConstruct
591 lines (555 loc) · 25.5 KB
/
SConstruct
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
# this is a build script that is intended to be run from scons (it will not work in python)
# it compiles the Fortran files needed to be used as Python packages for GSAS-II
#
# if the default options need to be overridden for this to work on your system, please let us
# know the details of what OS, compiler and python you are using as well as the command-line
# options you need.
from __future__ import division, print_function
import platform
import sys
import os
import glob
import subprocess
#==========================================================================================
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
def which_path(program):
"emulates Unix which: finds a program in path, but returns the path"
import os, sys
if sys.platform == "win32" and os.path.splitext(program)[1].lower() != '.exe':
program = program + '.exe'
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return fpath
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return path
return ""
def GetBinaryDir():
'''Format current platform, Python & numpy version;
note that this must match GSASIIpath.GetBinaryPrefix
'''
if sys.platform == "win32":
prefix = 'win'
elif sys.platform == "darwin":
prefix = 'mac'
elif sys.platform.startswith("linux"):
prefix = 'linux'
else:
print(u'Unknown platform: '+sys.platform)
raise Exception('Unknown platform')
if 'arm' in platform.machine() and sys.platform == "darwin":
bits = 'arm'
elif 'aarch' in platform.machine() and '64' in platform.architecture()[0]:
bits = 'arm64'
elif 'arm' in platform.machine():
bits = 'arm32'
elif '64' in platform.architecture()[0]:
bits = '64'
else:
bits = '32'
pyver = 'p{}.{}'.format(pyVersions[0].strip(),pyVersions[1].strip())
#pyver = 'p{}.{}'.format(*sys.version_info[0:2])
npver = 'n' + pyVersions[3][:pyVersions[3].find('.',2)]
return '_'.join([prefix,bits,pyver,npver])
def find(name, path):
'~unix find command; returns first file found'
for root, dirs, files in os.walk(path):
if sys.platform == "win32" or sys.platform == "darwin":
if name.lower() in [i.lower() for i in files]:
return os.path.join(root, name)
else:
if name in files:
return os.path.join(root, name)
def findInPython(name):
'find a file in the current Python directory'
base = os.path.split(sys.executable)[0]
if not sys.platform == "win32":
base = os.path.split(base)[0]
n = find(name,base)
if not n: raise Exception(f'{name} not found')
print(f'{name} found as {n}')
return n
#==========================================================================================
# misc initializations
# need command-line options for fortran command and fortran options
F2PYflags = '' # compiler options for f2py command
if 'arm' in platform.machine() and sys.platform == "darwin":
F2PYflags = '-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/include' # compiler options for f2py command
F2PYpath = ARGUMENTS.get('F2PYpath', '')
# find a default f2py relative to the scons location. Should be in the same place as f2py
spath = os.path.normpath(os.path.split(sys.executable)[0])
for pth in [F2PYpath,spath,os.path.normpath(os.path.join(spath,'..')),os.path.join(spath,'Scripts')]:
if not pth: continue
# look for f2py3 first
if sys.platform == "win32":
program = 'f2py3.exe'
else:
program = 'f2py3'
f2pyprogram = os.path.join(pth,program)
if is_exe(f2pyprogram):
F2PYpath,F2PYprog = os.path.split(f2pyprogram)
break
# not there, try f2py
if sys.platform == "win32":
program = 'f2py.exe'
else:
program = 'f2py'
f2pyprogram = os.path.join(pth,program)
if is_exe(f2pyprogram):
F2PYpath,F2PYprog = os.path.split(f2pyprogram)
break
# none of the above, look for f2py.py (probably obsolete)
program = 'f2py.py'
f2pyprogram = os.path.join(pth,program)
if os.path.exists(f2pyprogram) and os.path.splitext(program)[1] == '.py':
F2PYpath,F2PYprog = os.path.split(f2pyprogram)
break
else:
print ('Note: Using f2py from path (hope that works!)')
F2PYpath = which_path('f2py') # default path to f2py
F2PYprog = 'f2py'
# check if we have a working path to f2py:
f2pyprogram = os.path.normpath(os.path.join(F2PYpath,F2PYprog))
if os.path.exists(f2pyprogram) and os.path.splitext(program)[1] == '.py':
pass
elif is_exe(f2pyprogram):
pass
else:
print ('''
ERROR: The f2py program was not found. If this program is installed
but not in your path, you should specify the path on the command line:
scons -Q F2PYpath=/Library/Frameworks/Python.framework/Versions/6.2/bin/
scons -Q F2PYpath=D:/Python27/Scripts
''')
sys.exit()
GFORTpath = which_path('gfortran') # path to compiler
FCompiler='gfortran'
G77path = which_path('g77') # path to compiler
FORTpath = ""
FORTflags = ""
LDFLAGS = ''
SDKROOT = ''
tmpdir = None
#==========================================================================================
EXEsuffix = ''
# configure platform dependent options here:
if sys.platform == "win32":
F2PYsuffix = '.pyd'
EXEsuffix = '.exe'
if G77path != "":
FCompiler='g77'
elif GFORTpath != "":
FCompiler='gfortran'
else:
print ('No Fortran compiler in path')
sys.exit()
elif sys.platform == "darwin":
if 'arm' in platform.machine():
LDFLAGS = '-undefined dynamic_lookup -bundle -rpath ./ -mmacosx-version-min=11.1'
# I am not sure I completely understand the -rpath & -mmacosx-version-min options,
# but thet seem to work; this probably needs to be tested more
else:
LDFLAGS = '-undefined dynamic_lookup -bundle'
SDKROOT = os.environ.get('SDKROOT','')
F2PYsuffix = '.so'
elif sys.platform.startswith("linux"):
#LDFLAGS = '-Wall -shared -static-libgfortran -static-libgcc' # does not work with gfortran 4.4.4 20100726 (Red Hat 4.4.4-13)
F2PYsuffix = '.so'
else:
print ("Sorry, parameters for platform "+sys.platform+" are not yet defined")
sys.exit()
if ARGUMENTS.get('TMP'):
tmpdir = ARGUMENTS.get('TMP')
NISTcompileFlags = ''
if FCompiler == 'gfortran':
if ARGUMENTS.get('LIBGCC', '').upper().startswith('T'):
LDFLAGS += ' -static-libgcc'
NISTcompileFlags += ' -static-libgcc'
print('Static LIBGCC requested')
if ARGUMENTS.get('LIBGFORTRAN', '').upper().startswith('T'):
LDFLAGS += ' -static-libgfortran'
NISTcompileFlags += ' -static-libgfortran'
print('Static LIBGfortran requested')
C_only = False
if ARGUMENTS.get('C_ONLY', '').upper().startswith('T'):
C_only = True
print('Build of only C source code requested')
#==========================================================================================
# help
if 'help' in COMMAND_LINE_TARGETS:
print ("""
----------------------------------------------
Building Fortran routines for use with GSAS-II
----------------------------------------------
To build the compiled modules files needed to run GSAS-II, invoke this script:
scons [options]
where the following options are defined (all are optional):
-Q -- produces less output from scons
-n -- causes scons to show but not execute the commands it will perform
-c -- clean: causes scons to delete previously created files (but not from
install directory)
help -- causes this message to be displayed (no compiling is done)
install=T -- causes the module files to be placed in an installation directory
(../AllBinaries/<X>_NN_pv.v_nv.v) rather than ../bin, where:
<X> is mac, win or linux;
NN is 64 or 32 for Intel; arm64 or arm32 for ARM (aarch or arm)
pv.v is the Python version (p2.7 or p3.6,...) and
nv.v is the Numpy version (n1.13,...).
Normally used only by Brian or Bob for distribution of compiled software.
The following options override defaults set in the scons script:
FCompiler=<name> -- define the name of the fortran compiler, typically g77
or gfortran; default is to use g77 on Windows and gfortran elsewhere. If
you use something other than these, you must also specify F2PYflags.
FORTpath=<path> -- define a path to the fortran program; default is to use
first gfortran (g77 for Windows) found in path
FORTflags='string' -- string of options to be used for Fortran
during library build step
F2PYpath=<path> -- define a path to the f2py program; default is to use
first f2py found in path
F2PYflags='string' -- defines optional flags to be supplied to f2py:
Typically these option define which fortran compiler to use.
F2PYsuffix='.xxx' -- extension for output module files (default: win: '.pyd',
mac/linux: '.so')
LIBGCC=T -- adds the option -static-libgcc as an link option with gfortran. This
prevents use of the dynamic libgcc library, which must be then present on each
run-time computer. To use this, gfortran must be installed with the static
libraries.
LIBGFORTRAN=T -- adds the option -static-libgfortran as an link option with
gfortran. This prevents use of the dynamic libgcc library, which then must be
present on each run-time computer. To use this, gfortran must be installed
with the static libraries.
LDFLAGS='string' -- string of options to be used for f2py during link step
TMP=<path> --- where <path> is something like /tmp sets builds to be performed
in that directory.
C_ONLY=T -- causes build to only make the new fmask.so routine
Note that at present, this has been tested with 32-bit python on windows and
Mac & 64 bit on linux. 32-bit builds with anaconda/gfortran in 32-bit Python
is not working, at least not when installed in 64-bits Linux/Windows.
examples:
scons
(builds into ../bin for current platform using default options)
scons -Q install=T
(builds into ../bin<platform-dir> for module distribution)
""")
sys.exit()
#==========================================================================================
# get the python version number from the python image in the f2py directory
# find the python location associated with the f2py in use. Note
# that on Windows it may be in the parent of the f2py location.
# then run it to get info about the verision and the number of bits
pythonpath = ''
for program in ['python3','../python3','python','../python']:
if sys.platform == "win32" and os.path.splitext(program)[1].lower() != '.exe':
program = program + '.exe'
pythonprogram = os.path.normpath(os.path.join(F2PYpath,program))
if is_exe(pythonprogram):
pythonpath = os.path.split(program)[0]
break
else:
print ('python not found')
sys.exit()
p = subprocess.Popen(pythonprogram, stdout=subprocess.PIPE, stdin=subprocess.PIPE, encoding='utf-8')
p.stdin.write("""
import sys,platform;
print (str(sys.version_info[0]))
print (str(sys.version_info[1]))
print (platform.architecture()[0])
import numpy as np
print(np.__version__)
sys.exit()""")
p.stdin.close()
p.wait()
pyVersions = p.stdout.readlines()
#pyVersions = platform.python_version_tuple()
version = str(int(pyVersions[0])) + '.' + str(int(pyVersions[1]))
PlatformBits = '64bits'
if 'arm' in platform.machine() and sys.platform == "darwin":
PlatformBits = 'arm'
elif 'arm' in platform.machine() and '32' in platform.architecture()[0]:
PlatformBits = 'arm32'
elif 'aarch' in platform.machine():
PlatformBits = 'arm64'
elif '32' in platform.architecture()[0]:
PlatformBits = '32bits'
#PlatformBits = pyVersions[2][:-1]
#
# Set install location
if ARGUMENTS.get('install', '').upper().startswith('T'):
InstallLoc = os.path.join('..','AllBinaries', GetBinaryDir())
else:
InstallLoc = os.path.join('..','bin')
#==========================================================================================
# use the compiler choice to set compiler options, but don't change anything
# specified on the command line
try:
import sysconfig
pythonInc = sysconfig.get_paths()['include']
#pythonInc = os.path.split(findInPython('Python.h'))[0]
numpyInc = os.path.split( os.path.split(findInPython('ndarraytypes.h'))[0] )[0]
if sys.platform == "win32":
ver = str(sys.version_info.major)+str(sys.version_info.minor)
pythonLib = findInPython(f'python{ver}.lib')
if C_only: print('locations:\n',pythonLib,'\n',numpyInc)
if sys.platform == "win32" and C_only: print(pythonLib)
except TypeError:
numpyInc = pythonInc = ''
print('C header files not found from',os.path.split(sys.executable)[0])
if C_only: sys.exit()
C2SO = None
if FCompiler == 'gfortran':
if FORTpath == "": FORTpath = GFORTpath
if sys.platform.startswith("linux") and "64" in PlatformBits:
if 'aarch' in platform.machine(): # 64-bit Raspberry Pi
if FORTflags == "": FORTflags = ' -w -O2 -fPIC'
if F2PYflags == "": F2PYflags = '--fcompiler=gnu95 --f77exec=gfortran --f77flags="-fno-range-check"'
C2SO = 'gcc -shared -fPIC -I ' + pythonInc + ' -I ' + numpyInc # not tested
else: # 64-bit Intel Linux
if FORTflags == "": FORTflags = ' -w -O2 -fPIC -m64'
if F2PYflags == "": F2PYflags = '--fcompiler=gnu95 --f77exec=gfortran --f77flags="-fno-range-check -m64"' # --arch="-arch x86_64"'
C2SO = 'gcc -shared -fPIC -I ' + pythonInc + ' -I ' + numpyInc
elif sys.platform.startswith("linux") and 'arm' in platform.machine(): # 32-bit Raspberry Pi
if FORTflags == "": FORTflags = ' -w -O2 -fPIC'
if F2PYflags == "": F2PYflags = '--fcompiler=gnu95 --f77exec=gfortran --f77flags="-fno-range-check"'
C2SO = 'gcc -shared -fPIC -I ' + pythonInc + ' -I ' + numpyInc # not tested
elif sys.platform.startswith("linux"): # 32-bit Intel Linux
if FORTflags == "": FORTflags = ' -w -O2 -fPIC -m32'
if F2PYflags == "": F2PYflags = '--fcompiler=gnu95 --f77exec=gfortran --f77flags="-fno-range-check -m32"'
C2SO = 'gcc -shared -fPIC -I ' + pythonInc + ' -I ' + numpyInc # not tested
elif sys.platform == "darwin": # now 64 bit only
if 'arm' in PlatformBits: # Apple Silicon
#LDFLAGS += " -arch x86_64 -m64"
if FORTflags == "": FORTflags = ' -w -O2'
if F2PYflags == "": F2PYflags = '--fcompiler=gnu95 --f77exec=gfortran --f77flags="-fno-range-check"'
C2SO = 'clang -shared -undefined dynamic_lookup -I ' + pythonInc + ' -I ' + numpyInc # works
else:
LDFLAGS += " -arch x86_64 -m64"
if FORTflags == "": FORTflags = ' -w -O2 -m64'
if F2PYflags == "": F2PYflags = '--fcompiler=gnu95 --f77exec=gfortran --f77flags="-fno-range-check -m64"'
C2SO = 'clang -shared -undefined dynamic_lookup -I ' + pythonInc + ' -I ' + numpyInc
elif sys.platform == "win32" and "64" in PlatformBits: # 64-bit Windows
if FORTflags == "": FORTflags = ' -w -O2 -m64'
if F2PYflags == "":
F2PYflags = '--compiler=mingw32 --fcompiler=gfortran --f77flags="-fno-range-check -m64"'
C2SO = ['cl /EHsc /c fmask.c /I ' + os.path.normpath(pythonInc) + ' /I ' + os.path.normpath(numpyInc),
'link /DLL /OUT:fmask.pyd fmask.obj /LIBPATH ' + pythonLib,
]
elif sys.platform == "win32": # 32-bit windows
# the next line may need to be removed. When compiling with a 32-bit machine?
#if FORTflags == "": FORTflags = ' -w -O2 -m32'
if F2PYflags == "":
F2PYflags = '--compiler=mingw32 --fcompiler=gfortran --f77flags="-fno-range-check"'
elif FCompiler == 'g77':
if FORTpath == "": FORTpath = G77path
if sys.platform == "win32":
if F2PYflags == "": F2PYflags = '--compiler=mingw32 --fcompiler=g77'
if FORTflags == "": FORTflags = ' -w -O2 -fno-automatic -finit-local-zero -malign-double -mwindows'
else:
if F2PYflags == "": F2PYflags = '--fcompiler=gnu --f77exec=g77 --f77flags="-fno-range-check"'
else:
if FORTpath == "": print ('Likely error, FORTpath is not specified')
if F2PYflags == "":
print ('Error: specify a F2PYflags value')
sys.exit()
if tmpdir:
F2PYflags += " --build-dir " + tmpdir
F2PYflags += f" -I{os.getcwd()}"
#==========================================================================================
# Setup build Environment
if sys.platform == "win32":
env = Environment(ENV = os.environ)
else:
env = Environment()
# Define a builder to run f2py
def generate_f2py(source, target, env, for_signature):
module = os.path.splitext(str(source[0]))[0]
if len(liblist) > 0:
for lib in liblist:
module = module + ' ' + str(lib)
f2pyprogram = os.path.normpath(os.path.join(F2PYpath,F2PYprog))
if os.path.splitext(F2PYprog)[1] == '.py': # use f2py.py if no f2py[.exe]
f2pycmd = pythonprogram + ' ' + f2pyprogram + ' -c $SOURCE ' + ' -m ' + module + ' ' + F2PYflags
else:
f2pycmd = f2pyprogram + ' -c $SOURCE' + ' -m ' + module + ' ' + F2PYflags
if sys.platform == "win32":
installcmd = "copy " + os.path.splitext(str(source[0]))[0] + '*' + F2PYsuffix + ' ' + InstallLoc
else:
installcmd = "cp " + os.path.splitext(str(source[0]))[0] + '*' + F2PYsuffix + ' ' + InstallLoc
return [f2pycmd, installcmd]
f2py = Builder(generator = generate_f2py)
env.Append(BUILDERS = {'f2py' : f2py},)
# create a builder for the fortran compiler for library compilation so we can control how it is done
def generate_obj(source, target, env, for_signature):
dir = os.path.split(str(source[0]))[0]
obj = os.path.splitext(str(source[0]))[0]+'.o'
return os.path.join(FORTpath,FCompiler) + ' -c $SOURCE ' + FORTflags + ' -I' + dir + ' -o' + obj
fort = Builder(generator = generate_obj, suffix = '.o', src_suffix = '.for')
# create a library builder so we can control how it is done on windows
def generate_lib(source, target, env, for_signature):
srclst = ""
for s in source:
srclst += str(s) + " "
return os.path.join(FORTpath,'ar.exe') + ' -rs $TARGET ' + srclst
lib = Builder(generator = generate_lib, suffix = '.a',
src_suffix = '.o')
env.Append(BUILDERS = {'fort' : fort, 'lib' : lib},)
# Define a builder to compile and copy NIST*LATTICE programs
def generate_nist(source, target, env, for_signature):
#exe = os.path.splitext(str(source[0]))[0] + EXEsuffix
exe = target
cmd = os.path.join(FORTpath,FCompiler) + ' $SOURCE ' + NISTlib[0] + ' -o $TARGET' + NISTcompileFlags
if sys.platform == "win32":
installcmd = "copy $TARGET " + InstallLoc
else:
installcmd = "mv $TARGET " + InstallLoc
return [cmd, installcmd]
env.Append(BUILDERS = {'nist' : Builder(generator = generate_nist)},)
# build c-based .pyd/.so files; for now only fmask.c; more work needed
# for Windows if more c files are used.
def generate_c2so(source, target, env, for_signature):
if sys.platform == "win32":
installcmd = "copy $TARGET " + InstallLoc
else:
installcmd = "mv $TARGET " + InstallLoc
if type(C2SO) is list:
return C2SO + [installcmd]
else:
return [C2SO + ' -o $TARGET ' + str(source[0]), installcmd]
if C2SO:
c2so = Builder(generator = generate_c2so, suffix = F2PYsuffix, src_suffix = '.c')
env.Append(BUILDERS = {'c2so' : c2so},)
#==========================================================================================
# override from command-line options
for var in ['F2PYflags','F2PYpath','F2PYsuffix','FCompiler','FORTpath','FORTflags','LDFLAGS']:
if ARGUMENTS.get(var, None) is not None:
print ('Setting',var,'to "'+ARGUMENTS.get(var)+'" based on command line')
exec(var + "= ARGUMENTS.get('" + var +"')")
#==========================================================================================
# locate libraries to be built (in subdirectories named *subs)
liblist = []
NISTlib = []
for sub in glob.glob('*subs'):
if C_only: break
filelist = []
for file in glob.glob(os.path.join(sub,'*.for'))+glob.glob(os.path.join(sub,'*.f')):
#target = os.path.splitext(file)[0]+'.o'
target = env.fort(file) # connect .o files to .for files
#print ('Compile: ',file, target)
filelist.append(target)
for file in glob.glob(os.path.join(sub,'*.f90')):
target = env.fort(file) # connect .o files to .f90 files
filelist.append(target)
#lib = Library(sub, Glob(os.path.join(sub,'*.for'))) # register library to be created
if sys.platform == "win32":
lib = env.lib(sub, filelist)
else:
lib = Library(sub, filelist) # register library to be created
if 'NIST' in lib[0].name:
NISTlib = [lib[0].name]
else:
liblist.append(lib[0].name)
filename = str(lib[0])
# find modules that need to be built
modlist = []
for src in glob.glob('*.for'):
if C_only: break
#break # bail out early for testing
target = os.path.splitext(src)[0] + F2PYsuffix # xxx.pyd or xxx.so
out = env.f2py(target,src)
Clean(out, Glob(os.path.splitext(src)[0] + "*" + F2PYsuffix)) # this picks up old- & new-style .pyd/.so names
Depends(target, liblist) # make sure libraries are rebuilt if old
modlist.append(out[0].name)
clist = []
if C2SO:
# add fmask.so/.pyd from fmask.c
src = 'fmask.c'
target = 'fmask' + F2PYsuffix # xxx.pyd or xxx.so
out = env.c2so(target,src)
#Clean(target, Glob(os.path.splitext(src)[0] + "*" + F2PYsuffix)) # this picks up old- & new-style .pyd/.so names
clist.append(target)
exelist = []
# NIST*LATTICE programs
for src in 'LATTIC.f','convcell.f':
if C_only: break
target = os.path.splitext(src)[0] + EXEsuffix
out = env.nist(target,src)
Clean(out, target)
Depends(target, NISTlib) # make sure library is rebuilt if old
exelist.append(out[0].name)
#==========================================================================================
# all done with setup, finally ready to build something! but 1st show the
# user the final options and save in build notes; then let scons do the work
print ('Note: Use "scons help" to see build options')
print (80*'=')
for var in ['FCompiler','FORTpath','FORTflags','F2PYflags','F2PYpath','F2PYsuffix','LDFLAGS']:
print ('Variable',var,'is','"'+eval(var)+'"')
print ('Using python at', pythonprogram )
print ('Python/f2py version =',version,PlatformBits)
print ('Install directory is',InstallLoc)
print ('Will build object libraries:',)
for lib in liblist: print (" " + lib,)
print ("")
print ('f2py will build these modules:',)
for mod in modlist: print (" " + mod,)
print ("")
print ('Will compile these executables:',)
for mod in exelist: print (" " + mod,)
print ("")
print ('Will compile these C module(s):',)
for mod in clist: print (" " + mod,)
print ("")
print (80*'=')
print("Setting environment variables:")
# Setup build Environment
# add compiler, f2py & python locations to path
if pythonpath != "" and pythonpath != F2PYpath: env.PrependENVPath('PATH', pythonpath)
if F2PYpath != "": env.PrependENVPath('PATH', F2PYpath)
if FORTpath != "": env.PrependENVPath('PATH', FORTpath)
# add other needed environment variables
for var in ('LDFLAGS','SDKROOT'):
if eval(var) != "":
env['ENV'][var] = eval(var)
print("\t{} = {}".format(var,eval(var)))
if 'WINDIR' in os.environ:
env['ENV']['WINDIR'] = os.environ['WINDIR']
print("\t {} = {}".format('WINDIR',os.environ['WINDIR']))
print (80*'=')
#print (env.Dump())
if 'help' in COMMAND_LINE_TARGETS: sys.exit()
import datetime
if not os.path.exists(InstallLoc) and not GetOption('no_exec'):
print('Creating '+InstallLoc)
os.makedirs(InstallLoc)
if not GetOption('no_exec'):
fp = open(os.path.join(InstallLoc,'Build.notes.txt'),'w')
user = '?'
if 'USER' in os.environ:
user = os.environ.get('USER','?')
elif 'USERNAME' in os.environ:
user = os.environ.get('USERNAME','?')
fp.write('Created {} on {} by user "{}"\n\n'.format(datetime.datetime.isoformat(datetime.datetime.now()),
platform.node(),user))
try:
if sys.platform == "win32":
fp.write('Platform win32_ver: '+str(platform.win32_ver())+'\n')
elif sys.platform == "darwin":
fp.write('Platform mac_ver: {0:} on {2:}\n'.format(*platform.mac_ver()))
fp.write('Platform uname: '+str(list(platform.uname()))+'\n')
except:
pass
if 'BUILD_TAG' in os.environ:
fp.write('BUILD TAG: '+ os.environ['BUILD_TAG'] +'\n')
if 'CONDA_PREFIX' in os.environ:
fp.write('CONDA_PREFIX: '+ os.environ['CONDA_PREFIX'] +'\n')
fp.write('\n\tPython: '+platform.python_version()+'\n')
try:
import numpy
fp.write('\tnumpy: '+numpy.__version__+'\n\n')
except:
pass
for var in ['FCompiler','FORTpath','FORTflags','F2PYflags','F2PYpath','F2PYsuffix','LDFLAGS']:
fp.write('\tVariable '+var+' = "'+eval(var)+'"\n')
fp.close()