From Projucer to CMake

I’m a complete CMake newbie and the only reason I’m looking into it is to try and port our plugins to CLAP (hopefully, that’s coming to JUCE soon).

I find CMake to be convoluted and I can’t find an easy way to replicate the current setup we have using Projucer.

Using FRUT I was able to at least in part convert a .jucer file to CMakeLists.txt
However, the folder structure is completely messed up.
A typical plugin file structure for us is something like this:

PluginRepoFolder
    Source
        PluginProcessor.cpp
        PluginProcessor.h
        PluginEditor.cpp
        PluginEditor.h
        ...
OurFramework
    SubFolder
        File.cpp
        File.h
        ...
    ...

So the issues are:

  1. I can’t find a way to add folders that are outside the plugin repo to the project, it looks like they all need to be inside the plugin repo.

  2. I also can’t find a way to organize the files in folders, instead, the Xcode project generated by CMake has all the .cpp listed in Source Files and all the .h in Header Files:

Header Files
    PluginProcessor.h
    PluginEditor.h
    File.h
    ...
Source Files
    PluginProcessor.cpp
    PluginEditor.cpp
    File.cpp
    ...

That’s kinda ugly IMO :slight_smile:

1 Like
  1. the rationale is to have a CMakeLists.txt inside your framework and import it as a static library.
  2. source_group(TREE “${PROJECT_SOURCE_DIR}” FILES ${Source})

Hey Carlo! Big fan of your plugins :slight_smile:

Xcode is a bit of a special cookie. I’ve abandoned it for CLion, which has fantastic CMake integration, but before that, I spent many hours tweaking it to display JUCE projects decently.

A fair amount of that work is in my plugin template here: GitHub - sudara/pamplejuce: JUCE 6, Catch2 & CMake on Github Actions

I also can’t find a way to organize the files in folders, instead, the Xcode project generated by CMake has all the .cpp listed in Source Files and all the .h in Header Files

This and the excessive amount of targets are the current problems with Xcode+JUCE. It’s been a while, but here’s what I do in my projects (globs are dead, long live globs!)

# Why yes, we'd like all our Source files to be in our Source dir...
file(GLOB_RECURSE SourceFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/Source/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Source/*.h")
target_sources("${PROJECT_NAME}" PRIVATE ${SourceFiles})

# Grab our modules from the Module dir, while we are at it
file(GLOB_RECURSE ModuleFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/modules/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/modules/*.h")
target_sources("${PROJECT_NAME}" PRIVATE ${moduleFiles})

# Our file tree should uhhh, still look like our file tree
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/Source PREFIX "" FILES ${SourceFiles})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/modules PREFIX "" FILES ${ModuleFiles})

I wrote up an article on cmake with JUCE, maybe it can help with the transition. How to use CMake with JUCE · Melatonin

Also @benvining is doing a cmake series on the Audio Programmer’s youtube channel right now. (He might show up and say that the CMake devs (still) warn against using globs, even with CONFIGURE_DEPENDS but so far I haven’t run into any real world problems with them).

3 Likes

@audiothing just FYI jatin is working on making the CLAP extensions work with projucer also; he got it working yesterday and we might be able to merge it this weekend (we have mostly documentation work to do).

The resources others here shared are great, and i am really happy with cmake, but if you are porting to cmake just because of the CLAP extensions, and also if you hate CMake, you may want to wait until monday or try the stuff in this PR Add a CMake workflow for building a CLAP from a pre-built Projucer project by jatinchowdhury18 · Pull Request #43 · free-audio/clap-juce-extensions · GitHub (which we intend to merge after we resolve the conversation in that issue)

2 Likes

Thanks @otristan and @sudara! I made some progress. A few more questions:

  1. is there a way to then place each external “library” in another folder? Right now I’m seeing all the subfolders and files like this:
Plugin
    OurFrameworkSubFolder1
    OurFrameworkSubFolder2
    SourceSubFolder1
    SourceSubFolder2
    ...
    File.cpp
    File.h
    PluginProcessor.cpp
    PluginProcessor.h
    PluginEditor.cpp
    PluginEditor.h
    ...
  1. I’m seeing an incredible amount of warnings (8000+) that I don’t see with the XCode project generated by Projucer (10+). Not a big deal, but it’s annoying. Any flag I should set to avoid that?

@baconpaul yes I sent Jatin an email a few days ago, I look forward to the projucer implementation if it’s stable enough. I still feel like CMake is probably not the best solution for my needs, but I’m also afraid that the Projucer might be abandoned in the future, so I want to try to stay a bit ahead :wink:

1 Like
  1. if you use static library for your framework then it would do the trick.
    or just use multiple source_group

  2. target_link_libraries(myTarget PUBLIC juce::juce_recommended_warning_flags)

You can also do:

set_target_properties (YourTarget PROPERTIES 
    FOLDER someFolder)

I’m using multiple source_group, like this:

# Source
file(GLOB_RECURSE SourceFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/Source/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Source/*.h")
target_sources("${PROJECT_NAME}" PRIVATE ${SourceFiles})

# MyFramework
file(GLOB_RECURSE MyFramework CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/../MyFramework/Folder1/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../MyFramework/Folder1/*.h")
target_sources("${PROJECT_NAME}" PRIVATE ${MyFramework})

file(GLOB_RECURSE MyOtherFramework CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/../MyFramework/Folder2/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../MyFramework/Folder2/*.h")
target_sources("${PROJECT_NAME}" PRIVATE ${MyOtherFramework})

#
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/Source PREFIX "" FILES ${SourceFiles})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/../MyFramework/Folder1 PREFIX "" FILES ${MyFramework})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/../MyFramework/Folder2 PREFIX "" FILES ${MyOtherFramework})

I need to check the static library perhaps, not sure how to do it yet.

Regarding the warnings, I’m already using this:

target_link_libraries(MyPlugin
  PUBLIC
    juce::juce_recommended_config_flags
    juce::juce_recommended_lto_flags
    juce::juce_recommended_warning_flags
)

But yeah, I get 8000+ warnings compared to just about 10+ with Projucer Xcode project.

Using this will just change the top-level folder name. I’m not sure how to use it to group folders into another folder.

You can just specify nested folders, for example:

set_target_properties (target1 PROPERTIES 
            FOLDER outerFolder/folder1)

set_target_properties (target2 PROPERTIES 
            FOLDER outerFolder/folder2)