craftr-build / craftr-build-4.x

Frontend for the Craftr build framework.
https://craftr-build.github.io/craftr/
Other
60 stars 14 forks source link

Craftr 2 C build fails if gcc++ is not available #148

Closed tliron closed 7 years ago

tliron commented 7 years ago

I'm trying to cross compile and generally do not want to use the built in gcc. However, I'm having trouble just doing a craftr export to get things moving. I happy to have gcc installed but, but not gcc++, not that it matters because I don't want to use them!

I get this error:

Traceback (most recent call last):
  File "/usr/local/bin/craftr", line 9, in <module>
    load_entry_point('craftr-build', 'console_scripts', 'craftr')()
  File "/Depot/Build/craftr/craftr/__main__.py", line 402, in main_and_exit
    sys.exit(main())
  File "/Depot/Build/craftr/craftr/__main__.py", line 398, in main
    return commands[args.command].execute(parser, args)
  File "/Depot/Build/craftr/craftr/__main__.py", line 214, in execute
    module.run()
  File "/Depot/Build/craftr/craftr/core/session.py", line 430, in run
    exec(code, vars(self.namespace))
  File "/Depot/Projects/Cubism/Craftrfile", line 2, in <module>
    load_module('craftr.lang.cxx.*')
  File "/Depot/Build/craftr/craftr/defaults.py", line 204, in load_module
    loaded_module.run()
  File "/Depot/Build/craftr/craftr/core/session.py", line 430, in run
    exec(code, vars(self.namespace))
  File "/Depot/Build/craftr/craftr/stl/craftr.lang.cxx/Craftrfile", line 31, in <module>
    cxc = load_module(module).cxc
  File "/Depot/Build/craftr/craftr/defaults.py", line 204, in load_module
    loaded_module.run()
  File "/Depot/Build/craftr/craftr/core/session.py", line 430, in run
    exec(code, vars(self.namespace))
  File "/Depot/Build/craftr/craftr/stl/craftr.lang.cxx.clang/Craftrfile", line 507, in <module>
    cxc = ToolChain()
  File "/Depot/Build/craftr/craftr/stl/craftr.lang.cxx.clang/Craftrfile", line 245, in __init__
    self.cxx = CompilerLinker('c++', cpp)
  File "/Depot/Build/craftr/craftr/stl/craftr.lang.cxx.clang/Craftrfile", line 278, in __init__
    self.info = identify_compiler(program)
  File "/Depot/Build/craftr/craftr/stl/craftr.lang.cxx.clang/Craftrfile", line 165, in identify_compiler
    raise ToolDetectionError(exc)
craftr.defaults.ToolDetectionError: [Errno 2] No such file or directory: 'gcc++'
NiklasRosenstein commented 7 years ago

Hey, thanks for the report. I don't do cross compiling and am unexperienced with it, so I'm happy when people can test it a bit! I think this could be solved by making compiler availability optional until it is actually needed, i.e. in this case when you actually want to compile a C++ source file. Do you think that is an acceptable solution?

NiklasRosenstein commented 7 years ago

The change is in the development branch.

Do you have a sample project for your use case?

NiklasRosenstein commented 7 years ago

Btw. I also just noticed that someting goes wrong with the actual detection of the C++ compiler name. It should be g++ not gcc++ which is probably the reason why you get the error in the first place. I'll make a separate issue

tliron commented 7 years ago

Unfortunately I can't share my project.

In Craftr 1 I could have set the program arg when calling c_compile, but in Craftr 2 this is configured automatically in the craftr.lang.cxx modules. This is not too bad, because I can sent --option c= and --option cpp= to override these when I call craftr export. But I'm a bit sad, because it means my bash scripts that call Craftr are now more complex. I always prefer to put as much logic as possible in Python rather than bash.

I think the way to re-enable the older functionality would be:

NiklasRosenstein commented 7 years ago

