Allow ns3moduleheader taskgen with empty list of source headers (for completely optional ns-3 modules)
1 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
21 'devices/point-to-point',
26 'devices/virtual-net-device',
28 'applications/packet-sink',
29 'applications/udp-echo',
31 'routing/global-routing',
32 'routing/static-routing',
33 'routing/list-routing',
38 'applications/v4ping',
44 opt.sub_options('simulator')
46 opt.add_option('--enable-rpath',
47 help=("Link programs with rpath"
48 " (normally not needed, see "
49 " --run and --shell; moreover, only works in some"
50 " specific platforms, such as Linux and Solaris)"),
51 action="store_true", dest='enable_rpath', default=False)
53 opt.add_option('--enable-modules',
54 help=("Build only these modules (and dependencies)"),
55 dest='enable_modules')
58 conf.sub_config('core')
59 conf.sub_config('simulator')
60 conf.sub_config('devices/emu')
61 conf.sub_config('devices/wifi')
62 conf.sub_config('devices/tap-bridge')
63 conf.sub_config('contrib')
64 conf.sub_config('internet-stack')
66 blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant()))
67 conf.env.append_value('NS3_MODULE_PATH', blddir)
68 if Options.options.enable_rpath:
69 conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),))
71 ## Used to link the 'run-tests' program with all of ns-3 code
72 conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
75 def create_ns3_module(bld, name, dependencies=()):
76 module = bld.new_task_gen('cxx')
77 module.name = 'ns3-' + name
78 module.target = module.name
79 module.add_objects = ['ns3-' + dep for dep in dependencies]
80 module.module_deps = list(dependencies)
81 if not module.env['ENABLE_STATIC_NS3']:
82 module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS'])
83 elif module.env['CXX_NAME'] == 'gcc' and \
84 os.uname()[4] == 'x86_64' and \
85 module.env['ENABLE_PYTHON_BINDINGS']:
86 # enable that flag for static builds only on x86-64 platforms
87 # when gcc is present and only when we want python bindings
88 # (it's more efficient to not use this option if we can avoid it)
89 module.env.append_value('CXXFLAGS', '-mcmodel=large')
91 module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION")
94 def create_obj(bld, *args):
95 warnings.warn("(in %s) Use bld.new_task_gen(...) now, instead of bld.create_obj(...)" % str(bld.path),
96 DeprecationWarning, stacklevel=2)
97 return bld.new_task_gen(*args)
100 bld.create_ns3_module = types.MethodType(create_ns3_module, bld)
101 bld.create_obj = types.MethodType(create_obj, bld)
103 bld.add_subdirs(list(all_modules))
105 for module in all_modules:
106 modheader = bld.new_task_gen('ns3moduleheader')
107 modheader.module = module.split('/')[-1]
110 class ns3header_taskgen(TaskGen.task_gen):
111 """A set of NS-3 header files"""
113 def __init__(self, *args, **kwargs):
114 super(ns3header_taskgen, self).__init__(*args, **kwargs)
115 self.install_path = None
116 self.sub_dir = None # if not None, header files will be published as ns3/sub_dir/file.h
117 self.module = None # module name
120 if self.module is None:
121 raise Utils.WafError("'module' missing on ns3headers object %s" % self)
122 ns3_dir_node = self.bld.path.find_dir("ns3")
123 if self.sub_dir is not None:
124 ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir)
125 for filename in self.to_list(self.source):
126 src_node = self.path.find_resource(filename)
128 raise Utils.WafError("source ns3 header file %s not found" % (filename,))
129 dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename))
130 assert dst_node is not None
131 task = self.create_task('ns3header', self.env)
132 task.set_inputs([src_node])
133 task.set_outputs([dst_node])
135 class ns3header_task(Task.Task):
136 before = 'cc cxx gen_ns3_module_header_task'
139 assert len(self.inputs) == len(self.outputs)
140 inputs = [node.srcpath(self.env) for node in self.inputs]
141 outputs = [node.bldpath(self.env) for node in self.outputs]
142 for src, dst in zip(inputs, outputs):
147 shutil.copy2(src, dst)
148 ## make the headers in builddir read-only, to prevent
149 ## accidental modification
155 class gen_ns3_module_header_task(Task.Task):
157 after = 'ns3header_task'
160 assert len(self.outputs) == 1
161 header_files = [os.path.basename(node.abspath(self.env)) for node in self.inputs]
162 outfile = file(self.outputs[0].bldpath(self.env), "w")
165 print >> outfile, """
166 #ifdef NS3_MODULE_COMPILATION
167 # error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
170 #ifndef NS3_MODULE_%s
171 """ % (self.module.upper().replace('-', '_'),)
173 # if self.module_deps:
174 # print >> outfile, "// Module dependencies:"
175 # for dep in self.module_deps:
176 # print >> outfile, "#include \"%s-module.h\"" % dep
179 print >> outfile, "// Module headers:"
180 for header in header_files:
181 print >> outfile, "#include \"%s\"" % (header,)
183 print >> outfile, "#endif"
188 def sig_explicit_deps(self):
190 m.update('\n'.join([node.abspath(self.env) for node in self.inputs]))
196 except AttributeError:
197 "this is not a real hot zone, but we want to avoid surprizes here"
199 m.update("ns-3-module-header-%s" % self.module)
200 self.uid = m.digest()
204 class ns3moduleheader_taskgen(TaskGen.task_gen):
206 Generates a 'ns3/foo-module.h' header file that includes all
207 public ns3 headers of a certain module.
210 def __init__(self, *args, **kwargs):
211 super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs)
214 ## get all of the ns3 headers
215 ns3_dir_node = self.bld.path.find_dir("ns3")
216 all_headers_inputs = []
217 found_the_module = False
218 for ns3headers in self.bld.all_task_gen:
219 if isinstance(ns3headers, ns3header_taskgen):
220 if ns3headers.module != self.module:
222 found_the_module = True
223 for source in ns3headers.to_list(ns3headers.source):
224 source = os.path.basename(source)
225 node = ns3_dir_node.find_or_declare(os.path.basename(source))
227 fatal("missing header file %s" % (source,))
228 all_headers_inputs.append(node)
229 if not found_the_module:
230 raise Utils.WscriptError("error finding headers for module %s" % self.module)
231 if not all_headers_inputs:
233 module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env)
234 assert module_obj is not None
235 all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)]
236 task = self.create_task('gen_ns3_module_header', self.env)
237 task.set_inputs(all_headers_inputs)
238 task.set_outputs(all_headers_outputs)
239 task.module = self.module
240 task.module_deps = module_obj.module_deps