diff --git a/BREAKING-CHANGES.txt b/BREAKING-CHANGES.txt index 79c5bfd2c6..9af8dcdcb1 100644 --- a/BREAKING-CHANGES.txt +++ b/BREAKING-CHANGES.txt @@ -1,11 +1,35 @@ JUCE breaking changes ===================== +Develop +======= + +Change +------ +The global user module path setting in the Projucer can now only contain a +single path. + +Possible Issues +--------------- +Projects that previously relied on using multiple global user module paths +separated by a semicolon will fail to find these modules after re-saving. + +Workaround +---------- +Replace the multiple paths with a single global user module path. + +Rationale +--------- +Using multiple global user module paths did not work when saving a project +which exported to different OSes. Only allowing a single path will prevent this +from silently causing issues. + + Version 5.4.2 ============= Change ------ +------ The return type of Block::getBlockAreaWithinLayout() has been changed from Rectangle to a simpler BlockArea struct. @@ -26,7 +50,7 @@ GPL/Commercial licensed juce_graphics module that contains Rectangle. Change ------ +------ Renaming and deletion of open file handles on Windows is now possible using the FILE_SHARE_DELETE flag. @@ -45,7 +69,7 @@ This unifies the behaviour across OSes as POSIX systems already allow this. Change ------ +------ Multiple changes to low-level, non-public JNI and Android APIs. Possible Issues @@ -64,7 +88,7 @@ See the forum for further details. Change ------ +------ The minimum Android version for a JUCE app is now Android 4.1 Possible Issues diff --git a/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h b/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h index a59393ddf4..6c5048c984 100644 --- a/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h +++ b/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h @@ -198,7 +198,7 @@ private: String ("This should be the path to the folder containing the JUCE modules that you wish to use, typically the \"modules\" directory of your JUCE folder.") + (isThisOS ? " Use the button below to re-scan a new path." : "")); builder.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS, {}, {}, true), - String ("A semicolon-separated list of user module paths. These paths will be used to display any non-JUCE modules that are available.") + String ("A path to a folder containing any custom modules that you wish to use.") + (isThisOS ? " Use the button below to re-scan new paths." : "")); builder.add (new LabelPropertyComponent ("SDKs"), {}); diff --git a/extras/Projucer/Source/Application/jucer_Application.cpp b/extras/Projucer/Source/Application/jucer_Application.cpp index 58c185724b..520cf02809 100644 --- a/extras/Projucer/Source/Application/jucer_Application.cpp +++ b/extras/Projucer/Source/Application/jucer_Application.cpp @@ -1490,35 +1490,22 @@ void ProjucerApplication::showSetJUCEPathAlert() } -void ProjucerApplication::rescanJUCEPathModules() +void rescanModules (AvailableModuleList& list, const Array& paths, bool async) { - File jucePath (getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString()); - - if (isRunningCommandLine) - jucePathModuleList.scanPaths ({ jucePath }); + if (async) + list.scanPathsAsync (paths); else - jucePathModuleList.scanPathsAsync ({ jucePath }); + list.scanPaths (paths); } -static Array getSanitisedUserModulePaths() +void ProjucerApplication::rescanJUCEPathModules() { - Array paths; - - for (auto p : StringArray::fromTokens (getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()).get().toString(), ";", {})) - { - p = p.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); - paths.add (File::createFileWithoutCheckingPath (p.trim())); - } - - return paths; + rescanModules (jucePathModuleList, { getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString() }, ! isRunningCommandLine); } void ProjucerApplication::rescanUserPathModules() { - if (isRunningCommandLine) - userPathsModuleList.scanPaths (getSanitisedUserModulePaths()); - else - userPathsModuleList.scanPathsAsync (getSanitisedUserModulePaths()); + rescanModules (userPathsModuleList, { getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()).get().toString() }, ! isRunningCommandLine); } void ProjucerApplication::selectEditorColourSchemeWithName (const String& schemeName) diff --git a/extras/Projucer/Source/Application/jucer_CommandLine.cpp b/extras/Projucer/Source/Application/jucer_CommandLine.cpp index 0ac5ad87fa..591a0b8340 100644 --- a/extras/Projucer/Source/Application/jucer_CommandLine.cpp +++ b/extras/Projucer/Source/Application/jucer_CommandLine.cpp @@ -694,13 +694,6 @@ namespace || id == "androidSDKPath" || id == "androidNDKPath" || id == "defaultJuceModulePath" || id == "defaultUserModulePath"; } - static void checkIfUserModulesPathsAreValid (const String& list) - { - for (auto& p : StringArray::fromTokens (list, ";", {})) - if (! File (p.trim()).exists()) - ConsoleApplication::fail (p + " doesn't exist!"); - } - static void setGlobalPath (const ArgumentList& args) { args.checkMinNumArguments (3); @@ -742,19 +735,7 @@ namespace if (! childToSet.isValid()) ConsoleApplication::fail ("Failed to set the requested setting!"); - if (args[2].text == Ids::defaultUserModulePath.toString()) - { - auto pathList = args[3].text.removeCharacters ("\""); - - if (isThisOS (args[1].text)) - checkIfUserModulesPathsAreValid (pathList); - - childToSet.setProperty (args[2].text, pathList, nullptr); - } - else - { - childToSet.setProperty (args[2].text, args[3].resolveAsFile().getFullPathName(), nullptr); - } + childToSet.setProperty (args[2].text, args[3].resolveAsFile().getFullPathName(), nullptr); settingsFile.replaceWithText (settingsTree.toXmlString()); } @@ -776,8 +757,7 @@ namespace std::cout << "Creating directory " << outputDir.getFullPathName() << std::endl; } - File juceModulesPath; - Array userModulesPaths; + File juceModulesPath, userModulesPath; if (args.size() > 3) { @@ -788,15 +768,14 @@ namespace if (args.size() == 5) { - auto pathList = args[4].text.removeCharacters ("\""); - checkIfUserModulesPathsAreValid (pathList); + userModulesPath = args[4].resolveAsFile(); - for (auto& p : StringArray::fromTokens (pathList, ";", {})) - userModulesPaths.add ({ p }); + if (! userModulesPath.exists()) + ConsoleApplication::fail ("Specified JUCE modules directory doesn't exist."); } } - PIPGenerator generator (pipFile, outputDir, juceModulesPath, userModulesPaths); + PIPGenerator generator (pipFile, outputDir, juceModulesPath, userModulesPath); auto createJucerFileResult = generator.createJucerFile(); @@ -873,12 +852,11 @@ namespace << std::endl << " " << appName << " --set-global-search-path os identifier_to_set new_path" << std::endl << " Sets the global path for a specified os and identifier. The os should be either osx, windows or linux and the identifiers can be any of the following: " - << "defaultJuceModulePath, defaultUserModulePath, vst3Path, vstLegacyPath, aaxPath (not valid on linux), rtasPath (not valid on linux), androidSDKPath or androidNDKPath. " - "When setting defaultUserModulePath you can specify multiple paths by surrounding a semicolon-separated list of paths with double quotes \"like;so\"" << std::endl + << "defaultJuceModulePath, defaultUserModulePath, vst3Path, vstLegacyPath, aaxPath (not valid on linux), rtasPath (not valid on linux), androidSDKPath or androidNDKPath. " << std::endl << std::endl << " " << appName << " --create-project-from-pip path/to/PIP path/to/output path/to/JUCE/modules (optional) path/to/user/modules (optional)" << std::endl << " Generates a folder containing a JUCE project in the specified output path using the specified PIP file. Use the optional JUCE and user module paths to override " - "the global module paths (you can specify multiple user module paths by using a semicolon-separated list)." << std::endl + "the global module paths." << std::endl << std::endl << "Note that for any of the file-rewriting commands, add the option \"--lf\" if you want it to use LF linefeeds instead of CRLF" << std::endl << std::endl; diff --git a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp index 693b8537ca..9566e52a6a 100644 --- a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp +++ b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp @@ -99,10 +99,10 @@ static bool exporterRequiresExampleAssets (const String& exporterName, const Str } //============================================================================== -PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& jucePath, const Array& userPaths) +PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& jucePath, const File& userPath) : pipFile (pip), juceModulesPath (jucePath), - userModulesPaths (userPaths), + userModulesPath (userPath), metadata (parseJUCEHeaderMetadata (pipFile)) { if (output != File()) @@ -122,10 +122,10 @@ PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& juc outputDirectory = outputDirectory.getChildFile (metadata[Ids::name].toString()); useLocalCopy = metadata[Ids::useLocalCopy].toString().isNotEmpty() || isClipboard; - if (! userModulesPaths.isEmpty()) + if (userModulesPath != File()) { availableUserModules.reset (new AvailableModuleList()); - availableUserModules->scanPaths (userModulesPaths); + availableUserModules->scanPaths ({ userModulesPath }); } } diff --git a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h index f28337e2c0..dcd99d9461 100644 --- a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h +++ b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h @@ -33,7 +33,7 @@ class PIPGenerator { public: PIPGenerator (const File& pipFile, const File& outputDirectory = {}, - const File& pathToJUCEModules = {}, const Array& pathsToUserModules = {}); + const File& pathToJUCEModules = {}, const File& pathToUserModules = {}); //============================================================================== bool hasValidPIP() const noexcept { return ! metadata[Ids::name].toString().isEmpty(); } @@ -78,9 +78,8 @@ private: File getExamplesDirectory() const; //============================================================================== - File pipFile, outputDirectory, juceModulesPath; + File pipFile, outputDirectory, juceModulesPath, userModulesPath; - Array userModulesPaths; std::unique_ptr availableUserModules; var metadata;