There's actually four more ways to configure the toolchain. Note that in all places where you define the option c, the actual value that you want to set is craftr.lang.cxx.clang.c, it is just inherited from the global c option valaue.

  1. Use a .craftrconfig file next to your manifest.json and Craftrfile

    [craftr.lib.cxx.clang]  # or __global__
      c = gcc-...
  2. Set the option before you load the craftr.lang.cxx package

    session.options['craftr.lib.cxx.clang.c'] = 'gcc-...'  # preferred
    session.options['c'] = 'gcc-...'
  3. Specify the crossfile option (also the absolute option name is craftr.lang.cxx.clang.crossfile). Note that is also works with the previous two ways of defining option values.

    $ craftr export --option crossfile=cross.config

    cross.config:

    [binaries]
      c = gcc-...
  4. (Currently not documented) Instantiate your own toolchain. You need to load the Clang/GCC package instead of the cross-platform C/C++ package. This is probably a bit more tedious since it uses an API that is 1 level below c_compile() and cxx_binary() (the only difference is that there's no link_style parameter and you have to pass the language for compile() and the output_type for link())

      cxc = load_module('craftr.lang.cxx.clang').ToolChain(cross_config={
        c = 'gcc-...'
      })
    
      objs = cxc.compile('c', sources = glob(['src/*.c']))
      main = cxc.link('bin', inputs = objs)

I am not 100% sure if I want to bring the back the program = ... option for c_compile(). That is because for example cxx_binary() would need to receive the same parameter, especially for cross-compiling, as otherwise the default C-compiler will be invoked for linking. (Craftr uses the C compiler for the linking step).

tliron commented 7 years ago

Option #4 is what I was looking for, thanks!

I just want to point out that as gcc user it's weird to me to see everything defined in the clang module. I was quite confused by the code!

On Sun, Dec 4, 2016 at 6:23 PM, Niklas Rosenstein notifications@github.com wrote:

There's actually four more ways to configure the toolchain. Note that in all places where you define the option c, the actual value that you want to set is craftr.lang.cxx.clang.c, it is just inherited from the global c option valaue.

1.

Use a .craftrconfig file next to your manifest.json and Craftrfile

[craftr.lib.cxx.clang] # or global c = gcc-...

2.

Set the option before you load the craftr.lang.cxx package

session.options['craftr.lib.cxx.clang.c'] = 'gcc-...' # preferred session.options['c'] = 'gcc-...'

3.

Specify the crossfile option (also the absolute option name is craftr.lang.cxx.clang.crossfile).

$ craftr export --option crossfile=cross.config

cross.config:

[binaries]
  c = gcc-...

4.

(Currently not documented) Instantiate your own toolchain. You need to load the Clang/GCC package instead of the cross-platform C/C++ package. This is probably a bit more tedious since it uses an API that is 1 level below c_compile() and cxx_binary().

cxc = load_module('craftr.lang.cxx.clang').ToolChain(cross_config={ c = 'gcc-...' })

objs = cxc.compile('c', sources = glob(['src/*.c'])) main = cxc.link('bin', inputs = objs)


I am not 100% sure if I want to bring the back the program = ... option for c_compile(). That is because for example cxx_binary() would need to receive the same parameter, especially for cross-compiling, as otherwise the default C-compiler will be invoked for linking. (Craftr uses the C compiler for the linking step).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/craftr-build/craftr/issues/148#issuecomment-264743896, or mute the thread https://github.com/notifications/unsubscribe-auth/ABF_4U_lP78MquDYvClhQ2mxxlOvKzl2ks5rE1mIgaJpZM4LDsdr .

NiklasRosenstein commented 7 years ago

Great! :)

Yes, I believe so. It should be renamed to something else, not sure what though. It's covering the common parts of the Clang and GCC command-line interface. Maybe call it craftr.lang.cxx.unixtoolchain or so, but that's a pretty long name 😄

tliron commented 7 years ago

How about common_c?

They're not just Unix, since both of them can run on Windows, too. It could be a catchall for generic C-family compilers. (For example, if I want to inherit Toolchain and run my own.) What do you think?

NiklasRosenstein commented 7 years ago

Thanks I like your suggestions! I make it craftr.lang.cxx.common because it's not only about C but also ASM and C++. Note that you don't need to hurry updating your script, because you can still load it by its old name. You'll just get a warning like

"craftr.lang.cxx.clang" is deprecated, use "craftr.lang.cxx.common" instead
NiklasRosenstein commented 7 years ago

See 667048b