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.

423 lines
19KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #pragma once
  19. #include "../Project/jucer_Project.h"
  20. #include "../Utility/UI/PropertyComponents/jucer_PropertyComponentsWithEnablement.h"
  21. #include "../Utility/Helpers/jucer_ValueWithDefaultWrapper.h"
  22. #include "../Project/Modules/jucer_Modules.h"
  23. class ProjectSaver;
  24. //==============================================================================
  25. class ProjectExporter : private Value::Listener
  26. {
  27. public:
  28. ProjectExporter (Project&, const ValueTree& settings);
  29. virtual ~ProjectExporter() override = default;
  30. //==============================================================================
  31. struct ExporterTypeInfo
  32. {
  33. Identifier identifier;
  34. String displayName;
  35. String targetFolder;
  36. Image icon;
  37. };
  38. static std::vector<ExporterTypeInfo> getExporterTypeInfos();
  39. static ExporterTypeInfo getTypeInfoForExporter (const Identifier& exporterIdentifier);
  40. static ExporterTypeInfo getCurrentPlatformExporterTypeInfo();
  41. static std::unique_ptr<ProjectExporter> createNewExporter (Project&, const Identifier& exporterIdentifier);
  42. static std::unique_ptr<ProjectExporter> createExporterFromSettings (Project&, const ValueTree& settings);
  43. static bool canProjectBeLaunched (Project*);
  44. //==============================================================================
  45. // capabilities of exporter
  46. virtual bool usesMMFiles() const = 0;
  47. virtual void createExporterProperties (PropertyListBuilder&) = 0;
  48. virtual bool canLaunchProject() = 0;
  49. virtual bool launchProject() = 0;
  50. virtual void create (const OwnedArray<LibraryModule>&) const = 0; // may throw a SaveError
  51. virtual bool shouldFileBeCompiledByDefault (const File& path) const;
  52. virtual bool canCopeWithDuplicateFiles() = 0;
  53. virtual bool supportsUserDefinedConfigurations() const = 0; // false if exporter only supports two configs Debug and Release
  54. virtual void updateDeprecatedSettings() {}
  55. virtual void updateDeprecatedSettingsInteractively() {}
  56. virtual void initialiseDependencyPathValues() {}
  57. // IDE targeted by exporter
  58. virtual bool isXcode() const = 0;
  59. virtual bool isVisualStudio() const = 0;
  60. virtual bool isCodeBlocks() const = 0;
  61. virtual bool isMakefile() const = 0;
  62. virtual bool isAndroidStudio() const = 0;
  63. virtual bool isCLion() const = 0;
  64. // operating system targeted by exporter
  65. virtual bool isAndroid() const = 0;
  66. virtual bool isWindows() const = 0;
  67. virtual bool isLinux() const = 0;
  68. virtual bool isOSX() const = 0;
  69. virtual bool isiOS() const = 0;
  70. virtual String getDescription() { return {}; }
  71. //==============================================================================
  72. // cross-platform audio plug-ins supported by exporter
  73. virtual bool supportsTargetType (build_tools::ProjectType::Target::Type type) const = 0;
  74. inline bool shouldBuildTargetType (build_tools::ProjectType::Target::Type type) const
  75. {
  76. return project.shouldBuildTargetType (type) && supportsTargetType (type);
  77. }
  78. inline void callForAllSupportedTargets (std::function<void (build_tools::ProjectType::Target::Type)> callback)
  79. {
  80. for (int i = 0; i < build_tools::ProjectType::Target::unspecified; ++i)
  81. if (shouldBuildTargetType (static_cast<build_tools::ProjectType::Target::Type> (i)))
  82. callback (static_cast<build_tools::ProjectType::Target::Type> (i));
  83. }
  84. //==============================================================================
  85. bool mayCompileOnCurrentOS() const
  86. {
  87. #if JUCE_MAC
  88. return isOSX() || isAndroid() || isiOS();
  89. #elif JUCE_WINDOWS
  90. return isWindows() || isAndroid();
  91. #elif JUCE_LINUX
  92. return isLinux() || isAndroid();
  93. #else
  94. #error
  95. #endif
  96. }
  97. //==============================================================================
  98. String getUniqueName() const;
  99. File getTargetFolder() const;
  100. Project& getProject() noexcept { return project; }
  101. const Project& getProject() const noexcept { return project; }
  102. UndoManager* getUndoManager() const { return project.getUndoManagerFor (settings); }
  103. Value getSetting (const Identifier& nm) { return settings.getPropertyAsValue (nm, project.getUndoManagerFor (settings)); }
  104. String getSettingString (const Identifier& nm) const { return settings [nm]; }
  105. Value getTargetLocationValue() { return targetLocationValue.getPropertyAsValue(); }
  106. String getTargetLocationString() const { return targetLocationValue.get(); }
  107. String getExtraCompilerFlagsString() const { return extraCompilerFlagsValue.get().toString().replaceCharacters ("\r\n", " "); }
  108. String getExtraLinkerFlagsString() const { return extraLinkerFlagsValue.get().toString().replaceCharacters ("\r\n", " "); }
  109. String getExternalLibrariesString() const { return getSearchPathsFromString (externalLibrariesValue.get().toString()).joinIntoString (";"); }
  110. bool shouldUseGNUExtensions() const { return gnuExtensionsValue.get(); }
  111. String getVSTLegacyPathString() const { return vstLegacyPathValueWrapper.getCurrentValue(); }
  112. String getAAXPathString() const { return aaxPathValueWrapper.getCurrentValue(); }
  113. String getRTASPathString() const { return rtasPathValueWrapper.getCurrentValue(); }
  114. // NB: this is the path to the parent "modules" folder that contains the named module, not the
  115. // module folder itself.
  116. ValueWithDefault getPathForModuleValue (const String& moduleID);
  117. String getPathForModuleString (const String& moduleID) const;
  118. void removePathForModule (const String& moduleID);
  119. TargetOS::OS getTargetOSForExporter() const;
  120. build_tools::RelativePath getLegacyModulePath (const String& moduleID) const;
  121. String getLegacyModulePath() const;
  122. // Returns a path to the actual module folder itself
  123. build_tools::RelativePath getModuleFolderRelativeToProject (const String& moduleID) const;
  124. void updateOldModulePaths();
  125. build_tools::RelativePath rebaseFromProjectFolderToBuildTarget (const build_tools::RelativePath& path) const;
  126. void addToExtraSearchPaths (const build_tools::RelativePath& pathFromProjectFolder, int index = -1);
  127. void addToModuleLibPaths (const build_tools::RelativePath& pathFromProjectFolder);
  128. void addProjectPathToBuildPathList (StringArray&, const build_tools::RelativePath&, int index = -1) const;
  129. std::unique_ptr<Drawable> getBigIcon() const;
  130. std::unique_ptr<Drawable> getSmallIcon() const;
  131. build_tools::Icons getIcons() const { return { getSmallIcon(), getBigIcon() }; }
  132. String getExporterIdentifierMacro() const
  133. {
  134. return "JUCER_" + settings.getType().toString() + "_"
  135. + String::toHexString (getTargetLocationString().hashCode()).toUpperCase();
  136. }
  137. // An exception that can be thrown by the create() method.
  138. void createPropertyEditors (PropertyListBuilder&);
  139. void addSettingsForProjectType (const build_tools::ProjectType&);
  140. //==============================================================================
  141. void copyMainGroupFromProject();
  142. Array<Project::Item>& getAllGroups() noexcept { jassert (itemGroups.size() > 0); return itemGroups; }
  143. const Array<Project::Item>& getAllGroups() const noexcept { jassert (itemGroups.size() > 0); return itemGroups; }
  144. Project::Item& getModulesGroup();
  145. //==============================================================================
  146. StringArray linuxLibs, linuxPackages, makefileExtraLinkerFlags;
  147. //==============================================================================
  148. StringPairArray msvcExtraPreprocessorDefs;
  149. String msvcDelayLoadedDLLs;
  150. StringArray mingwLibs, windowsLibs;
  151. //==============================================================================
  152. StringArray androidLibs;
  153. //==============================================================================
  154. StringArray extraSearchPaths;
  155. StringArray moduleLibSearchPaths;
  156. //==============================================================================
  157. class BuildConfiguration : public ReferenceCountedObject
  158. {
  159. public:
  160. BuildConfiguration (Project& project, const ValueTree& configNode, const ProjectExporter&);
  161. ~BuildConfiguration();
  162. using Ptr = ReferenceCountedObjectPtr<BuildConfiguration>;
  163. //==============================================================================
  164. virtual void createConfigProperties (PropertyListBuilder&) = 0;
  165. virtual String getModuleLibraryArchName() const = 0;
  166. //==============================================================================
  167. String getName() const { return configNameValue.get(); }
  168. bool isDebug() const { return isDebugValue.get(); }
  169. String getTargetBinaryRelativePathString() const { return targetBinaryPathValue.get(); }
  170. String getTargetBinaryNameString (bool isUnityPlugin = false) const
  171. {
  172. return (isUnityPlugin ? Project::addUnityPluginPrefixIfNecessary (targetNameValue.get().toString())
  173. : targetNameValue.get().toString());
  174. }
  175. int getOptimisationLevelInt() const { return optimisationLevelValue.get(); }
  176. String getGCCOptimisationFlag() const;
  177. bool isLinkTimeOptimisationEnabled() const { return linkTimeOptimisationValue.get(); }
  178. String getBuildConfigPreprocessorDefsString() const { return ppDefinesValue.get(); }
  179. StringPairArray getAllPreprocessorDefs() const; // includes inherited definitions
  180. StringPairArray getUniquePreprocessorDefs() const; // returns pre-processor definitions that are not already in the project pre-processor defs
  181. String getHeaderSearchPathString() const { return headerSearchPathValue.get(); }
  182. StringArray getHeaderSearchPaths() const;
  183. String getLibrarySearchPathString() const { return librarySearchPathValue.get(); }
  184. StringArray getLibrarySearchPaths() const;
  185. String getGCCLibraryPathFlags() const;
  186. //==============================================================================
  187. Value getValue (const Identifier& nm) { return config.getPropertyAsValue (nm, getUndoManager()); }
  188. UndoManager* getUndoManager() const { return project.getUndoManagerFor (config); }
  189. //==============================================================================
  190. void createPropertyEditors (PropertyListBuilder&);
  191. void addRecommendedLinuxCompilerWarningsProperty (PropertyListBuilder&);
  192. void addRecommendedLLVMCompilerWarningsProperty (PropertyListBuilder&);
  193. StringArray getRecommendedCompilerWarningFlags() const;
  194. void addGCCOptimisationProperty (PropertyListBuilder&);
  195. void removeFromExporter();
  196. //==============================================================================
  197. ValueTree config;
  198. Project& project;
  199. const ProjectExporter& exporter;
  200. protected:
  201. ValueWithDefault isDebugValue, configNameValue, targetNameValue, targetBinaryPathValue, recommendedWarningsValue, optimisationLevelValue,
  202. linkTimeOptimisationValue, ppDefinesValue, headerSearchPathValue, librarySearchPathValue, userNotesValue;
  203. private:
  204. std::map<String, StringArray> recommendedCompilerWarningFlags;
  205. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BuildConfiguration)
  206. };
  207. void addNewConfigurationFromExisting (const BuildConfiguration& configToCopy);
  208. void addNewConfiguration (bool isDebugConfig);
  209. bool hasConfigurationNamed (const String& name) const;
  210. String getUniqueConfigName (String name) const;
  211. String getExternalLibraryFlags (const BuildConfiguration& config) const;
  212. //==============================================================================
  213. struct ConfigIterator
  214. {
  215. ConfigIterator (ProjectExporter& exporter);
  216. bool next();
  217. BuildConfiguration& operator*() const { return *config; }
  218. BuildConfiguration* operator->() const { return config.get(); }
  219. BuildConfiguration::Ptr config;
  220. int index;
  221. private:
  222. ProjectExporter& exporter;
  223. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConfigIterator)
  224. };
  225. struct ConstConfigIterator
  226. {
  227. ConstConfigIterator (const ProjectExporter& exporter);
  228. bool next();
  229. const BuildConfiguration& operator*() const { return *config; }
  230. const BuildConfiguration* operator->() const { return config.get(); }
  231. BuildConfiguration::Ptr config;
  232. int index;
  233. private:
  234. const ProjectExporter& exporter;
  235. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConstConfigIterator)
  236. };
  237. int getNumConfigurations() const;
  238. BuildConfiguration::Ptr getConfiguration (int index) const;
  239. ValueTree getConfigurations() const;
  240. virtual void createDefaultConfigs();
  241. void createDefaultModulePaths();
  242. //==============================================================================
  243. Value getExporterPreprocessorDefsValue() { return extraPPDefsValue.getPropertyAsValue(); }
  244. String getExporterPreprocessorDefsString() const { return extraPPDefsValue.get(); }
  245. // includes exporter, project + config defs
  246. StringPairArray getAllPreprocessorDefs (const BuildConfiguration& config, const build_tools::ProjectType::Target::Type targetType) const;
  247. // includes exporter + project defs
  248. StringPairArray getAllPreprocessorDefs() const;
  249. void addTargetSpecificPreprocessorDefs (StringPairArray& defs, const build_tools::ProjectType::Target::Type targetType) const;
  250. String replacePreprocessorTokens (const BuildConfiguration&, const String& sourceString) const;
  251. ValueTree settings;
  252. enum GCCOptimisationLevel
  253. {
  254. gccO0 = 1,
  255. gccO1 = 4,
  256. gccO2 = 5,
  257. gccO3 = 3,
  258. gccOs = 2,
  259. gccOfast = 6
  260. };
  261. protected:
  262. //==============================================================================
  263. String name;
  264. Project& project;
  265. const build_tools::ProjectType& projectType;
  266. const String projectName;
  267. const File projectFolder;
  268. //==============================================================================
  269. ValueWithDefaultWrapper vstLegacyPathValueWrapper, rtasPathValueWrapper, aaxPathValueWrapper;
  270. ValueWithDefault targetLocationValue, extraCompilerFlagsValue, extraLinkerFlagsValue, externalLibrariesValue,
  271. userNotesValue, gnuExtensionsValue, bigIconValue, smallIconValue, extraPPDefsValue;
  272. Value projectCompilerFlagSchemesValue;
  273. HashMap<String, ValueWithDefault> compilerFlagSchemesMap;
  274. mutable Array<Project::Item> itemGroups;
  275. Project::Item* modulesGroup = nullptr;
  276. virtual BuildConfiguration::Ptr createBuildConfig (const ValueTree&) const = 0;
  277. void addDefaultPreprocessorDefs (StringPairArray&) const;
  278. static String getDefaultBuildsRootFolder() { return "Builds/"; }
  279. static String getStaticLibbedFilename (String name) { return addSuffix (addLibPrefix (name), ".a"); }
  280. static String getDynamicLibbedFilename (String name) { return addSuffix (addLibPrefix (name), ".so"); }
  281. virtual void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) = 0;
  282. //==============================================================================
  283. static void createDirectoryOrThrow (const File& dirToCreate)
  284. {
  285. if (! dirToCreate.createDirectory())
  286. throw build_tools::SaveError ("Can't create folder: " + dirToCreate.getFullPathName());
  287. }
  288. static void writeXmlOrThrow (const XmlElement& xml, const File& file, const String& encoding,
  289. int maxCharsPerLine, bool useUnixNewLines = false)
  290. {
  291. XmlElement::TextFormat format;
  292. format.customEncoding = encoding;
  293. format.lineWrapLength = maxCharsPerLine;
  294. format.newLineChars = useUnixNewLines ? "\n" : "\r\n";
  295. MemoryOutputStream mo (8192);
  296. xml.writeTo (mo, format);
  297. build_tools::overwriteFileIfDifferentOrThrow (file, mo);
  298. }
  299. private:
  300. //==============================================================================
  301. void valueChanged (Value&) override { updateCompilerFlagValues(); }
  302. void updateCompilerFlagValues();
  303. //==============================================================================
  304. static String addLibPrefix (const String name)
  305. {
  306. return name.startsWith ("lib") ? name
  307. : "lib" + name;
  308. }
  309. static String addSuffix (const String name, const String suffix)
  310. {
  311. return name.endsWithIgnoreCase (suffix) ? name
  312. : name + suffix;
  313. }
  314. void createDependencyPathProperties (PropertyListBuilder&);
  315. void createIconProperties (PropertyListBuilder&);
  316. void addVSTPathsIfPluginOrHost();
  317. void addCommonAudioPluginSettings();
  318. void addLegacyVSTFolderToPathIfSpecified();
  319. build_tools::RelativePath getInternalVST3SDKPath();
  320. void addAAXFoldersToPath();
  321. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectExporter)
  322. };