-
Notifications
You must be signed in to change notification settings - Fork 7
/
SConstruct
752 lines (632 loc) · 30.6 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
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
help_message = """
OpenLoops build system
Usage: scons [options] <loops>=proc1,proc2,...
<loops> determines the content of the process library
- t=tree, l=loop, s=loop_squared, p=pseudo_tree;
if 'l' is present, any combination of these is allowed (inalphabetic order),
otherwise 't' must be alone
- If a processes ends with a '.coll' it is treated as a process collection,
i.e. the corresponding list of processes from the collection file on the web
server is used. The special collection all.coll downloads all processes.
- Several <loops> arguments can be given, even with the same <loops>.
Options
-c (SCons built-in)
Clean, i.e. delete object files and libraries.
See also clean=... option.
gjobs=<n>
Generate 'n' processes simultaneously.
n > 1 implies --glog
n < 1 uses the number of CPU core of the machine
glog=0/1
Write generator output to a log file; implied if gjobs > 1.
force_download=0/1
Download processes even if they seem to be up-to-date.
process_update=0/1
If the downloader is used: select all downloaded processes
(i.e. their version.info file contains 'process_update').
If the generator is used: select all processes
which have been generated or downloaded before.
release=<r>
A string of max. length 8 to specify the OpenLoops library version number
(this does not affect the process libraries).
generator=0/1/2
0: off
1: use the process generator
2: use the process downloader
compile=0/1/2
0: don't compile
1: compile processes,
compile generic libraries only if no process was specified
2: compile processes and generic libraries
debug=0/1
Add debug flags to Fortran compiler flags.
clean=procs,src
Only effective in conjunction with -c.
procs: delete the proclib and process_obj directories
which contain libraries and object code of all processes.
src: delete process source of the given processes,
rsp. the process_src directory which contains
the source of all processes if 'procs' is also given.
Also built-in SCons options can be used. However:
- no_exec (-n) will not work properly,
because the process generator is run in a sub-process.
(the compile script cannot know what to do
unless the generator finished generating the source code)
- SCons options are not passed to the process generator.
For more options see ./pyol/config/default.cfg.
User defined options can be set in ./openloops.cfg#include "global_coli.h"
in the same way as in default.cfg.
"""
# TODO
# - Use kind types from kind_types module in CutTools.
# - When compiling a process: check for compatibility with the OpenLoops version.
import os
import sys
import subprocess
sys.path.insert(0, os.path.abspath(os.path.join('pyol', 'tools')))
import OLBaseConfig
import OLToolbox
from OLLibrary import CPPContainer, OLLibrary
if '--help' in sys.argv or '-h' in sys.argv:
print help_message
Exit(0)
scons_cmd = sys.argv[0]
process_arguments = filter(lambda el: el[0] in
OLBaseConfig.loops_specifications, ARGLIST)
commandline_options = filter(lambda el: el[0] not in
OLBaseConfig.loops_specifications, ARGLIST)
config = OLBaseConfig.get_config(commandline_options)
SetOption('num_jobs', config['num_jobs'])
generator_options = ['--jobs=' + str(config['gjobs'])]
if config['glog']:
generator_options.append('--log')
if config['force_download']:
force_download_flag = ['--force']
else:
force_download_flag = []
if config['release']:
release_version = 'version ' +config['release']
else:
release_version = ''
svn_revision = str(OLToolbox.get_svn_revision(mandatory = False))
# Install directory; only effect is that this is put into
# the openloops library as a string. TODO: override by command line argument;
# and actually install the libraries there
install_path = os.getcwd()
generate_process_true = ((config['generator'] == 1) and
not GetOption('clean') and not GetOption('no_exec'))
download_process_true = ((config['generator'] == 2) and
not GetOption('clean') and not GetOption('no_exec'))
if config['compile'] == 0 or (config['compile'] == 1 and
(len(process_arguments) > 0 or
config['process_update'])):
compile_libraries = []
else:
compile_libraries = config['compile_libraries']
# Coli legacy cpp defines (default)
# - ALLCHECK (false) -- print maximal information
# - CHECK (false) -- perform various checks
# - SING (true) -- take singular contributions into account
# - PUBCHECK (false) -- check against publication
# Coli cpp defines
# - SING -- take singular contributions into account
# - CHECK -- perform various checks
# - WARN -- issue warnings
# - NEWCHECK -- print untested scalar function calls
cpp_defines = map(lambda lib: 'USE_' + lib.upper(), config['link_libraries'])
cpp_defines += [('KIND_TYPES', 'kind_types'),
('DREALKIND', 'dp'),
('QREALKIND', 'qp'),
'USE_' + config['fortran_tool'].upper(),
('OL_INSTALL_PATH', '\\"' + install_path + '\\"'),
'SING']
if config['collier_legacy']:
cpp_defines.append('COLLIER_LEGACY')
else:
cpp_defines.append('collierdd')
# ================= #
# Generic libraries #
# ================= #
lib_src_dirs = {}
lib_obj_dirs = {}
lib_mod_dirs = {}
for libname in ['olcommon', 'rambo', 'qcdloop', 'oneloop', 'cuttools', 'samurai', 'collier', 'openloops']:
lib_src_dirs[libname] = os.path.join(config['lib_src_dir'], libname, 'src')
lib_obj_dirs[libname] = os.path.join(config['lib_src_dir'], libname, 'obj')
lib_mod_dirs[libname] = os.path.join(config['lib_src_dir'], libname, 'mod')
if config['collier_legacy']:
lib_src_dirs['collier'] = os.path.join(config['lib_src_dir'], 'collier', 'src_legacy')
# OLCommon
olcommon_dp_src = ['kind_types.F90', 'debug.F90', 'cwrappers.c']
olcommon_mp_src = ['common.F90']
# Rambo
rambo_dp_src = ['rambo.f']
# QCDLoop
qcdloop_dp_src = [
'aacbc.f', 'aaccc.f', 'aacinv.f', 'aaxbx.f', 'aaxcx.f', 'aaxdx.f', 'aaxex.f', 'aaxinv.f',
'auxCD.f', 'ddilog.f', 'ff2dl2.f', 'ffabcd.f', 'ffca0.f', 'ffcb0.f', 'ffcb1.f', 'ffcb2.f',
'ffcb2p.f', 'ffcc0.f', 'ffcc0p.f', 'ffcc1.f', 'ffcdb0.f', 'ffcel2.f', 'ffcel3.f', 'ffcel4.f',
'ffcel5.f', 'ffceta.f', 'ffcli2.f', 'ffcrr.f', 'ffcxr.f', 'ffcxs3.f', 'ffcxs4.f', 'ffcxyz.f',
'ffdcc0.f', 'ffdcxs.f', 'ffdel2.f', 'ffdel3.f', 'ffdel4.f', 'ffdel5.f', 'ffdel6.f', 'ffdl2i.f',
'ffdl5p.f', 'ffdxc0.f', 'ffinit_mine.f', 'ffrcvr.f', 'fftran.f', 'ffxb0.f', 'ffxb1.f', 'ffxb2p.f',
'ffxc0.f', 'ffxc0i.f', 'ffxc0p.f', 'ffxc1.f', 'ffxd0.f', 'ffxd0h.f', 'ffxd0i.f', 'ffxd0p.f',
'ffxd1.f', 'ffxdb0.f', 'ffxdbd.f', 'ffxdi.f', 'ffxdpv.f', 'ffxe0.f', 'ffxe1.f', 'ffxf0.f',
'ffxf0h.f', 'ffxli2.f', 'ffxxyz.f', 'npoin.f', 'qlbox1.f', 'qlbox10.f', 'qlbox11.f', 'qlbox12.f',
'qlbox13.f', 'qlbox14.f', 'qlbox15.f', 'qlbox16.f', 'qlbox2.f', 'qlbox3.f', 'qlbox4.f', 'qlbox5.f',
'qlbox6.f', 'qlbox7.f', 'qlbox8.f', 'qlbox9.f', 'qlcLi2omx2.f', 'qlcLi2omx3.f', 'qlfndd.f',
'qlfunctions.f', 'qlI1.f', 'qlI2.f', 'qlI2fin.f', 'qlI3.f', 'qlI3fin.f', 'qlI3sub.f', 'qlI4.f',
'qlI4array.f', 'qlI4DNS41.f', 'qlI4fin.f', 'qlI4sub0m.f', 'qlI4sub1m.f', 'qlI4sub2m.f',
'qlI4sub2ma.f', 'qlI4sub2mo.f', 'qlI4sub3m.f', 'qlinit.f', 'qlkfn.f', 'qlLi2omprod.f',
'qlLi2omrat.f', 'qlLi2omx.f', 'qlLi2omx2.f', 'qllnomrat4.f', 'qllnrat.f', 'qlratgam.f',
'qlratreal.f', 'qlsnglsort.f', 'qlspencer.f', 'qltri1.f', 'qltri2.f', 'qltri3.f', 'qltri4.f',
'qltri5.f', 'qltri6.f', 'qltrisort.f', 'qlxpicheck.f', 'qlYcalc.f', 'qlzero.f', 'spence.f']
# OneLOop -- contains both, dp and qp routines
oneloop_dp_src = ['avh_olo_qp.f90']
# OpenLoops
openloops_mp_src = [
'contractions.F90', 'converter.F90', 'counterterms.F90', 'helicity.F90',
'i-operator.F90', 'kinematics.F90', 'laststep.F90', 'loopmom_tensor.F90',
'looproutines.F90', 'Lpropagators.F90', 'Lvertices.F90', 'parameters.F90',
'parameters_init.F90', 'renormalisation_qcd.F90',
'propagators.F90', 'vertices.F90', 'wavefunctions.F90']
openloops_dp_src = [
'helicity_init.F90', 'init_ui.F90', 'stability.F90', 'tensor_handling.F90']
if config['interface'] >= 1:
openloops_dp_src.append('ol_interface.F90')
if config['interface'] >= 2:
openloops_dp_src.append('blha_interface.F90')
openloops_version_src = 'version.F90'
# CutTools -- contains both, dp and qp routines
cuttools_dp_src = [
'cts_combinatorics.f90', 'cts_constants.f90', 'cts_cutroutines.f90', 'cts_cuttools.f90',
'cts_dynamics.f90', 'cts_kinematics.f90', 'cts_loopfunctions.f90', 'cts_tensors.f90',
'cts_type.f90', 'mpnumdummy.f90']
# Samurai
samurai_dp_src = [
'constants.f90', 'kinematic.f90', 'ltest.f90', 'maccu.f90', 'madds.f90',
'mcgs.f90', 'mfunctions.f90', 'mgetbase.f90', 'mgetc1.f90', 'mgetc2.f90',
'mgetc3.f90', 'mgetc4.f90', 'mgetc5.f90', 'mgetkin.f90', 'mgetqs.f90',
'mglobal.f90', 'mmasters.f90', 'mmisavholo.f90', 'mmisgolem.f90',
'mmishighrank.f90', 'mmislooptools.f90', 'mmisqcdloop.f90', 'mrestore.f90',
'msamurai.f90', 'mtens.f90', 'mtests.f90', 'ncuts.f90', 'notfirst.f90',
'options.f90', 'precision.f90', 'save.f90']
# Collier
if config['collier_legacy']:
collier_inc_dp = [
'coli_checkparams.h', 'coli_common_cache.h', 'coli_common.h',
'coli_params_cache.h', 'coli_params.h']
collier_src_mp = []
collier_src_dp = [
# DD
'DD_aux.F', 'DD_2pt.F', 'DD_3pt.F', 'DD_3pt_coll.F',
'DD_4pt.F', 'DD_5pt.F', 'DD_6pt.F', 'DD_newinterface.F', 'dcuhre.F',
# Coli
'coli_aux.F', 'coli_b0.F', 'coli_c0.F', 'coli_cache.F', 'coli_ctoliserg.F',
'coli_ctolis.F', 'coli_d0.F', 'coli_d0reg.F', 'coli_oint2.F', 'coli_oint.F',
# BuildTensors
'bt_Combinatorics.F90', 'bt_Interface.F90',
'bt_BuildTensors.F90', 'bt_Checks.F90', 'bt_FourVectors.F90',
'bt_GramCayley.F90', 'bt_LightCone.F90', 'bt_MatrixManipulations.F90',
'bt_TensorManipulations.F90', 'bt_TensorReduction.F90', 'bt_TI_interface.F90']
else:
collier_inc_dp = []
collier_src_mp = []
collier_src_dp = [
# Aux/
'Combinatorics.F90', 'cache.F90', 'master.F90',
# COLI/
'coli_aux.F', 'coli_aux2.F90', 'coli_b0.F', 'coli_c0.F', 'coli_d0.F',
'coli_d0reg.F', 'coli_stat.F90', 'reductionAB.F90', 'reductionC.F90',
'reductionD.F90', 'reductionEFG.F90', 'reductionTN.F90',
# DDlib/
'DD_global.F90', 'DD_2pt.F', 'DD_3pt.F', 'DD_4pt.F', 'DD_5pt.F',
'DD_6pt.F', 'DD_aux.F', 'DD_to_COLLIER.F',
# tensors/
'BuildTensors.F90', 'InitTensors.F90', 'TensorReduction.F90',
# ./
'COLLIER.F90', 'collier_aux.F90', 'collier_coefs.F90',
'collier_global.F90', 'collier_init.F90', 'collier_tensors.F90']
if compile_libraries:
cpp_container = CPPContainer(scons_cmd = scons_cmd,
mp = config['precision'],
version = release_version,
revision = svn_revision,
cpp_defs = cpp_defines,
target = 'cpp_generic',
target_prefix = os.path.join('..', 'obj', ''))
if 'olcommon' in compile_libraries:
olcommon_lib = OLLibrary(
name = 'olcommon',
linklibs = ([] if sys.platform.startswith('freebsd') else ['dl']),
target_dir = config['generic_lib_dir'],
src_dir = lib_src_dirs['olcommon'],
dp_src = olcommon_dp_src,
mp_src = olcommon_mp_src,
to_cpp = cpp_container)
if 'rambo' in compile_libraries:
VariantDir(lib_obj_dirs['rambo'],
lib_src_dirs['rambo'], duplicate = 0)
rambo_lib = OLLibrary(name = 'rambo',
target_dir = config['generic_lib_dir'],
src_dir = lib_obj_dirs['rambo'],
dp_src = rambo_dp_src)
if 'qcdloop' in compile_libraries:
VariantDir(lib_obj_dirs['qcdloop'],
lib_src_dirs['qcdloop'], duplicate = 0)
qcdloop_lib = OLLibrary(name = 'qcdloop',
target_dir = config['generic_lib_dir'],
src_dir = lib_obj_dirs['qcdloop'],
mod_dir = '',
dp_src = qcdloop_dp_src)
if 'oneloop' in compile_libraries:
VariantDir(lib_obj_dirs['oneloop'],
lib_src_dirs['oneloop'], duplicate = 0)
oneloop_lib = OLLibrary(name = 'oneloop',
target_dir = config['generic_lib_dir'],
mod_dependencies = ['olcommon'],
src_dir = lib_obj_dirs['oneloop'],
dp_src = oneloop_dp_src)
if 'cuttools' in compile_libraries:
VariantDir(lib_obj_dirs['cuttools'],
lib_src_dirs['cuttools'], duplicate = 0)
cuttools_lib = OLLibrary(name = 'cuttools',
target_dir = config['generic_lib_dir'],
mod_dependencies = ['oneloop', 'olcommon'],
linklibs = [ll for ll in config['link_libraries']
if ll == 'qcdloop'],
src_dir = lib_obj_dirs['cuttools'],
dp_src = cuttools_dp_src)
if 'samurai' in compile_libraries:
VariantDir(lib_obj_dirs['samurai'],
lib_src_dirs['samurai'], duplicate = 0)
samurai_lib = OLLibrary(name = 'samurai',
target_dir = config['generic_lib_dir'],
mod_dependencies = ['oneloop'],
linklibs = [ll for ll in config['link_libraries']
if ll == 'qcdloop'],
src_dir = lib_obj_dirs['samurai'],
dp_src = samurai_dp_src)
if 'collier' in compile_libraries:
collier_lib = OLLibrary(name = 'collier',
target_dir = config['generic_lib_dir'],
mod_dependencies = ['olcommon'],
src_dir = lib_src_dirs['collier'],
mp_src = collier_src_mp,
dp_src = collier_src_dp,
to_cpp = cpp_container)
# collier: preprocess include files, but don't add them to the list of source files
cpp_container.add(src_dir = lib_src_dirs['collier'],
dp_src = collier_inc_dp)
if 'openloops' in compile_libraries:
openloops_lib = OLLibrary(
name = 'openloops',
target_dir = config['generic_lib_dir'],
mod_dependencies = list(set(config['link_libraries'])
& set(['olcommon', 'collier', 'cuttools',
'samurai', 'oneloop', 'rambo'])),
linklibs = list(set(config['link_libraries']) & set(['rambo'])),
src_dir = lib_src_dirs['openloops'],
mp_src = openloops_mp_src,
dp_src = openloops_dp_src,
version_src = [openloops_version_src],
to_cpp = cpp_container)
if '@all' in config['import_env']:
imported_env = os.environ
else:
imported_env = {}
for envvar in config['import_env']:
imported_env[envvar] = os.environ.get(envvar, '')
env = Environment(tools = ['default', 'textfile'] + [config['fortran_tool']],
ENV = imported_env,
CCFLAGS = config['ccflags'] + config['generic_optimisation'],
FORTRANFLAGS = config['f77_flags'] + config['generic_optimisation'],
F90FLAGS = config['f90_flags'] + config['generic_optimisation'],
LINKFLAGS = config['link_flags'],
LIBPATH = [config['generic_lib_dir']],
RPATH = [Literal('\$$ORIGIN')],
F90 = config['fortran_compiler'],
FORTRAN = config['fortran_compiler'],
CC = config['cc'])
if config['fortran_tool'] == 'gfortran':
# SCons bug: FORTRANMODDIRPREFIX is missing in gfortran tool
env.Replace(FORTRANMODDIRPREFIX = '-J')
# determine gfortran version;
# do not use CCVERSION, because mit might not be from gcc
gfort_exitcode = 1
try:
gfort_proc = subprocess.Popen(
[config['fortran_compiler'], '-dumpversion'],
stdout=subprocess.PIPE)
gfort_out, gfort_err = gfort_proc.communicate()
gfort_exitcode = gfort_proc.returncode
except OSError:
pass
if not gfort_exitcode: # else ignore and continue without version check
if tuple(map(int, gfort_out.strip().split('.')[:2])) < (4,6):
print ('ERROR: This OpenLoops version requires gfortran 4.6 ' +
'or later (found %s)' % env.subst('$CCVERSION'))
Exit(1)
if compile_libraries:
if not GetOption('clean'):
if not cpp_container.run():
print '*** cpp failed ***'
Exit(1)
env_noautomatic = env.Clone()
env_noautomatic.AppendUnique(F90FLAGS = config['noautomatic'],
FORTRANFLAGS = config['noautomatic'])
if 'olcommon' in compile_libraries:
libolcommon = olcommon_lib.compile(env = env, shared = config['shared_libraries'])
env.Alias('olcommon', libolcommon)
Default('olcommon')
Clean(libolcommon, [lib_obj_dirs['olcommon'], lib_mod_dirs['olcommon']])
if 'rambo' in compile_libraries:
librambo = rambo_lib.compile(env = env, shared = config['shared_libraries'])
env.Alias('rambo', librambo)
Default('rambo')
Clean(librambo, [lib_obj_dirs['rambo'], lib_mod_dirs['rambo']])
if 'qcdloop' in compile_libraries:
libqcdloop = qcdloop_lib.compile(env = env_noautomatic, shared = config['shared_libraries'])
env.Alias('qcdloop', libqcdloop)
Default('qcdloop')
Clean(libqcdloop, [lib_obj_dirs['qcdloop']])
if 'oneloop' in compile_libraries:
liboneloop = oneloop_lib.compile(env = env, shared = config['shared_libraries'])
env.Alias('oneloop', liboneloop)
Default('oneloop')
Clean(liboneloop, [lib_obj_dirs['oneloop'], lib_mod_dirs['oneloop']])
if 'cuttools' in compile_libraries:
libcuttools = cuttools_lib.compile(env = env_noautomatic, shared = config['shared_libraries'])
env.Alias('cuttools', libcuttools)
Default('cuttools')
Clean(libcuttools, [lib_obj_dirs['cuttools'], lib_mod_dirs['cuttools']])
if 'samurai' in compile_libraries:
libsamurai = samurai_lib.compile(env = env, shared = config['shared_libraries'])
env.Alias('samurai', libsamurai)
Default('samurai')
Clean(libsamurai, [lib_obj_dirs['samurai'], lib_mod_dirs['samurai']])
if 'collier' in compile_libraries:
libcollier = collier_lib.compile(env = env, shared = config['shared_libraries'])
env.Alias('collier', libcollier)
Default('collier')
Clean(libcollier, [lib_obj_dirs['collier'], lib_mod_dirs['collier']])
if 'openloops' in compile_libraries:
libopenloops = openloops_lib.compile(env = env, shared = config['shared_libraries'])
env.Alias('openloops', libopenloops)
Default('openloops')
Clean(libopenloops, [lib_obj_dirs['openloops'], lib_mod_dirs['openloops']])
if GetOption('clean') and compile_libraries:
if not cpp_container.run(clean = True):
print '*** cpp cleanup failed ***'
Exit(1)
# ================= #
# Process libraries #
# ================= #
# parse process arguments
# <loops>=proc1,proc2,coll/...
# (several arguments possible, also with the same <loops>)
# --> process_list = [(loops,proc1),(loops,proc2),(loops,collproc1),...]
version_db_url = (config['remote_process_url'] + '/%s/processes/' +
str(config['process_api_version']) + '/versions.db')
collection_url = config['remote_process_url'] + '/%s/collections'
def split_processlist(loops, procs):
"""Convert (loops=L, procs=P1,P2,P3,...) to [(L,P1),(L,P2),(L,P3),...].
Replace collections (process ending with '/' or '.coll') by the list
of processes from the collection file on the server."""
proclist = sum([proclist.split(',') for proclist in procs.split()], [])
proclist = [proc for proc in proclist if proc]
collections = [coll[:-1] + '.coll' for coll in proclist if coll.endswith('/')]
collections.extend([coll for coll in proclist if coll.endswith('.coll')])
proclist = [(loops, proc) for proc in proclist
if not (proc.endswith('/') or coll.endswith('.coll'))]
for coll in collections:
coll_repo = False
for repo in config['process_repositories']:
if coll == OLToolbox.repo_name(repo) + '.coll':
coll_repo = repo
break
process_coll = []
if coll == 'all.coll':
for repo in config['process_repositories']:
process_db = OLToolbox.ProcessDB(db=(version_db_url % repo))
process_coll += process_db.content.keys()
elif coll_repo:
process_db = OLToolbox.ProcessDB(db=(version_db_url % coll_repo))
process_coll += process_db.content.keys()
else:
found_collection = False
first_repo = True
for repo in config['process_repositories']:
if first_repo:
# check if the collection is available locally
process_coll_add = OLToolbox.import_list(coll, fatal=False)
else:
process_coll_add = None
if process_coll_add is None:
# check if the collection is available in the repository
process_coll_add = OLToolbox.import_list(
os.path.join(collection_url % repo, coll), fatal=False)
if process_coll_add is not None:
if not '<' in ''.join(process_coll_add):
# if it is not an html file with an error message
found_collection = True
process_coll.extend(process_coll_add)
first_repo = False
if not found_collection:
print 'ERROR: process collection ' + coll + ' not found.'
Exit(1)
proclist += [(loops, proc) for proc in process_coll]
return proclist
def get_auto_loops((loops, processlib)):
"""Determine 'auto' loops specifications from version.info in the process source directory."""
if loops == 'auto':
loops = OLToolbox.import_dictionary(
os.path.join(config['process_src_dir'], processlib, 'version.info'),
error_message = (
'ERROR: auto loops specification not available for ' + processlib)
)['loops']
if loops == 'auto' or loops not in OLBaseConfig.loops_specifications:
print 'ERROR: invalid loops specification for', processlib
Exit(1)
return (loops, processlib)
def find_process_src(generate = True):
"""Find all generated / downloaded processes.
if generate: return (loops,process) for all processes which exist
(i.e. there is a directory which contains version.info)
if only download (generate = False): return only those processes
for which version.info contains 'hash'
(i.e. they are controlled by the downloader)."""
process_list = []
if os.path.isdir(config['process_src_dir']):
process_directories = os.listdir(config['process_src_dir'])
else:
return process_list
for procdir in process_directories:
version_info = OLToolbox.import_dictionary(
os.path.join(config['process_src_dir'], procdir, 'version.info'),
fatal = False)
if version_info:
loops = version_info['loops']
process_hash = version_info.get('hash', None)
if process_hash or generate:
# download: only add if process_hash != None;
# generate: always add
process_list.append((loops, procdir))
return process_list
def revoke_processes():
"""Revocation of deprecated processes.
Remove processes (src, obj, lib) listed in 'revoke' on the server
if the process source directory contains version.info with 'hash'."""
revocation_list = OLToolbox.import_list(os.path.join(collection_url, 'revoke'), fatal = False)
if revocation_list is None:
revocation_list = []
for proc in revocation_list:
processlib_src_dir = os.path.join(config['process_src_dir'], proc)
processlib_obj_dir = os.path.join(config['process_obj_dir'], proc)
if os.path.isdir(processlib_src_dir):
version_info = OLToolbox.import_dictionary(os.path.join(processlib_src_dir, 'version.info'), fatal = False)
if version_info and 'hash' in version_info:
print 'revoking', proc
Execute(Delete(processlib_src_dir))
if os.path.isdir(processlib_obj_dir):
Execute(Delete(processlib_obj_dir))
revoke_libs = [os.path.join(config['process_lib_dir'], 'libopenloops_' + proc + '_' + lps + '.*')
for lps in OLBaseConfig.loops_specifications if lps != 'auto']
revoke_libs = sum([Glob(patt) for patt in revoke_libs], [])
if revoke_libs:
Execute(Delete(revoke_libs))
def download_processes(processes):
"""Download processes"""
try:
err = subprocess.call(
['python2', config['process_download_script']] +
force_download_flag + processes +
['='.join(arg) for arg in commandline_options])
except OSError:
# try again with 'python' instead of 'python2'
err = subprocess.call(
['python', config['process_download_script']] +
force_download_flag + processes +
['='.join(arg) for arg in commandline_options])
if err:
print 'ERROR: process downloader failed.'
Exit(1)
def generate_process(loops, processlib):
"""Generate a process library"""
if subprocess.call(
[scons_cmd, '-Q'] + generator_options +
['-f', config['code_generator_script'],
'PROC=' + processlib, 'LOOPS=' + loops] +
['='.join(arg) for arg in commandline_options]) != 0:
print 'ERROR: code generator failed.'
Exit(1)
process_list = sum([split_processlist(loops, procs) for (loops, procs) in process_arguments], [])
if config['process_update']:
process_list.extend(find_process_src(generate_process_true))
if download_process_true:
proc_ls = list(set([proc for loops, proc in process_list]))
if proc_ls or config['process_update']:
revoke_processes()
download_processes(proc_ls)
process_list = map(get_auto_loops, process_list)
process_list = list(set(process_list))
env.Append(RPATH = [Literal('\$$ORIGIN/../lib')])
for (loops, processlib) in process_list:
print 'process library:', processlib + '_' + loops
# process library name and directories
processlib_name = 'openloops_' + processlib.lower() + '_' + loops
processlib_info = os.path.join(config['process_lib_dir'], 'lib' + processlib_name + '.info')
processlib_src_dir = os.path.join(config['process_src_dir'], processlib)
processlib_obj_dir = os.path.join(config['process_obj_dir'], processlib)
# run the process code generator
if generate_process_true:
generate_process(loops, processlib)
# compile process
if config['compile'] > 0 and not GetOption('clean'):
# list of process library source files
process_dp_src, process_mp_src, info_files = OLToolbox.get_processlib_src(
loops, processlib, config['process_src_dir'],
compile_extra=config['compile_extra'])
# prepend global libary info
library_info_file = os.path.join(processlib_src_dir, 'info_' + processlib + '.txt')
if os.path.isfile(library_info_file):
info_files.insert(0, library_info_file)
# set up process library source files for preprocessing
process_cpp_container = CPPContainer(
scons_cmd = scons_cmd,
mp = config['precision'],
cpp_defs = cpp_defines + [OLBaseConfig.loops_cppdefs[loopspec] for loopspec in loops],
target = 'cpp_' + processlib,
target_prefix = os.path.join('..', '..', processlib_obj_dir, ''))
# set up process library
process_lib = OLLibrary(name = processlib_name,
target_dir = config['process_lib_dir'],
# need to include oneloop mod dir for ifort
mod_dependencies = ['olcommon', 'openloops', 'oneloop'],
mod_dir = os.path.join(processlib_obj_dir, 'mod'),
mp_src = process_mp_src,
dp_src = process_dp_src,
to_cpp = process_cpp_container)
# preprocess process library source files
if not process_cpp_container.run():
print '***', processlib, 'cpp failed ***'
Exit(1)
# delete all libraries for the process
delete_libs = [os.path.join(config['process_lib_dir'],
'libopenloops_' + processlib.lower() + '_' + lps + '.*')
for lps in OLBaseConfig.loops_specifications if lps not in ('auto', loops)]
delete_libs = sum([Glob(patt) for patt in delete_libs], [])
if delete_libs:
Execute(Delete(delete_libs))
# compile process library
libprocess = process_lib.compile(
env = env,
shared = config['shared_libraries'],
env_mod = [
('^(virtual_\d|tensorsum_|loop_)',
{'F90FLAGS': config['f90_flags'] + config['loop_optimisation']}),
('',
{'F90FLAGS': config['f90_flags'] + config['born_optimisation']})]
)
# concatenate subprocess info files to a library info file
libprocess_info = env.Substfile(processlib_info, info_files, LINESEPARATOR = '')
libprocess += libprocess_info
Alias('lib' + processlib, libprocess)
Default('lib' + processlib)
if GetOption('clean'):
if config['compile'] > 0:
# delete process object code
Execute(Delete(processlib_obj_dir))
delete_libs = [os.path.join(config['process_lib_dir'],
'libopenloops_' + processlib + '_' + lps + '.*')
for lps in OLBaseConfig.loops_specifications if lps != 'auto']
delete_libs = sum([Glob(patt) for patt in delete_libs], [])
if delete_libs:
Execute(Delete(delete_libs))
if 'src' in config['clean']:
# delete process library source directory
Execute(Delete(processlib_src_dir))
if GetOption('clean') and 'procs' in config['clean']:
Execute(Delete(config['process_obj_dir']))
Execute(Delete(config['process_lib_dir']))
if 'src' in config['clean']:
Execute(Delete(config['process_src_dir']))