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.

302 lines
11KB

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