RFC: Clang driver redesign

Hi,

The clang driver has been the subject of much dislike for a while now, and
for a while I've wanted to sort it out. I'm chairing a BoF session on it a
the dev meeting later this month, and as a precursor to that I've started
putting together a requirements document.

The initial aim of this document is to work out the specific requirements
for a Clang compiler driver. Then, we can see if the current driver doesn't
meet them (it won't!) and design a solution based on actual use cases.

The first draft of this document is attached in HTML form and inline below
in ReST form. I've documented the obvious use cases that I can think of, but
I am certain to have missed some out. I've also started a strawman proposal
solution, with the intention of stimulating discussion by providing
something concrete.

Please comment! The more feedback I get (even "I don't really care" is
useful) the better prepared I can be for the BoF and the better driver Clang
will get as a result.

Cheers,

James

clang-driver-spec.html (17.5 KB)

I resent this. I am using it for cross-compilation all the time and it
is trivial to use for me. Let's at least call the child by name: Linux
support is a mess and needs to improve. Pretty much all other platforms
shouldn't be negatively effected by that.

Joerg

Actually I'm not referring explicitly to Linux - the use case that springs
most to mind is our own, which is cross-compiling for baremetal ARM targets.

I have to use -ccc-host-triple arm-freebsd-eabi because otherwise the driver
attempts to autoconfigure from the host GCC (freebsd uses as and ld directly
and happens (!!) to default to looking in the current directory first).

Just make sure you have arm-freebsd-eabi-{as,ld} around in PATH and be
done.

Joerg

Hi James,

It would be worth linking to this somewhere in your draft, as a lot of the issues have already been discussed:

http://clang.llvm.org/UniversalDriver.html

The first draft of this document is attached in HTML form and inline below
in ReST form. I've documented the obvious use cases that I can think of, but
I am certain to have missed some out. I've also started a strawman proposal
solution, with the intention of stimulating discussion by providing
something concrete.

Since we're throwing up use-cases, here are the ones I have where the current driver is not the best:

Driving plugins that produce some non-LLVM output. I have written one that generates JavaScript from an ObjC AST and there are others that generate different compiler IRs for codegen by something other than LLVM. Invoking these is pretty painful with the current driver. It would be great to be able to just provide a config file that would remove the LLVM CodeGen and substitute something else. Currently I have to do something like -fsyntax-only (which seems nonsense, because I actually do want code generated, just not LLVM code), -load full/path/to/plugin.so and a few more options.

Shipping a cross-compile toolchain: Most of these include gcc, binutils, headers and libraries. Including clang with the toolchain wouldn't make sense, because it would be the same clang as the version for the host system, unlike GCC where you need one specifically configured for each target. Ideally, you'd just provide a config file that would tell clang where to find everything and it would just work.

Driving extra LLVM optimisations. I have a set for Objective-C that will automatically add themselves to the optimisation toolchain if the library is loaded. Currently this is done by adding -Xclang -load -Xclang path/to/plugin.so to the command line. This is far from ideal, I'd like to be able to provide a config file that said something like 'when compiling Objective-C, load this library'. I imagine other libraries may eventually want to add some library-specific optimisations. For example, GObject or Qt's signals and slots mechanism may both benefit from running some extra LLVM passes that optimise their specific uses.

Finally, an idea that's been floated before and may or may not require changes to the driver is that of a compile daemon. This would start once, parse all prefix headers, and then spawn threads to handle the parsing and compiling of each new source file. It could more easily limit resource usage than a parallel make (for example, C source files typically take under 100MB to compile, C++ ones can take 500MB easily if they're full of templates - being able to limit clangd (clanged?) to using 1GB of RAM would be better than running make -j2 on a quad-core system). Ideally, it could also be used from libclang so that files could be parsed frequently and sent off for codegen when clangd has spare resources and the file has been unmodified for a while (i.e. not when it's being frequently queried by the IDE for code completion, or autocorrection).

From a user perspective, the command line should be simple. Being able to easily add command line arguments that simply map to combinations of others would be a huge win for usability. As a user, I want to be able to just say something like -target=touchpad and have it load touchpad.conf, which specifies all of the arguments for that specific cross-compile toolchain. I want it to load my user config and add a -fexperimental-stuff option, which expands to -Xclang -load -Xclang ~/my/buggy/experimental/optimisations.so

A lot of the things I want are possible with the current driver, but they require command lines so complicated that people generally just don't bother with them.

David

-- Sent from my brain

I'm with you on that one. I really dream of something like having a "sdk folder" which contains headers, libraries, binutils (if needed), and a configuration file, and just being able to invoke clang, telling it where the folder is, and having it cross compile my code.

The configuration file should have a predefined name and location inside the sdk folder, so you don't have to tell clang where it is, and it should contain default target triple, path relative to the SDK root of headers, libraries, tools, and any other information clang need, so you just have to drop the sdk folder wherever you want, and invoke clang with something like this:

clang --sdk=<path to my sdk>

-- Jean-Daniel

I think that the whatever you decide to do, you should make the new driver a separate executable.
That way you can develop it and test it as a separate unit.

Or you can change Clang so that the driver is a plugin that can be freely substituted.

+1. This would also be very useful for OpenCL C standard libraries
such as libclc which require a specific set of command line options
to be provided to the frontend. Currently I have a shell script for
testing purposes which acts as a wrapper around the clang driver,
which I would ideally like to replace with some kind of driver
configuration file generated at compile time.

Thanks,