A question on Cmake and the Projucer

Hi,

I’m looking to automate my workflow, specifically with codesigning, using Github Actions.
Mainly from this article.

However I don’t want to use the template given in that article and would rather build my own cmake configuration and workflow from scratch. However I still want to use the projucer. Is there a way to sync the CmakeLists.txt with the projucer because from what i have seen you either use the projucer, or use cmake and build with the command line. I guess you could use both but it seems tedious to syncronise them manually.

How do other people handle their codesigning and automation workflow?

It really needs to be one or the other. CMake is generally more friendly for CI but it’s not impossible to use the Projucer in CI. It has command line support. Two options jump out to me (if you don’t want to move to CMake)

  1. Build the Projucer from the JUCE source, the projects are already included to do so, or you could even use CMake to do this!

  2. Download the best fit pre-built version of the Projucer from GitHub during your build and use that.

Option 2 is going to be faster but it’s normally best to always use a version of the Projucer that matches your JUCE source code. Option 1 can be made faster in most situations by employing some basic caching techniques on GitHub Actions.

I’ve been using a bunch of ruby files that I wrote myself, and that only depend on ruby. Took me a few days over a period of several years, for convenience I recently started using TeamCity to run them. make_release.rb → out comes a signed/notarized installer. Projucer builds I put into a git submodule.
I’m seriously considering not porting over several projects to CMake and sticking with the straightforward solution, because just evaluating CMake and learning the basics already cost me more time than all the work I ever spent on those ruby scripts :wink:

Maybe relevant: I’m forced to use physical build machines, and I’m only targeting macos and windows.

Projucer/Cmake is kind of a small part of the build process… at minimum they just make an xcode/VS project which you then compile from. Seems like most of the time spent building is spent gitting/notarizing/wrapping/xcodebuilding/msbuilding/applescripting a nice DMG… I say stick with your Ruby scripts and the Projucer is very nice with all its boxes that show you what the options are. I also think the JUCE team has done a great job with juceaide too.

hmm i see thank you for all your input.
I think going forward I will try this:
Use Projucer for buidling and testing on my own system,
then use CMake to build using github actions when I’m ready to distribute the current version to testers.

I am currently trying to port over a projucer project for use with CMake but a few strange things have happened:

  • the .jucer file has disappeared. I intended to keep it but it is now gone. I have not deleted it so I can only assume that a cmake process has deleted it but I do not know.
  • It is is unsure what to do with the /JuceLibraryCode directory

When using the projucer, the project had the automatically generated folder “JuceLibraryCode” which contained the JuceHeader.h but now cmake does not know how to handle it. What must I include in CMakeLists.txt to fix this?

I think this is unlikely to have been caused by CMake, but I can’t be certain without knowing what CMake commands you used, and the contents of your CMakeLists. If you’re not using some kind of version control system (git or similar), then I’d highly recommend it, so that you can restore files that have been accidentally deleted.

It’s not clear what this means - the contents of the error message would be helpful. That said, the contents of JuceLibraryCode are not used by the JUCE CMake support. You shouldn’t add any of those files to your CMakeLists. Once you’ve completed the transition to CMake, you can remove that folder completely. Again, it’s a good idea to set up version control on your projects, so that you can restore this folder and roll-back to a working Projucer build if necessary.

I’d also recommend reading through the example projects at examples/CMake. The CMakeLists for these projects are heavily commented, and include information about setting up the generated JuceHeader.

Thank you for for your reply I probably haven’t been very clear.

The compiler was simply saing “JuceHeader.h not found”
I looked at the audio plugin example and it seems I might have missed.

juce_generate_juce_header(AudioPluginExample)

I am in the process of moving my projects to github like a good developer :smiley: but since I did not want to track changes in the jucer file I added it to the gitignore! It seems like it is lost in the sands of time … is not even in the recycle bin of my system.
Strangely the projucer is still open with the deleted project file and I haven’t closed it yet in case I am still able to save it (when I try to cmd+s it says saved but there is no corresponding .jucer file saved anywhere). Are there other ways to generate .jucer files that don’t involve going Projucer > File > New Project?

You know this now, but for the benefit of readers in the future, it’s strongly recommended to commit the .jucer file to version control when working with the Projucer.

Can you try “save as” to save it to a new location, then copy it back to the original location?

It seems I just had to modify the project in some way before it actually registered and resaved a new .jucer file and JuceLibraryCode folder. Right now though it looks like I am just getting errors from cmake - looks like a name collision between juce::Point and my own “struct Point {”. Looks like I’ve got some refactoring to do…

You shouldn’t be declaring classes in the juce namespace…?

Yes I know, I declared a “struct Point…” in my own Source File, but when I tried to compile with cmake it said that the reference to “Point” is ambiguous because JUCE also has a Point class. The issue went away when I put my Point struct into its own namespace. I can only assume that the compiler that cmake is using is stricter than the compiler that I use when I build with XCode and the projcuer.

Were you relying on the using namespace juce declaration that can be automatically added to the JuceHeader.h?

Ahh i see. In the Header generated by

juce_generate_juce_header(AudioPluginExample)

It did have “using namespace juce”
looks like you can set that flag using the " DONT_SET_USING_JUCE_NAMESPACE" compiler definition.

My new trouble is that of integrating my own GUI library. I have a few classes and LookAndFeel methods that I use across my different plugins for consistency, stored on my local machine. What would people recommend I do for integrating it into my own projects? Should I create its own dedicated Github Repo and refer to that in my project?

A good starting point is to put all of the shared code into a JUCE module. There’s a markdown document in the docs folder that explains how to structure module files, and you can look at the JUCE modules for examples.

Once you’ve done that, you have two broad options:

  • Create a git repo for the shared code, and add it as a submodule of each project that uses the code. This is a good approach if you want to work on each project individually, and may need different versions of the shared code in each project. This approach also allows you to make the shared code open-source without publishing the dependent projects.
  • Alternatively, use a ‘monorepo’ layout, where everything (all projects and shared code) are stored in the same repository. This approach makes sense if you always want to keep all of your projects up-to-date with the same shared code and other dependencies. It’s also a lot simpler and easier to work with.

I see…
I think I would want a combination of these approaches. i.e. each project and the shared code have their own repo, but each project also keeps an up to date version of the shared code.

So if I understand correctly the monorepo is one git repository whose root directory will look like:

/ShareCode
/Project1
/Project2
.gitignore.

And then working on each of these projects would require commiting and pushing to this main repository?
I also eventually want to integrate Github Actions, where I would want a push of a certain project e.g. Project1 to trigger Project1 to build/codesign/etc. but then if I work on Project2 and push, I want the Project2 Github workflow to execute. Is this still easily possible in a monorepo?

There are monorepo workflows where you can selectively build certain things based on which files changed. In my experience monorepos are a lot easier to work with. However if I really need to make something a dependency just have the minimum number of repos possible and try not to go too nested, I would also personally avoid using submodules, I would use a separate git repo but if you’re using CMake I would suggest either FetchContent or CPM to manage the dependencies.

I see, I could imagine only having JUCE as a submodule in the monolith, then use
git submodule update --init
when I want to update juce.

yeah the will likely be fine although personally I still prefer using CMake FetchContent or CPM, that way the dependency and version is more clearly stated in code rather than that bit being in git. Also if someone checks out your code they don’t have to run git submodule update --init as well as running cmake, they can just run the cmake command and everything will just work.

1 Like