-
Notifications
You must be signed in to change notification settings - Fork 13
/
wscript
752 lines (635 loc) · 27.2 KB
/
wscript
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
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
from __future__ import print_function
import os, os.path
import sys
import shutil
import types
import warnings
from waflib import TaskGen, Task, Options, Build, Utils
from waflib.Errors import WafError
import wutils
try:
set
except NameError:
from sets import Set as set # Python 2.3 fallback
all_modules = []
for dirname in os.listdir('src'):
if dirname.startswith('.') or dirname == 'CVS':
continue
path = os.path.join('src', dirname)
if not os.path.isdir(path):
continue
if os.path.exists(os.path.join(path, 'wscript')):
all_modules.append(dirname)
all_modules.sort()
def options(opt):
opt.add_option('--enable-rpath',
help=("Link programs with rpath"
" (normally not needed, see "
" --run and --shell; moreover, only works in some"
" specific platforms, such as Linux and Solaris)"),
action="store_true", dest='enable_rpath', default=False)
opt.add_option('--enable-modules',
help=("Build only these modules (and dependencies)"),
dest='enable_modules')
opt.load('boost', tooldir=['waf-tools'])
for module in all_modules:
opt.recurse(module, mandatory=False)
def configure(conf):
conf.env['REQUIRED_BOOST_LIBS'] = []
for module in all_modules:
conf.recurse (module, name="required_boost_libs", mandatory=False)
if conf.env['REQUIRED_BOOST_LIBS'] is not []:
conf.load('boost')
conf.check_boost(lib=' '.join (conf.env['REQUIRED_BOOST_LIBS']), mandatory=False)
if not conf.env['LIB_BOOST']:
conf.check_boost(lib=' '.join (conf.env['REQUIRED_BOOST_LIBS']), libpath="/usr/lib64", mandatory=False)
if not conf.env['LIB_BOOST']:
conf.env['LIB_BOOST'] = []
# Append blddir to the module path before recursing into modules
blddir = os.path.abspath(os.path.join(conf.bldnode.abspath(), conf.variant))
conf.env.append_value('NS3_MODULE_PATH', blddir)
for module in all_modules:
conf.recurse(module, mandatory=False)
# Remove duplicate path items
conf.env['NS3_MODULE_PATH'] = wutils.uniquify_list(conf.env['NS3_MODULE_PATH'])
if Options.options.enable_rpath:
conf.env.append_value('RPATH', '-Wl,-rpath,%s' % (os.path.join(blddir),))
## Used to link the 'test-runner' program with all of ns-3 code
conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
# we need the 'ns3module' waf "feature" to be created because code
# elsewhere looks for it to find the ns3 module objects.
@TaskGen.feature('ns3module')
def _add_test_code(module):
pass
def create_ns3_module(bld, name, dependencies=(), test=False):
static = bool(bld.env.ENABLE_STATIC_NS3)
# Create a separate library for this module.
if static:
module = bld(features='cxx cxxstlib ns3module')
else:
module = bld(features='cxx cxxshlib ns3module')
module.target = '%s/ns%s-%s%s' % (bld.srcnode.path_from(module.path), wutils.VERSION,
name, bld.env.BUILD_SUFFIX)
linkflags = []
cxxflags = []
ccflags = []
if not static:
cxxflags = module.env['shlib_CXXFLAGS']
ccflags = module.env['shlib_CXXFLAGS']
# Turn on the link flags for shared libraries if we have the
# proper compiler and platform.
if module.env['CXX_NAME'] in ['gcc', 'icc'] and module.env['WL_SONAME_SUPPORTED']:
# Get the module library name without any relative paths
# at its beginning because all of the libraries will end
# up in the same directory.
module_library_name = module.env.cshlib_PATTERN % (os.path.basename(module.target),)
linkflags = '-Wl,--soname=' + module_library_name
cxxdefines = ["NS3_MODULE_COMPILATION"]
ccdefines = ["NS3_MODULE_COMPILATION"]
module.env.append_value('CXXFLAGS', cxxflags)
module.env.append_value('CCFLAGS', ccflags)
module.env.append_value('LINKFLAGS', linkflags)
module.env.append_value('CXXDEFINES', cxxdefines)
module.env.append_value('CCDEFINES', ccdefines)
module.is_static = static
module.vnum = wutils.VNUM
# Add the proper path to the module's name.
# Set the libraries this module depends on.
module.module_deps = list(dependencies)
module.install_path = "${LIBDIR}"
module.name = "ns3-" + name
module.dependencies = dependencies
# Initially create an empty value for this because the pcfile
# writing task assumes every module has a uselib attribute.
module.uselib = ''
module.use = ['ns3-' + dep for dep in dependencies]
module.test = test
module.is_ns3_module = True
module.ns3_dir_location = bld.path.path_from(bld.srcnode)
module.env.append_value("INCLUDES", '#')
module.pcfilegen = bld(features='ns3pcfile')
module.pcfilegen.module = module.name
return module
@TaskGen.feature("ns3testlib")
@TaskGen.before_method("apply_incpaths")
def apply_incpaths_ns3testlib(self):
if not self.source:
return
testdir = self.source[-1].parent.path_from(self.bld.srcnode)
self.env.append_value("DEFINES", 'NS_TEST_SOURCEDIR="%s"' % (testdir,))
def create_ns3_module_test_library(bld, name):
# Create an ns3 module for the test library that depends only on
# the module being tested.
library_name = name + "-test"
library = bld.create_ns3_module(library_name, [name], test=True)
library.features += " ns3testlib"
# Modify attributes for the test library that are different from a
# normal module.
del library.is_ns3_module
library.is_ns3_module_test_library = True
library.module_name = 'ns3-' + name
# Add this module and test library to the list.
bld.env.append_value('NS3_MODULES_WITH_TEST_LIBRARIES', [(library.module_name, library.name)])
# Set the include path from the build directory to modules.
relative_path_from_build_to_here = bld.path.path_from(bld.bldnode)
include_flag = '-I' + relative_path_from_build_to_here
library.env.append_value('CXXFLAGS', include_flag)
library.env.append_value('CCFLAGS', include_flag)
return library
def create_obj(bld, *args):
warnings.warn("(in %s) Use bld(...) call now, instead of bld.create_obj(...)" % str(bld.path),
DeprecationWarning, stacklevel=2)
return bld(*args)
def ns3_python_bindings(bld):
# this method is called from a module wscript, so remember bld.path is not bindings/python!
module_abs_src_path = bld.path.abspath()
module = os.path.basename(module_abs_src_path)
env = bld.env
env.append_value("MODULAR_BINDINGS_MODULES", "ns3-"+module)
if Options.options.apiscan:
return
if not env['ENABLE_PYTHON_BINDINGS']:
return
bindings_dir = bld.path.find_dir("bindings")
if bindings_dir is None or not os.path.exists(bindings_dir.abspath()):
warnings.warn("(in %s) Requested to build modular python bindings, but apidefs dir not found "
"=> skipped the bindings." % str(bld.path),
Warning, stacklevel=2)
return
if ("ns3-%s" % (module,)) not in env.NS3_ENABLED_MODULES:
#print "bindings for module %s which is not enabled, skip" % module
return
env.append_value('PYTHON_MODULES_BUILT', module)
try:
apidefs = env['PYTHON_BINDINGS_APIDEFS'].replace("-", "_")
except AttributeError:
# we likely got an empty list for env['PYTHON_BINDINGS_APIDEFS']
return
#debug = ('PYBINDGEN_DEBUG' in os.environ)
debug = True # XXX
source = [bld.srcnode.find_resource('bindings/python/ns3modulegen-modular.py'),
bld.path.find_resource("bindings/modulegen__%s.py" % apidefs)]
modulegen_customizations = bindings_dir.find_resource("modulegen_customizations.py")
if modulegen_customizations is not None:
source.append(modulegen_customizations)
modulegen_local = bld.path.find_resource("bindings/modulegen_local.py")
# the local customization file may or not exist
if modulegen_local is not None:
source.append("bindings/modulegen_local.py")
module_py_name = module.replace('-', '_')
module_target_dir = bld.srcnode.find_dir("bindings/python/ns").path_from(bld.path)
# if bindings/<module>.py exists, it becomes the module frontend, and the C extension befomes _<module>
if bld.path.find_resource("bindings/%s.py" % (module_py_name,)) is not None:
bld(features='copy',
source=("bindings/%s.py" % (module_py_name,)),
target=('%s/%s.py' % (module_target_dir, module_py_name)))
extension_name = '_%s' % (module_py_name,)
bld.install_files('${PYTHONARCHDIR}/ns', ["bindings/%s.py" % (module_py_name,)])
else:
extension_name = module_py_name
target = ['bindings/ns3module.cc', 'bindings/ns3module.h', 'bindings/ns3modulegen.log']
#if not debug:
# target.append('ns3modulegen.log')
argv = ['NS3_ENABLED_FEATURES=${FEATURES}',
'GCC_RTTI_ABI_COMPLETE=${GCC_RTTI_ABI_COMPLETE}',
'${PYTHON}']
#if debug:
# argv.extend(["-m", "pdb"])
argv.extend(['${SRC[0]}', module_abs_src_path, apidefs, extension_name, '${TGT[0]}'])
argv.extend(['2>', '${TGT[2]}']) # 2> ns3modulegen.log
features = []
for (name, caption, was_enabled, reason_not_enabled) in env['NS3_OPTIONAL_FEATURES']:
if was_enabled:
features.append(name)
bindgen = bld(features='command', source=source, target=target, command=argv)
bindgen.env['FEATURES'] = ','.join(features)
bindgen.dep_vars = ['FEATURES', "GCC_RTTI_ABI_COMPLETE"]
bindgen.before = 'cxx'
bindgen.after = 'gen_ns3_module_header'
bindgen.name = "pybindgen(ns3 module %s)" % module
bindgen.install_path = None
# generate the extension module
pymod = bld(features='cxx cxxshlib pyext')
pymod.source = ['bindings/ns3module.cc']
pymod.target = '%s/%s' % (module_target_dir, extension_name)
pymod.name = 'ns3module_%s' % module
pymod.use = ["%s" % mod for mod in pymod.env['NS3_ENABLED_MODULES']] # Should be '"ns3-"+module', but see bug 1117
if pymod.env['ENABLE_STATIC_NS3']:
if sys.platform == 'darwin':
pymod.env.append_value('LINKFLAGS', '-Wl,-all_load')
for mod in pymod.usel:
#mod = mod.split("--lib")[0]
pymod.env.append_value('LINKFLAGS', '-l' + mod)
else:
pymod.env.append_value('LINKFLAGS', '-Wl,--whole-archive,-Bstatic')
for mod in pymod.use:
#mod = mod.split("--lib")[0]
pymod.env.append_value('LINKFLAGS', '-l' + mod)
pymod.env.append_value('LINKFLAGS', '-Wl,-Bdynamic,--no-whole-archive')
defines = list(pymod.env['DEFINES'])
defines.extend(['NS_DEPRECATED=', 'NS3_DEPRECATED_H'])
if Options.platform == 'win32':
try:
defines.remove('_DEBUG') # causes undefined symbols on win32
except ValueError:
pass
pymod.env['DEFINES'] = defines
pymod.includes = '# bindings'
pymod.install_path = '${PYTHONARCHDIR}/ns'
# Workaround to a WAF bug, remove this when ns-3 upgrades to WAF > 1.6.10
# https://www.nsnam.org/bugzilla/show_bug.cgi?id=1335
# http://code.google.com/p/waf/issues/detail?id=1098
if Utils.unversioned_sys_platform() == 'darwin':
pymod.mac_bundle = True
return pymod
def build(bld):
bld.create_ns3_module = types.MethodType(create_ns3_module, bld)
bld.create_ns3_module_test_library = types.MethodType(create_ns3_module_test_library, bld)
bld.create_obj = types.MethodType(create_obj, bld)
bld.ns3_python_bindings = types.MethodType(ns3_python_bindings, bld)
# Remove these modules from the list of all modules.
for not_built in bld.env['MODULES_NOT_BUILT']:
# XXX Because these modules are located in subdirectories of
# test, their names in the all_modules list include the extra
# relative path "test/". If these modules are moved into the
# src directory, then this if block should be removed.
if not_built == 'ns3tcp' or not_built == 'ns3wifi':
not_built = 'test/' + not_built
if not_built in all_modules:
all_modules.remove(not_built)
bld.recurse(list(all_modules))
for module in all_modules:
modheader = bld(features='ns3moduleheader')
modheader.module = module.split('/')[-1]
class ns3pcfile_task(Task.Task):
after = 'cxx'
def __str__(self):
"string to display to the user"
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
return 'pcfile: %s\n' % (tgt_str)
def runnable_status(self):
return super(ns3pcfile_task, self).runnable_status()
def _self_libs(self, env, name, libdir):
if env['ENABLE_STATIC_NS3']:
path_st = 'STLIBPATH_ST'
lib_st = 'STLIB_ST'
lib_marker = 'STLIB_MARKER'
else:
path_st = 'LIBPATH_ST'
lib_st = 'LIB_ST'
lib_marker = 'SHLIB_MARKER'
retval = [env[path_st] % libdir]
if env[lib_marker]:
retval.append(env[lib_marker])
retval.append(env[lib_st] % name)
return retval
def _lib(self, env, dep):
libpath = env['LIBPATH_%s' % dep]
linkflags = env['LINKFLAGS_%s' % dep]
libs = env['LIB_%s' % dep]
retval = []
for path in libpath:
retval.append(env['LIBPATH_ST'] % path)
retval = retval + linkflags
for lib in libs:
retval.append(env['LIB_ST'] % lib)
return retval
def _listify(self, v):
if isinstance(v, list):
return v
else:
return [v]
def _cflags(self, dep):
flags = self.env['CFLAGS_%s' % dep]
return self._listify(flags)
def _cxxflags(self, dep):
return self._listify(self.env['CXXFLAGS_%s' % dep])
def _defines(self, dep):
return [self.env['DEFINES_ST'] % define for define in self.env['DEFINES_%s' % dep]]
def _includes(self, dep):
includes = self.env['INCLUDES_%s' % dep]
return [self.env['CPPPATH_ST'] % include for include in includes]
def _generate_pcfile(self, name, use, env, outfilename):
outfile = open(outfilename, 'wt')
prefix = env.PREFIX
includedir = Utils.subst_vars('${INCLUDEDIR}/%s%s' % (wutils.APPNAME, wutils.VERSION), env)
libdir = env.LIBDIR
libs = self._self_libs(env, "%s%s-%s%s" % (wutils.APPNAME, wutils.VERSION, name[4:], env.BUILD_SUFFIX), '${libdir}')
for dep in use:
libs += self._lib(env, dep)
for dep in env.LIBS:
libs += self.env['LIB_ST'] % dep
cflags = [self.env['CPPPATH_ST'] % '${includedir}']
requires = []
for dep in use:
cflags = cflags + self._cflags(dep) + self._cxxflags(dep) + \
self._defines(dep) + self._includes(dep)
if dep.startswith('ns3-'):
dep_name = dep[4:]
requires.append("libns%s-%s%s" % (wutils.VERSION, dep_name, env.BUILD_SUFFIX))
print("""\
prefix=%s
libdir=%s
includedir=%s
Name: lib%s
Description: ns-3 module %s
Version: %s
Libs: %s
Cflags: %s
Requires: %s\
""" % (prefix, libdir, includedir,
name, name, wutils.VERSION, ' '.join(libs), ' '.join(cflags), ' '.join(requires)), file=outfile)
outfile.close()
def run(self):
output_filename = self.outputs[0].abspath()
self._generate_pcfile(self.module.name,
self.module.to_list(self.module.use),
self.env, output_filename)
@TaskGen.feature('ns3pcfile')
@TaskGen.after_method('process_rule')
def apply(self):
module = self.bld.find_ns3_module(self.module)
output_filename = 'lib%s.pc' % os.path.basename(module.target)
output_node = self.path.find_or_declare(output_filename)
assert output_node is not None, str(self)
task = self.create_task('ns3pcfile')
self.bld.install_files('${LIBDIR}/pkgconfig', output_node)
task.set_outputs([output_node])
task.module = module
@TaskGen.feature('ns3header')
@TaskGen.after_method('process_rule')
def apply_ns3header(self):
if self.module is None:
raise WafError("'module' missing on ns3headers object %s" % self)
ns3_dir_node = self.bld.path.find_or_declare("ns3")
for filename in set(self.to_list(self.source)):
src_node = self.path.find_resource(filename)
if src_node is None:
raise WafError("source ns3 header file %s not found" % (filename,))
dst_node = ns3_dir_node.find_or_declare(src_node.name)
assert dst_node is not None
task = self.create_task('ns3header')
task.mode = getattr(self, 'mode', 'install')
if task.mode == 'install':
self.bld.install_files('${INCLUDEDIR}/%s%s/ns3' % (wutils.APPNAME, wutils.VERSION), [src_node])
task.set_inputs([src_node])
task.set_outputs([dst_node])
else:
task.header_to_remove = dst_node
self.headers = set(self.to_list(self.source))
self.source = '' # tell WAF not to process these files further
class ns3header_task(Task.Task):
before = 'cxx gen_ns3_module_header'
color = 'BLUE'
def __str__(self):
"string to display to the user"
env = self.env
src_str = ' '.join([a.bldpath() for a in self.inputs])
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
if self.outputs: sep = ' -> '
else: sep = ''
if self.mode == 'remove':
return 'rm-ns3-header %s' % (self.header_to_remove.abspath(),)
return 'install-ns3-header: %s' % (tgt_str)
def __repr__(self):
return str(self)
def uid(self):
try:
return self.uid_
except AttributeError:
m = Utils.md5()
up = m.update
up(self.__class__.__name__.encode())
for x in self.inputs + self.outputs:
up(x.abspath().encode())
up(self.mode.encode())
if self.mode == 'remove':
up(self.header_to_remove.abspath().encode())
self.uid_ = m.digest()
return self.uid_
def runnable_status(self):
if self.mode == 'remove':
if os.path.exists(self.header_to_remove.abspath()):
return Task.RUN_ME
else:
return Task.SKIP_ME
else:
return super(ns3header_task, self).runnable_status()
def run(self):
if self.mode == 'install':
assert len(self.inputs) == len(self.outputs)
inputs = [node.abspath() for node in self.inputs]
outputs = [node.abspath() for node in self.outputs]
for src, dst in zip(inputs, outputs):
try:
os.chmod(dst, 0o600)
except OSError:
pass
shutil.copy2(src, dst)
## make the headers in builddir read-only, to prevent
## accidental modification
os.chmod(dst, 0o400)
return 0
else:
assert len(self.inputs) == 0
assert len(self.outputs) == 0
out_file_name = self.header_to_remove.abspath()
try:
os.unlink(out_file_name)
except OSError as ex:
if ex.errno != 2:
raise
return 0
@TaskGen.feature('ns3privateheader')
@TaskGen.after_method('process_rule')
def apply_ns3privateheader(self):
if self.module is None:
raise WafError("'module' missing on ns3headers object %s" % self)
ns3_dir_node = self.bld.path.find_or_declare("ns3/private")
for filename in set(self.to_list(self.source)):
src_node = self.path.find_resource(filename)
if src_node is None:
raise WafError("source ns3 header file %s not found" % (filename,))
dst_node = ns3_dir_node.find_or_declare(src_node.name)
assert dst_node is not None
task = self.create_task('ns3privateheader')
task.mode = getattr(self, 'mode', 'install')
if task.mode == 'install':
task.set_inputs([src_node])
task.set_outputs([dst_node])
else:
task.header_to_remove = dst_node
self.headers = set(self.to_list(self.source))
self.source = '' # tell WAF not to process these files further
class ns3privateheader_task(Task.Task):
before = 'cxx gen_ns3_module_header'
after = 'ns3header'
color = 'BLUE'
def __str__(self):
"string to display to the user"
env = self.env
src_str = ' '.join([a.bldpath() for a in self.inputs])
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
if self.outputs: sep = ' -> '
else: sep = ''
if self.mode == 'remove':
return 'rm-ns3-header %s' % (self.header_to_remove.abspath(),)
return 'install-ns3-header: %s' % (tgt_str)
def __repr__(self):
return str(self)
def uid(self):
try:
return self.uid_
except AttributeError:
m = Utils.md5()
up = m.update
up(self.__class__.__name__.encode())
for x in self.inputs + self.outputs:
up(x.abspath().encode())
up(self.mode.encode())
if self.mode == 'remove':
up(self.header_to_remove.abspath().encode())
self.uid_ = m.digest()
return self.uid_
def runnable_status(self):
if self.mode == 'remove':
if os.path.exists(self.header_to_remove.abspath()):
return Task.RUN_ME
else:
return Task.SKIP_ME
else:
return super(ns3privateheader_task, self).runnable_status()
def run(self):
if self.mode == 'install':
assert len(self.inputs) == len(self.outputs)
inputs = [node.abspath() for node in self.inputs]
outputs = [node.abspath() for node in self.outputs]
for src, dst in zip(inputs, outputs):
try:
os.chmod(dst, 0o600)
except OSError:
pass
shutil.copy2(src, dst)
## make the headers in builddir read-only, to prevent
## accidental modification
os.chmod(dst, 0o400)
return 0
else:
assert len(self.inputs) == 0
assert len(self.outputs) == 0
out_file_name = self.header_to_remove.abspath()
try:
os.unlink(out_file_name)
except OSError as ex:
if ex.errno != 2:
raise
return 0
class gen_ns3_module_header_task(Task.Task):
before = 'cxx'
after = 'ns3header'
color = 'BLUE'
def runnable_status(self):
if self.mode == 'remove':
if os.path.exists(self.header_to_remove.abspath()):
return Task.RUN_ME
else:
return Task.SKIP_ME
else:
return super(gen_ns3_module_header_task, self).runnable_status()
def __str__(self):
"string to display to the user"
env = self.env
src_str = ' '.join([a.bldpath() for a in self.inputs])
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
if self.outputs: sep = ' -> '
else: sep = ''
if self.mode == 'remove':
return 'rm-module-header %s' % (self.header_to_remove.abspath(),)
return 'gen-module-header: %s' % (tgt_str)
def run(self):
if self.mode == 'remove':
assert len(self.inputs) == 0
assert len(self.outputs) == 0
out_file_name = self.header_to_remove.abspath()
try:
os.unlink(out_file_name)
except OSError as ex:
if ex.errno != 2:
raise
return 0
assert len(self.outputs) == 1
out_file_name = self.outputs[0].get_bld().abspath()#self.env)
header_files = [os.path.basename(node.abspath()) for node in self.inputs]
outfile = open(out_file_name, "w")
header_files.sort()
print("""
#ifdef NS3_MODULE_COMPILATION
# error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
#endif
#ifndef NS3_MODULE_%s
""" % (self.module.upper().replace('-', '_'),), file=outfile)
# if self.module_deps:
# print >> outfile, "// Module dependencies:"
# for dep in self.module_deps:
# print >> outfile, "#include \"%s-module.h\"" % dep
print(file=outfile)
print("// Module headers:", file=outfile)
for header in header_files:
print("#include \"%s\"" % (header,), file=outfile)
print("#endif", file=outfile)
outfile.close()
return 0
def sig_explicit_deps(self):
self.m.update('\n'.join(sorted([node.abspath() for node in self.inputs])).encode('utf-8'))
return self.m.digest()
def unique_id(self):
try:
return self.uid
except AttributeError:
"this is not a real hot zone, but we want to avoid surprizes here"
m = Utils.md5()
m.update("ns-3-module-header-%s" % self.module)
self.uid = m.digest()
return self.uid
# Generates a 'ns3/foo-module.h' header file that includes all public
# ns3 headers of a certain module.
@TaskGen.feature('ns3moduleheader')
@TaskGen.after_method('process_rule')
def apply_ns3moduleheader(self):
## get all of the ns3 headers
ns3_dir_node = self.bld.path.find_or_declare("ns3")
all_headers_inputs = []
found_the_module = False
for ns3headers in self.bld.all_task_gen:
if 'ns3header' in getattr(ns3headers, "features", []):
if ns3headers.module != self.module:
continue
found_the_module = True
for source in sorted(ns3headers.headers):
source = os.path.basename(source)
node = ns3_dir_node.find_or_declare(os.path.basename(source))
if node is None:
fatal("missing header file %s" % (source,))
all_headers_inputs.append(node)
if not found_the_module:
raise WafError("error finding headers for module %s" % self.module)
if not all_headers_inputs:
return
try:
module_obj = self.bld.get_tgen_by_name("ns3-" + self.module)
except WafError: # maybe the module was disabled, and therefore removed
return
all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)]
task = self.create_task('gen_ns3_module_header')
task.module = self.module
task.mode = getattr(self, "mode", "install")
if task.mode == 'install':
assert module_obj is not None, self.module
self.bld.install_files('${INCLUDEDIR}/%s%s/ns3' % (wutils.APPNAME, wutils.VERSION),
ns3_dir_node.find_or_declare("%s-module.h" % self.module))
task.set_inputs(all_headers_inputs)
task.set_outputs(all_headers_outputs)
task.module_deps = module_obj.module_deps
else:
task.header_to_remove = all_headers_outputs[0]