1 | # |
---|
2 | # Copyright 2012-2016 Chris Johns (chrisj@rtems.org) |
---|
3 | # |
---|
4 | # Redistribution and use in source and binary forms, with or without |
---|
5 | # modification, are permitted provided that the following conditions are met: |
---|
6 | |
---|
7 | # 1. Redistributions of source code must retain the above copyright notice, this |
---|
8 | # list of conditions and the following disclaimer. |
---|
9 | |
---|
10 | # 2. Redistributions in binary form must reproduce the above copyright notice, |
---|
11 | # this list of conditions and the following disclaimer in the documentation |
---|
12 | # and/or other materials provided with the distribution. |
---|
13 | |
---|
14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
---|
15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
---|
17 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
---|
18 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
19 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
---|
20 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
---|
21 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
---|
22 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
---|
23 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
24 | |
---|
25 | # |
---|
26 | # RTEMS support for applications. |
---|
27 | # |
---|
28 | |
---|
29 | import copy |
---|
30 | import os |
---|
31 | import os.path |
---|
32 | from . import pkgconfig |
---|
33 | import re |
---|
34 | import subprocess |
---|
35 | |
---|
36 | rtems_default_version = None |
---|
37 | rtems_filters = None |
---|
38 | rtems_long_commands = False |
---|
39 | |
---|
40 | def options(opt): |
---|
41 | opt.add_option('--rtems', |
---|
42 | default = None, |
---|
43 | dest = 'rtems_path', |
---|
44 | help = 'Path to an installed RTEMS (defaults to prefix).') |
---|
45 | opt.add_option('--rtems-tools', |
---|
46 | default = None, |
---|
47 | dest = 'rtems_tools', |
---|
48 | help = 'Path to RTEMS tools (defaults to path to installed RTEMS).') |
---|
49 | opt.add_option('--rtems-version', |
---|
50 | default = None, |
---|
51 | dest = 'rtems_version', |
---|
52 | help = 'RTEMS version (default is derived from prefix).') |
---|
53 | opt.add_option('--rtems-archs', |
---|
54 | default = 'all', |
---|
55 | dest = 'rtems_archs', |
---|
56 | help = 'List of RTEMS architectures to build.') |
---|
57 | opt.add_option('--rtems-bsps', |
---|
58 | default = 'all', |
---|
59 | dest = 'rtems_bsps', |
---|
60 | help = 'List of BSPs to build.') |
---|
61 | opt.add_option('--show-commands', |
---|
62 | action = 'store_true', |
---|
63 | default = False, |
---|
64 | dest = 'show_commands', |
---|
65 | help = 'Print the commands as strings.') |
---|
66 | |
---|
67 | def init(ctx, filters = None, version = None, long_commands = False): |
---|
68 | global rtems_filters |
---|
69 | global rtems_default_version |
---|
70 | global rtems_long_commands |
---|
71 | |
---|
72 | # |
---|
73 | # Set the RTEMS filter to the context. |
---|
74 | # |
---|
75 | rtems_filters = filters |
---|
76 | |
---|
77 | # |
---|
78 | # Set the default version, can be overridden. |
---|
79 | # |
---|
80 | rtems_default_version = version |
---|
81 | |
---|
82 | # |
---|
83 | # Set the long commands option. |
---|
84 | # |
---|
85 | rtems_long_commands = long_commands |
---|
86 | |
---|
87 | try: |
---|
88 | import waflib.Options |
---|
89 | import waflib.ConfigSet |
---|
90 | |
---|
91 | # |
---|
92 | # Load the configuation set from the lock file. |
---|
93 | # |
---|
94 | env = waflib.ConfigSet.ConfigSet() |
---|
95 | env.load(waflib.Options.lockfile) |
---|
96 | |
---|
97 | # |
---|
98 | # Check the tools, architectures and bsps. |
---|
99 | # |
---|
100 | rtems_version, rtems_path, rtems_bin, rtems_tools, archs, arch_bsps = \ |
---|
101 | check_options(ctx, |
---|
102 | env.options['prefix'], |
---|
103 | env.options['rtems_tools'], |
---|
104 | env.options['rtems_path'], |
---|
105 | env.options['rtems_version'], |
---|
106 | env.options['rtems_archs'], |
---|
107 | env.options['rtems_bsps']) |
---|
108 | |
---|
109 | # |
---|
110 | # Update the contextes for all the bsps. |
---|
111 | # |
---|
112 | from waflib.Build import BuildContext, CleanContext, \ |
---|
113 | InstallContext, UninstallContext |
---|
114 | for x in arch_bsps: |
---|
115 | for y in (BuildContext, CleanContext, InstallContext, UninstallContext): |
---|
116 | name = y.__name__.replace('Context','').lower() |
---|
117 | class context(y): |
---|
118 | cmd = name + '-' + x |
---|
119 | variant = x |
---|
120 | |
---|
121 | # |
---|
122 | # Transform the command to per BSP commands. |
---|
123 | # |
---|
124 | commands = [] |
---|
125 | for cmd in waflib.Options.commands: |
---|
126 | if cmd in ['build', 'clean', 'install']: |
---|
127 | for x in arch_bsps: |
---|
128 | commands += [cmd + '-' + x] |
---|
129 | else: |
---|
130 | commands += [cmd] |
---|
131 | waflib.Options.commands = commands |
---|
132 | except: |
---|
133 | pass |
---|
134 | |
---|
135 | def configure(conf, bsp_configure = None): |
---|
136 | # |
---|
137 | # Check the environment for any flags. |
---|
138 | # |
---|
139 | for f in ['CC', 'CXX', 'AS', 'LD', 'AR', 'LINK_CC', 'LINK_CXX', |
---|
140 | 'CPPFLAGS', 'CFLAGS', 'CXXFLAGS', 'ASFLAGS', 'LINKFLAGS', 'LIB' |
---|
141 | 'WFLAGS', 'RFLAGS', 'MFLAGS', 'IFLAGS']: |
---|
142 | if f in os.environ: |
---|
143 | conf.msg('Environment variable set', f, color = 'RED') |
---|
144 | |
---|
145 | # |
---|
146 | # Handle the configurable commands options. |
---|
147 | # |
---|
148 | if conf.options.show_commands: |
---|
149 | show_commands = 'yes' |
---|
150 | else: |
---|
151 | show_commands = 'no' |
---|
152 | if rtems_long_commands and os.name == 'nt': |
---|
153 | long_commands = 'yes' |
---|
154 | else: |
---|
155 | long_commands = 'no' |
---|
156 | |
---|
157 | rtems_version, rtems_path, rtems_bin, rtems_tools, archs, arch_bsps = \ |
---|
158 | check_options(conf, |
---|
159 | conf.options.prefix, |
---|
160 | conf.options.rtems_tools, |
---|
161 | conf.options.rtems_path, |
---|
162 | conf.options.rtems_version, |
---|
163 | conf.options.rtems_archs, |
---|
164 | conf.options.rtems_bsps) |
---|
165 | |
---|
166 | if rtems_tools is None: |
---|
167 | conf.fatal('RTEMS tools not found.') |
---|
168 | |
---|
169 | _log_header(conf) |
---|
170 | |
---|
171 | conf.msg('RTEMS Version', rtems_version, 'YELLOW') |
---|
172 | conf.msg('Architectures', ', '.join(archs), 'YELLOW') |
---|
173 | |
---|
174 | tools = {} |
---|
175 | env = conf.env.derive() |
---|
176 | |
---|
177 | for ab in arch_bsps: |
---|
178 | conf.setenv(ab, env) |
---|
179 | |
---|
180 | conf.msg('Board Support Package', ab, 'YELLOW') |
---|
181 | |
---|
182 | # |
---|
183 | # Show and long commands support. |
---|
184 | # |
---|
185 | conf.env.SHOW_COMMANDS = show_commands |
---|
186 | conf.env.LONG_COMMANDS = long_commands |
---|
187 | |
---|
188 | conf.msg('Show commands', show_commands) |
---|
189 | conf.msg('Long commands', long_commands) |
---|
190 | |
---|
191 | arch = _arch_from_arch_bsp(ab) |
---|
192 | bsp = _bsp_from_arch_bsp(ab) |
---|
193 | |
---|
194 | conf.env.ARCH_BSP = '%s/%s' % (arch.split('-')[0], bsp) |
---|
195 | |
---|
196 | conf.env.RTEMS_PATH = rtems_path |
---|
197 | conf.env.RTEMS_VERSION = rtems_version |
---|
198 | conf.env.RTEMS_ARCH_BSP = ab |
---|
199 | conf.env.RTEMS_ARCH = arch.split('-')[0] |
---|
200 | conf.env.RTEMS_ARCH_RTEMS = arch |
---|
201 | conf.env.RTEMS_BSP = bsp |
---|
202 | |
---|
203 | tools = _find_tools(conf, arch, [rtems_bin] + rtems_tools, tools) |
---|
204 | for t in tools[arch]: |
---|
205 | conf.env[t] = tools[arch][t] |
---|
206 | |
---|
207 | conf.load('gcc') |
---|
208 | conf.load('g++') |
---|
209 | conf.load('gas') |
---|
210 | |
---|
211 | # |
---|
212 | # Get the version of the tools being used. |
---|
213 | # |
---|
214 | rtems_cc = conf.env.CC[0] |
---|
215 | try: |
---|
216 | import waflib.Context |
---|
217 | out = conf.cmd_and_log([rtems_cc, '--version'], |
---|
218 | output = waflib.Context.STDOUT) |
---|
219 | except Exception as e: |
---|
220 | conf.fatal('CC version not found: %s' % (e.stderr)) |
---|
221 | # |
---|
222 | # First line is the version |
---|
223 | # |
---|
224 | vline = out.split('\n')[0] |
---|
225 | conf.msg('Compiler version (%s)' % (os.path.basename(rtems_cc)), |
---|
226 | ' '.join(vline.split()[2:])) |
---|
227 | |
---|
228 | flags = _load_flags(conf, ab, rtems_path) |
---|
229 | |
---|
230 | cflags = _filter_flags('cflags', flags['CFLAGS'], |
---|
231 | arch, rtems_path) |
---|
232 | ldflags = _filter_flags('ldflags', flags['LDFLAGS'], |
---|
233 | arch, rtems_path) |
---|
234 | |
---|
235 | conf.env.CFLAGS = cflags['cflags'] |
---|
236 | conf.env.CXXFLAGS = conf.env.CFLAGS |
---|
237 | conf.env.ASFLAGS = cflags['cflags'] |
---|
238 | conf.env.WFLAGS = cflags['warnings'] |
---|
239 | conf.env.RFLAGS = cflags['specs'] |
---|
240 | conf.env.MFLAGS = cflags['machines'] |
---|
241 | conf.env.IFLAGS = cflags['includes'] |
---|
242 | conf.env.LINKFLAGS = cflags['cflags'] + ldflags['ldflags'] |
---|
243 | conf.env.LIB = flags['LIB'] |
---|
244 | conf.env.LIBPATH = ldflags['libpath'] |
---|
245 | |
---|
246 | conf.env.RTRACE_WRAPPER_ST = '-W %s' |
---|
247 | |
---|
248 | # |
---|
249 | # Checks for various RTEMS features. |
---|
250 | # |
---|
251 | conf.multicheck({ 'header_name': 'rtems/score/cpuopts.h'}, |
---|
252 | msg = 'Checking for RTEMS CPU options header', |
---|
253 | mandatory = True) |
---|
254 | load_cpuopts(conf, ab, rtems_path) |
---|
255 | if conf.env['RTEMS_SMP'] == 'Yes': |
---|
256 | conf.env.CXXFLAGS += ['-std=gnu++11'] |
---|
257 | conf.multicheck({ 'header_name': 'rtems.h'}, |
---|
258 | msg = 'Checking for RTEMS header', |
---|
259 | mandatory = True) |
---|
260 | |
---|
261 | # |
---|
262 | # Add tweaks. |
---|
263 | # |
---|
264 | tweaks(conf, ab) |
---|
265 | |
---|
266 | # |
---|
267 | # If the user has supplied a BSP specific configure function |
---|
268 | # call it. |
---|
269 | # |
---|
270 | if bsp_configure: |
---|
271 | bsp_configure(conf, ab) |
---|
272 | |
---|
273 | conf.setenv('', env) |
---|
274 | |
---|
275 | conf.env.RTEMS_TOOLS = rtems_tools |
---|
276 | conf.env.ARCHS = archs |
---|
277 | conf.env.ARCH_BSPS = arch_bsps |
---|
278 | |
---|
279 | conf.env.SHOW_COMMANDS = show_commands |
---|
280 | conf.env.LONG_COMMANDS = long_commands |
---|
281 | |
---|
282 | def build(bld): |
---|
283 | if bld.env.SHOW_COMMANDS == 'yes': |
---|
284 | output_command_line() |
---|
285 | if bld.env.LONG_COMMANDS == 'yes': |
---|
286 | long_command_line() |
---|
287 | |
---|
288 | def load_cpuopts(conf, arch_bsp, rtems_path): |
---|
289 | options = ['RTEMS_DEBUG', |
---|
290 | 'RTEMS_MULTIPROCESSING', |
---|
291 | 'RTEMS_NEWLIB', |
---|
292 | 'RTEMS_POSIX_API', |
---|
293 | 'RTEMS_SMP', |
---|
294 | 'RTEMS_NETWORKING'] |
---|
295 | for opt in options: |
---|
296 | enabled = check_opt(conf, opt, 'rtems/score/cpuopts.h', arch_bsp, rtems_path) |
---|
297 | if enabled: |
---|
298 | conf.env[opt] = 'Yes' |
---|
299 | else: |
---|
300 | conf.env[opt] = 'No' |
---|
301 | |
---|
302 | def check_opt(conf, opt, header, arch_bsp, rtems_path): |
---|
303 | code = '#include <%s>%s' % (header, os.linesep) |
---|
304 | code += '#ifndef %s%s' % (opt, os.linesep) |
---|
305 | code += ' #error %s is not defined%s' % (opt, os.linesep) |
---|
306 | code += '#endif%s' % (os.linesep) |
---|
307 | code += '#if %s%s' % (opt, os.linesep) |
---|
308 | code += ' /* %s is true */%s' % (opt, os.linesep) |
---|
309 | code += '#else%s' % (os.linesep) |
---|
310 | code += ' #error %s is false%s' % (opt, os.linesep) |
---|
311 | code += '#endif%s' % (os.linesep) |
---|
312 | code += 'int main() { return 0; }%s' % (os.linesep) |
---|
313 | try: |
---|
314 | conf.check_cc(fragment = code, |
---|
315 | execute = False, |
---|
316 | define_ret = False, |
---|
317 | msg = 'Checking for %s' % (opt)) |
---|
318 | except conf.errors.WafError: |
---|
319 | return False; |
---|
320 | return True |
---|
321 | |
---|
322 | def tweaks(conf, arch_bsp): |
---|
323 | # |
---|
324 | # Hack to work around NIOS2 naming. |
---|
325 | # |
---|
326 | if conf.env.RTEMS_ARCH in ['nios2']: |
---|
327 | conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-littlenios2'] |
---|
328 | elif conf.env.RTEMS_ARCH in ['arm']: |
---|
329 | conf.env.OBJCOPY_FLAGS = ['-I', 'binary', '-O', 'elf32-littlearm'] |
---|
330 | else: |
---|
331 | conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-' + conf.env.RTEMS_ARCH] |
---|
332 | |
---|
333 | # |
---|
334 | # Check for a i386 PC bsp. |
---|
335 | # |
---|
336 | if re.match('i386-.*-pc[3456]86', arch_bsp) is not None: |
---|
337 | conf.env.LINKFLAGS += ['-Wl,-Ttext,0x00100000'] |
---|
338 | |
---|
339 | if '-ffunction-sections' in conf.env.CFLAGS: |
---|
340 | conf.env.LINKFLAGS += ['-Wl,--gc-sections'] |
---|
341 | |
---|
342 | def check_options(ctx, prefix, rtems_tools, rtems_path, rtems_version, rtems_archs, rtems_bsps): |
---|
343 | # |
---|
344 | # Set defaults |
---|
345 | # |
---|
346 | if rtems_version is None: |
---|
347 | if rtems_default_version is None: |
---|
348 | m = re.compile('[^0-9.]*([0-9.]+)$').match(prefix) |
---|
349 | if m: |
---|
350 | rtems_version = m.group(1) |
---|
351 | else: |
---|
352 | ctx.fatal('RTEMS version cannot derived from prefix: ' + prefix) |
---|
353 | else: |
---|
354 | rtems_version = rtems_default_version |
---|
355 | if rtems_path is None: |
---|
356 | rtems_path = prefix |
---|
357 | if rtems_tools is None: |
---|
358 | rtems_tools = rtems_path |
---|
359 | |
---|
360 | # |
---|
361 | # Check the paths are valid. |
---|
362 | # |
---|
363 | if not os.path.exists(rtems_path): |
---|
364 | ctx.fatal('RTEMS path not found.') |
---|
365 | if os.path.exists(os.path.join(rtems_path, 'lib', 'pkgconfig')): |
---|
366 | rtems_config = None |
---|
367 | elif os.path.exists(os.path.join(rtems_path, 'rtems-config')): |
---|
368 | rtems_config = os.path.join(rtems_path, 'rtems-config') |
---|
369 | else: |
---|
370 | ctx.fatal('RTEMS path is not valid. No lib/pkgconfig or rtems-config found.') |
---|
371 | if os.path.exists(os.path.join(rtems_path, 'bin')): |
---|
372 | rtems_bin = os.path.join(rtems_path, 'bin') |
---|
373 | else: |
---|
374 | ctx.fatal('RTEMS path is not valid. No bin directory found.') |
---|
375 | |
---|
376 | # |
---|
377 | # We can more than one path to tools. This happens when testing different |
---|
378 | # versions. |
---|
379 | # |
---|
380 | rt = rtems_tools.split(',') |
---|
381 | tools = [] |
---|
382 | for path in rt: |
---|
383 | if not os.path.exists(path): |
---|
384 | ctx.fatal('RTEMS tools path not found: ' + path) |
---|
385 | if not os.path.exists(os.path.join(path, 'bin')): |
---|
386 | ctx.fatal('RTEMS tools path does not contain a \'bin\' directory: ' + path) |
---|
387 | tools += [os.path.join(path, 'bin')] |
---|
388 | |
---|
389 | # |
---|
390 | # Filter the tools. |
---|
391 | # |
---|
392 | tools = filter(ctx, 'tools', tools) |
---|
393 | |
---|
394 | # |
---|
395 | # Match the archs requested against the ones found. If the user |
---|
396 | # wants all (default) set all used. |
---|
397 | # |
---|
398 | if rtems_archs == 'all': |
---|
399 | archs = _find_installed_archs(rtems_config, rtems_path, rtems_version) |
---|
400 | else: |
---|
401 | archs = _check_archs(rtems_config, rtems_archs, rtems_path, rtems_version) |
---|
402 | |
---|
403 | # |
---|
404 | # Filter the architectures. |
---|
405 | # |
---|
406 | archs = filter(ctx, 'archs', archs) |
---|
407 | |
---|
408 | # |
---|
409 | # We some. |
---|
410 | # |
---|
411 | if len(archs) == 0: |
---|
412 | ctx.fatal('Could not find any architectures') |
---|
413 | |
---|
414 | # |
---|
415 | # Get the list of valid BSPs. This process filters the architectures |
---|
416 | # to those referenced by the BSPs. |
---|
417 | # |
---|
418 | if rtems_bsps == 'all': |
---|
419 | arch_bsps = _find_installed_arch_bsps(rtems_config, rtems_path, archs, rtems_version) |
---|
420 | else: |
---|
421 | arch_bsps = _check_arch_bsps(rtems_bsps, rtems_config, rtems_path, archs, rtems_version) |
---|
422 | |
---|
423 | if len(arch_bsps) == 0: |
---|
424 | ctx.fatal('No valid arch/bsps found') |
---|
425 | |
---|
426 | # |
---|
427 | # Filter the bsps. |
---|
428 | # |
---|
429 | arch_bsps = filter(ctx, 'bsps', arch_bsps) |
---|
430 | |
---|
431 | return rtems_version, rtems_path, rtems_bin, tools, archs, arch_bsps |
---|
432 | |
---|
433 | def check_env(ctx, var): |
---|
434 | if var in ctx.env and len(ctx.env[var]) != 0: |
---|
435 | return True |
---|
436 | return False |
---|
437 | |
---|
438 | def check(ctx, option): |
---|
439 | if option in ctx.env: |
---|
440 | return ctx.env[option] == 'Yes' |
---|
441 | return False |
---|
442 | |
---|
443 | def check_debug(ctx): |
---|
444 | return check(ctx, 'RTEMS_DEBUG') |
---|
445 | |
---|
446 | def check_multiprocessing(ctx): |
---|
447 | return check(ctx, 'RTEMS_MULTIPROCESSING') |
---|
448 | |
---|
449 | def check_newlib(ctx): |
---|
450 | return check(ctx, 'RTEMS_NEWLIB') |
---|
451 | |
---|
452 | def check_posix(ctx): |
---|
453 | return check(ctx, 'RTEMS_POSIX_API') |
---|
454 | |
---|
455 | def check_smp(ctx): |
---|
456 | return check(ctx, 'RTEMS_SMP') |
---|
457 | |
---|
458 | def check_networking(ctx): |
---|
459 | return check(ctx, 'RTEMS_NETWORKING') |
---|
460 | |
---|
461 | def arch(arch_bsp): |
---|
462 | """ Given an arch/bsp return the architecture.""" |
---|
463 | return _arch_from_arch_bsp(arch_bsp).split('-')[0] |
---|
464 | |
---|
465 | def bsp(arch_bsp): |
---|
466 | """ Given an arch/bsp return the BSP.""" |
---|
467 | return _bsp_from_arch_bsp(arch_bsp) |
---|
468 | |
---|
469 | def arch_bsps(ctx): |
---|
470 | """ Return the list of arch/bsps we are building.""" |
---|
471 | return ctx.env.ARCH_BSPS |
---|
472 | |
---|
473 | def arch_bsp_env(ctx, arch_bsp): |
---|
474 | return ctx.env_of_name(arch_bsp).derive() |
---|
475 | |
---|
476 | def filter(ctx, filter, items): |
---|
477 | if rtems_filters is None: |
---|
478 | return items |
---|
479 | if type(rtems_filters) is not dict: |
---|
480 | ctx.fatal("Invalid RTEMS filter type, " \ |
---|
481 | "ie { 'tools': { 'in': [], 'out': [] }, 'arch': {}, 'bsps': {} }") |
---|
482 | if filter not in rtems_filters: |
---|
483 | return items |
---|
484 | items_in = [] |
---|
485 | items_out = [] |
---|
486 | if 'in' in rtems_filters[filter]: |
---|
487 | items_in = copy.copy(rtems_filters[filter]['in']) |
---|
488 | if 'out' in rtems_filters[filter]: |
---|
489 | items_out = copy.copy(rtems_filters[filter]['out']) |
---|
490 | filtered_items = [] |
---|
491 | for i in items: |
---|
492 | item = i |
---|
493 | ab = '%s/%s' % (arch(item), bsp(item)) |
---|
494 | for inre in items_in: |
---|
495 | if re.compile(inre).match(ab): |
---|
496 | items_in.remove(inre) |
---|
497 | filtered_items += [item] |
---|
498 | item = None |
---|
499 | break |
---|
500 | if item is not None: |
---|
501 | for outre in items_out: |
---|
502 | if re.compile(outre).match(ab): |
---|
503 | item = None |
---|
504 | break |
---|
505 | if item is not None: |
---|
506 | filtered_items += [item] |
---|
507 | if len(items_in) != 0: |
---|
508 | ctx.fatal('Following %s not found: %s' % (filter, ', '.join(items_in))) |
---|
509 | return sorted(filtered_items) |
---|
510 | |
---|
511 | def arch_rtems_version(version, arch): |
---|
512 | """ Return the RTEMS architecture path, ie sparc-rtems4.11.""" |
---|
513 | return '%s-rtems%s' % (arch, version) |
---|
514 | |
---|
515 | def arch_bsp_path(version, arch_bsp): |
---|
516 | """ Return the BSP path.""" |
---|
517 | return '%s/%s' % (arch_rtems_version(version, arch(arch_bsp)), bsp(arch_bsp)) |
---|
518 | |
---|
519 | def arch_bsp_include_path(version, arch_bsp): |
---|
520 | """ Return the BSP include path.""" |
---|
521 | return '%s/lib/include' % (arch_bsp_path(version, arch_bsp)) |
---|
522 | |
---|
523 | def arch_bsp_lib_path(version, arch_bsp): |
---|
524 | """ Return the BSP library path. """ |
---|
525 | return '%s/lib' % (arch_bsp_path(version, arch_bsp)) |
---|
526 | |
---|
527 | def library_path(library, cc, cflags): |
---|
528 | cmd = cc + cflags + ['-print-file-name=%s' % library] |
---|
529 | a = subprocess.check_output(cmd) |
---|
530 | lib = os.path.abspath(a.strip()) |
---|
531 | if os.path.exists(lib): |
---|
532 | return os.path.dirname(lib) |
---|
533 | return None |
---|
534 | |
---|
535 | def root_filesystem(bld, name, files, tar, obj): |
---|
536 | bld(name = name + '_tar', |
---|
537 | target = tar, |
---|
538 | source = files, |
---|
539 | rule = 'SDIR=$PWD && cd ../.. && tar --format=ustar -cf $SDIR/${TGT} $(echo "${SRC}" | sed -e "s/\.\.\/\.\.\///\")') |
---|
540 | bld.objects(name = name, |
---|
541 | target = obj, |
---|
542 | source = tar, |
---|
543 | rule = '${OBJCOPY} -I binary -B ${RTEMS_ARCH} ${OBJCOPY_FLAGS} ${SRC} ${TGT}') |
---|
544 | |
---|
545 | def clone_tasks(bld): |
---|
546 | if bld.cmd == 'build': |
---|
547 | for obj in bld.all_task_gen[:]: |
---|
548 | for x in arch_bsp: |
---|
549 | cloned_obj = obj.clone(x) |
---|
550 | kind = Options.options.build_kind |
---|
551 | if kind.find(x) < 0: |
---|
552 | cloned_obj.posted = True |
---|
553 | obj.posted = True |
---|
554 | |
---|
555 | # |
---|
556 | # From the demos. Use this to get the command to cut+paste to play. |
---|
557 | # |
---|
558 | def output_command_line(): |
---|
559 | # first, display strings, people like them |
---|
560 | from waflib import Utils, Logs |
---|
561 | from waflib.Context import Context |
---|
562 | def exec_command(self, cmd, **kw): |
---|
563 | subprocess = Utils.subprocess |
---|
564 | kw['shell'] = isinstance(cmd, str) |
---|
565 | if isinstance(cmd, str): |
---|
566 | Logs.info('%s' % cmd) |
---|
567 | else: |
---|
568 | cmd = ' '.join(cmd) |
---|
569 | Logs.info('(%d) %s' % (len(cmd), cmd)) # here is the change |
---|
570 | Logs.debug('runner_env: kw=%s' % kw) |
---|
571 | try: |
---|
572 | if self.logger: |
---|
573 | self.logger.info(cmd) |
---|
574 | kw['stdout'] = kw['stderr'] = subprocess.PIPE |
---|
575 | p = subprocess.Popen(cmd, **kw) |
---|
576 | (out, err) = p.communicate() |
---|
577 | if out: |
---|
578 | self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) |
---|
579 | if err: |
---|
580 | self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) |
---|
581 | return p.returncode |
---|
582 | else: |
---|
583 | p = subprocess.Popen(cmd, **kw) |
---|
584 | return p.wait() |
---|
585 | except OSError: |
---|
586 | return -1 |
---|
587 | Context.exec_command = exec_command |
---|
588 | |
---|
589 | # Change the outputs for tasks too |
---|
590 | from waflib.Task import Task |
---|
591 | def display(self): |
---|
592 | return '' # no output on empty strings |
---|
593 | |
---|
594 | Task.__str__ = display |
---|
595 | |
---|
596 | # |
---|
597 | # From the extras. Use this to support long command lines. |
---|
598 | # |
---|
599 | def long_command_line(): |
---|
600 | def exec_command(self, cmd, **kw): |
---|
601 | # workaround for command line length limit: |
---|
602 | # http://support.microsoft.com/kb/830473 |
---|
603 | import tempfile |
---|
604 | tmp = None |
---|
605 | try: |
---|
606 | if not isinstance(cmd, str) and len(str(cmd)) > 8192: |
---|
607 | (fd, tmp) = tempfile.mkstemp(dir=self.generator.bld.bldnode.abspath()) |
---|
608 | flat = ['"%s"' % x.replace('\\', '\\\\').replace('"', '\\"') for x in cmd[1:]] |
---|
609 | try: |
---|
610 | os.write(fd, ' '.join(flat).encode()) |
---|
611 | finally: |
---|
612 | if tmp: |
---|
613 | os.close(fd) |
---|
614 | # Line may be very long: |
---|
615 | # Logs.debug('runner:' + ' '.join(flat)) |
---|
616 | cmd = [cmd[0], '@' + tmp] |
---|
617 | ret = super(self.__class__, self).exec_command(cmd, **kw) |
---|
618 | finally: |
---|
619 | if tmp: |
---|
620 | os.remove(tmp) |
---|
621 | return ret |
---|
622 | for k in 'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split(): |
---|
623 | cls = Task.classes.get(k) |
---|
624 | if cls: |
---|
625 | derived_class = type(k, (cls,), {}) |
---|
626 | derived_class.exec_command = exec_command |
---|
627 | if hasattr(cls, 'hcode'): |
---|
628 | derived_class.hcode = cls.hcode |
---|
629 | |
---|
630 | def _find_tools(conf, arch, paths, tools): |
---|
631 | if arch not in tools: |
---|
632 | arch_tools = {} |
---|
633 | arch_tools['CC'] = conf.find_program([arch + '-gcc'], path_list = paths) |
---|
634 | arch_tools['CXX'] = conf.find_program([arch + '-g++'], path_list = paths) |
---|
635 | arch_tools['LINK_CC'] = arch_tools['CC'] |
---|
636 | arch_tools['LINK_CXX'] = arch_tools['CXX'] |
---|
637 | arch_tools['AS'] = conf.find_program([arch + '-gcc'], path_list = paths) |
---|
638 | arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) |
---|
639 | arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) |
---|
640 | arch_tools['NM'] = conf.find_program([arch + '-nm'], path_list = paths) |
---|
641 | arch_tools['OBJDUMP'] = conf.find_program([arch + '-objdump'], path_list = paths) |
---|
642 | arch_tools['OBJCOPY'] = conf.find_program([arch + '-objcopy'], path_list = paths) |
---|
643 | arch_tools['READELF'] = conf.find_program([arch + '-readelf'], path_list = paths) |
---|
644 | arch_tools['STRIP'] = conf.find_program([arch + '-strip'], path_list = paths) |
---|
645 | arch_tools['RTEMS_LD'] = conf.find_program(['rtems-ld'], path_list = paths, |
---|
646 | mandatory = False) |
---|
647 | arch_tools['RTEMS_TLD'] = conf.find_program(['rtems-tld'], path_list = paths, |
---|
648 | mandatory = False) |
---|
649 | arch_tools['RTEMS_BIN2C'] = conf.find_program(['rtems-bin2c'], path_list = paths, |
---|
650 | mandatory = False) |
---|
651 | arch_tools['TAR'] = conf.find_program(['tar'], mandatory = False) |
---|
652 | tools[arch] = arch_tools |
---|
653 | return tools |
---|
654 | |
---|
655 | def _find_installed_archs(config, path, version): |
---|
656 | archs = [] |
---|
657 | if config is None: |
---|
658 | for d in os.listdir(path): |
---|
659 | if d.endswith('-rtems' + version): |
---|
660 | archs += [d] |
---|
661 | else: |
---|
662 | a = subprocess.check_output([config, '--list-format', '"%(arch)s"']) |
---|
663 | a = a[:-1].replace('"', '') |
---|
664 | archs = set(a.split()) |
---|
665 | archs = ['%s-rtems%s' % (x, version) for x in archs] |
---|
666 | archs.sort() |
---|
667 | return archs |
---|
668 | |
---|
669 | def _check_archs(config, req, path, version): |
---|
670 | installed = _find_installed_archs(config, path, version) |
---|
671 | archs = [] |
---|
672 | for a in req.split(','): |
---|
673 | arch = a + '-rtems' + version |
---|
674 | if arch in installed: |
---|
675 | archs += [arch] |
---|
676 | archs.sort() |
---|
677 | return archs |
---|
678 | |
---|
679 | def _find_installed_arch_bsps(config, path, archs, version): |
---|
680 | arch_bsps = [] |
---|
681 | if config is None: |
---|
682 | for f in os.listdir(_pkgconfig_path(path)): |
---|
683 | if f.endswith('.pc'): |
---|
684 | if _arch_from_arch_bsp(f[:-3]) in archs: |
---|
685 | arch_bsps += [f[:-3]] |
---|
686 | else: |
---|
687 | ab = subprocess.check_output([config, '--list-format']) |
---|
688 | ab = ab[:-1].replace('"', '') |
---|
689 | ab = ab.replace('/', '-rtems%s-' % (version)) |
---|
690 | arch_bsps = [x for x in set(ab.split())] |
---|
691 | arch_bsps.sort() |
---|
692 | return arch_bsps |
---|
693 | |
---|
694 | def _check_arch_bsps(req, config, path, archs, version): |
---|
695 | archs_bsps = [] |
---|
696 | for ab in req.split(','): |
---|
697 | abl = ab.split('/') |
---|
698 | if len(abl) != 2: |
---|
699 | return [] |
---|
700 | found = False |
---|
701 | for arch in archs: |
---|
702 | a = '%s-rtems%s' % (abl[0], version) |
---|
703 | if a == arch: |
---|
704 | found = True |
---|
705 | break |
---|
706 | if not found: |
---|
707 | return [] |
---|
708 | archs_bsps += ['%s-%s' % (a, abl[1])] |
---|
709 | if len(archs_bsps) == 0: |
---|
710 | return [] |
---|
711 | installed = _find_installed_arch_bsps(config, path, archs, version) |
---|
712 | bsps = [] |
---|
713 | for b in archs_bsps: |
---|
714 | if b in installed: |
---|
715 | bsps += [b] |
---|
716 | bsps.sort() |
---|
717 | return bsps |
---|
718 | |
---|
719 | def _arch_from_arch_bsp(arch_bsp): |
---|
720 | return '-'.join(arch_bsp.split('-')[:2]) |
---|
721 | |
---|
722 | def _bsp_from_arch_bsp(arch_bsp): |
---|
723 | return '-'.join(arch_bsp.split('-')[2:]) |
---|
724 | |
---|
725 | def _pkgconfig_path(path): |
---|
726 | return os.path.join(path, 'lib', 'pkgconfig') |
---|
727 | |
---|
728 | def _load_flags(conf, arch_bsp, path): |
---|
729 | if not os.path.exists(path): |
---|
730 | ctx.fatal('RTEMS path not found.') |
---|
731 | if os.path.exists(_pkgconfig_path(path)): |
---|
732 | pc = os.path.join(_pkgconfig_path(path), arch_bsp + '.pc') |
---|
733 | conf.to_log('Opening and load pkgconfig: ' + pc) |
---|
734 | pkg = pkgconfig.package(pc) |
---|
735 | config = None |
---|
736 | elif os.path.exists(os.path.join(path, 'rtems-config')): |
---|
737 | config = os.path.join(path, 'rtems-config') |
---|
738 | pkg = None |
---|
739 | flags = {} |
---|
740 | _log_header(conf) |
---|
741 | flags['CFLAGS'] = _load_flags_set('CFLAGS', arch_bsp, conf, config, pkg) |
---|
742 | flags['LDFLAGS'] = _load_flags_set('LDFLAGS', arch_bsp, conf, config, pkg) |
---|
743 | flags['LIB'] = _load_flags_set('LIB', arch_bsp, conf, config, pkg) |
---|
744 | return flags |
---|
745 | |
---|
746 | def _load_flags_set(flags, arch_bsp, conf, config, pkg): |
---|
747 | conf.to_log('%s ->' % flags) |
---|
748 | if pkg is not None: |
---|
749 | flagstr = '' |
---|
750 | try: |
---|
751 | flagstr = pkg.get(flags) |
---|
752 | except pkgconfig.error as e: |
---|
753 | conf.to_log('pkconfig warning: ' + e.msg) |
---|
754 | conf.to_log(' ' + flagstr) |
---|
755 | else: |
---|
756 | flags_map = { 'CFLAGS': '--cflags', |
---|
757 | 'LDFLAGS': '--ldflags', |
---|
758 | 'LIB': '--libs' } |
---|
759 | ab = arch_bsp.split('-') |
---|
760 | #conf.check_cfg(path = config, |
---|
761 | # package = '', |
---|
762 | # uselib_store = 'rtems', |
---|
763 | # args = '--bsp %s/%s %s' % (ab[0], ab[2], flags_map[flags])) |
---|
764 | #print conf.env |
---|
765 | #print '%r' % conf |
---|
766 | #flagstr = '-l -c' |
---|
767 | flagstr = subprocess.check_output([config, '--bsp', '%s/%s' % (ab[0], ab[2]), flags_map[flags]]) |
---|
768 | #print flags, ">>>>", flagstr |
---|
769 | if flags == 'CFLAGS': |
---|
770 | flagstr += ' -DWAF_BUILD=1' |
---|
771 | if flags == 'LIB': |
---|
772 | flagstr = 'rtemscpu rtemsbsp c rtemscpu rtemsbsp' |
---|
773 | return flagstr.split() |
---|
774 | |
---|
775 | def _filter_flags(label, flags, arch, rtems_path): |
---|
776 | |
---|
777 | flag_groups = \ |
---|
778 | [ { 'key': 'warnings', 'path': False, 'flags': { '-W': 1 }, 'cflags': False, 'lflags': False }, |
---|
779 | { 'key': 'includes', 'path': True, 'flags': { '-I': 1, '-isystem': 2, '-sysroot': 2 } }, |
---|
780 | { 'key': 'libpath', 'path': True, 'flags': { '-L': 1 } }, |
---|
781 | { 'key': 'machines', 'path': True, 'flags': { '-O': 1, '-m': 1, '-f': 1 } }, |
---|
782 | { 'key': 'specs', 'path': True, 'flags': { '-q': 1, '-B': 2, '--specs': 2 } } ] |
---|
783 | |
---|
784 | flags = _strip_cflags(flags) |
---|
785 | |
---|
786 | _flags = { label: [] } |
---|
787 | for fg in flag_groups: |
---|
788 | _flags[fg['key']] = [] |
---|
789 | |
---|
790 | iflags = iter(flags) |
---|
791 | for opt in iflags: |
---|
792 | in_label = True |
---|
793 | opts = [] |
---|
794 | for fg in flag_groups: |
---|
795 | key = fg['key'] |
---|
796 | for flag in fg['flags']: |
---|
797 | if opt.startswith(flag): |
---|
798 | opt_count = fg['flags'][flag] |
---|
799 | if opt_count > 1: |
---|
800 | if opt != flag: |
---|
801 | opt_count -= 1 |
---|
802 | if fg['path'] and arch in opt: |
---|
803 | opt = '%s%s/%s' % (flag, rtems_path, |
---|
804 | opt[opt.find(arch):]) |
---|
805 | opts += [opt] |
---|
806 | for c in range(1, opt_count): |
---|
807 | opt = next(iflags) |
---|
808 | if fg['path'] and arch in opt: |
---|
809 | opt = '%s%s/%s' % (f, rtems_path, |
---|
810 | opt[opt.find(arch):]) |
---|
811 | opts += [opt] |
---|
812 | _flags[key] += opts |
---|
813 | if label in fg and not fg[label]: |
---|
814 | in_label = False |
---|
815 | break |
---|
816 | if in_label: |
---|
817 | _flags[label] += opts |
---|
818 | return _flags |
---|
819 | |
---|
820 | def _strip_cflags(cflags): |
---|
821 | _cflags = [] |
---|
822 | for o in cflags: |
---|
823 | if o.startswith('-O'): |
---|
824 | pass |
---|
825 | elif o.startswith('-g'): |
---|
826 | pass |
---|
827 | else: |
---|
828 | _cflags += [o] |
---|
829 | return _cflags |
---|
830 | |
---|
831 | def _log_header(conf): |
---|
832 | conf.to_log('-----------------------------------------') |
---|
833 | |
---|
834 | from waflib import Task |
---|
835 | from waflib import TaskGen |
---|
836 | from waflib import Utils |
---|
837 | from waflib import Node |
---|
838 | from waflib.Tools.ccroot import link_task, USELIB_VARS |
---|
839 | |
---|
840 | USELIB_VARS['rap'] = set(['RTEMS_LINKFLAGS']) |
---|
841 | USELIB_VARS['rtrace'] = set(['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPPER', 'RTRACE_LINKCMDS']) |
---|
842 | |
---|
843 | class rap(link_task): |
---|
844 | "Link object files into a RTEMS application" |
---|
845 | run_str = '${RTEMS_LD} ${RTEMS_LINKFLAGS} --cc ${CC} ${SRC} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' |
---|
846 | ext_out = ['.rap'] |
---|
847 | vars = ['RTEMS_LINKFLAGS', 'LINKDEPS'] |
---|
848 | inst_to = '${BINDIR}' |
---|
849 | |
---|
850 | class rtrace(link_task): |
---|
851 | "Link object files into a RTEMS trace application" |
---|
852 | run_str = '${RTEMS_TLD} ${RTACE_FLAGS} ${RTRACE_WRAPPER_ST:RTRACE_WRAPPER} -C ${RTRACE_CFG} -r ${RTEMS_PATH} -B ${ARCH_BSP} -c ${CC} -l ${CC} -- ${SRC} ${LINKFLAGS} ${RTRACE_LINKFLAGS} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' |
---|
853 | ext_out = ['.texe'] |
---|
854 | vars = ['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPER', 'RTRACE_LINKFLAGS', 'LINKDEPS'] |
---|
855 | inst_to = '${BINDIR}' |
---|
856 | color = 'PINK' |
---|