The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #include "../Project/jucer_Project.h"
  18. #include "../Project/jucer_Module.h"
  19. #include "jucer_CommandLine.h"
  20. //==============================================================================
  21. namespace
  22. {
  23. void hideDockIcon()
  24. {
  25. #if JUCE_MAC
  26. Process::setDockIconVisible (false);
  27. #endif
  28. }
  29. File getFile (const String& filename)
  30. {
  31. return File::getCurrentWorkingDirectory().getChildFile (filename.unquoted());
  32. }
  33. bool checkArgumentCount (const StringArray& args, int minNumArgs)
  34. {
  35. if (args.size() < minNumArgs)
  36. {
  37. std::cout << "Not enough arguments!" << std::endl;
  38. return false;
  39. }
  40. return true;
  41. }
  42. //==============================================================================
  43. /* Running a command-line of the form "introjucer --resave foobar.jucer" will try to load
  44. that project and re-export all of its targets.
  45. */
  46. int resaveProject (const StringArray& args, bool justSaveResources)
  47. {
  48. hideDockIcon();
  49. if (! checkArgumentCount (args, 2))
  50. return 1;
  51. const File projectFile (getFile (args[1]));
  52. if (! projectFile.exists())
  53. {
  54. std::cout << "The file " << projectFile.getFullPathName() << " doesn't exist!" << std::endl;
  55. return 1;
  56. }
  57. if (! projectFile.hasFileExtension (Project::projectFileExtension))
  58. {
  59. std::cout << projectFile.getFullPathName() << " isn't a valid jucer project file!" << std::endl;
  60. return 1;
  61. }
  62. Project proj (projectFile);
  63. if (! proj.loadFrom (projectFile, true))
  64. {
  65. std::cout << "Failed to load the project file: " << projectFile.getFullPathName() << std::endl;
  66. return 1;
  67. }
  68. std::cout << (justSaveResources ? "The Introjucer - Re-saving project resources: "
  69. : "The Introjucer - Re-saving file: ")
  70. << projectFile.getFullPathName() << std::endl;
  71. Result error (justSaveResources ? proj.saveResourcesOnly (projectFile)
  72. : proj.saveProject (projectFile, true));
  73. if (error.failed())
  74. {
  75. std::cout << "Error when saving: " << error.getErrorMessage() << std::endl;
  76. return 1;
  77. }
  78. return 0;
  79. }
  80. //==============================================================================
  81. String getModulePackageName (const LibraryModule& module)
  82. {
  83. return module.getID() + ".jucemodule";
  84. }
  85. int zipModule (const File& targetFolder, const File& moduleFolder)
  86. {
  87. jassert (targetFolder.isDirectory());
  88. const File moduleFolderParent (moduleFolder.getParentDirectory());
  89. LibraryModule module (moduleFolder.getChildFile (ModuleDescription::getManifestFileName()));
  90. if (! module.isValid())
  91. {
  92. std::cout << moduleFolder.getFullPathName() << " is not a valid module folder!" << std::endl;
  93. return 1;
  94. }
  95. const File targetFile (targetFolder.getChildFile (getModulePackageName (module)));
  96. ZipFile::Builder zip;
  97. {
  98. DirectoryIterator i (moduleFolder, true, "*", File::findFiles);
  99. while (i.next())
  100. if (! i.getFile().isHidden())
  101. zip.addFile (i.getFile(), 9, i.getFile().getRelativePathFrom (moduleFolderParent));
  102. }
  103. std::cout << "Writing: " << targetFile.getFullPathName() << std::endl;
  104. TemporaryFile temp (targetFile);
  105. ScopedPointer<FileOutputStream> out (temp.getFile().createOutputStream());
  106. bool ok = out != nullptr && zip.writeToStream (*out, nullptr);
  107. out = nullptr;
  108. ok = ok && temp.overwriteTargetFileWithTemporary();
  109. if (! ok)
  110. {
  111. std::cout << "Failed to write to the target file: " << targetFile.getFullPathName() << std::endl;
  112. return 1;
  113. }
  114. return 0;
  115. }
  116. int buildModules (const StringArray& args, const bool buildAllWithIndex)
  117. {
  118. hideDockIcon();
  119. if (! checkArgumentCount (args, 3))
  120. return 1;
  121. const File targetFolder (getFile (args[1]));
  122. if (! targetFolder.isDirectory())
  123. {
  124. std::cout << "The first argument must be the directory to put the result." << std::endl;
  125. return 1;
  126. }
  127. if (buildAllWithIndex)
  128. {
  129. const File folderToSearch (getFile (args[2]));
  130. DirectoryIterator i (folderToSearch, false, "*", File::findDirectories);
  131. var infoList;
  132. while (i.next())
  133. {
  134. LibraryModule module (i.getFile().getChildFile (ModuleDescription::getManifestFileName()));
  135. if (module.isValid())
  136. {
  137. const int result = zipModule (targetFolder, i.getFile());
  138. if (result != 0)
  139. return result;
  140. var moduleInfo (new DynamicObject());
  141. moduleInfo.getDynamicObject()->setProperty ("file", getModulePackageName (module));
  142. moduleInfo.getDynamicObject()->setProperty ("info", module.moduleInfo.moduleInfo);
  143. infoList.append (moduleInfo);
  144. }
  145. }
  146. const File indexFile (targetFolder.getChildFile ("modulelist"));
  147. std::cout << "Writing: " << indexFile.getFullPathName() << std::endl;
  148. indexFile.replaceWithText (JSON::toString (infoList), false, false);
  149. }
  150. else
  151. {
  152. for (int i = 2; i < args.size(); ++i)
  153. {
  154. const int result = zipModule (targetFolder, getFile (args[i]));
  155. if (result != 0)
  156. return result;
  157. }
  158. }
  159. return 0;
  160. }
  161. int showStatus (const StringArray& args)
  162. {
  163. hideDockIcon();
  164. if (! checkArgumentCount (args, 2))
  165. return 1;
  166. const File projectFile (getFile (args[1]));
  167. Project proj (projectFile);
  168. const Result result (proj.loadDocument (projectFile));
  169. if (result.failed())
  170. {
  171. std::cout << "Failed to load project: " << projectFile.getFullPathName() << std::endl;
  172. return 1;
  173. }
  174. std::cout << "Project file: " << projectFile.getFullPathName() << std::endl
  175. << "Name: " << proj.getTitle() << std::endl
  176. << "UID: " << proj.getProjectUID() << std::endl;
  177. EnabledModuleList& modules = proj.getModules();
  178. const int numModules = modules.getNumModules();
  179. if (numModules > 0)
  180. {
  181. std::cout << "Modules:" << std::endl;
  182. for (int i = 0; i < numModules; ++i)
  183. std::cout << " " << modules.getModuleID (i) << std::endl;
  184. }
  185. return 0;
  186. }
  187. bool matchArgument (const String& arg, const String& possible)
  188. {
  189. return arg == possible
  190. || arg == "-" + possible
  191. || arg == "--" + possible;
  192. }
  193. //==============================================================================
  194. int showHelp()
  195. {
  196. hideDockIcon();
  197. std::cout << "The Introjucer!" << std::endl
  198. << std::endl
  199. << "Usage: " << std::endl
  200. << std::endl
  201. << " introjucer --resave project_file" << std::endl
  202. << " Resaves all files and resources in a project." << std::endl
  203. << std::endl
  204. << " introjucer --resave-resources project_file" << std::endl
  205. << " Resaves just the binary resources for a project." << std::endl
  206. << std::endl
  207. << " introjucer --status project_file" << std::endl
  208. << " Displays information about a project." << std::endl
  209. << std::endl
  210. << " introjucer --buildmodule target_folder module_folder" << std::endl
  211. << " Zips a module into a downloadable file format." << std::endl
  212. << std::endl
  213. << " introjucer --buildallmodules target_folder module_folder" << std::endl
  214. << " Zips all modules in a given folder and creates an index for them." << std::endl
  215. << std::endl;
  216. return 0;
  217. }
  218. }
  219. //==============================================================================
  220. int performCommandLine (const String& commandLine)
  221. {
  222. StringArray args;
  223. args.addTokens (commandLine, true);
  224. args.trim();
  225. if (matchArgument (args[0], "help")) return showHelp();
  226. if (matchArgument (args[0], "resave")) return resaveProject (args, false);
  227. if (matchArgument (args[0], "resave-resources")) return resaveProject (args, true);
  228. if (matchArgument (args[0], "buildmodule")) return buildModules (args, false);
  229. if (matchArgument (args[0], "buildallmodules")) return buildModules (args, true);
  230. if (matchArgument (args[0], "status")) return showStatus (args);
  231. return commandLineNotPerformed;
  232. }