1 | # |
---|
2 | # Copyright 2012, 2013 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 | import pkgconfig |
---|
33 | import re |
---|
34 | import subprocess |
---|
35 | |
---|
36 | rtems_filters = None |
---|
37 | |
---|
38 | def options(opt): |
---|
39 | opt.add_option('--rtems', |
---|
40 | default = None, |
---|
41 | dest = 'rtems_path', |
---|
42 | help = 'Path to an installed RTEMS (defaults to prefix).') |
---|
43 | opt.add_option('--rtems-tools', |
---|
44 | default = None, |
---|
45 | dest = 'rtems_tools', |
---|
46 | help = 'Path to RTEMS tools (defaults to path to installed RTEMS).') |
---|
47 | opt.add_option('--rtems-version', |
---|
48 | default = None, |
---|
49 | dest = 'rtems_version', |
---|
50 | help = 'RTEMS version (default is derived from prefix).') |
---|
51 | opt.add_option('--rtems-archs', |
---|
52 | default = 'all', |
---|
53 | dest = 'rtems_archs', |
---|
54 | help = 'List of RTEMS architectures to build.') |
---|
55 | opt.add_option('--rtems-bsps', |
---|
56 | default = 'all', |
---|
57 | dest = 'rtems_bsps', |
---|
58 | help = 'List of BSPs to build.') |
---|
59 | opt.add_option('--show-commands', |
---|
60 | action = 'store_true', |
---|
61 | default = False, |
---|
62 | dest = 'show_commands', |
---|
63 | help = 'Print the commands as strings.') |
---|
64 | |
---|
65 | def init(ctx, filters = None): |
---|
66 | global rtems_filters |
---|
67 | |
---|
68 | try: |
---|
69 | import waflib.Options |
---|
70 | import waflib.ConfigSet |
---|
71 | |
---|
72 | # |
---|
73 | # Load the configuation set from the lock file. |
---|
74 | # |
---|
75 | env = waflib.ConfigSet.ConfigSet() |
---|
76 | env.load(waflib.Options.lockfile) |
---|
77 | |
---|
78 | # |
---|
79 | # Set the RTEMS filter to the context. |
---|
80 | # |
---|
81 | rtems_filters = filters |
---|
82 | |
---|
83 | # |
---|
84 | # Check the tools, architectures and bsps. |
---|
85 | # |
---|
86 | rtems_version, rtems_path, rtems_bin, rtems_tools, archs, arch_bsps = \ |
---|
87 | check_options(ctx, |
---|
88 | env.options['prefix'], |
---|
89 | env.options['rtems_tools'], |
---|
90 | env.options['rtems_path'], |
---|
91 | env.options['rtems_version'], |
---|
92 | env.options['rtems_archs'], |
---|
93 | env.options['rtems_bsps']) |
---|
94 | |
---|
95 | # |
---|
96 | # Update the contextes for all the bsps. |
---|
97 | # |
---|
98 | from waflib.Build import BuildContext, CleanContext, \ |
---|
99 | InstallContext, UninstallContext |
---|
100 | for x in arch_bsps: |
---|
101 | for y in (BuildContext, CleanContext, InstallContext, UninstallContext): |
---|
102 | name = y.__name__.replace('Context','').lower() |
---|
103 | class context(y): |
---|
104 | cmd = name + '-' + x |
---|
105 | variant = x |
---|
106 | |
---|
107 | # |
---|
108 | # Add the various commands. |
---|
109 | # |
---|
110 | for cmd in ['build', 'clean', 'install']: |
---|
111 | if cmd in waflib.Options.commands: |
---|
112 | waflib.Options.commands.remove(cmd) |
---|
113 | for x in arch_bsps: |
---|
114 | waflib.Options.commands.insert(0, cmd + '-' + x) |
---|
115 | except: |
---|
116 | pass |
---|
117 | |
---|
118 | def configure(conf, bsp_configure = None): |
---|
119 | # |
---|
120 | # Handle the show commands option. |
---|
121 | # |
---|
122 | if conf.options.show_commands: |
---|
123 | show_commands = 'yes' |
---|
124 | else: |
---|
125 | show_commands = 'no' |
---|
126 | |
---|
127 | rtems_version, rtems_path, rtems_bin, rtems_tools, archs, arch_bsps = \ |
---|
128 | check_options(conf, |
---|
129 | conf.options.prefix, |
---|
130 | conf.options.rtems_tools, |
---|
131 | conf.options.rtems_path, |
---|
132 | conf.options.rtems_version, |
---|
133 | conf.options.rtems_archs, |
---|
134 | conf.options.rtems_bsps) |
---|
135 | |
---|
136 | if rtems_tools is None: |
---|
137 | conf.fatal('RTEMS tools not found.') |
---|
138 | |
---|
139 | _log_header(conf) |
---|
140 | |
---|
141 | conf.msg('Architectures', ', '.join(archs), 'YELLOW') |
---|
142 | |
---|
143 | tools = {} |
---|
144 | env = conf.env.derive() |
---|
145 | |
---|
146 | for ab in arch_bsps: |
---|
147 | conf.setenv(ab, env) |
---|
148 | |
---|
149 | conf.msg('Board Support Package', ab, 'YELLOW') |
---|
150 | |
---|
151 | arch = _arch_from_arch_bsp(ab) |
---|
152 | bsp = _bsp_from_arch_bsp(ab) |
---|
153 | |
---|
154 | conf.env.ARCH_BSP = '%s/%s' % (arch.split('-')[0], bsp) |
---|
155 | |
---|
156 | conf.env.RTEMS_PATH = rtems_path |
---|
157 | conf.env.RTEMS_VERSION = rtems_version |
---|
158 | conf.env.RTEMS_ARCH_BSP = ab |
---|
159 | conf.env.RTEMS_ARCH = arch.split('-')[0] |
---|
160 | conf.env.RTEMS_ARCH_RTEMS = arch |
---|
161 | conf.env.RTEMS_BSP = bsp |
---|
162 | |
---|
163 | tools = _find_tools(conf, arch, [rtems_bin] + rtems_tools, tools) |
---|
164 | for t in tools[arch]: |
---|
165 | conf.env[t] = tools[arch][t] |
---|
166 | |
---|
167 | conf.load('gcc') |
---|
168 | conf.load('g++') |
---|
169 | conf.load('gas') |
---|
170 | |
---|
171 | flags = _load_flags(conf, ab, rtems_path) |
---|
172 | |
---|
173 | cflags = _filter_flags('cflags', flags['CFLAGS'], |
---|
174 | arch, rtems_path) |
---|
175 | ldflags = _filter_flags('ldflags', flags['LDFLAGS'], |
---|
176 | arch, rtems_path) |
---|
177 | |
---|
178 | conf.env.CFLAGS = cflags['cflags'] |
---|
179 | conf.env.CXXFLAGS = conf.env.CFLAGS |
---|
180 | conf.env.ASFLAGS = cflags['cflags'] |
---|
181 | conf.env.WFLAGS = cflags['warnings'] |
---|
182 | conf.env.RFLAGS = cflags['specs'] |
---|
183 | conf.env.MFLAGS = cflags['machines'] |
---|
184 | conf.env.IFLAGS = cflags['includes'] |
---|
185 | conf.env.LINKFLAGS = cflags['cflags'] + ldflags['ldflags'] |
---|
186 | conf.env.LIB = flags['LIB'] |
---|
187 | |
---|
188 | conf.env.RTRACE_WRAPPER_ST = '-W %s' |
---|
189 | |
---|
190 | # |
---|
191 | # Checks for various RTEMS features. |
---|
192 | # |
---|
193 | conf.multicheck({ 'header_name': 'rtems/score/cpuopts.h'}, |
---|
194 | msg = 'Checking for RTEMS CPU options header', |
---|
195 | mandatory = True) |
---|
196 | load_cpuopts(conf, ab, rtems_path) |
---|
197 | if conf.env['RTEMS_SMP'] == 'Yes': |
---|
198 | conf.env.CXXFLAGS += ['-std=gnu++11'] |
---|
199 | conf.multicheck({ 'header_name': 'rtems.h'}, |
---|
200 | msg = 'Checking for RTEMS header', |
---|
201 | mandatory = True) |
---|
202 | |
---|
203 | # |
---|
204 | # Add tweaks. |
---|
205 | # |
---|
206 | tweaks(conf, ab) |
---|
207 | |
---|
208 | # |
---|
209 | # If the user has supplied a BSP specific configure function |
---|
210 | # call it. |
---|
211 | # |
---|
212 | if bsp_configure: |
---|
213 | bsp_configure(conf, ab) |
---|
214 | |
---|
215 | # |
---|
216 | # Show commands support the user can supply. |
---|
217 | # |
---|
218 | conf.env.SHOW_COMMANDS = show_commands |
---|
219 | |
---|
220 | conf.setenv('', env) |
---|
221 | |
---|
222 | conf.env.RTEMS_TOOLS = rtems_tools |
---|
223 | conf.env.ARCHS = archs |
---|
224 | conf.env.ARCH_BSPS = arch_bsps |
---|
225 | |
---|
226 | conf.env.SHOW_COMMANDS = show_commands |
---|
227 | |
---|
228 | def build(bld): |
---|
229 | if bld.env.SHOW_COMMANDS == 'yes': |
---|
230 | output_command_line() |
---|
231 | |
---|
232 | def load_cpuopts(conf, arch_bsp, rtems_path): |
---|
233 | options = ['RTEMS_DEBUG', |
---|
234 | 'RTEMS_MULTIPROCESSING', |
---|
235 | 'RTEMS_NEWLIB', |
---|
236 | 'RTEMS_POSIX_API', |
---|
237 | 'RTEMS_SMP', |
---|
238 | 'RTEMS_NETWORKING'] |
---|
239 | for opt in options: |
---|
240 | enabled = check_opt(conf, opt, 'rtems/score/cpuopts.h', arch_bsp, rtems_path) |
---|
241 | if enabled: |
---|
242 | conf.env[opt] = 'Yes' |
---|
243 | else: |
---|
244 | conf.env[opt] = 'No' |
---|
245 | |
---|
246 | def check_opt(conf, opt, header, arch_bsp, rtems_path): |
---|
247 | code = '#include <%s>%s' % (header, os.linesep) |
---|
248 | code += '#ifndef %s%s' % (opt, os.linesep) |
---|
249 | code += ' #error %s is not defined%s' % (opt, os.linesep) |
---|
250 | code += '#endif%s' % (os.linesep) |
---|
251 | code += '#if %s%s' % (opt, os.linesep) |
---|
252 | code += ' /* %s is true */%s' % (opt, os.linesep) |
---|
253 | code += '#else%s' % (os.linesep) |
---|
254 | code += ' #error %s is false%s' % (opt, os.linesep) |
---|
255 | code += '#endif%s' % (os.linesep) |
---|
256 | code += 'int main() { return 0; }%s' % (os.linesep) |
---|
257 | try: |
---|
258 | conf.check_cc(fragment = code, |
---|
259 | execute = False, |
---|
260 | define_ret = False, |
---|
261 | msg = 'Checking for %s' % (opt)) |
---|
262 | except conf.errors.WafError: |
---|
263 | return False; |
---|
264 | return True |
---|
265 | |
---|
266 | def tweaks(conf, arch_bsp): |
---|
267 | # |
---|
268 | # Hack to work around NIOS2 naming. |
---|
269 | # |
---|
270 | if conf.env.RTEMS_ARCH in ['nios2']: |
---|
271 | conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-littlenios2'] |
---|
272 | elif conf.env.RTEMS_ARCH in ['arm']: |
---|
273 | conf.env.OBJCOPY_FLAGS = ['-I', 'binary', '-O', 'elf32-littlearm'] |
---|
274 | else: |
---|
275 | conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-' + conf.env.RTEMS_ARCH] |
---|
276 | |
---|
277 | # |
---|
278 | # Check for a i386 PC bsp. |
---|
279 | # |
---|
280 | if re.match('i386-.*-pc[3456]86', arch_bsp) is not None: |
---|
281 | conf.env.LINKFLAGS += ['-Wl,-Ttext,0x00100000'] |
---|
282 | |
---|
283 | if '-ffunction-sections' in conf.env.CFLAGS: |
---|
284 | conf.env.LINKFLAGS += ['-Wl,--gc-sections'] |
---|
285 | |
---|
286 | def check_options(ctx, prefix, rtems_tools, rtems_path, rtems_version, rtems_archs, rtems_bsps): |
---|
287 | # |
---|
288 | # Set defaults |
---|
289 | # |
---|
290 | if rtems_version is None: |
---|
291 | m = re.compile('[^0-9.]*([0-9.]+)$').match(prefix) |
---|
292 | if m: |
---|
293 | rtems_version = m.group(1) |
---|
294 | else: |
---|
295 | ctx.fatal('RTEMS version cannot derived from prefix: ' + prefix) |
---|
296 | if rtems_path is None: |
---|
297 | rtems_path = prefix |
---|
298 | if rtems_tools is None: |
---|
299 | rtems_tools = rtems_path |
---|
300 | |
---|
301 | # |
---|
302 | # Check the paths are valid. |
---|
303 | # |
---|
304 | if not os.path.exists(rtems_path): |
---|
305 | ctx.fatal('RTEMS path not found.') |
---|
306 | if os.path.exists(os.path.join(rtems_path, 'lib', 'pkgconfig')): |
---|
307 | rtems_config = None |
---|
308 | elif os.path.exists(os.path.join(rtems_path, 'rtems-config')): |
---|
309 | rtems_config = os.path.join(rtems_path, 'rtems-config') |
---|
310 | else: |
---|
311 | ctx.fatal('RTEMS path is not valid. No lib/pkgconfig or rtems-config found.') |
---|
312 | if os.path.exists(os.path.join(rtems_path, 'bin')): |
---|
313 | rtems_bin = os.path.join(rtems_path, 'bin') |
---|
314 | else: |
---|
315 | ctx.fatal('RTEMS path is not valid. No bin directory found.') |
---|
316 | |
---|
317 | # |
---|
318 | # We can more than one path to tools. This happens when testing different |
---|
319 | # versions. |
---|
320 | # |
---|
321 | rt = rtems_tools.split(',') |
---|
322 | tools = [] |
---|
323 | for path in rt: |
---|
324 | if not os.path.exists(path): |
---|
325 | ctx.fatal('RTEMS tools path not found: ' + path) |
---|
326 | if not os.path.exists(os.path.join(path, 'bin')): |
---|
327 | ctx.fatal('RTEMS tools path does not contain a \'bin\' directory: ' + path) |
---|
328 | tools += [os.path.join(path, 'bin')] |
---|
329 | |
---|
330 | # |
---|
331 | # Filter the tools. |
---|
332 | # |
---|
333 | tools = filter(ctx, 'tools', tools) |
---|
334 | |
---|
335 | # |
---|
336 | # Match the archs requested against the ones found. If the user |
---|
337 | # wants all (default) set all used. |
---|
338 | # |
---|
339 | if rtems_archs == 'all': |
---|
340 | archs = _find_installed_archs(rtems_config, rtems_path, rtems_version) |
---|
341 | else: |
---|
342 | archs = _check_archs(rtems_config, rtems_archs, rtems_path, rtems_version) |
---|
343 | |
---|
344 | # |
---|
345 | # Filter the architectures. |
---|
346 | # |
---|
347 | archs = filter(ctx, 'archs', archs) |
---|
348 | |
---|
349 | # |
---|
350 | # We some. |
---|
351 | # |
---|
352 | if len(archs) == 0: |
---|
353 | ctx.fatal('Could not find any architectures') |
---|
354 | |
---|
355 | # |
---|
356 | # Get the list of valid BSPs. This process filters the architectures |
---|
357 | # to those referenced by the BSPs. |
---|
358 | # |
---|
359 | if rtems_bsps == 'all': |
---|
360 | arch_bsps = _find_installed_arch_bsps(rtems_config, rtems_path, archs, rtems_version) |
---|
361 | else: |
---|
362 | arch_bsps = _check_arch_bsps(rtems_bsps, rtems_config, rtems_path, archs, rtems_version) |
---|
363 | |
---|
364 | if len(arch_bsps) == 0: |
---|
365 | ctx.fatal('No valid arch/bsps found') |
---|
366 | |
---|
367 | # |
---|
368 | # Filter the bsps. |
---|
369 | # |
---|
370 | arch_bsps = filter(ctx, 'bsps', arch_bsps) |
---|
371 | |
---|
372 | return rtems_version, rtems_path, rtems_bin, tools, archs, arch_bsps |
---|
373 | |
---|
374 | def check_env(ctx, var): |
---|
375 | if var in ctx.env and len(ctx.env[var]) != 0: |
---|
376 | return True |
---|
377 | return False |
---|
378 | |
---|
379 | def check(ctx, option): |
---|
380 | if option in ctx.env: |
---|
381 | return ctx.env[option] == 'Yes' |
---|
382 | return False |
---|
383 | |
---|
384 | def check_debug(ctx): |
---|
385 | return check(ctx, 'RTEMS_DEBUG') |
---|
386 | |
---|
387 | def check_multiprocessing(ctx): |
---|
388 | return check(ctx, 'RTEMS_MULTIPROCESSING') |
---|
389 | |
---|
390 | def check_newlib(ctx): |
---|
391 | return check(ctx, 'RTEMS_NEWLIB') |
---|
392 | |
---|
393 | def check_posix(ctx): |
---|
394 | return check(ctx, 'RTEMS_POSIX_API') |
---|
395 | |
---|
396 | def check_smp(ctx): |
---|
397 | return check(ctx, 'RTEMS_SMP') |
---|
398 | |
---|
399 | def check_networking(ctx): |
---|
400 | return check(ctx, 'RTEMS_NETWORKING') |
---|
401 | |
---|
402 | def arch(arch_bsp): |
---|
403 | """ Given an arch/bsp return the architecture.""" |
---|
404 | return _arch_from_arch_bsp(arch_bsp).split('-')[0] |
---|
405 | |
---|
406 | def bsp(arch_bsp): |
---|
407 | """ Given an arch/bsp return the BSP.""" |
---|
408 | return _bsp_from_arch_bsp(arch_bsp) |
---|
409 | |
---|
410 | def arch_bsps(ctx): |
---|
411 | """ Return the list of arch/bsps we are building.""" |
---|
412 | return ctx.env.ARCH_BSPS |
---|
413 | |
---|
414 | def arch_bsp_env(ctx, arch_bsp): |
---|
415 | return ctx.env_of_name(arch_bsp).derive() |
---|
416 | |
---|
417 | def filter(ctx, filter, items): |
---|
418 | if rtems_filters is None: |
---|
419 | return items |
---|
420 | if type(rtems_filters) is not dict: |
---|
421 | ctx.fatal("Invalid RTEMS filter type, " \ |
---|
422 | "ie { 'tools': { 'in': [], 'out': [] }, 'arch': {}, 'bsps': {} }") |
---|
423 | if filter not in rtems_filters: |
---|
424 | return items |
---|
425 | items_in = [] |
---|
426 | items_out = [] |
---|
427 | if 'in' in rtems_filters[filter]: |
---|
428 | items_in = copy.copy(rtems_filters[filter]['in']) |
---|
429 | if 'out' in rtems_filters[filter]: |
---|
430 | items_out = copy.copy(rtems_filters[filter]['out']) |
---|
431 | filtered_items = [] |
---|
432 | for i in items: |
---|
433 | item = i |
---|
434 | ab = '%s/%s' % (arch(item), bsp(item)) |
---|
435 | for inre in items_in: |
---|
436 | if re.compile(inre).match(ab): |
---|
437 | items_in.remove(inre) |
---|
438 | filtered_items += [item] |
---|
439 | item = None |
---|
440 | break |
---|
441 | if item is not None: |
---|
442 | for outre in items_out: |
---|
443 | if re.compile(outre).match(ab): |
---|
444 | item = None |
---|
445 | break |
---|
446 | if item is not None: |
---|
447 | filtered_items += [item] |
---|
448 | if len(items_in) != 0: |
---|
449 | ctx.fatal('Following %s not found: %s' % (filter, ', '.join(items_in))) |
---|
450 | return sorted(filtered_items) |
---|
451 | |
---|
452 | def arch_rtems_version(version, arch): |
---|
453 | """ Return the RTEMS architecture path, ie sparc-rtems4.11.""" |
---|
454 | return '%s-rtems%s' % (arch, version) |
---|
455 | |
---|
456 | def arch_bsp_path(version, arch_bsp): |
---|
457 | """ Return the BSP path.""" |
---|
458 | return '%s/%s' % (arch_rtems_version(version, arch(arch_bsp)), bsp(arch_bsp)) |
---|
459 | |
---|
460 | def arch_bsp_include_path(version, arch_bsp): |
---|
461 | """ Return the BSP include path.""" |
---|
462 | return '%s/lib/include' % (arch_bsp_path(version, arch_bsp)) |
---|
463 | |
---|
464 | def arch_bsp_lib_path(version, arch_bsp): |
---|
465 | """ Return the BSP library path. """ |
---|
466 | return '%s/lib' % (arch_bsp_path(version, arch_bsp)) |
---|
467 | |
---|
468 | def library_path(library, cc, cflags): |
---|
469 | cmd = cc + cflags + ['-print-file-name=%s' % library] |
---|
470 | a = subprocess.check_output(cmd) |
---|
471 | lib = os.path.abspath(a.strip()) |
---|
472 | if os.path.exists(lib): |
---|
473 | return os.path.dirname(lib) |
---|
474 | return None |
---|
475 | |
---|
476 | def clone_tasks(bld): |
---|
477 | if bld.cmd == 'build': |
---|
478 | for obj in bld.all_task_gen[:]: |
---|
479 | for x in arch_bsp: |
---|
480 | cloned_obj = obj.clone(x) |
---|
481 | kind = Options.options.build_kind |
---|
482 | if kind.find(x) < 0: |
---|
483 | cloned_obj.posted = True |
---|
484 | obj.posted = True |
---|
485 | |
---|
486 | # |
---|
487 | # From the demos. Use this to get the command to cut+paste to play. |
---|
488 | # |
---|
489 | def output_command_line(): |
---|
490 | # first, display strings, people like them |
---|
491 | from waflib import Utils, Logs |
---|
492 | from waflib.Context import Context |
---|
493 | def exec_command(self, cmd, **kw): |
---|
494 | subprocess = Utils.subprocess |
---|
495 | kw['shell'] = isinstance(cmd, str) |
---|
496 | if isinstance(cmd, str): |
---|
497 | Logs.info('%s' % cmd) |
---|
498 | else: |
---|
499 | Logs.info('%s' % ' '.join(cmd)) # here is the change |
---|
500 | Logs.debug('runner_env: kw=%s' % kw) |
---|
501 | try: |
---|
502 | if self.logger: |
---|
503 | self.logger.info(cmd) |
---|
504 | kw['stdout'] = kw['stderr'] = subprocess.PIPE |
---|
505 | p = subprocess.Popen(cmd, **kw) |
---|
506 | (out, err) = p.communicate() |
---|
507 | if out: |
---|
508 | self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) |
---|
509 | if err: |
---|
510 | self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) |
---|
511 | return p.returncode |
---|
512 | else: |
---|
513 | p = subprocess.Popen(cmd, **kw) |
---|
514 | return p.wait() |
---|
515 | except OSError: |
---|
516 | return -1 |
---|
517 | Context.exec_command = exec_command |
---|
518 | |
---|
519 | # Change the outputs for tasks too |
---|
520 | from waflib.Task import Task |
---|
521 | def display(self): |
---|
522 | return '' # no output on empty strings |
---|
523 | |
---|
524 | Task.__str__ = display |
---|
525 | |
---|
526 | def _find_tools(conf, arch, paths, tools): |
---|
527 | if arch not in tools: |
---|
528 | arch_tools = {} |
---|
529 | arch_tools['CC'] = conf.find_program([arch + '-gcc'], path_list = paths) |
---|
530 | arch_tools['CXX'] = conf.find_program([arch + '-g++'], path_list = paths) |
---|
531 | arch_tools['AS'] = conf.find_program([arch + '-gcc'], path_list = paths) |
---|
532 | arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) |
---|
533 | arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) |
---|
534 | arch_tools['LINK_CC'] = arch_tools['CC'] |
---|
535 | arch_tools['LINK_CXX'] = arch_tools['CXX'] |
---|
536 | arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) |
---|
537 | arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) |
---|
538 | arch_tools['NM'] = conf.find_program([arch + '-nm'], path_list = paths) |
---|
539 | arch_tools['OBJDUMP'] = conf.find_program([arch + '-objdump'], path_list = paths) |
---|
540 | arch_tools['OBJCOPY'] = conf.find_program([arch + '-objcopy'], path_list = paths) |
---|
541 | arch_tools['READELF'] = conf.find_program([arch + '-readelf'], path_list = paths) |
---|
542 | arch_tools['STRIP'] = conf.find_program([arch + '-strip'], path_list = paths) |
---|
543 | arch_tools['RTEMS_LD'] = conf.find_program(['rtems-ld'], path_list = paths, |
---|
544 | mandatory = False) |
---|
545 | arch_tools['RTEMS_TLD'] = conf.find_program(['rtems-tld'], path_list = paths, |
---|
546 | mandatory = False) |
---|
547 | arch_tools['RTEMS_BIN2C'] = conf.find_program(['rtems-bin2c'], path_list = paths, |
---|
548 | mandatory = False) |
---|
549 | arch_tools['TAR'] = conf.find_program(['tar'], mandatory = False) |
---|
550 | tools[arch] = arch_tools |
---|
551 | return tools |
---|
552 | |
---|
553 | def _find_installed_archs(config, path, version): |
---|
554 | archs = [] |
---|
555 | if config is None: |
---|
556 | for d in os.listdir(path): |
---|
557 | if d.endswith('-rtems' + version): |
---|
558 | archs += [d] |
---|
559 | else: |
---|
560 | a = subprocess.check_output([config, '--list-format', '"%(arch)s"']) |
---|
561 | a = a[:-1].replace('"', '') |
---|
562 | archs = set(a.split()) |
---|
563 | archs = ['%s-rtems4.11' % (x) for x in archs] |
---|
564 | archs.sort() |
---|
565 | return archs |
---|
566 | |
---|
567 | def _check_archs(config, req, path, version): |
---|
568 | installed = _find_installed_archs(config, path, version) |
---|
569 | archs = [] |
---|
570 | for a in req.split(','): |
---|
571 | arch = a + '-rtems' + version |
---|
572 | if arch in installed: |
---|
573 | archs += [arch] |
---|
574 | archs.sort() |
---|
575 | return archs |
---|
576 | |
---|
577 | def _find_installed_arch_bsps(config, path, archs, version): |
---|
578 | arch_bsps = [] |
---|
579 | if config is None: |
---|
580 | for f in os.listdir(_pkgconfig_path(path)): |
---|
581 | if f.endswith('.pc'): |
---|
582 | if _arch_from_arch_bsp(f[:-3]) in archs: |
---|
583 | arch_bsps += [f[:-3]] |
---|
584 | else: |
---|
585 | ab = subprocess.check_output([config, '--list-format']) |
---|
586 | ab = ab[:-1].replace('"', '') |
---|
587 | ab = ab.replace('/', '-rtems%s-' % (version)) |
---|
588 | arch_bsps = [x for x in set(ab.split())] |
---|
589 | arch_bsps.sort() |
---|
590 | return arch_bsps |
---|
591 | |
---|
592 | def _check_arch_bsps(req, config, path, archs, version): |
---|
593 | archs_bsps = [] |
---|
594 | for ab in req.split(','): |
---|
595 | abl = ab.split('/') |
---|
596 | if len(abl) != 2: |
---|
597 | return [] |
---|
598 | found = False |
---|
599 | for arch in archs: |
---|
600 | a = '%s-rtems%s' % (abl[0], version) |
---|
601 | if a == arch: |
---|
602 | found = True |
---|
603 | break |
---|
604 | if not found: |
---|
605 | return [] |
---|
606 | archs_bsps += ['%s-%s' % (a, abl[1])] |
---|
607 | if len(archs_bsps) == 0: |
---|
608 | return [] |
---|
609 | installed = _find_installed_arch_bsps(config, path, archs, version) |
---|
610 | bsps = [] |
---|
611 | for b in archs_bsps: |
---|
612 | if b in installed: |
---|
613 | bsps += [b] |
---|
614 | bsps.sort() |
---|
615 | return bsps |
---|
616 | |
---|
617 | def _arch_from_arch_bsp(arch_bsp): |
---|
618 | return '-'.join(arch_bsp.split('-')[:2]) |
---|
619 | |
---|
620 | def _bsp_from_arch_bsp(arch_bsp): |
---|
621 | return '-'.join(arch_bsp.split('-')[2:]) |
---|
622 | |
---|
623 | def _pkgconfig_path(path): |
---|
624 | return os.path.join(path, 'lib', 'pkgconfig') |
---|
625 | |
---|
626 | def _load_flags(conf, arch_bsp, path): |
---|
627 | if not os.path.exists(path): |
---|
628 | ctx.fatal('RTEMS path not found.') |
---|
629 | if os.path.exists(_pkgconfig_path(path)): |
---|
630 | pc = os.path.join(_pkgconfig_path(path), arch_bsp + '.pc') |
---|
631 | conf.to_log('Opening and load pkgconfig: ' + pc) |
---|
632 | pkg = pkgconfig.package(pc) |
---|
633 | config = None |
---|
634 | elif os.path.exists(os.path.join(path, 'rtems-config')): |
---|
635 | config = os.path.join(path, 'rtems-config') |
---|
636 | pkg = None |
---|
637 | flags = {} |
---|
638 | _log_header(conf) |
---|
639 | flags['CFLAGS'] = _load_flags_set('CFLAGS', arch_bsp, conf, config, pkg) |
---|
640 | flags['LDFLAGS'] = _load_flags_set('LDFLAGS', arch_bsp, conf, config, pkg) |
---|
641 | flags['LIB'] = _load_flags_set('LIB', arch_bsp, conf, config, pkg) |
---|
642 | return flags |
---|
643 | |
---|
644 | def _load_flags_set(flags, arch_bsp, conf, config, pkg): |
---|
645 | conf.to_log('%s ->' % flags) |
---|
646 | if pkg is not None: |
---|
647 | flagstr = '' |
---|
648 | try: |
---|
649 | flagstr = pkg.get(flags) |
---|
650 | except pkgconfig.error as e: |
---|
651 | conf.to_log('pkconfig warning: ' + e.msg) |
---|
652 | conf.to_log(' ' + flagstr) |
---|
653 | else: |
---|
654 | flags_map = { 'CFLAGS': '--cflags', |
---|
655 | 'LDFLAGS': '--ldflags', |
---|
656 | 'LIB': '--libs' } |
---|
657 | ab = arch_bsp.split('-') |
---|
658 | #conf.check_cfg(path = config, |
---|
659 | # package = '', |
---|
660 | # uselib_store = 'rtems', |
---|
661 | # args = '--bsp %s/%s %s' % (ab[0], ab[2], flags_map[flags])) |
---|
662 | #print conf.env |
---|
663 | #print '%r' % conf |
---|
664 | #flagstr = '-l -c' |
---|
665 | flagstr = subprocess.check_output([config, '--bsp', '%s/%s' % (ab[0], ab[2]), flags_map[flags]]) |
---|
666 | #print flags, ">>>>", flagstr |
---|
667 | if flags == 'CFLAGS': |
---|
668 | flagstr += ' -DWAF_BUILD=1' |
---|
669 | if flags == 'LIB': |
---|
670 | flagstr = 'rtemscpu rtemsbsp c rtemscpu rtemsbsp' |
---|
671 | return flagstr.split() |
---|
672 | |
---|
673 | def _filter_flags(label, flags, arch, rtems_path): |
---|
674 | |
---|
675 | flag_groups = \ |
---|
676 | [ { 'key': 'warnings', 'path': False, 'flags': { '-W': 1 }, 'cflags': False, 'lflags': False }, |
---|
677 | { 'key': 'includes', 'path': True, 'flags': { '-I': 1, '-isystem': 2, '-sysroot': 2 } }, |
---|
678 | { 'key': 'machines', 'path': True, 'flags': { '-O': 1, '-m': 1, '-f': 1 } }, |
---|
679 | { 'key': 'specs', 'path': True, 'flags': { '-q': 1, '-B': 2, '--specs': 2 } } ] |
---|
680 | |
---|
681 | flags = _strip_cflags(flags) |
---|
682 | |
---|
683 | _flags = { label: [] } |
---|
684 | for fg in flag_groups: |
---|
685 | _flags[fg['key']] = [] |
---|
686 | |
---|
687 | iflags = iter(flags) |
---|
688 | for opt in iflags: |
---|
689 | in_label = True |
---|
690 | opts = [] |
---|
691 | for fg in flag_groups: |
---|
692 | key = fg['key'] |
---|
693 | for flag in fg['flags']: |
---|
694 | if opt.startswith(flag): |
---|
695 | opt_count = fg['flags'][flag] |
---|
696 | if opt_count > 1: |
---|
697 | if opt != flag: |
---|
698 | opt_count -= 1 |
---|
699 | if fg['path'] and arch in opt: |
---|
700 | opt = '%s%s/%s' % (flag, rtems_path, |
---|
701 | opt[opt.find(arch):]) |
---|
702 | opts += [opt] |
---|
703 | for c in range(1, opt_count): |
---|
704 | opt = next(iflags) |
---|
705 | if fg['path'] and arch in opt: |
---|
706 | opt = '%s%s/%s' % (f, rtems_path, |
---|
707 | opt[opt.find(arch):]) |
---|
708 | opts += [opt] |
---|
709 | _flags[key] += opts |
---|
710 | if label in fg and not fg[label]: |
---|
711 | in_label = False |
---|
712 | break |
---|
713 | if in_label: |
---|
714 | _flags[label] += opts |
---|
715 | return _flags |
---|
716 | |
---|
717 | def _strip_cflags(cflags): |
---|
718 | _cflags = [] |
---|
719 | for o in cflags: |
---|
720 | if o.startswith('-O'): |
---|
721 | pass |
---|
722 | elif o.startswith('-g'): |
---|
723 | pass |
---|
724 | else: |
---|
725 | _cflags += [o] |
---|
726 | return _cflags |
---|
727 | |
---|
728 | def _log_header(conf): |
---|
729 | conf.to_log('-----------------------------------------') |
---|
730 | |
---|
731 | from waflib import Task |
---|
732 | from waflib import TaskGen |
---|
733 | from waflib import Utils |
---|
734 | from waflib import Node |
---|
735 | from waflib.Tools.ccroot import link_task, USELIB_VARS |
---|
736 | |
---|
737 | USELIB_VARS['rap'] = set(['RTEMS_LINKFLAGS']) |
---|
738 | USELIB_VARS['rtrace'] = set(['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPPER', 'RTRACE_LINKCMDS']) |
---|
739 | |
---|
740 | @TaskGen.extension('.c') |
---|
741 | |
---|
742 | class rap(link_task): |
---|
743 | "Link object files into a RTEMS application" |
---|
744 | 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}' |
---|
745 | ext_out = ['.rap'] |
---|
746 | vars = ['RTEMS_LINKFLAGS', 'LINKDEPS'] |
---|
747 | inst_to = '${BINDIR}' |
---|
748 | |
---|
749 | class rtrace(link_task): |
---|
750 | "Link object files into a RTEMS trace application" |
---|
751 | 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}' |
---|
752 | ext_out = ['.texe'] |
---|
753 | vars = ['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPER', 'RTRACE_LINKFLAGS', 'LINKDEPS'] |
---|
754 | inst_to = '${BINDIR}' |
---|
755 | color = 'PINK' |
---|