LEFT | RIGHT |
1 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8;
-*- | 1 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8;
-*- |
2 | 2 |
3 import os, os.path | 3 import os, os.path |
| 4 import sys |
4 import shutil | 5 import shutil |
5 import types | 6 import types |
6 import warnings | 7 import warnings |
7 | 8 |
8 import TaskGen | 9 import TaskGen |
9 import Task | 10 import Task |
10 import Options | 11 import Options |
11 import Build | 12 import Build |
12 import Utils | 13 import Utils |
| 14 import Constants |
| 15 |
| 16 import ccroot |
| 17 ccroot.USE_TOP_LEVEL = True |
13 | 18 |
14 try: | 19 try: |
15 set | 20 set |
16 except NameError: | 21 except NameError: |
17 from sets import Set as set # Python 2.3 fallback | 22 from sets import Set as set # Python 2.3 fallback |
18 | 23 |
19 all_modules = ( | 24 all_modules = [ |
20 'core', | 25 'core', |
21 'common', | 26 'network', |
22 'simulator', | 27 'config-store', |
23 'contrib', | 28 'internet', |
24 'node', | 29 'propagation', |
25 'internet-stack', | 30 'point-to-point', |
26 'devices/point-to-point', | 31 'csma', |
27 'devices/csma', | 32 'emu', |
28 'devices/emu', | 33 'bridge', |
29 'devices/bridge', | 34 'tap-bridge', |
30 'devices/tap-bridge', | 35 'virtual-net-device', |
31 'devices/virtual-net-device', | 36 'applications', |
32 'applications/onoff', | 37 'nix-vector-routing', |
33 'applications/packet-sink', | 38 'olsr', |
34 'applications/udp-echo', | 39 'aodv', |
35 'routing/nix-vector-routing', | 40 'dsdv', |
36 'routing/olsr', | 41 'click', |
37 'routing/global-routing', | 42 'openflow', |
38 'routing/static-routing', | |
39 'routing/list-routing', | |
40 'routing/aodv', | |
41 'mobility', | 43 'mobility', |
42 'devices/wifi', | 44 'wifi', |
43 'helper', | 45 'netanim', |
44 'contrib/stats', | 46 'stats', |
45 'applications/v4ping', | 47 'uan', |
46 'devices/uan', | 48 'spectrum', |
47 'devices/spectrum', | 49 'mesh',··· |
48 'devices/mesh',··· | |
49 'devices/mesh/dot11s', | |
50 'devices/mesh/flame', | |
51 'applications/ping6', | |
52 'applications/radvd', | |
53 'test', | 50 'test', |
54 'test/perf', | |
55 'test/ns3tcp', | 51 'test/ns3tcp', |
56 'test/nsctcp', | |
57 'test/ns3wifi', | 52 'test/ns3wifi', |
58 'contrib/flow-monitor', | 53 'flow-monitor', |
59 'applications/udp-client-server', | 54 'wimax', |
60 'devices/wimax', | 55 'lte', |
61 'mpi', | 56 'mpi', |
62 'contrib/topology-read', | 57 'topology-read', |
63 'contrib/energy', | 58 'energy', |
64 'contrib/jamming', | 59 'tools', |
65 ) | 60 'visualizer', |
| 61 'point-to-point-layout', |
| 62 'csma-layout', |
| 63 'template', |
| 64 'jamming', |
| 65 ] |
66 | 66 |
67 def set_options(opt): | 67 def set_options(opt): |
68 opt.sub_options('simulator') | 68 opt.sub_options('core') |
| 69 opt.sub_options('click') |
| 70 opt.sub_options('openflow') |
69 | 71 |
70 opt.add_option('--enable-rpath', | 72 opt.add_option('--enable-rpath', |
71 help=("Link programs with rpath" | 73 help=("Link programs with rpath" |
72 " (normally not needed, see " | 74 " (normally not needed, see " |
73 " --run and --shell; moreover, only works in some" | 75 " --run and --shell; moreover, only works in some" |
74 " specific platforms, such as Linux and Solaris)"), | 76 " specific platforms, such as Linux and Solaris)"), |
75 action="store_true", dest='enable_rpath', default=False) | 77 action="store_true", dest='enable_rpath', default=False) |
76 ···· | 78 ···· |
77 opt.add_option('--enable-modules', | 79 opt.add_option('--enable-modules', |
78 help=("Build only these modules (and dependencies)"), | 80 help=("Build only these modules (and dependencies)"), |
79 dest='enable_modules') | 81 dest='enable_modules') |
80 | 82 |
81 def configure(conf): | 83 def configure(conf): |
82 conf.sub_config('core') | 84 conf.sub_config('core') |
83 conf.sub_config('simulator') | 85 conf.sub_config('emu') |
84 conf.sub_config('devices/emu') | 86 conf.sub_config('tap-bridge') |
85 conf.sub_config('devices/tap-bridge') | 87 conf.sub_config('config-store') |
86 conf.sub_config('contrib') | 88 conf.sub_config('internet') |
87 conf.sub_config('internet-stack') | 89 conf.sub_config('netanim') |
88 conf.sub_config('helper') | |
89 conf.sub_config('test') | 90 conf.sub_config('test') |
| 91 conf.sub_config('click') |
| 92 conf.sub_config('openflow') |
| 93 conf.sub_config('stats') |
90 | 94 |
91 blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) | 95 blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) |
92 conf.env.append_value('NS3_MODULE_PATH', blddir) | 96 conf.env.append_value('NS3_MODULE_PATH', blddir) |
93 if Options.options.enable_rpath: | 97 if Options.options.enable_rpath: |
94 conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),)
) | 98 conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),)
) |
95 | 99 |
96 ## Used to link the 'test-runner' program with all of ns-3 code | 100 ## Used to link the 'test-runner' program with all of ns-3 code |
97 conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_
modules] | 101 conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_
modules] |
98 | 102 |
99 | 103 |
100 def create_ns3_module(bld, name, dependencies=()): | 104 def create_ns3_module(bld, name, dependencies=(), test=False): |
101 module = bld.new_task_gen('cxx', 'cc') | 105 # Create a separate library for this module. |
| 106 if bld.env['ENABLE_STATIC_NS3']: |
| 107 module = bld.new_task_gen('cxx', 'cstaticlib') |
| 108 else: |
| 109 module = bld.new_task_gen('cxx', 'cshlib') |
| 110 if not test: |
| 111 pcfile = bld.new_task_gen('ns3pcfile') |
| 112 pcfile.module = module |
| 113 |
| 114 # Initially create an empty value for this because the pcfile |
| 115 # writing task assumes every module has a uselib attribute. |
| 116 module.uselib = '' |
| 117 |
| 118 module.is_ns3_module = True |
102 module.name = 'ns3-' + name | 119 module.name = 'ns3-' + name |
103 module.target = module.name | 120 # Add the proper path to the module's name. |
104 module.add_objects = ['ns3-' + dep for dep in dependencies] | 121 module.target = '%s/ns3-%s' % (bld.srcnode.relpath_gen(bld.path), name) |
| 122 # Set the libraries this module depends on.·· |
| 123 module.uselib_local = ['ns3-' + dep for dep in dependencies] |
105 module.module_deps = list(dependencies) | 124 module.module_deps = list(dependencies) |
106 if not module.env['ENABLE_STATIC_NS3']: | 125 if not module.env['ENABLE_STATIC_NS3']: |
107 module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS']) | 126 module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS']) |
108 module.env.append_value('CCFLAGS', module.env['shlib_CXXFLAGS']) | 127 module.env.append_value('CCFLAGS', module.env['shlib_CXXFLAGS']) |
| 128 # Turn on the link flags for shared libraries if we have the |
| 129 # proper compiler and platform. |
| 130 if module.env['CXX_NAME'] in ['gcc', 'icc'] and module.env['WL_SONAME_SU
PPORTED']: |
| 131 # Get the module library name without any relative paths |
| 132 # at its beginning because all of the libraries will end |
| 133 # up in the same directory. |
| 134 module_library_name = os.path.basename(ccroot.get_target_name(module
)) |
| 135 module.env.append_value('LINKFLAGS', '-Wl,--soname=%s' % module_libr
ary_name) |
109 elif module.env['CXX_NAME'] in ['gcc', 'icc'] and \ | 136 elif module.env['CXX_NAME'] in ['gcc', 'icc'] and \ |
110 os.uname()[4] == 'x86_64' and \ | 137 os.uname()[4] == 'x86_64' and \ |
111 module.env['ENABLE_PYTHON_BINDINGS']: | 138 module.env['ENABLE_PYTHON_BINDINGS']: |
112 # enable that flag for static builds only on x86-64 platforms | 139 # enable that flag for static builds only on x86-64 platforms |
113 # when gcc is present and only when we want python bindings | 140 # when gcc is present and only when we want python bindings |
114 # (it's more efficient to not use this option if we can avoid it) | 141 # (it's more efficient to not use this option if we can avoid it) |
115 module.env.append_value('CXXFLAGS', '-mcmodel=large') | 142 module.env.append_value('CXXFLAGS', '-mcmodel=large') |
116 module.env.append_value('CCFLAGS', '-mcmodel=large') | 143 module.env.append_value('CCFLAGS', '-mcmodel=large') |
117 ········ | 144 ········ |
118 module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION") | 145 module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION") |
119 module.env.append_value('CCDEFINES', "NS3_MODULE_COMPILATION") | 146 module.env.append_value('CCDEFINES', "NS3_MODULE_COMPILATION") |
120 return module | 147 return module |
121 | 148 |
| 149 def create_ns3_module_test_library(bld, name): |
| 150 # Create an ns3 module for the test library that depends only on |
| 151 # the module being tested. |
| 152 library_name = name + "-test" |
| 153 library = bld.create_ns3_module(library_name, [name], test = True) |
| 154 |
| 155 # Modify attributes for the test library that are different from a |
| 156 # normal module. |
| 157 del library.is_ns3_module |
| 158 library.is_ns3_module_test_library = True |
| 159 library.module_name = 'ns3-' + name |
| 160 |
| 161 # Add this module and test library to the list. |
| 162 bld.env.append_value('NS3_MODULES_WITH_TEST_LIBRARIES', (library.module_name
, library.name)) |
| 163 |
| 164 # Set the include path from the build directory to modules.· |
| 165 relative_path_from_build_to_here = bld.path.relpath_gen(bld.bldnode) |
| 166 include_flag = '-I' + relative_path_from_build_to_here |
| 167 library.env.append_value('CXXFLAGS', include_flag) |
| 168 library.env.append_value('CCFLAGS', include_flag) |
| 169 |
| 170 return library |
| 171 |
122 def create_obj(bld, *args): | 172 def create_obj(bld, *args): |
123 warnings.warn("(in %s) Use bld.new_task_gen(...) now, instead of bld.create_
obj(...)" % str(bld.path), | 173 warnings.warn("(in %s) Use bld.new_task_gen(...) now, instead of bld.create_
obj(...)" % str(bld.path), |
124 DeprecationWarning, stacklevel=2) | 174 DeprecationWarning, stacklevel=2) |
125 return bld.new_task_gen(*args) | 175 return bld.new_task_gen(*args) |
126 | 176 |
| 177 |
| 178 def ns3_python_bindings(bld): |
| 179 # this method is called from a module wscript, so remember bld.path is not b
indings/python! |
| 180 module_abs_src_path = bld.path.abspath() |
| 181 module = os.path.basename(module_abs_src_path) |
| 182 env = bld.env |
| 183 env.append_value("MODULAR_BINDINGS_MODULES", "ns3-"+module) |
| 184 |
| 185 if not env['ENABLE_PYTHON_BINDINGS']: |
| 186 return |
| 187 if env['BINDINGS_TYPE'] not in ('modular', 'both'): |
| 188 return |
| 189 |
| 190 bindings_dir = bld.path.find_dir("bindings") |
| 191 if bindings_dir is None or not os.path.exists(bindings_dir.abspath()): |
| 192 warnings.warn("(in %s) Requested to build modular python bindings, but a
pidefs dir not found " |
| 193 "=> skipped the bindings." % str(bld.path), |
| 194 Warning, stacklevel=2) |
| 195 return |
| 196 |
| 197 if ("ns3-%s" % (module,)) not in env.NS3_ENABLED_MODULES: |
| 198 #print "bindings for module %s which is not enabled, skip" % module |
| 199 return |
| 200 |
| 201 env.append_value('PYTHON_MODULES_BUILT', module) |
| 202 apidefs = env['PYTHON_BINDINGS_APIDEFS'].replace("-", "_") |
| 203 |
| 204 #debug = ('PYBINDGEN_DEBUG' in os.environ) |
| 205 debug = True # XXX |
| 206 source = [bld.srcnode.find_resource('bindings/python/ns3modulegen-modular.py
').relpath_gen(bld.path), |
| 207 "bindings/modulegen__%s.py" % apidefs] |
| 208 |
| 209 if bindings_dir.find_resource("modulegen_customizations.py") is not None: |
| 210 source.append("bindings/modulegen_customizations.py") |
| 211 |
| 212 # the local customization file may or not exist |
| 213 if bld.path.find_resource("bindings/modulegen_local.py"): |
| 214 source.append("bindings/modulegen_local.py") |
| 215 |
| 216 module_py_name = module.replace('-', '_') |
| 217 module_target_dir = bld.srcnode.find_dir("bindings/python/ns").relpath_gen(b
ld.path) |
| 218 |
| 219 # if bindings/<module>.py exists, it becomes the module frontend, and the C
extension befomes _<module> |
| 220 if bld.path.find_resource("bindings/%s.py" % (module_py_name,)) is not None: |
| 221 bld.new_task_gen( |
| 222 features='copy', |
| 223 source=("bindings/%s.py" % (module_py_name,)), |
| 224 target=('%s/%s.py' % (module_target_dir, module_py_name))) |
| 225 extension_name = '_%s' % (module_py_name,) |
| 226 else: |
| 227 extension_name = module_py_name |
| 228 |
| 229 target = ['bindings/ns3module.cc', 'bindings/ns3module.h', 'bindings/ns3modu
legen.log'] |
| 230 #if not debug: |
| 231 # target.append('ns3modulegen.log') |
| 232 |
| 233 argv = ['NS3_ENABLED_FEATURES=${FEATURES}', '${PYTHON}'] |
| 234 #if debug: |
| 235 # argv.extend(["-m", "pdb"]) |
| 236 ···· |
| 237 argv.extend(['${SRC[0]}', module_abs_src_path, apidefs, extension_name, '${T
GT[0]}']) |
| 238 |
| 239 argv.extend(['2>', '${TGT[2]}']) # 2> ns3modulegen.log |
| 240 |
| 241 features = [] |
| 242 for (name, caption, was_enabled, reason_not_enabled) in env['NS3_OPTIONAL_FE
ATURES']: |
| 243 if was_enabled: |
| 244 features.append(name) |
| 245 |
| 246 bindgen = bld.new_task_gen('command', source=source, target=target, command=
argv) |
| 247 bindgen.env['FEATURES'] = ','.join(features) |
| 248 bindgen.dep_vars = ['FEATURES'] |
| 249 bindgen.before = 'cxx' |
| 250 bindgen.after = 'gen_ns3_module_header_task' |
| 251 bindgen.name = "pybindgen(ns3 module %s)" % module |
| 252 |
| 253 # generate the extension module |
| 254 pymod = bld.new_task_gen(features='cxx cshlib pyext') |
| 255 pymod.source = ['bindings/ns3module.cc'] |
| 256 pymod.target = '%s/%s' % (module_target_dir, extension_name) |
| 257 pymod.name = 'ns3module_%s' % module |
| 258 pymod.uselib_local = pymod.env['NS3_ENABLED_MODULES'] # Should be '"ns3-"+m
odule', but see bug 1117 |
| 259 if pymod.env['ENABLE_STATIC_NS3']: |
| 260 if sys.platform == 'darwin': |
| 261 pymod.env.append_value('LINKFLAGS', '-Wl,-all_load') |
| 262 for mod in pymod.uselib_local: |
| 263 pymod.env.append_value('LINKFLAGS', '-l' + mod) |
| 264 else: |
| 265 pymod.env.append_value('LINKFLAGS', '-Wl,--whole-archive,-Bstatic') |
| 266 for mod in pymod.uselib_local: |
| 267 pymod.env.append_value('LINKFLAGS', '-l' + mod) |
| 268 pymod.env.append_value('LINKFLAGS', '-Wl,-Bdynamic,--no-whole-archiv
e') |
| 269 defines = list(pymod.env['CXXDEFINES']) |
| 270 defines.extend(['NS_DEPRECATED=', 'NS3_DEPRECATED_H']) |
| 271 if Options.platform == 'win32': |
| 272 try: |
| 273 defines.remove('_DEBUG') # causes undefined symbols on win32 |
| 274 except ValueError: |
| 275 pass |
| 276 pymod.env['CXXDEFINES'] = defines |
| 277 pymod.includes = 'bindings' |
| 278 return pymod |
| 279 |
| 280 |
127 def build(bld): | 281 def build(bld): |
128 bld.create_ns3_module = types.MethodType(create_ns3_module, bld) | 282 bld.create_ns3_module = types.MethodType(create_ns3_module, bld) |
| 283 bld.create_ns3_module_test_library = types.MethodType(create_ns3_module_test
_library, bld) |
129 bld.create_obj = types.MethodType(create_obj, bld) | 284 bld.create_obj = types.MethodType(create_obj, bld) |
| 285 bld.ns3_python_bindings = types.MethodType(ns3_python_bindings, bld) |
130 ···· | 286 ···· |
131 bld.add_subdirs(list(all_modules)) | 287 bld.add_subdirs(list(all_modules)) |
132 | 288 |
133 for module in all_modules: | 289 for module in all_modules: |
134 modheader = bld.new_task_gen('ns3moduleheader') | 290 modheader = bld.new_task_gen('ns3moduleheader') |
135 modheader.module = module.split('/')[-1] | 291 modheader.module = module.split('/')[-1] |
| 292 |
| 293 class ns3pcfile_task(Task.Task): |
| 294 after = 'cc cxx' |
| 295 def __str__(self): |
| 296 "string to display to the user" |
| 297 tgt_str = ' '.join([a.nice_path(self.env) for a in self.outputs]) |
| 298 return 'pcfile: %s\n' % (tgt_str) |
| 299 def runnable_status(self): |
| 300 return super(ns3pcfile_task, self).runnable_status() |
| 301 def _self_libs(self, env, name, libdir): |
| 302 if env['ENABLE_STATIC_NS3']: |
| 303 path_st = 'STATICLIBPATH_ST' |
| 304 lib_st = 'STATICLIB_ST' |
| 305 lib_marker = 'STATICLIB_MARKER' |
| 306 else: |
| 307 path_st = 'LIBPATH_ST' |
| 308 lib_st = 'LIB_ST' |
| 309 lib_marker = 'SHLIB_MARKER' |
| 310 retval = [env[path_st] % libdir, |
| 311 env[lib_marker], |
| 312 env[lib_st] % name] |
| 313 return retval |
| 314 def _lib(self, env, dep): |
| 315 libpath = env['LIBPATH_%s' % dep] |
| 316 linkflags = env['LINKFLAGS_%s' % dep] |
| 317 libs = env['LIB_%s' % dep] |
| 318 retval = [] |
| 319 for path in libpath: |
| 320 retval.append(env['LIBPATH_ST'] % path) |
| 321 retval = retval + linkflags |
| 322 for lib in libs: |
| 323 retval.append(env['LIB_ST'] % lib) |
| 324 return retval |
| 325 def _listify(self, v): |
| 326 if isinstance(v, list): |
| 327 return v |
| 328 else: |
| 329 return [v] |
| 330 def _cflags(self, dep): |
| 331 flags = self.env['CFLAGS_%s' % dep] |
| 332 return self._listify(flags) |
| 333 def _cxxflags(self, dep): |
| 334 return self._listify(self.env['CXXFLAGS_%s' % dep]) |
| 335 def _defines(self, dep): |
| 336 defines = self.env['CCDEFINES_%s' % dep] + self.env['CXXDEFINES_%s' % de
p] |
| 337 return [self.env['CCDEFINES_ST'] % define for define in self.env['CCDEFI
NES_%s' % dep]] + \ |
| 338 [self.env['CXXDEFINES_ST'] % define for define in self.env['CXXDEFIN
ES_%s' % dep]]· |
| 339 def _includes(self, dep): |
| 340 includes = self.env['CPPPATH_%s' % dep] |
| 341 return [self.env['CPPPATH_ST'] % include for include in includes] |
| 342 |
| 343 def _generate_pcfile(self, name, use, uselib_local, prefix, outfilename): |
| 344 outfile = open(outfilename, 'w') |
| 345 includedir = os.path.join(prefix, 'include') |
| 346 libdir = os.path.join(prefix, 'lib') |
| 347 libs = self._self_libs(self.env, name, '${libdir}') |
| 348 for dep in use: |
| 349 libs = libs + self._lib(self.env, dep) |
| 350 for dep in uselib_local: |
| 351 libs = libs + [self.env['LIB_ST'] % dep] |
| 352 cflags = [self.env['CPPPATH_ST'] % '${includedir}'] |
| 353 for dep in use: |
| 354 cflags = cflags + self._cflags(dep) + self._cxxflags(dep) + \ |
| 355 self._defines(dep) + self._includes(dep) |
| 356 print >> outfile, """ |
| 357 prefix=%s |
| 358 libdir=%s |
| 359 includedir=%s |
| 360 |
| 361 Name: lib%s |
| 362 Description: ns-3 module %s |
| 363 Version: devel |
| 364 Libs: %s |
| 365 Cflags: %s |
| 366 """ % (prefix, libdir, includedir, |
| 367 name, name, ' '.join(libs), ' '.join(cflags)) |
| 368 outfile.close() |
| 369 |
| 370 def run(self): |
| 371 output_filename = self.outputs[0].bldpath(self.env) |
| 372 self._generate_pcfile(self.module.name, self.module.uselib,· |
| 373 self.module.uselib_local, |
| 374 self.env['PREFIX'], output_filename) |
| 375 |
| 376 class ns3pcfile_taskgen(TaskGen.task_gen): |
| 377 def __init__(self, *args, **kwargs): |
| 378 super(ns3pcfile_taskgen, self).__init__(*args, **kwargs) |
| 379 def apply(self): |
| 380 output_filename = 'lib%s.pc' % self.module.name |
| 381 output_node = self.path.find_or_declare(output_filename) |
| 382 assert output_node is not None, str(self) |
| 383 task = self.create_task('ns3pcfile', env=self.env) |
| 384 self.bld.install_files(os.path.join('${PREFIX}', 'lib', 'pkgconfig'), |
| 385 output_node) |
| 386 task.set_outputs([output_node]) |
| 387 task.module = self.module |
136 | 388 |
137 | 389 |
138 class ns3header_taskgen(TaskGen.task_gen): | 390 class ns3header_taskgen(TaskGen.task_gen): |
139 """A set of NS-3 header files""" | 391 """A set of NS-3 header files""" |
140 COLOR = 'BLUE' | 392 COLOR = 'BLUE' |
141 def __init__(self, *args, **kwargs): | 393 def __init__(self, *args, **kwargs): |
142 super(ns3header_taskgen, self).__init__(*args, **kwargs) | 394 super(ns3header_taskgen, self).__init__(*args, **kwargs) |
143 self.install_path = None | 395 self.install_path = None |
144 self.sub_dir = None # if not None, header files will be published as ns3
/sub_dir/file.h | 396 self.sub_dir = None # if not None, header files will be published as ns3
/sub_dir/file.h |
145 self.module = None # module name | 397 self.module = None # module name |
| 398 self.mode = 'install' |
146 | 399 |
147 def apply(self): | 400 def apply(self): |
| 401 for filename in set(self.to_list(self.source)): |
| 402 src_node = self.path.find_resource(filename) |
| 403 self.bld.install_files('${PREFIX}/include/ns3', [src_node]) |
148 if self.module is None: | 404 if self.module is None: |
149 raise Utils.WafError("'module' missing on ns3headers object %s" % se
lf) | 405 raise Utils.WafError("'module' missing on ns3headers object %s" % se
lf) |
150 ns3_dir_node = self.bld.path.find_dir("ns3") | 406 ns3_dir_node = self.bld.path.find_dir("ns3") |
151 if self.sub_dir is not None: | 407 if self.sub_dir is not None: |
152 ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir) | 408 ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir) |
153 for filename in set(self.to_list(self.source)): | 409 for filename in set(self.to_list(self.source)): |
154 src_node = self.path.find_resource(filename) | 410 src_node = self.path.find_resource(filename) |
155 if src_node is None: | 411 if src_node is None: |
156 raise Utils.WafError("source ns3 header file %s not found" % (fi
lename,)) | 412 raise Utils.WafError("source ns3 header file %s not found" % (fi
lename,)) |
157 dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename)) | 413 dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename)) |
158 assert dst_node is not None | 414 assert dst_node is not None |
159 task = self.create_task('ns3header', env=self.env) | 415 task = self.create_task('ns3header', env=self.env) |
160 task.set_inputs([src_node]) | 416 task.mode = self.mode |
161 task.set_outputs([dst_node]) | 417 if self.mode == 'install': |
| 418 task.set_inputs([src_node]) |
| 419 task.set_outputs([dst_node]) |
| 420 else: |
| 421 task.header_to_remove = dst_node |
162 | 422 |
163 class ns3header_task(Task.Task): | 423 class ns3header_task(Task.Task): |
164 before = 'cc cxx gen_ns3_module_header_task' | 424 before = 'cc cxx gen_ns3_module_header_task' |
165 color = 'BLUE' | 425 color = 'BLUE' |
| 426 |
| 427 def __str__(self): |
| 428 "string to display to the user" |
| 429 env = self.env |
| 430 src_str = ' '.join([a.nice_path(env) for a in self.inputs]) |
| 431 tgt_str = ' '.join([a.nice_path(env) for a in self.outputs]) |
| 432 if self.outputs: sep = ' -> ' |
| 433 else: sep = '' |
| 434 if self.mode == 'remove': |
| 435 return 'rm-ns3-header %s\n' % (self.header_to_remove.bldpath(self.en
v),) |
| 436 return 'install-ns3-header: %s%s%s\n' % (src_str, sep, tgt_str) |
| 437 |
| 438 def runnable_status(self): |
| 439 if self.mode == 'remove': |
| 440 if os.path.exists(self.header_to_remove.bldpath(self.env)): |
| 441 return Constants.RUN_ME |
| 442 else: |
| 443 return Constants.SKIP_ME |
| 444 else: |
| 445 return super(ns3header_task, self).runnable_status() |
| 446 |
166 def run(self): | 447 def run(self): |
167 assert len(self.inputs) == len(self.outputs) | 448 if self.mode == 'install': |
168 inputs = [node.srcpath(self.env) for node in self.inputs] | 449 assert len(self.inputs) == len(self.outputs) |
169 outputs = [node.bldpath(self.env) for node in self.outputs] | 450 inputs = [node.srcpath(self.env) for node in self.inputs] |
170 for src, dst in zip(inputs, outputs): | 451 outputs = [node.bldpath(self.env) for node in self.outputs] |
| 452 for src, dst in zip(inputs, outputs): |
| 453 try: |
| 454 os.chmod(dst, 0600) |
| 455 except OSError: |
| 456 pass |
| 457 shutil.copy2(src, dst) |
| 458 ## make the headers in builddir read-only, to prevent |
| 459 ## accidental modification |
| 460 os.chmod(dst, 0400) |
| 461 return 0 |
| 462 else: |
| 463 assert len(self.inputs) == 0 |
| 464 assert len(self.outputs) == 0 |
| 465 out_file_name = self.header_to_remove.bldpath(self.env) |
171 try: | 466 try: |
172 os.chmod(dst, 0600) | 467 os.unlink(out_file_name) |
173 except OSError: | 468 except OSError, ex: |
174 pass | 469 if ex.errno != 2: |
175 shutil.copy2(src, dst) | 470 raise |
176 ## make the headers in builddir read-only, to prevent | 471 return 0 |
177 ## accidental modification | |
178 os.chmod(dst, 0400) | |
179 return 0 | |
180 | |
181 | 472 |
182 | 473 |
183 class gen_ns3_module_header_task(Task.Task): | 474 class gen_ns3_module_header_task(Task.Task): |
184 before = 'cc cxx' | 475 before = 'cc cxx' |
185 after = 'ns3header_task' | 476 after = 'ns3header_task' |
186 color = 'BLUE' | 477 color = 'BLUE' |
| 478 |
| 479 def runnable_status(self): |
| 480 if self.mode == 'remove': |
| 481 if os.path.exists(self.header_to_remove.bldpath(self.env)): |
| 482 return Constants.RUN_ME |
| 483 else: |
| 484 return Constants.SKIP_ME |
| 485 else: |
| 486 return super(gen_ns3_module_header_task, self).runnable_status() |
| 487 |
| 488 def __str__(self): |
| 489 "string to display to the user" |
| 490 env = self.env |
| 491 src_str = ' '.join([a.nice_path(env) for a in self.inputs]) |
| 492 tgt_str = ' '.join([a.nice_path(env) for a in self.outputs]) |
| 493 if self.outputs: sep = ' -> ' |
| 494 else: sep = '' |
| 495 if self.mode == 'remove': |
| 496 return 'rm-module-header %s\n' % (self.header_to_remove.bldpath(self
.env),) |
| 497 return 'gen-module-header: %s%s%s\n' % (src_str, sep, tgt_str) |
| 498 |
187 def run(self): | 499 def run(self): |
| 500 if self.mode == 'remove': |
| 501 assert len(self.inputs) == 0 |
| 502 assert len(self.outputs) == 0 |
| 503 out_file_name = self.header_to_remove.bldpath(self.env) |
| 504 try: |
| 505 os.unlink(out_file_name) |
| 506 except OSError, ex: |
| 507 if ex.errno != 2: |
| 508 raise |
| 509 return 0 |
| 510 ········ |
188 assert len(self.outputs) == 1 | 511 assert len(self.outputs) == 1 |
| 512 out_file_name = self.outputs[0].bldpath(self.env) |
189 header_files = [os.path.basename(node.abspath(self.env)) for node in sel
f.inputs] | 513 header_files = [os.path.basename(node.abspath(self.env)) for node in sel
f.inputs] |
190 outfile = file(self.outputs[0].bldpath(self.env), "w") | 514 outfile = file(out_file_name, "w") |
191 header_files.sort() | 515 header_files.sort() |
192 | 516 |
193 print >> outfile, """ | 517 print >> outfile, """ |
194 #ifdef NS3_MODULE_COMPILATION | 518 #ifdef NS3_MODULE_COMPILATION |
195 # error "Do not include ns3 module aggregator headers from other modules; these
are meant only for end user scripts." | 519 # error "Do not include ns3 module aggregator headers from other modules; these
are meant only for end user scripts." |
196 #endif | 520 #endif |
197 | 521 |
198 #ifndef NS3_MODULE_%s | 522 #ifndef NS3_MODULE_%s |
199 """ % (self.module.upper().replace('-', '_'),) | 523 """ % (self.module.upper().replace('-', '_'),) |
200 | 524 |
201 # if self.module_deps: | 525 # if self.module_deps: |
202 # print >> outfile, "// Module dependencies:" | 526 # print >> outfile, "// Module dependencies:" |
203 # for dep in self.module_deps: | 527 # for dep in self.module_deps: |
204 # print >> outfile, "#include \"%s-module.h\"" % dep | 528 # print >> outfile, "#include \"%s-module.h\"" % dep |
205 | 529 |
206 print >> outfile | 530 print >> outfile |
207 print >> outfile, "// Module headers:" | 531 print >> outfile, "// Module headers:" |
208 for header in header_files: | 532 for header in header_files: |
209 print >> outfile, "#include \"%s\"" % (header,) | 533 print >> outfile, "#include \"%s\"" % (header,) |
210 | 534 |
211 print >> outfile, "#endif" | 535 print >> outfile, "#endif" |
212 | 536 |
213 outfile.close() | 537 outfile.close() |
214 return 0 | 538 return 0 |
215 | 539 |
216 def sig_explicit_deps(self): | 540 def sig_explicit_deps(self): |
217 m = Utils.md5() | 541 self.m.update('\n'.join([node.abspath(self.env) for node in self.inputs]
)) |
218 m.update('\n'.join([node.abspath(self.env) for node in self.inputs])) | 542 return self.m.digest() |
219 return m.digest() | |
220 | 543 |
221 def unique_id(self): | 544 def unique_id(self): |
222 try: | 545 try: |
223 return self.uid | 546 return self.uid |
224 except AttributeError: | 547 except AttributeError: |
225 "this is not a real hot zone, but we want to avoid surprizes here" | 548 "this is not a real hot zone, but we want to avoid surprizes here" |
226 m = Utils.md5() | 549 m = Utils.md5() |
227 m.update("ns-3-module-header-%s" % self.module) | 550 m.update("ns-3-module-header-%s" % self.module) |
228 self.uid = m.digest() | 551 self.uid = m.digest() |
229 return self.uid | 552 return self.uid |
230 | 553 |
231 | 554 |
232 class ns3moduleheader_taskgen(TaskGen.task_gen): | 555 class ns3moduleheader_taskgen(TaskGen.task_gen): |
233 """ | 556 """ |
234 Generates a 'ns3/foo-module.h' header file that includes all | 557 Generates a 'ns3/foo-module.h' header file that includes all |
235 public ns3 headers of a certain module. | 558 public ns3 headers of a certain module. |
236 """ | 559 """ |
237 COLOR = 'BLUE' | 560 COLOR = 'BLUE' |
238 def __init__(self, *args, **kwargs): | 561 def __init__(self, *args, **kwargs): |
239 super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs) | 562 super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs) |
| 563 self.mode = 'install' |
240 | 564 |
241 def apply(self): | 565 def apply(self): |
242 ## get all of the ns3 headers | 566 ## get all of the ns3 headers |
243 ns3_dir_node = self.bld.path.find_dir("ns3") | 567 ns3_dir_node = self.bld.path.find_dir("ns3") |
244 all_headers_inputs = [] | 568 all_headers_inputs = [] |
245 found_the_module = False | 569 found_the_module = False |
246 for ns3headers in self.bld.all_task_gen: | 570 for ns3headers in self.bld.all_task_gen: |
247 if isinstance(ns3headers, ns3header_taskgen): | 571 if isinstance(ns3headers, ns3header_taskgen): |
248 if ns3headers.module != self.module: | 572 if ns3headers.module != self.module: |
249 continue | 573 continue |
250 found_the_module = True | 574 found_the_module = True |
251 for source in set(ns3headers.to_list(ns3headers.source)): | 575 for source in set(ns3headers.to_list(ns3headers.source)): |
252 source = os.path.basename(source) | 576 source = os.path.basename(source) |
253 node = ns3_dir_node.find_or_declare(os.path.basename(source)
) | 577 node = ns3_dir_node.find_or_declare(os.path.basename(source)
) |
254 if node is None: | 578 if node is None: |
255 fatal("missing header file %s" % (source,)) | 579 fatal("missing header file %s" % (source,)) |
256 all_headers_inputs.append(node) | 580 all_headers_inputs.append(node) |
257 if not found_the_module: | 581 if not found_the_module: |
258 raise Utils.WscriptError("error finding headers for module %s" % sel
f.module) | 582 raise Utils.WscriptError("error finding headers for module %s" % sel
f.module) |
259 if not all_headers_inputs: | 583 if not all_headers_inputs: |
260 return | 584 return |
261 module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env) | 585 self.bld.install_files('${PREFIX}/include/ns3',· |
262 assert module_obj is not None | 586 ns3_dir_node.find_or_declare("%s-module.h" % self
.module)) |
263 all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self
.module)] | 587 all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self
.module)] |
264 task = self.create_task('gen_ns3_module_header', env=self.env) | 588 task = self.create_task('gen_ns3_module_header', env=self.env) |
265 task.set_inputs(all_headers_inputs) | |
266 task.set_outputs(all_headers_outputs) | |
267 task.module = self.module | 589 task.module = self.module |
268 task.module_deps = module_obj.module_deps | 590 task.mode = self.mode |
| 591 if self.mode == 'install': |
| 592 task.set_inputs(all_headers_inputs) |
| 593 task.set_outputs(all_headers_outputs) |
| 594 module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env) |
| 595 assert module_obj is not None, self.module |
| 596 task.module_deps = module_obj.module_deps |
| 597 else: |
| 598 task.header_to_remove = all_headers_outputs[0] |
269 | 599 |
270 def install(self): | 600 def install(self): |
271 pass | 601 pass |
LEFT | RIGHT |