diff --git a/docs/JUCE Module Format.md b/docs/JUCE Module Format.md index 60bacd4e21..c114b302aa 100644 --- a/docs/JUCE Module Format.md +++ b/docs/JUCE Module Format.md @@ -185,11 +185,18 @@ Possible values: parent folder, which need to be added to a project's header search path - OSXFrameworks - - (Optional) A list (space or comma-separated) of OSX frameworks that are needed + - (Optional) A list (space or comma-separated) of OSX frameworks that are needed by this module + +- WeakOSXFrameworks + - (Optional) A list (space or comma-separated) of weak linked OSX frameworks that are needed by this module - iOSFrameworks - - (Optional) Like OSXFrameworks, but for iOS targets + - (Optional) A list (space or comma-separated) of iOS frameworks that are needed by this module + +- WeakiOSFrameworks + - (Optional) A list (space or comma-separated) of weak linked iOS frameworks that are needed + by this module - linuxPackages - (Optional) A list (space or comma-separated) pkg-config packages that should be used to pass diff --git a/extras/Build/CMake/JUCEModuleSupport.cmake b/extras/Build/CMake/JUCEModuleSupport.cmake index 9781ccf505..ff2f51edc1 100644 --- a/extras/Build/CMake/JUCEModuleSupport.cmake +++ b/extras/Build/CMake/JUCEModuleSupport.cmake @@ -265,22 +265,29 @@ endfunction() # ================================================================================================== -# Takes a target, a link visibility, and a variable-length list of framework -# names. On macOS, finds the requested frameworks using `find_library` and -# links them. On iOS, links directly with `-framework Name`. +# Takes a target, a link visibility, if it should be a weak link, and a variable-length list of +# framework names. On macOS, for non-weak links, this finds the requested frameworks using +# `find_library`. function(_juce_link_frameworks target visibility) - foreach(framework IN LISTS ARGN) + set(options WEAK) + cmake_parse_arguments(JUCE_LINK_FRAMEWORKS "${options}" "" "" ${ARGN}) + foreach(framework IN LISTS JUCE_LINK_FRAMEWORKS_UNPARSED_ARGUMENTS) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - find_library("juce_found_${framework}" "${framework}" REQUIRED) - target_link_libraries("${target}" "${visibility}" "${juce_found_${framework}}") + if(JUCE_LINK_FRAMEWORKS_WEAK) + set(framework_flags "-weak_framework ${framework}") + else() + find_library("juce_found_${framework}" "${framework}" REQUIRED) + set(framework_flags "${juce_found_${framework}}") + endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") # CoreServices is only available on iOS 12+, we must link it weakly on earlier platforms - if((framework STREQUAL "CoreServices") AND (CMAKE_OSX_DEPLOYMENT_TARGET LESS 12.0)) + if(JUCE_LINK_FRAMEWORKS_WEAK OR ((framework STREQUAL "CoreServices") AND (CMAKE_OSX_DEPLOYMENT_TARGET LESS 12.0))) set(framework_flags "-weak_framework ${framework}") else() set(framework_flags "-framework ${framework}") endif() - + endif() + if(NOT framework_flags STREQUAL "") target_link_libraries("${target}" "${visibility}" "${framework_flags}") endif() endforeach() @@ -391,6 +398,11 @@ endfunction() # ================================================================================================== +function(_juce_remove_empty_list_elements arg) + list(FILTER ${arg} EXCLUDE REGEX "^$") + set(${arg} ${${arg}} PARENT_SCOPE) +endfunction() + function(juce_add_module module_path) set(one_value_args INSTALL_PATH ALIAS_NAMESPACE) cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN}) @@ -522,26 +534,34 @@ function(juce_add_module module_path) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") _juce_get_metadata("${metadata_dict}" OSXFrameworks module_osxframeworks) + _juce_remove_empty_list_elements(module_osxframeworks) foreach(module_framework IN LISTS module_osxframeworks) - if(module_framework STREQUAL "") - continue() - endif() - _juce_link_frameworks("${module_name}" INTERFACE "${module_framework}") endforeach() + _juce_get_metadata("${metadata_dict}" WeakOSXFrameworks module_weakosxframeworks) + + _juce_remove_empty_list_elements(module_weakosxframeworks) + foreach(module_framework IN LISTS module_weakosxframeworks) + _juce_link_frameworks("${module_name}" INTERFACE WEAK "${module_framework}") + endforeach() + _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" OSXLibs) elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") _juce_get_metadata("${metadata_dict}" iOSFrameworks module_iosframeworks) + _juce_remove_empty_list_elements(module_iosframeworks) foreach(module_framework IN LISTS module_iosframeworks) - if(module_framework STREQUAL "") - continue() - endif() - _juce_link_frameworks("${module_name}" INTERFACE "${module_framework}") endforeach() + _juce_get_metadata("${metadata_dict}" WeakiOSFrameworks module_weakiosframeworks) + + _juce_remove_empty_list_elements(module_weakiosframeworks) + foreach(module_framework IN LISTS module_weakiosframeworks) + _juce_link_frameworks("${module_name}" INTERFACE WEAK "${module_framework}") + endforeach() + _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" iOSLibs) elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD")) _juce_get_metadata("${metadata_dict}" linuxPackages module_linuxpackages) diff --git a/extras/Projucer/Source/Application/jucer_CommandLine.cpp b/extras/Projucer/Source/Application/jucer_CommandLine.cpp index 3ad3d48e83..bc3b14eb1a 100644 --- a/extras/Projucer/Source/Application/jucer_CommandLine.cpp +++ b/extras/Projucer/Source/Application/jucer_CommandLine.cpp @@ -323,7 +323,7 @@ namespace var moduleInfo (new DynamicObject()); moduleInfo.getDynamicObject()->setProperty ("file", getModulePackageName (module)); - moduleInfo.getDynamicObject()->setProperty ("info", module.moduleInfo.getModuleInfo()); + moduleInfo.getDynamicObject()->setProperty ("info", module.moduleDescription.getModuleInfo()); infoList.append (moduleInfo); } } diff --git a/extras/Projucer/Source/Project/Modules/jucer_Modules.cpp b/extras/Projucer/Source/Project/Modules/jucer_Modules.cpp index a32c7a175e..060f91b452 100644 --- a/extras/Projucer/Source/Project/Modules/jucer_Modules.cpp +++ b/extras/Projucer/Source/Project/Modules/jucer_Modules.cpp @@ -23,7 +23,7 @@ //============================================================================== LibraryModule::LibraryModule (const ModuleDescription& d) - : moduleInfo (d) + : moduleDescription (d) { } @@ -36,15 +36,15 @@ void LibraryModule::writeIncludes (ProjectSaver& projectSaver, OutputStream& out if (modules.shouldCopyModuleFilesLocally (moduleID)) { - auto juceModuleFolder = moduleInfo.getFolder(); + auto juceModuleFolder = moduleDescription.getFolder(); auto localModuleFolder = project.getLocalModuleFolder (moduleID); localModuleFolder.createDirectory(); projectSaver.copyFolder (juceModuleFolder, localModuleFolder); } - out << "#include <" << moduleInfo.getModuleFolder().getFileName() << "/" - << moduleInfo.getHeader().getFileName() + out << "#include <" << moduleDescription.getModuleFolder().getFileName() << "/" + << moduleDescription.getHeader().getFileName() << ">" << newLine; } @@ -71,7 +71,7 @@ void LibraryModule::addSearchPathsToExporter (ProjectExporter& exporter) const if (moduleLibDir.exists()) exporter.addToModuleLibPaths ({ libSubdirPath, moduleRelativePath.getRoot() }); - auto extraInternalSearchPaths = moduleInfo.getExtraSearchPaths().trim(); + auto extraInternalSearchPaths = moduleDescription.getExtraSearchPaths().trim(); if (extraInternalSearchPaths.isNotEmpty()) { @@ -84,7 +84,7 @@ void LibraryModule::addSearchPathsToExporter (ProjectExporter& exporter) const void LibraryModule::addDefinesToExporter (ProjectExporter& exporter) const { - auto extraDefs = moduleInfo.getPreprocessorDefs().trim(); + auto extraDefs = moduleDescription.getPreprocessorDefs().trim(); if (extraDefs.isNotEmpty()) exporter.getExporterPreprocessorDefsValue() = exporter.getExporterPreprocessorDefsString() + "\n" + extraDefs; @@ -98,7 +98,7 @@ void LibraryModule::addCompileUnitsToExporter (ProjectExporter& exporter, Projec auto moduleID = getID(); auto localModuleFolder = modules.shouldCopyModuleFilesLocally (moduleID) ? project.getLocalModuleFolder (moduleID) - : moduleInfo.getFolder(); + : moduleDescription.getFolder(); Array compiled; findAndAddCompiledUnits (exporter, &projectSaver, compiled); @@ -118,6 +118,8 @@ void LibraryModule::addLibsToExporter (ProjectExporter& exporter) const auto& project = exporter.getProject(); + auto moduleInfo = moduleDescription.getModuleInfo(); + if (exporter.isXcode()) { auto& xcodeExporter = dynamic_cast (exporter); @@ -130,26 +132,29 @@ void LibraryModule::addLibsToExporter (ProjectExporter& exporter) const xcodeExporter.xcodeFrameworks.add ("AudioUnit"); } - auto frameworks = moduleInfo.getModuleInfo() [xcodeExporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString(); + auto frameworks = moduleInfo[xcodeExporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString(); xcodeExporter.xcodeFrameworks.addTokens (frameworks, ", ", {}); - parseAndAddLibsToList (xcodeExporter.xcodeLibs, moduleInfo.getModuleInfo() [exporter.isOSX() ? "OSXLibs" : "iOSLibs"].toString()); + auto weakFrameworks = moduleInfo[xcodeExporter.isOSX() ? "WeakOSXFrameworks" : "WeakiOSFrameworks"].toString(); + xcodeExporter.xcodeWeakFrameworks.addTokens (weakFrameworks, ", ", {}); + + parseAndAddLibsToList (xcodeExporter.xcodeLibs, moduleInfo[exporter.isOSX() ? "OSXLibs" : "iOSLibs"].toString()); } else if (exporter.isLinux()) { - parseAndAddLibsToList (exporter.linuxLibs, moduleInfo.getModuleInfo() ["linuxLibs"].toString()); - parseAndAddLibsToList (exporter.linuxPackages, moduleInfo.getModuleInfo() ["linuxPackages"].toString()); + parseAndAddLibsToList (exporter.linuxLibs, moduleInfo["linuxLibs"].toString()); + parseAndAddLibsToList (exporter.linuxPackages, moduleInfo["linuxPackages"].toString()); } else if (exporter.isWindows()) { if (exporter.isCodeBlocks()) - parseAndAddLibsToList (exporter.mingwLibs, moduleInfo.getModuleInfo() ["mingwLibs"].toString()); + parseAndAddLibsToList (exporter.mingwLibs, moduleInfo["mingwLibs"].toString()); else - parseAndAddLibsToList (exporter.windowsLibs, moduleInfo.getModuleInfo() ["windowsLibs"].toString()); + parseAndAddLibsToList (exporter.windowsLibs, moduleInfo["windowsLibs"].toString()); } else if (exporter.isAndroid()) { - parseAndAddLibsToList (exporter.androidLibs, moduleInfo.getModuleInfo() ["androidLibs"].toString()); + parseAndAddLibsToList (exporter.androidLibs, moduleInfo["androidLibs"].toString()); } } @@ -163,7 +168,7 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P void LibraryModule::getConfigFlags (Project& project, OwnedArray& flags) const { - auto header = moduleInfo.getHeader(); + auto header = moduleDescription.getHeader(); jassert (header.exists()); StringArray lines; @@ -348,7 +353,7 @@ void LibraryModule::addBrowseableCode (ProjectExporter& exporter, const Array 0) s.set ("OTHER_LDFLAGS", linkerFlags.joinIntoString (" ").quoted()); @@ -2054,6 +2057,7 @@ public: }; mutable StringArray xcodeFrameworks; + mutable StringArray xcodeWeakFrameworks; StringArray xcodeLibs; private: