Browse Source

macOS/iOS: Add the ability to weak link module frameworks

pull/22/head
Tom Poole 3 years ago
parent
commit
e5cbcd7628
6 changed files with 81 additions and 45 deletions
  1. +9
    -2
      docs/JUCE Module Format.md
  2. +36
    -16
      extras/Build/CMake/JUCEModuleSupport.cmake
  3. +1
    -1
      extras/Projucer/Source/Application/jucer_CommandLine.cpp
  4. +21
    -16
      extras/Projucer/Source/Project/Modules/jucer_Modules.cpp
  5. +10
    -10
      extras/Projucer/Source/Project/Modules/jucer_Modules.h
  6. +4
    -0
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h

+ 9
- 2
docs/JUCE Module Format.md View File

@@ -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


+ 36
- 16
extras/Build/CMake/JUCEModuleSupport.cmake View File

@@ -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)


+ 1
- 1
extras/Projucer/Source/Application/jucer_CommandLine.cpp View File

@@ -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);
}
}


+ 21
- 16
extras/Projucer/Source/Project/Modules/jucer_Modules.cpp View File

@@ -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<File> 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<XcodeProjectExporter&> (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<Project::ConfigFlag>& 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<Fi
auto sourceGroup = Project::Item::createGroup (exporter.getProject(), getID(), "__mainsourcegroup" + getID(), false);
auto moduleFromProject = exporter.getModuleFolderRelativeToProject (getID());
auto moduleHeader = moduleInfo.getHeader();
auto moduleHeader = moduleDescription.getHeader();
auto& project = exporter.getProject();


+ 10
- 10
extras/Projucer/Source/Project/Modules/jucer_Modules.h View File

@@ -29,16 +29,16 @@ class LibraryModule
public:
LibraryModule (const ModuleDescription&);
bool isValid() const { return moduleInfo.isValid(); }
String getID() const { return moduleInfo.getID(); }
String getVendor() const { return moduleInfo.getVendor(); }
String getVersion() const { return moduleInfo.getVersion(); }
String getName() const { return moduleInfo.getName(); }
String getDescription() const { return moduleInfo.getDescription(); }
String getLicense() const { return moduleInfo.getLicense(); }
String getMinimumCppStandard() const { return moduleInfo.getMinimumCppStandard(); }
bool isValid() const { return moduleDescription.isValid(); }
String getID() const { return moduleDescription.getID(); }
String getVendor() const { return moduleDescription.getVendor(); }
String getVersion() const { return moduleDescription.getVersion(); }
String getName() const { return moduleDescription.getName(); }
String getDescription() const { return moduleDescription.getDescription(); }
String getLicense() const { return moduleDescription.getLicense(); }
String getMinimumCppStandard() const { return moduleDescription.getMinimumCppStandard(); }
File getFolder() const { return moduleInfo.getFolder(); }
File getFolder() const { return moduleDescription.getFolder(); }
void writeIncludes (ProjectSaver&, OutputStream&);
void addSettingsForModuleToExporter (ProjectExporter&, ProjectSaver&) const;
@@ -61,7 +61,7 @@ public:
build_tools::ProjectType::Target::Type forTarget =
build_tools::ProjectType::Target::unspecified) const;
ModuleDescription moduleInfo;
ModuleDescription moduleDescription;
private:
void addSearchPathsToExporter (ProjectExporter&) const;


+ 4
- 0
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h View File

@@ -1696,6 +1696,9 @@ public:
StringArray linkerFlags, librarySearchPaths;
getLinkerSettings (config, linkerFlags, librarySearchPaths);
for (const auto& weakFramework : owner.xcodeWeakFrameworks)
linkerFlags.add ("-weak_framework " + weakFramework);
if (linkerFlags.size() > 0)
s.set ("OTHER_LDFLAGS", linkerFlags.joinIntoString (" ").quoted());
@@ -2054,6 +2057,7 @@ public:
};
mutable StringArray xcodeFrameworks;
mutable StringArray xcodeWeakFrameworks;
StringArray xcodeLibs;
private:


Loading…
Cancel
Save