|
gjcarneiro@537
|
1 |
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
|
gjcarneiro@537
|
2 |
|
|
gjc@761
|
3 |
import os, os.path
|
|
gjcarneiro@693
|
4 |
import shutil
|
|
gjc@1217
|
5 |
import types
|
|
gjc@4064
|
6 |
import warnings
|
|
gjcarneiro@693
|
7 |
|
|
gjc@4064
|
8 |
import TaskGen
|
|
gjc@4064
|
9 |
import Task
|
|
gjc@4064
|
10 |
import Options
|
|
gjc@4064
|
11 |
import Build
|
|
gjc@4326
|
12 |
import Utils
|
|
gjcarneiro@693
|
13 |
|
|
gjc@969
|
14 |
all_modules = (
|
|
gjcarneiro@600
|
15 |
'core',
|
|
gjcarneiro@600
|
16 |
'common',
|
|
gjcarneiro@600
|
17 |
'simulator',
|
|
gjc@1878
|
18 |
'contrib',
|
|
gjcarneiro@600
|
19 |
'node',
|
|
mathieu@3260
|
20 |
'internet-stack',
|
|
emmanuelle@972
|
21 |
'devices/point-to-point',
|
|
craigdo@1272
|
22 |
'devices/csma',
|
|
craigdo@3854
|
23 |
'devices/emu',
|
|
craigdo@3826
|
24 |
'devices/bridge',
|
|
craigdo@4163
|
25 |
'devices/tap-bridge',
|
|
gjc@4541
|
26 |
'devices/virtual-net-device',
|
|
craigdo@1496
|
27 |
'applications/onoff',
|
|
craigdo@1496
|
28 |
'applications/packet-sink',
|
|
craigdo@1496
|
29 |
'applications/udp-echo',
|
|
gjc@1716
|
30 |
'routing/olsr',
|
|
tomh@1120
|
31 |
'routing/global-routing',
|
|
tomh@4573
|
32 |
'routing/static-routing',
|
|
tomh@4573
|
33 |
'routing/list-routing',
|
|
mathieu@968
|
34 |
'mobility',
|
|
mathieu@1882
|
35 |
'devices/wifi',
|
|
mathieu@2603
|
36 |
'helper',
|
|
tjkopena@3570
|
37 |
'contrib/stats',
|
|
craigdo@3821
|
38 |
'applications/v4ping',
|
|
vincent@4731
|
39 |
'applications/ping6',
|
|
vincent@4731
|
40 |
'applications/radvd',
|
|
gjc@969
|
41 |
)
|
|
gjcarneiro@600
|
42 |
|
|
gjcarneiro@537
|
43 |
def set_options(opt):
|
|
gjcarneiro@537
|
44 |
opt.sub_options('simulator')
|
|
gjc@955
|
45 |
|
|
gjc@955
|
46 |
opt.add_option('--enable-rpath',
|
|
gjc@955
|
47 |
help=("Link programs with rpath"
|
|
gjc@955
|
48 |
" (normally not needed, see "
|
|
gjc@955
|
49 |
" --run and --shell; moreover, only works in some"
|
|
gjc@955
|
50 |
" specific platforms, such as Linux and Solaris)"),
|
|
gjc@955
|
51 |
action="store_true", dest='enable_rpath', default=False)
|
|
craigdo@4164
|
52 |
|
|
gjc@1858
|
53 |
opt.add_option('--enable-modules',
|
|
gjc@1858
|
54 |
help=("Build only these modules (and dependencies)"),
|
|
gjc@1858
|
55 |
dest='enable_modules')
|
|
gjc@1858
|
56 |
|
|
gjcarneiro@537
|
57 |
def configure(conf):
|
|
gjcarneiro@537
|
58 |
conf.sub_config('core')
|
|
gjcarneiro@537
|
59 |
conf.sub_config('simulator')
|
|
craigdo@3854
|
60 |
conf.sub_config('devices/emu')
|
|
guangyu@4470
|
61 |
conf.sub_config('devices/wifi')
|
|
craigdo@4163
|
62 |
conf.sub_config('devices/tap-bridge')
|
|
mathieu@3063
|
63 |
conf.sub_config('contrib')
|
|
fw@3579
|
64 |
conf.sub_config('internet-stack')
|
|
gjcarneiro@537
|
65 |
|
|
gjc@4064
|
66 |
blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant()))
|
|
mathieu@3498
|
67 |
conf.env.append_value('NS3_MODULE_PATH', blddir)
|
|
gjc@4064
|
68 |
if Options.options.enable_rpath:
|
|
gjc@1306
|
69 |
conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),))
|
|
gjc@761
|
70 |
|
|
gjc@928
|
71 |
## Used to link the 'run-tests' program with all of ns-3 code
|
|
gjc@928
|
72 |
conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
|
|
gjc@928
|
73 |
|
|
gjc@1858
|
74 |
|
|
gjc@1217
|
75 |
def create_ns3_module(bld, name, dependencies=()):
|
|
gjc@4368
|
76 |
module = bld.new_task_gen('cxx')
|
|
gjc@1217
|
77 |
module.name = 'ns3-' + name
|
|
gjc@1217
|
78 |
module.target = module.name
|
|
gjc@1220
|
79 |
module.add_objects = ['ns3-' + dep for dep in dependencies]
|
|
gjc@2611
|
80 |
module.module_deps = list(dependencies)
|
|
mathieu@4392
|
81 |
if not module.env['ENABLE_STATIC_NS3']:
|
|
mathieu@4392
|
82 |
module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS'])
|
|
mathieu@4395
|
83 |
elif module.env['CXX_NAME'] == 'gcc' and \
|
|
mathieu@4395
|
84 |
os.uname()[4] == 'x86_64' and \
|
|
mathieu@4395
|
85 |
module.env['ENABLE_PYTHON_BINDINGS']:
|
|
mathieu@4395
|
86 |
# enable that flag for static builds only on x86-64 platforms
|
|
mathieu@4395
|
87 |
# when gcc is present and only when we want python bindings
|
|
mathieu@4395
|
88 |
# (it's more efficient to not use this option if we can avoid it)
|
|
mathieu@4395
|
89 |
module.env.append_value('CXXFLAGS', '-mcmodel=large')
|
|
mathieu@4395
|
90 |
|
|
gjc@2611
|
91 |
module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION")
|
|
gjc@1217
|
92 |
return module
|
|
gjc@4064
|
93 |
|
|
gjc@4064
|
94 |
def create_obj(bld, *args):
|
|
gjc@4064
|
95 |
warnings.warn("(in %s) Use bld.new_task_gen(...) now, instead of bld.create_obj(...)" % str(bld.path),
|
|
gjc@4064
|
96 |
DeprecationWarning, stacklevel=2)
|
|
gjc@4064
|
97 |
return bld.new_task_gen(*args)
|
|
gjc@955
|
98 |
|
|
gjcarneiro@537
|
99 |
def build(bld):
|
|
gjc@1217
|
100 |
bld.create_ns3_module = types.MethodType(create_ns3_module, bld)
|
|
gjc@4064
|
101 |
bld.create_obj = types.MethodType(create_obj, bld)
|
|
gjcarneiro@600
|
102 |
|
|
gjc@969
|
103 |
bld.add_subdirs(list(all_modules))
|
|
gjcarneiro@693
|
104 |
|
|
gjc@2611
|
105 |
for module in all_modules:
|
|
gjc@4064
|
106 |
modheader = bld.new_task_gen('ns3moduleheader')
|
|
gjc@2611
|
107 |
modheader.module = module.split('/')[-1]
|
|
gjc@2611
|
108 |
|
|
gjc@1220
|
109 |
|
|
gjc@4064
|
110 |
class ns3header_taskgen(TaskGen.task_gen):
|
|
gjcarneiro@693
|
111 |
"""A set of NS-3 header files"""
|
|
gjc@4064
|
112 |
COLOR = 'BLUE'
|
|
gjc@4064
|
113 |
def __init__(self, *args, **kwargs):
|
|
gjc@4064
|
114 |
super(ns3header_taskgen, self).__init__(*args, **kwargs)
|
|
gjc@4064
|
115 |
self.install_path = None
|
|
gjc@1877
|
116 |
self.sub_dir = None # if not None, header files will be published as ns3/sub_dir/file.h
|
|
gjc@2609
|
117 |
self.module = None # module name
|
|
gjc@2611
|
118 |
|
|
gjcarneiro@693
|
119 |
def apply(self):
|
|
gjc@2609
|
120 |
if self.module is None:
|
|
gjc@4064
|
121 |
raise Utils.WafError("'module' missing on ns3headers object %s" % self)
|
|
gjc@4326
|
122 |
ns3_dir_node = self.bld.path.find_dir("ns3")
|
|
gjc@1877
|
123 |
if self.sub_dir is not None:
|
|
gjc@1877
|
124 |
ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir)
|
|
gjcarneiro@693
|
125 |
for filename in self.to_list(self.source):
|
|
gjc@4064
|
126 |
src_node = self.path.find_resource(filename)
|
|
gjcarneiro@693
|
127 |
if src_node is None:
|
|
gjc@4064
|
128 |
raise Utils.WafError("source ns3 header file %s not found" % (filename,))
|
|
gjc@4064
|
129 |
dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename))
|
|
gjcarneiro@693
|
130 |
assert dst_node is not None
|
|
gjc@4064
|
131 |
task = self.create_task('ns3header', self.env)
|
|
gjc@954
|
132 |
task.set_inputs([src_node])
|
|
gjc@954
|
133 |
task.set_outputs([dst_node])
|
|
gjcarneiro@693
|
134 |
|
|
gjc@4064
|
135 |
class ns3header_task(Task.Task):
|
|
gjc@4066
|
136 |
before = 'cc cxx gen_ns3_module_header_task'
|
|
gjc@4064
|
137 |
color = 'BLUE'
|
|
gjc@4064
|
138 |
def run(self):
|
|
gjc@4064
|
139 |
assert len(self.inputs) == len(self.outputs)
|
|
gjc@4064
|
140 |
inputs = [node.srcpath(self.env) for node in self.inputs]
|
|
gjc@4064
|
141 |
outputs = [node.bldpath(self.env) for node in self.outputs]
|
|
gjc@4064
|
142 |
for src, dst in zip(inputs, outputs):
|
|
gjc@4064
|
143 |
try:
|
|
gjc@4064
|
144 |
os.chmod(dst, 0600)
|
|
gjc@4064
|
145 |
except OSError:
|
|
gjc@4064
|
146 |
pass
|
|
gjc@4064
|
147 |
shutil.copy2(src, dst)
|
|
gjc@4064
|
148 |
## make the headers in builddir read-only, to prevent
|
|
gjc@4064
|
149 |
## accidental modification
|
|
gjc@4064
|
150 |
os.chmod(dst, 0400)
|
|
gjc@4064
|
151 |
return 0
|
|
gjcarneiro@693
|
152 |
|
|
gjc@2611
|
153 |
|
|
gjc@2611
|
154 |
|
|
gjc@4064
|
155 |
class gen_ns3_module_header_task(Task.Task):
|
|
gjc@4064
|
156 |
before = 'cc cxx'
|
|
gjc@4066
|
157 |
after = 'ns3header_task'
|
|
gjc@4064
|
158 |
color = 'BLUE'
|
|
gjc@4064
|
159 |
def run(self):
|
|
gjc@4064
|
160 |
assert len(self.outputs) == 1
|
|
gjc@4064
|
161 |
header_files = [os.path.basename(node.abspath(self.env)) for node in self.inputs]
|
|
gjc@4064
|
162 |
outfile = file(self.outputs[0].bldpath(self.env), "w")
|
|
gjc@4064
|
163 |
header_files.sort()
|
|
gjc@2611
|
164 |
|
|
gjc@4064
|
165 |
print >> outfile, """
|
|
gjc@2611
|
166 |
#ifdef NS3_MODULE_COMPILATION
|
|
gjc@2611
|
167 |
# error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
|
|
gjc@2611
|
168 |
#endif
|
|
gjc@2611
|
169 |
|
|
gjc@2611
|
170 |
#ifndef NS3_MODULE_%s
|
|
gjc@4064
|
171 |
""" % (self.module.upper().replace('-', '_'),)
|
|
gjc@2611
|
172 |
|
|
gjc@4064
|
173 |
# if self.module_deps:
|
|
gjc@4064
|
174 |
# print >> outfile, "// Module dependencies:"
|
|
gjc@4064
|
175 |
# for dep in self.module_deps:
|
|
gjc@4064
|
176 |
# print >> outfile, "#include \"%s-module.h\"" % dep
|
|
gjc@2611
|
177 |
|
|
gjc@4064
|
178 |
print >> outfile
|
|
gjc@4064
|
179 |
print >> outfile, "// Module headers:"
|
|
gjc@4064
|
180 |
for header in header_files:
|
|
gjc@4064
|
181 |
print >> outfile, "#include \"%s\"" % (header,)
|
|
gjc@2611
|
182 |
|
|
gjc@4064
|
183 |
print >> outfile, "#endif"
|
|
gjc@2611
|
184 |
|
|
gjc@4064
|
185 |
outfile.close()
|
|
gjc@4064
|
186 |
return 0
|
|
gjc@2611
|
187 |
|
|
gjc@4126
|
188 |
def sig_explicit_deps(self):
|
|
gjc@4326
|
189 |
m = Utils.md5()
|
|
gjc@4126
|
190 |
m.update('\n'.join([node.abspath(self.env) for node in self.inputs]))
|
|
gjc@4126
|
191 |
return m.digest()
|
|
gjc@4126
|
192 |
|
|
gjc@4126
|
193 |
def unique_id(self):
|
|
gjc@4126
|
194 |
try:
|
|
gjc@4126
|
195 |
return self.uid
|
|
gjc@4126
|
196 |
except AttributeError:
|
|
gjc@4126
|
197 |
"this is not a real hot zone, but we want to avoid surprizes here"
|
|
gjc@4326
|
198 |
m = Utils.md5()
|
|
gjc@4126
|
199 |
m.update("ns-3-module-header-%s" % self.module)
|
|
gjc@4126
|
200 |
self.uid = m.digest()
|
|
gjc@4126
|
201 |
return self.uid
|
|
gjc@4126
|
202 |
|
|
gjc@2611
|
203 |
|
|
gjc@4064
|
204 |
class ns3moduleheader_taskgen(TaskGen.task_gen):
|
|
gjc@2611
|
205 |
"""
|
|
gjc@2611
|
206 |
Generates a 'ns3/foo-module.h' header file that includes all
|
|
gjc@2611
|
207 |
public ns3 headers of a certain module.
|
|
gjc@2611
|
208 |
"""
|
|
gjc@4064
|
209 |
COLOR = 'BLUE'
|
|
gjc@4064
|
210 |
def __init__(self, *args, **kwargs):
|
|
gjc@4064
|
211 |
super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs)
|
|
gjc@2611
|
212 |
|
|
gjc@2611
|
213 |
def apply(self):
|
|
gjc@2611
|
214 |
## get all of the ns3 headers
|
|
gjc@4326
|
215 |
ns3_dir_node = self.bld.path.find_dir("ns3")
|
|
gjc@2611
|
216 |
all_headers_inputs = []
|
|
gjc@4750
|
217 |
found_the_module = False
|
|
gjc@4326
|
218 |
for ns3headers in self.bld.all_task_gen:
|
|
gjc@3001
|
219 |
if isinstance(ns3headers, ns3header_taskgen):
|
|
gjc@2611
|
220 |
if ns3headers.module != self.module:
|
|
gjc@2611
|
221 |
continue
|
|
gjc@4750
|
222 |
found_the_module = True
|
|
gjc@2611
|
223 |
for source in ns3headers.to_list(ns3headers.source):
|
|
gjc@2611
|
224 |
source = os.path.basename(source)
|
|
gjc@4064
|
225 |
node = ns3_dir_node.find_or_declare(os.path.basename(source))
|
|
gjc@2611
|
226 |
if node is None:
|
|
gjc@2611
|
227 |
fatal("missing header file %s" % (source,))
|
|
gjc@2611
|
228 |
all_headers_inputs.append(node)
|
|
gjc@4750
|
229 |
if not found_the_module:
|
|
gjc@4750
|
230 |
raise Utils.WscriptError("error finding headers for module %s" % self.module)
|
|
gjc@4326
|
231 |
if not all_headers_inputs:
|
|
gjc@4750
|
232 |
return
|
|
gjc@4326
|
233 |
module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env)
|
|
gjc@2611
|
234 |
assert module_obj is not None
|
|
gjc@4064
|
235 |
all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)]
|
|
gjc@4064
|
236 |
task = self.create_task('gen_ns3_module_header', self.env)
|
|
gjc@2611
|
237 |
task.set_inputs(all_headers_inputs)
|
|
gjc@2611
|
238 |
task.set_outputs(all_headers_outputs)
|
|
gjc@2611
|
239 |
task.module = self.module
|
|
gjc@2611
|
240 |
task.module_deps = module_obj.module_deps
|
|
gjc@2611
|
241 |
|
|
gjc@2611
|
242 |
def install(self):
|
|
gjc@2611
|
243 |
pass
|