[PATCH] rtems: Add support for building with Clang/LLVM

Chris Johns chrisj at rtems.org
Tue Mar 17 02:09:37 UTC 2020


On 17/3/20 7:30 am, Hesham Almatary wrote:
> Hi Chris,
> 
> On Sun, 15 Mar 2020 at 21:09, Chris Johns <chrisj at rtems.org
> <mailto:chrisj at rtems.org>> wrote:
> 
>     Hi Hesham,
> 
>     This is a great addition to rtems_waf, some comments below.
> 
>     On 16/3/20 2:56 am, Hesham Almatary wrote:
>     > ---
>     >  rtems.py | 85 +++++++++++++++++++++++++++++++++++++++++---------------
>     >  1 file changed, 62 insertions(+), 23 deletions(-)
>     >
>     > diff --git a/rtems.py b/rtems.py
>     > index ffb386f..f1ef4de 100644
>     > --- a/rtems.py
>     > +++ b/rtems.py
>     > @@ -1,4 +1,5 @@
>>     > +# Copyright 2020 Hesham Almatary
>     >  # Copyright 2012-2016 Chris Johns (chrisj at rtems.org
>     <mailto:chrisj at rtems.org>)
>     >  #
>     >  # Redistribution and use in source and binary forms, with or without
>     > @@ -63,6 +64,10 @@ def options(opt):
>     >                     default = 'all',
>     >                     dest = 'rtems_bsps',
>     >                     help = 'List of BSPs to build.')
>     > +    opt.add_option('--rtems-compiler',
>     > +                   default = 'gcc',
>     > +                   dest = 'rtems_compiler',
>     > +                   help = 'RTEMS compiler to use available options are
>     clang and gcc (defaults to gcc).')
>     >      opt.add_option('--show-commands',
>     >                     action = 'store_true',
>     >                     default = False,
>     > @@ -104,15 +109,17 @@ def init(ctx, filters = None, version = None,
>     long_commands = False, bsp_init =
>     >          #
>     >          # Check the tools, architectures and bsps.
>     >          #
>     > -        rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \
>     > +        rtems_compiler, rtems_version, rtems_path, rtems_tools, archs,
>     arch_bsps = \
>     >              check_options(ctx,
>     >                            env.options['prefix'],
>     > +                          env.options['rtems_compiler'],
>     >                            env.options['rtems_tools'],
>     >                            env.options['rtems_path'],
>     >                            env.options['rtems_version'],
>     >                            env.options['rtems_archs'],
>     >                            env.options['rtems_bsps'])
>>     > +        print("RTEMS Compiler is " + rtems_compiler)
> 
>     Please use `conf.msg()`. See https://git.rtems.org/rtems_waf/tree/rtems.py#n248
> 
>     >          #
>     >          # Update the contexts for all the bsps.
>     >          #
>     > @@ -176,9 +183,10 @@ def configure(conf, bsp_configure = None):
>     >      else:
>     >          long_commands = 'no'
>>     > -    rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \
>     > +    rtems_compiler, rtems_version, rtems_path, rtems_tools, archs,
>     arch_bsps = \
>     >          check_options(conf,
>     >                        conf.options.prefix,
>     > +                      conf.options.rtems_compiler,
>     >                        conf.options.rtems_tools,
>     >                        conf.options.rtems_path,
>     >                        conf.options.rtems_version,
>     > @@ -222,13 +230,19 @@ def configure(conf, bsp_configure = None):
>     >          conf.env.RTEMS_ARCH_RTEMS = arch
>     >          conf.env.RTEMS_BSP = bsp
>>     > -        tools = _find_tools(conf, arch, rtems_tools, tools)
>     > +        tools = _find_tools(conf, arch, rtems_compiler, rtems_tools, tools)
>     >          for t in tools[arch]:
>     >              conf.env[t] = tools[arch][t]
>>     > -        conf.load('gcc')
>     > -        conf.load('g++')
>     > -        conf.load('gas')
>     > +        if rtems_compiler == 'gcc':
>     > +            conf.load('gcc')
>     > +            conf.load('g++')
>     > +            conf.load('gas')
>     > +        elif rtems_compiler == 'clang':
>     > +            conf.load('clang')
>     > +            conf.load('clang++')
>     > +        else:
>     > +            conf.fatal('Unknown RTEMS compiler: ' + rtems_compiler)
>>     >          #
>     >          # Get the version of the tools being used.
>     > @@ -388,7 +402,7 @@ def tweaks(conf, arch_bsp):
>     >      if '-ffunction-sections' in conf.env.CFLAGS:
>     >        conf.env.LINKFLAGS += ['-Wl,--gc-sections']
>>     > -def check_options(ctx, prefix, rtems_tools, rtems_path, rtems_version,
>     rtems_archs, rtems_bsps):
>     > +def check_options(ctx, prefix, rtems_compiler, rtems_tools, rtems_path,
>     rtems_version, rtems_archs, rtems_bsps):
>     >      #
>     >      # Set defaults
>     >      #
>     > @@ -406,6 +420,12 @@ def check_options(ctx, prefix, rtems_tools,
>     rtems_path, rtems_version, rtems_arc
>     >      if rtems_tools is None:
>     >          rtems_tools = rtems_path
>>     > +    #
>     > +    # Check the compiler option is valid.
>     > +    #
>     > +    if rtems_compiler not in ['gcc', 'clang']:
> 
>     Key in compiler dict? See below.
> 
>     > +        ctx.fatal('Valid RTEMS compilers are gcc or clang')
>     > +
>     >      #
>     >      # Check the paths are valid.
>     >      #
>     > @@ -476,7 +496,7 @@ def check_options(ctx, prefix, rtems_tools,
>     rtems_path, rtems_version, rtems_arc
>     >      #
>     >      arch_bsps = filter(ctx, 'bsps', arch_bsps)
>>     > -    return rtems_version, rtems_path, tools, archs, arch_bsps
>     > +    return rtems_compiler, rtems_version, rtems_path, tools, archs, arch_bsps
>>     >  def check_env(ctx, var):
>     >      if var in ctx.env and len(ctx.env[var]) != 0:
>     > @@ -682,22 +702,40 @@ def long_command_line():
>     >              if hasattr(cls, 'hcode'):
>     >                  derived_class.hcode = cls.hcode
>>     > -def _find_tools(conf, arch, paths, tools):
>     > +def _find_tools(conf, arch, rtems_compiler, paths, tools):
>     >      if arch not in tools:
>     >          arch_tools = {}
>     > -        arch_tools['CC']          = conf.find_program([arch + '-gcc'],
>     path_list = paths)
>     > -        arch_tools['CXX']         = conf.find_program([arch + '-g++'],
>     path_list = paths)
>     > -        arch_tools['LINK_CC']     = arch_tools['CC']
>     > -        arch_tools['LINK_CXX']    = arch_tools['CXX']
>     > -        arch_tools['AS']          = conf.find_program([arch + '-gcc'],
>     path_list = paths)
>     > -        arch_tools['LD']          = conf.find_program([arch + '-ld'], 
>     path_list = paths)
>     > -        arch_tools['AR']          = conf.find_program([arch + '-ar'],
>     path_list = paths)
>     > -        arch_tools['NM']          = conf.find_program([arch + '-nm'],
>     path_list = paths)
>     > -        arch_tools['OBJDUMP']     = conf.find_program([arch +
>     '-objdump'], path_list = paths)
>     > -        arch_tools['OBJCOPY']     = conf.find_program([arch +
>     '-objcopy'], path_list = paths)
>     > -        arch_tools['READELF']     = conf.find_program([arch +
>     '-readelf'], path_list = paths)
>     > -        arch_tools['STRIP']       = conf.find_program([arch + '-strip'],
>     path_list = paths)
>     > -        arch_tools['RANLIB']      = conf.find_program([arch + '-ranlib'],
>     path_list = paths)
>     > +        if rtems_compiler == 'gcc':
>     > +            arch_tools['CC']          = conf.find_program([arch +
>     '-gcc'], path_list = paths)
>     > +            arch_tools['CXX']         = conf.find_program([arch +
>     '-g++'], path_list = paths)
>     > +            arch_tools['LINK_CC']     = arch_tools['CC']
>     > +            arch_tools['LINK_CXX']    = arch_tools['CXX']
>     > +            arch_tools['AS']          = conf.find_program([arch +
>     '-gcc'], path_list = paths)
>     > +            arch_tools['LD']          = conf.find_program([arch +
>     '-ld'],  path_list = paths)
>     > +            arch_tools['AR']          = conf.find_program([arch + '-ar'],
>     path_list = paths)
>     > +            arch_tools['NM']          = conf.find_program([arch + '-nm'],
>     path_list = paths)
>     > +            arch_tools['OBJDUMP']     = conf.find_program([arch +
>     '-objdump'], path_list = paths)
>     > +            arch_tools['OBJCOPY']     = conf.find_program([arch +
>     '-objcopy'], path_list = paths)
>     > +            arch_tools['READELF']     = conf.find_program([arch +
>     '-readelf'], path_list = paths)
>     > +            arch_tools['STRIP']       = conf.find_program([arch +
>     '-strip'], path_list = paths)
>     > +            arch_tools['RANLIB']      = conf.find_program([arch +
>     '-ranlib'], path_list = paths)
>     > +        elif rtems_compiler == 'clang':
>     > +            arch_tools['CC']          = conf.find_program('clang')
>     > +            arch_tools['CXX']         = conf.find_program('clang++')
>     > +            arch_tools['LINK_CC']     = arch_tools['CC']
>     > +            arch_tools['LINK_CXX']    = arch_tools['CXX']
>     > +            arch_tools['AS']          = conf.find_program('clang')
>     > +            arch_tools['LD']          = conf.find_program('lld')
>     > +            arch_tools['AR']          = conf.find_program('llvm-ar')
>     > +            arch_tools['NM']          = conf.find_program('llvm-nm')
>     > +            arch_tools['OBJDUMP']     = conf.find_program('llvm-objdump')
>     > +            arch_tools['OBJCOPY']     = conf.find_program('llvm-objcopy')
>     > +            arch_tools['READELF']     = conf.find_program('llvm-readelf')
>     > +            arch_tools['STRIP']       = conf.find_program('llvm-strip')
>     > +            arch_tools['RANLIB']      = conf.find_program('llvm-ranlib')
> 
>     Could this be defined in a compile dict?
> 
> Do you mean just the names of the tools being values?

Yes, you iterate over the list items for each compiler rather than hard coding
them here.

>     Why does llvm not require a path_list?
> 
> I didn’t want to restrict the search path to rtems-prefix only but rather search
> from $PATH.

I would prefer the operation of rtems_waf be consistent. I do not think
introducing a change based on the type of tool is a good thing.

> That follows the rtems/waf (new build system) convention by default.

Do you mean the work Sebastian is doing? If you are, it currently might but that
work is not finished and it may change, partially to make it consistent with
this package. This has not been discussed.

> As you know, Clang/LLVM don’t need multiple builds for each target/OS, but they
> have all backends for all supported architectures and OSes with a single
> frontend. 

Yes I do know this.

> So putting a custom Clang/LLVM build in RTEMS tools like we do with
> gcc didn’t make much sense to me. 

I am not following this. The enumeration of the arch specific tools when
configuring will still happen for llvm the same way it does for gcc, it is just
the tool name will be the same for more than one BSP configured at once. Each
BSP instance in waf needs a copy. The gcc arch specific tools all need to be in
the same directory and there is an assumption they are all the same build.

I have resisted depending on anything in an environment for years because it is
fragile. A path is problematic, it can be be wrong and the a default path is
used and it points to the wrong set of tools. We then need to document a
specific step, i.e. the second step ...

https://docs.rtems.org/branches/master/user/start/bsp-build.html#manual-bsp-build

They get hard to manage with multiple installed versions, e.g. when you close a
terminal and come back and forget to set the correct path. With rtem_waf after
the configure has run you can reboot a machine, open a terminal, cd to the top
of the source and enter `waf` and it builds. You do not need to remember to do
anything extra. At my age I need all the help I can get. :)

Chris


More information about the devel mailing list