Accessing Projucer LLVM/clang compilation chain?


#1

Hi,

In the Faust project we have a LLVM backend that allows to compile Faust DSP source to LLVM IR, then JIT it to native code. This is what can be done using the embeddable libfaust as described here : http://faust.grame.fr/news/2016/01/12/using-dynamic-compiler.html

In the Projucer LLVM/clang compilation chain accessible for that kind of use ? I mean : would it be possible to “plug” libfaust in Projucer so that Faust DSP source code could be dynamically compiled and executed?


#2

Yes - quite possible! It’s a bit too complicated to give a quick explanation here of how to do this, but basically you’d want to just modify the code in some C++ files using the same mechanism that the code editor does. This is all on the open-source side of the projucer so you can probably figure out how it works…


#3

I was not aware of the existence of “open-source side of the producer”: can you possibly point me the relevant files?

Thanks


#4

Well, the whole of the projucer folder is open-source - maybe start by looking at Projucer/Source/LiveBuildEngine


#5

OK, so I see only a few specific exported symbols in JUCECompileEngine.dylib, so I guess the whole LLVM IR + JIT API will not be available to link with… and I guess our libfaust library will find the LLVM function entry points it needs.


#6

To be more precise : libfaust (the Faust C++ compiler as a library) contains a backend that can emit LLVM IR (so create a LLVM module), then JIT it (using the LLVM JIT API), then export a set of native entry points used to create, init, and run the audio DSP component.

The need would be to be able to use the same LLVM/Clang code that is already compiled and linked in JUCECompileEngine.dylib, and link with internal LLVM functions.


#7

OK, but then why even bother using the projucer? If you’re already creating LLVM IR then you just need LLVM itself, right?

What I thought you meant was to use the projucer instead of dealing with Clang/LLVM. E.g. you could just have something that converts FAUST code into C++ and lets the projucer take care of recompiling/loading/running it.


#8

This could be a way yes, since Faust compiler can directly output C++.


#9

Hello,

I would like to play with the projucer live build engine. And I right in thinking based on what you said, that assuming i can work out whats going on in the projucer code I should be up to knock something up to do the kind of PowerPoint live coding for audio that Timur/Fabian did at the JUCE summit in 2015 without access to any non-public headers etc?

cheers

oli


#10

Stefan Gränitz told me at ADC that one possible solution would be to produce a C++ file (from the Faust compiler) that would be dynamically recompiled by the projucer live build engine each time the C++ changes. So we would have the following chain :

Faust DSP source ==> libfaust with C++ backed ==> C++ file ==> live build engine ==> executable code

instead of the currently tested chain:

Faust DSP source ==> libfaust with LLVM IR backed ==> LLVM IR module ==> LLVM JIT ==> executable code


#11

Take a look here… rough around the edges and still unfinished and a lot to do, but it’s a starting point if you are interested in bringing this forward

i suggest you to try with a debug projucer build with child process disabled so to be able to debug the message passing between projucer and the dylib easily.

i think you can plug the libfaust somehow in LiveCodeBuilder class… hope it helps!


#12

cool!

i got an error #include “llvm/BitCode/ReaderWriter.h” not found, then a bunch of linker errors. should your script checkout the correct llvm/clang versions?


#13

yes, i have not updated that since some time. makes sense to checkout a specific llvm + clang version (i think 3.8 or 3.9 should be ok) . if i find 5 minutes later i will update that


#14

Updated to use the release_39 branch.


#15

Thanks. Any chance you could briefly explain how to use this? I’m not sure how it works with the producer and the closed source live build engine.


#16

it’s a starting point of a reverse engineered juce compiler engine. it uses clang to generate the llvm modules and recompiles them when the files changes in the projucer and do some generated binary caching on disk. basically if you want to integrate with the live compiler of the projucer, this is just an implementation based on analysing the classes in the jucer (the client server communication protocol).

compile it in debug and make a symbolic link of it in the application projuce folder (where you normally put the real closed source one), compile projucer in debug with child process set to false and start putting some breakpoints in the live builder class to see how projucer communicate with the compiler…