Best way to build projects for embedded targets not supported by the Projucer with CMake

First of all, I’m not that skilled when it comes to complicated build systems and so on. I’ve always been a fan of the Projucer being an easy tool to generate all I needed. Until now…

I’m about to build software for embedded Intel FPGA ARM SoCs using C++ and OpenCL. This requires invoking some custom cross compiler toolchain for the ARM and the Intel FPGA compiler for OpenCL as an extra step to compile the CL sources. However the same software should still build on standard Windows/Linux/MacOS targets. I got this working by writing my first CMakeLists (you can find the result here) and running them in CLion and Visual Studio 2017. This worked quite well for some limited test projects only relying on the std lib, however for a real project I now want to add JUCE to be able to set up a JUCE Application and use my collection of own modules.

I first found FRUT, but when I read that this relies on specifying the JUCE-exporters to use I came to the conclusion that this can’t be the right tool to create a JUCE application for a custom target like mine.

I then found juce-cmake which looked a bit more promising to me, but I can’t get it working, maybe due to my lack of CMake expert knowledge. I opened an issue for the errors I’m getting in the repo.

As another solution I thought of manually including the headers and sources, but I’m not sure what’s about all the things normally defined in AppConfig.h and JuceHeader.h. At last I thought about creating a project with the Projucer once to just have AppConfig and JuceHeader and then include all headers and sources manually.

In the end I’m not sure what would be the best solution in terms of maintainability and flexibility, so I could need some input from the community on how to do this right. Has anyone done anything similar already and how did he/she solve it? Would love to get some input before trying out a lot of things that only lead to frustration :wink:

I write software for embedded platforms based on ARM. I just cross compile using makefiles generated by Projucer. For me it’s the most flexible and time saving solution - I don’t want to add an additional layer of configuration required by some extra tools. I call many hardware related libraries and drivers, so these parts of my code are separated into classes which are just not reusable on other targets or there are defines in these classes if they are expected to work with all targets.

Does this work without any adjustments to the Makefile for your cases? Because in my case it won’t, as I need to perform tasks that can’t be done with the options the Projucer gives me. So If I used Projucer as the project generation tool I probably always needed to make huge changes to the auto-generated Makefile after saving some changes to the project in the Projucer. If you need modifications to your Makefile too, how do you handle them when changing the project through the Projucer?

On the other hand, CMake gives me the freedom to express all target-specific adjustments and manage project-specific stuff at the same time, this is why I went for CMake and hoped to be able to integrate the JUCE-Part into this workflow

Of course I need to include some extra libraries to link + set some compiler options but fortunately everything can be done until now in Projucer. In the past there were some minor bugs or rather inconveniences in Projucer that some architecture targets were not exported as desired but now all such issues are gone.

What changes to Makefile would be hard to handle by Projucer in your case?

Due to a total lack of time I haven’t checked CMake possibilities in the area of embedded development yet (plus I tend to limit a number of tools) - fortunately this part of development was always quite smooth, rather a lot of time I spent fighting embedded architecture in terms of optimisation, SIMD operations, manual distribution of threads on cores, OpenGL and GLES issues etc.

1 Like

The most important thing that cannot be handled by the Projucer is the management/compilation of the CL sources.

  • In case of a build for a standard PC target, the CL sourcefiles are copied next to the binary folder and compiled at runtime by the CL platform
  • In case of an FPGA-Build, the CL sourcefiles are compiled by the Intel aoc compiler and the resulting FPGA configuration ist stored next to the binary. As compiling FPGA configurations can take several hours, this should only happen if any changes were made to the cl sources
  • For development it’s also desirable to compile the cl sources for emulation - this is a lot faster than compiling it for the FPGA and allows emulating the FPGA build on an x86 Linux machine

All this three cases need different library linkage (no problem for the Projucer) and different invocation of the copy-steps or the OpenCL compiler if changes were made to the CL sources.

Furthermore, I need the ability to pass parameters to the FPGA compiler to specify which FPGA device I’m targeting.

One last thing I like about CMake is the integration into CLion, which I love. Here I’m able to start a remote debugging session on my SoC via GDB and get the very same debugging experience as if I would debug a native build. Don’t know how to do this with CLion if I switched to a Makefile based build

Ok, please drop a line when you find some solution for your platform.