| @@ -659,6 +659,13 @@ namespace | |||||
| || id == "androidSDKPath" || id == "androidNDKPath" || id == "defaultJuceModulePath" || id == "defaultUserModulePath"; | || 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) | static void setGlobalPath (const ArgumentList& args) | ||||
| { | { | ||||
| args.checkMinNumArguments (3); | args.checkMinNumArguments (3); | ||||
| @@ -697,9 +704,16 @@ namespace | |||||
| ConsoleApplication::fail ("Failed to set the requested setting!"); | ConsoleApplication::fail ("Failed to set the requested setting!"); | ||||
| if (args[2].text == Ids::defaultUserModulePath.toString()) | if (args[2].text == Ids::defaultUserModulePath.toString()) | ||||
| childToSet.setProperty (args[2].text, args[3].text.removeCharacters ("\""), nullptr); | |||||
| { | |||||
| auto pathList = args[3].text.removeCharacters ("\""); | |||||
| checkIfUserModulesPathsAreValid (pathList); | |||||
| childToSet.setProperty (args[2].text, pathList, nullptr); | |||||
| } | |||||
| else | 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()); | settingsFile.replaceWithText (settingsTree.toXmlString()); | ||||
| } | } | ||||
| @@ -721,17 +735,27 @@ namespace | |||||
| std::cout << "Creating directory " << outputDir.getFullPathName() << std::endl; | std::cout << "Creating directory " << outputDir.getFullPathName() << std::endl; | ||||
| } | } | ||||
| File juceDir; | |||||
| File juceModulesPath; | |||||
| Array<File> userModulesPaths; | |||||
| if (args.size() > 3) | if (args.size() > 3) | ||||
| { | { | ||||
| juceDir = args[3].resolveAsFile(); | |||||
| juceModulesPath = args[3].resolveAsFile(); | |||||
| if (! juceDir.exists()) | |||||
| if (! juceModulesPath.exists()) | |||||
| ConsoleApplication::fail ("Specified JUCE modules directory doesn't exist."); | ConsoleApplication::fail ("Specified JUCE modules directory doesn't exist."); | ||||
| if (args.size() == 5) | |||||
| { | |||||
| auto pathList = args[4].text.removeCharacters ("\""); | |||||
| checkIfUserModulesPathsAreValid (pathList); | |||||
| for (auto& p : StringArray::fromTokens (pathList, ";", {})) | |||||
| userModulesPaths.add ({ p }); | |||||
| } | |||||
| } | } | ||||
| PIPGenerator generator (pipFile, outputDir, juceDir); | |||||
| PIPGenerator generator (pipFile, outputDir, juceModulesPath, userModulesPaths); | |||||
| auto createJucerFileResult = generator.createJucerFile(); | auto createJucerFileResult = generator.createJucerFile(); | ||||
| @@ -811,8 +835,9 @@ namespace | |||||
| << "defaultJuceModulePath, defaultUserModulePath, vst3Path, aaxPath (not valid on linux), rtasPath (not valid on linux), androidSDKPath or androidNDKPath. " | << "defaultJuceModulePath, defaultUserModulePath, vst3Path, 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 | "When setting defaultUserModulePath you can specify multiple paths by surrounding a semicolon-separated list of paths with double quotes \"like;so\"" << std::endl | ||||
| << std::endl | << std::endl | ||||
| << " " << appName << " --create-project-from-pip path/to/PIP path/to/output path/to/JUCE/modules (optional)" << std::endl | |||||
| << " Generates a JUCE project from a PIP file." << 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 | |||||
| << 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 | << "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; | << std::endl; | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "../../Application/jucer_Headers.h" | #include "../../Application/jucer_Headers.h" | ||||
| #include "../../ProjectSaving/jucer_ProjectExporter.h" | #include "../../ProjectSaving/jucer_ProjectExporter.h" | ||||
| #include "jucer_PIPGenerator.h" | #include "jucer_PIPGenerator.h" | ||||
| #include "../../Project/jucer_Module.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| static String removeEnclosed (const String& input, const String& start, const String& end) | static String removeEnclosed (const String& input, const String& start, const String& end) | ||||
| @@ -97,9 +98,10 @@ static bool isMobileExporter (const String& exporterName) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& juceDir) | |||||
| PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& jucePath, const Array<File>& userPaths) | |||||
| : pipFile (pip), | : pipFile (pip), | ||||
| juceDirectory (juceDir), | |||||
| juceModulesPath (jucePath), | |||||
| userModulesPaths (userPaths), | |||||
| metadata (parsePIPMetadata()) | metadata (parsePIPMetadata()) | ||||
| { | { | ||||
| if (output != File()) | if (output != File()) | ||||
| @@ -118,6 +120,12 @@ PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& juc | |||||
| outputDirectory = outputDirectory.getChildFile (metadata[Ids::name].toString()); | outputDirectory = outputDirectory.getChildFile (metadata[Ids::name].toString()); | ||||
| useLocalCopy = metadata[Ids::useLocalCopy].toString().isNotEmpty() || isClipboard; | useLocalCopy = metadata[Ids::useLocalCopy].toString().isNotEmpty() || isClipboard; | ||||
| if (! userModulesPaths.isEmpty()) | |||||
| { | |||||
| availableUserModules.reset (new AvailableModuleList()); | |||||
| availableUserModules->scanPaths (userModulesPaths); | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -291,7 +299,7 @@ ValueTree PIPGenerator::createModulePathChild (const String& moduleID) | |||||
| ValueTree modulePath (Ids::MODULEPATH); | ValueTree modulePath (Ids::MODULEPATH); | ||||
| modulePath.setProperty (Ids::ID, moduleID, nullptr); | modulePath.setProperty (Ids::ID, moduleID, nullptr); | ||||
| modulePath.setProperty (Ids::path, juceDirectory.getFullPathName(), nullptr); | |||||
| modulePath.setProperty (Ids::path, getPathForModule (moduleID).getFullPathName(), nullptr); | |||||
| return modulePath; | return modulePath; | ||||
| } | } | ||||
| @@ -348,12 +356,7 @@ ValueTree PIPGenerator::createExporterChild (const String& exporterName) | |||||
| auto modules = StringArray::fromTokens (metadata[Ids::dependencies_].toString(), ",", {}); | auto modules = StringArray::fromTokens (metadata[Ids::dependencies_].toString(), ",", {}); | ||||
| for (auto m : modules) | for (auto m : modules) | ||||
| { | |||||
| m = m.trim(); | |||||
| if (isJUCEModule (m)) | |||||
| modulePaths.addChild (createModulePathChild (m), -1, nullptr); | |||||
| } | |||||
| modulePaths.addChild (createModulePathChild (m.trim()), -1, nullptr); | |||||
| exporter.addChild (modulePaths, -1, nullptr); | exporter.addChild (modulePaths, -1, nullptr); | ||||
| } | } | ||||
| @@ -368,7 +371,7 @@ ValueTree PIPGenerator::createModuleChild (const String& moduleID) | |||||
| module.setProperty (Ids::ID, moduleID, nullptr); | module.setProperty (Ids::ID, moduleID, nullptr); | ||||
| module.setProperty (Ids::showAllCode, 1, nullptr); | module.setProperty (Ids::showAllCode, 1, nullptr); | ||||
| module.setProperty (Ids::useLocalCopy, 0, nullptr); | module.setProperty (Ids::useLocalCopy, 0, nullptr); | ||||
| module.setProperty (Ids::useGlobalPath, (juceDirectory == File() ? 1 : 0), nullptr); | |||||
| module.setProperty (Ids::useGlobalPath, (getPathForModule (moduleID) == File() ? 1 : 0), nullptr); | |||||
| return module; | return module; | ||||
| } | } | ||||
| @@ -407,12 +410,7 @@ void PIPGenerator::addModules (ValueTree& jucerTree) | |||||
| modules.mergeArray (getModulesRequiredForAudioProcessor()); | modules.mergeArray (getModulesRequiredForAudioProcessor()); | ||||
| for (auto& m : modules) | for (auto& m : modules) | ||||
| { | |||||
| m = m.trim(); | |||||
| if (isJUCEModule (m)) | |||||
| modulesTree.addChild (createModuleChild (m), -1, nullptr); | |||||
| } | |||||
| modulesTree.addChild (createModuleChild (m.trim()), -1, nullptr); | |||||
| jucerTree.addChild (modulesTree, -1, nullptr); | jucerTree.addChild (modulesTree, -1, nullptr); | ||||
| } | } | ||||
| @@ -597,3 +595,18 @@ StringArray PIPGenerator::getPluginCharacteristics() const | |||||
| return {}; | return {}; | ||||
| } | } | ||||
| File PIPGenerator::getPathForModule (const String& moduleID) const | |||||
| { | |||||
| if (isJUCEModule (moduleID)) | |||||
| { | |||||
| if (juceModulesPath != File()) | |||||
| return juceModulesPath; | |||||
| } | |||||
| else if (availableUserModules != nullptr) | |||||
| { | |||||
| return availableUserModules->getModuleWithID (moduleID).second.getParentDirectory(); | |||||
| } | |||||
| return {}; | |||||
| } | |||||
| @@ -32,7 +32,8 @@ | |||||
| class PIPGenerator | class PIPGenerator | ||||
| { | { | ||||
| public: | public: | ||||
| PIPGenerator (const File& pipFile, const File& outputDirectory = {}, const File& juceDirectory = {}); | |||||
| PIPGenerator (const File& pipFile, const File& outputDirectory = {}, | |||||
| const File& pathToJUCEModules = {}, const Array<File>& pathsToUserModules = {}); | |||||
| //============================================================================== | //============================================================================== | ||||
| bool hasValidPIP() const noexcept { return ! metadata[Ids::name].toString().isEmpty(); } | bool hasValidPIP() const noexcept { return ! metadata[Ids::name].toString().isEmpty(); } | ||||
| @@ -77,8 +78,14 @@ private: | |||||
| StringArray getExtraPluginFormatsToBuild() const; | StringArray getExtraPluginFormatsToBuild() const; | ||||
| StringArray getPluginCharacteristics() const; | StringArray getPluginCharacteristics() const; | ||||
| File getPathForModule (const String&) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| File pipFile, outputDirectory, juceDirectory; | |||||
| File pipFile, outputDirectory, juceModulesPath; | |||||
| Array<File> userModulesPaths; | |||||
| std::unique_ptr<AvailableModuleList> availableUserModules; | |||||
| var metadata; | var metadata; | ||||
| bool isTemp = false; | bool isTemp = false; | ||||