How do you create a second debug config with CMake?

In my plugin I want Debug and Debug_Editor. This was easy to do with Projucer, any idea how to do in CMake? I’m trying:

set(CMAKE_CONFIGURATION_TYPES Debug Release Debug_Editor Release_Editor)
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING "Reset the configurations to what we need" FORCE)

set (CMAKE_C_FLAGS_DEBUG_EDITOR ${CMAKE_C_FLAGS_DEBUG})
set (CMAKE_CXX_FLAGS_DEBUG_EDITOR ${CMAKE_CXX_FLAGS_DEBUG})

However, in Xcode and Visual Studio, NDEBUG and _NDEBUG are still defined for Debug_Editor.

The issue is here in JUCEModuleSupport.cmake line 75. You can’t just assume that the debug config is always just named DEBUG.

function(_juce_add_standard_defs juce_target)
    target_compile_definitions(${juce_target} INTERFACE
        JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1
        $<IF:$<CONFIG:DEBUG>,DEBUG=1 _DEBUG=1,NDEBUG=1 _NDEBUG=1>
        $<$<PLATFORM_ID:Android>:JUCE_ANDROID=1>)
endfunction()

Could you make a change like this: Don't assume the Debug config is named Debug · reFX/JUCE@4ff5fd3 · GitHub

And then I can add set (JUCE_DEBUG_CONFIGS "Debug,Debug_Editor") to my CMakeLists.txt?

You’re right that it’s an error for JUCE to assume the debug config is always just Debug, but CMake already has a property for this built in, I advise against adding a JUCE-specific property/variable for this.

IMHO the correct way to handle this is:

  • JUCE should check the value of the DEBUG_CONFIGURATIONS global property
  • You should set that property in your CMakeLists.txt before adding JUCE

@benvining Does this look better:

function(_juce_add_standard_defs juce_target)
    get_property (CFGS GLOBAL PROPERTY DEBUG_CONFIGURATIONS)

    if (NOT CFGS)
        target_compile_definitions(${juce_target} INTERFACE
            JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1
            $<IF:$<CONFIG:DEBUG>,DEBUG=1 _DEBUG=1,NDEBUG=1 _NDEBUG=1>
            $<$<PLATFORM_ID:Android>:JUCE_ANDROID=1>)
    else ()
        string(TOUPPER "${CFGS}" CFGS)
        string(REPLACE ";" "," CFGS "${CFGS}")

        target_compile_definitions(${juce_target} INTERFACE
            JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1
            $<IF:$<CONFIG:${CFGS}>,DEBUG=1 _DEBUG=1,NDEBUG=1 _NDEBUG=1>
            $<$<PLATFORM_ID:Android>:JUCE_ANDROID=1>)
    endif ()
endfunction()
1 Like

I would write it like this:

function(_juce_add_standard_defs juce_target)

  get_cmake_property (debug_configs DEBUG_CONFIGURATIONS)

  if(NOT debug_configs)
    set (debug_configs Debug)
  endif()

  list (JOIN debug_configs "," debug_configs)

  target_compile_definitions ("${juce_target}" INTERFACE
    JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1
    $<IF:$<CONFIG:${debug_configs}>,DEBUG=1 _DEBUG=1,NDEBUG=1 _NDEBUG=1>
    $<$<PLATFORM_ID:Android>:JUCE_ANDROID=1>)

endfunction()

The following in JUCEHelperTargets.cmake also needs to be updated to support multiple configs.

# ==================================================================================================

add_library(juce_recommended_config_flags INTERFACE)
add_library(juce::juce_recommended_config_flags ALIAS juce_recommended_config_flags)

if((CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") OR (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
    target_compile_options(juce_recommended_config_flags INTERFACE
        $<IF:$<CONFIG:Debug>,/Od /Zi,/Ox> $<$<STREQUAL:"${CMAKE_CXX_COMPILER_ID}","MSVC">:/MP> /EHsc)
elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
       OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
       OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
    target_compile_options(juce_recommended_config_flags INTERFACE
        $<$<CONFIG:Debug>:-g -O0>
        $<$<CONFIG:Release>:-O3>)
endif()

# ==================================================================================================

add_library(juce_recommended_lto_flags INTERFACE)
add_library(juce::juce_recommended_lto_flags ALIAS juce_recommended_lto_flags)

if((CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") OR (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
    target_compile_options(juce_recommended_lto_flags INTERFACE
        $<$<CONFIG:Release>:$<IF:$<STREQUAL:"${CMAKE_CXX_COMPILER_ID}","MSVC">,-GL,-flto>>)
    target_link_libraries(juce_recommended_lto_flags INTERFACE
        $<$<CONFIG:Release>:$<$<STREQUAL:"${CMAKE_CXX_COMPILER_ID}","MSVC">:-LTCG>>)
elseif((NOT MINGW) AND ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
                     OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
                     OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")))
    target_compile_options(juce_recommended_lto_flags INTERFACE $<$<CONFIG:Release>:-flto>)
    target_link_libraries(juce_recommended_lto_flags INTERFACE $<$<CONFIG:Release>:-flto>)
endif()

Yeah you’re right. The same generator expression pattern I showed above can be used here.

1 Like

I think I have it all working now, I’ve squashed it all into one commit.

1 Like

The multi-argument form of $<CONFIG> isn’t supported in JUCE’s minimum-required CMake (3.15). I’ve got a patch on the way that should work for all of the CMake versions we support.

2 Likes

Is there a reason for this low requirement? Is there a block preventing people from installing a later version of CMake?

That’s on develop now:

Not necessarily, but at the same time we don’t want to set an arbitrarily high usage requirement. As long as the burden for supporting an older version is reasonable (and for the most part, CMake 3.15 is usable), there’s not much reason to move.

Shouldn’t this line:

$<$<CONFIG:Release>:-O3>)

Be something like:

$<$<NOT:${debug_config}>>:-O3>

I’m not sure, but it’s possible people have other sorts of builds beyond just debug and release. Making all non-debug builds fully optimised seems a bit surprising.

In that case, I think we need another property for “Release” builds…

I think the intention of CMake’s global DEBUG_CONFIGURATIONS property is that all configurations not listed there are for release purposes. Using $<CONFIG:Release> doesn’t even cover all of CMake’s built-in configurations, since it leaves out MinSizeRel and RelWithDebInfo.