Using CMake flow to build libraries, Android apps

Thanks a lot, I’ll give it a try!

Your recipe above worked (so far), thanks!

A couple of minor caveats:

  1. I had to add_library() as STATIC rather than OBJECT for my JUCE dependencies library: CMake complained about cyclic dependencies. I guess this isn’t a problem though.

  2. I had to add the juce:: namespace everywhere (not a problem, just a note for anyone else following this)

  3. I wasn’t able to use the following:

     const juce::String getApplicationName() override
     {
        return juce::ProjectInfo::projectName;
     }
 
     const juce::String getApplicationVersion() override
     {
        return juce::ProjectInfo::versionString;
     }

in my juce::JUCEApplication; I assume juce::ProjectInfo is created along with JuceHeader.h. Not a show-stopper by any means; I can hard-code them for now and worst case, just define these some other way. Would be nice to re-use the JUCE way though.

Following up on this thread @reuk @eyalamir as I am trying to contribute to Eyal’s CMake template, which has every project type except for the library type - as I mostly am making libraries it would be convenient to have a Github template set up with as much of the boiler plate as possible.

I tried the above recommendations, and unfortunately it seems that for me, the call

_juce_initialise_target(${TargetName})

is the single difference between the template building successfully or not. Without this line, there are many errors where juce_core’s .cpp files cannot find their own .h nor other symbols referenced from other headers.

Here’s what I have so far, if anyone can recommend a better way of doing it than this, thanks in advance!

project(LibraryTemplate VERSION 0.0.1)

set (TargetName ${PROJECT_NAME})

add_library(${TargetName} OBJECT)

_juce_initialise_target(${TargetName})

target_link_libraries(${TargetName}
        PRIVATE
        juce::juce_core
        PUBLIC
        juce::juce_recommended_config_flags
        juce::juce_recommended_warning_flags)

target_compile_definitions(${TargetName}
        INTERFACE
        $<TARGET_PROPERTY:${TargetName},COMPILE_DEFINITIONS>)

target_include_directories(${TargetName}
        INTERFACE
        $<TARGET_PROPERTY:${TargetName},INCLUDE_DIRECTORIES>)

set(SOURCES
    Source/LibraryAPI.cpp
    Source/LibraryImpl.cpp)

target_sources(${TargetName} PRIVATE ${SOURCES})

add_library(${TargetName}_shared SHARED)
add_library(${TargetName}_static STATIC)

target_link_libraries(${TargetName}_shared PUBLIC ${TargetName})
target_link_libraries(${TargetName}_static PUBLIC ${TargetName})

This might be a better reference, I was also trying to determine in what scenarios having both a static library and a consuming CLI app using juce_core would cause problems:

Maybe it was privately linking to juce_core in the static library that allowed things to (seemingly) work alright?

Here is also @eyalamir 's upstream equivalent, i noted he also needed to use the private _juce_initialise_target and so there is perhaps no better way to do this as of yet. (Caveat: I suspected in some projects I worked on that libraries could compile with JUCE without this call, but only if other non-library projects were part of the same larger CMake project and JUCE had the right visibility between parts of the larger project.)

I was also curious about the purpose of

target_compile_definitions(DLL PRIVATE JUCE_STANDALONE_APPLICATION=1)

as I did not need to add it to mine for things to work.

1 Like

When I remove it and try to build, I get the following warning:

#ifndef    JUCE_STANDALONE_APPLICATION
 JUCE_COMPILER_WARNING ("Please re-save your project with the latest Projucer version to avoid this warning")
 #define   JUCE_STANDALONE_APPLICATION 0
#endif

And I like my builds warning-free. :slight_smile:

2 Likes