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.

1870 lines
85KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. class MSVCProjectExporterBase : public ProjectExporter
  20. {
  21. public:
  22. MSVCProjectExporterBase (Project& p, const ValueTree& t, const char* const folderName)
  23. : ProjectExporter (p, t)
  24. {
  25. if (getTargetLocationString().isEmpty())
  26. getTargetLocationValue() = getDefaultBuildsRootFolder() + folderName;
  27. updateOldSettings();
  28. initialiseDependencyPathValues();
  29. }
  30. virtual int getVisualStudioVersion() const = 0;
  31. virtual String getSolutionComment() const = 0;
  32. virtual String getToolsVersion() const = 0;
  33. virtual String getDefaultToolset() const = 0;
  34. virtual String getDefaultWindowsTargetPlatformVersion() const = 0;
  35. //==============================================================================
  36. Value getIPPLibraryValue() { return getSetting (Ids::IPPLibrary); }
  37. String getIPPLibrary() const { return settings [Ids::IPPLibrary]; }
  38. Value getPlatformToolsetValue() { return getSetting (Ids::toolset); }
  39. String getPlatformToolset() const
  40. {
  41. const String s (settings [Ids::toolset].toString());
  42. return s.isNotEmpty() ? s : getDefaultToolset();
  43. }
  44. Value getWindowsTargetPlatformVersionValue() { return getSetting (Ids::windowsTargetPlatformVersion); }
  45. String getWindowsTargetPlatformVersion() const
  46. {
  47. String targetPlatform = settings [Ids::windowsTargetPlatformVersion];
  48. return (targetPlatform.isNotEmpty() ? targetPlatform : getDefaultWindowsTargetPlatformVersion());
  49. }
  50. Value getCppStandardValue() { return getSetting (Ids::cppLanguageStandard); }
  51. String getCppLanguageStandard() const { return settings [Ids::cppLanguageStandard]; }
  52. //==============================================================================
  53. void addToolsetProperty (PropertyListBuilder& props, const char** names, const var* values, int num)
  54. {
  55. props.add (new ChoicePropertyComponent (getPlatformToolsetValue(), "Platform Toolset",
  56. StringArray (names, num), Array<var> (values, num)));
  57. }
  58. void addIPPLibraryProperty (PropertyListBuilder& props)
  59. {
  60. static const char* ippOptions[] = { "No", "Yes (Default Mode)", "Multi-Threaded Static Library", "Single-Threaded Static Library", "Multi-Threaded DLL", "Single-Threaded DLL" };
  61. static const var ippValues[] = { var(), "true", "Parallel_Static", "Sequential", "Parallel_Dynamic", "Sequential_Dynamic" };
  62. props.add (new ChoicePropertyComponent (getIPPLibraryValue(), "Use IPP Library",
  63. StringArray (ippOptions, numElementsInArray (ippValues)),
  64. Array<var> (ippValues, numElementsInArray (ippValues))));
  65. }
  66. void addCppStandardProperty (PropertyListBuilder& props, const char** names, const var* values, int num)
  67. {
  68. props.add (new ChoicePropertyComponent (getCppStandardValue(), "C++ standard to use",
  69. StringArray (names, num), Array<var> (values, num)));
  70. }
  71. void addWindowsTargetPlatformProperties (PropertyListBuilder& props)
  72. {
  73. static const char* targetPlatformNames[] = { "(default)", "8.1", "10.0.10240.0", "10.0.10586.0", "10.0.14393.0", "10.0.15063.0" };
  74. static const var targetPlatforms[] = { var(), "8.1", "10.0.10240.0", "10.0.10586.0", "10.0.14393.0", "10.0.15063.0" };
  75. props.add (new ChoicePropertyComponent (getWindowsTargetPlatformVersionValue(), "Windows Target Platform",
  76. StringArray (targetPlatformNames, numElementsInArray (targetPlatformNames)),
  77. Array<var> (targetPlatforms, numElementsInArray (targetPlatforms))),
  78. "Specifies the version of the Windows SDK that will be used when building this project. "
  79. "The default value for this exporter is " + getDefaultWindowsTargetPlatformVersion());
  80. }
  81. void addPlatformToolsetToPropertyGroup (XmlElement& p) const
  82. {
  83. forEachXmlChildElementWithTagName (p, e, "PropertyGroup")
  84. e->createNewChildElement ("PlatformToolset")->addTextElement (getPlatformToolset());
  85. }
  86. void addWindowsTargetPlatformVersionToPropertyGroup (XmlElement& p) const
  87. {
  88. const String& targetVersion = getWindowsTargetPlatformVersion();
  89. if (targetVersion.isNotEmpty())
  90. forEachXmlChildElementWithTagName (p, e, "PropertyGroup")
  91. e->createNewChildElement ("WindowsTargetPlatformVersion")->addTextElement (getWindowsTargetPlatformVersion());
  92. }
  93. void addIPPSettingToPropertyGroup (XmlElement& p) const
  94. {
  95. String ippLibrary = getIPPLibrary();
  96. if (ippLibrary.isNotEmpty())
  97. forEachXmlChildElementWithTagName (p, e, "PropertyGroup")
  98. e->createNewChildElement ("UseIntelIPP")->addTextElement (ippLibrary);
  99. }
  100. void create (const OwnedArray<LibraryModule>&) const override
  101. {
  102. createResourcesAndIcon();
  103. for (int i = 0; i < targets.size(); ++i)
  104. if (MSVCTargetBase* target = targets[i])
  105. target->writeProjectFile();
  106. {
  107. MemoryOutputStream mo;
  108. writeSolutionFile (mo, "11.00", getSolutionComment());
  109. overwriteFileIfDifferentOrThrow (getSLNFile(), mo);
  110. }
  111. }
  112. //==============================================================================
  113. class MSVCBuildConfiguration : public BuildConfiguration
  114. {
  115. public:
  116. MSVCBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e)
  117. : BuildConfiguration (p, settings, e)
  118. {
  119. if (getWarningLevel() == 0)
  120. getWarningLevelValue() = 4;
  121. setValueIfVoid (shouldGenerateManifestValue(), true);
  122. setValueIfVoid (getArchitectureType(), get64BitArchName());
  123. }
  124. Value getWarningLevelValue() { return getValue (Ids::winWarningLevel); }
  125. int getWarningLevel() const { return config [Ids::winWarningLevel]; }
  126. Value getWarningsTreatedAsErrors() { return getValue (Ids::warningsAreErrors); }
  127. bool areWarningsTreatedAsErrors() const { return config [Ids::warningsAreErrors]; }
  128. Value getPrebuildCommand() { return getValue (Ids::prebuildCommand); }
  129. String getPrebuildCommandString() const { return config [Ids::prebuildCommand]; }
  130. Value getPostbuildCommand() { return getValue (Ids::postbuildCommand); }
  131. String getPostbuildCommandString() const { return config [Ids::postbuildCommand]; }
  132. Value shouldGenerateDebugSymbolsValue() { return getValue (Ids::alwaysGenerateDebugSymbols); }
  133. bool shouldGenerateDebugSymbols() const { return config [Ids::alwaysGenerateDebugSymbols]; }
  134. Value shouldGenerateManifestValue() { return getValue (Ids::generateManifest); }
  135. bool shouldGenerateManifest() const { return config [Ids::generateManifest]; }
  136. Value shouldLinkIncrementalValue() { return getValue (Ids::enableIncrementalLinking); }
  137. bool shouldLinkIncremental() const { return config [Ids::enableIncrementalLinking]; }
  138. Value getWholeProgramOptValue() { return getValue (Ids::wholeProgramOptimisation); }
  139. bool shouldDisableWholeProgramOpt() const { return static_cast<int> (config [Ids::wholeProgramOptimisation]) > 0; }
  140. Value getUsingRuntimeLibDLL() { return getValue (Ids::useRuntimeLibDLL); }
  141. bool isUsingRuntimeLibDLL() const { return config [Ids::useRuntimeLibDLL]; }
  142. String getIntermediatesPath() const { return config [Ids::intermediatesPath].toString(); }
  143. Value getIntermediatesPathValue() { return getValue (Ids::intermediatesPath); }
  144. String getCharacterSet() const { return config [Ids::characterSet].toString(); }
  145. Value getCharacterSetValue() { return getValue (Ids::characterSet); }
  146. Value getArchitectureType() { return getValue (Ids::winArchitecture); }
  147. bool is64Bit() const { return config [Ids::winArchitecture].toString() == get64BitArchName(); }
  148. Value getFastMathValue() { return getValue (Ids::fastMath); }
  149. bool isFastMathEnabled() const { return config [Ids::fastMath]; }
  150. String get64BitArchName() const { return "x64"; }
  151. String get32BitArchName() const { return "Win32"; }
  152. String createMSVCConfigName() const
  153. {
  154. return getName() + "|" + (config [Ids::winArchitecture] == get64BitArchName() ? "x64" : "Win32");
  155. }
  156. String getOutputFilename (const String& suffix, bool forceSuffix) const
  157. {
  158. const String target (File::createLegalFileName (getTargetBinaryNameString().trim()));
  159. if (forceSuffix || ! target.containsChar ('.'))
  160. return target.upToLastOccurrenceOf (".", false, false) + suffix;
  161. return target;
  162. }
  163. var getDefaultOptimisationLevel() const override { return var ((int) (isDebug() ? optimisationOff : optimiseMaxSpeed)); }
  164. void createConfigProperties (PropertyListBuilder& props) override
  165. {
  166. const String archTypes[] = { get32BitArchName(), get64BitArchName() };
  167. props.add (new ChoicePropertyComponent (getArchitectureType(), "Architecture",
  168. StringArray (archTypes, numElementsInArray (archTypes)),
  169. Array<var> (archTypes, numElementsInArray (archTypes))));
  170. props.add (new BooleanPropertyComponent (getFastMathValue(), "Relax IEEE compliance", "Enabled"),
  171. "Enable this to use FAST_MATH non-IEEE mode. (Warning: this can have unexpected results!)");
  172. static const char* optimisationLevels[] = { "No optimisation", "Minimise size", "Maximise speed", 0 };
  173. const int optimisationLevelValues[] = { optimisationOff, optimiseMinSize, optimiseMaxSpeed, 0 };
  174. props.add (new ChoicePropertyComponent (getOptimisationLevel(), "Optimisation",
  175. StringArray (optimisationLevels),
  176. Array<var> (optimisationLevelValues)),
  177. "The optimisation level for this configuration");
  178. props.add (new TextPropertyComponent (getIntermediatesPathValue(), "Intermediates path", 2048, false),
  179. "An optional path to a folder to use for the intermediate build files. Note that Visual Studio allows "
  180. "you to use macros in this path, e.g. \"$(TEMP)\\MyAppBuildFiles\\$(Configuration)\", which is a handy way to "
  181. "send them to the user's temp folder.");
  182. static const char* warningLevelNames[] = { "Low", "Medium", "High", nullptr };
  183. const int warningLevels[] = { 2, 3, 4 };
  184. props.add (new ChoicePropertyComponent (getWarningLevelValue(), "Warning Level",
  185. StringArray (warningLevelNames), Array<var> (warningLevels, numElementsInArray (warningLevels))));
  186. props.add (new BooleanPropertyComponent (getWarningsTreatedAsErrors(), "Warnings", "Treat warnings as errors"));
  187. {
  188. static const char* runtimeNames[] = { "(Default)", "Use static runtime", "Use DLL runtime", nullptr };
  189. const var runtimeValues[] = { var(), var (false), var (true) };
  190. props.add (new ChoicePropertyComponent (getUsingRuntimeLibDLL(), "Runtime Library",
  191. StringArray (runtimeNames), Array<var> (runtimeValues, numElementsInArray (runtimeValues))),
  192. "If the static runtime is selected then your app/plug-in will not be dependent upon users having Microsoft's redistributable "
  193. "C++ runtime installed. However, if you are linking libraries from different sources you must select the same type of runtime "
  194. "used by the libraries.");
  195. }
  196. {
  197. static const char* wpoNames[] = { "Enable link-time code generation when possible",
  198. "Always disable link-time code generation", nullptr };
  199. const var wpoValues[] = { var(), var (1) };
  200. props.add (new ChoicePropertyComponent (getWholeProgramOptValue(), "Whole Program Optimisation",
  201. StringArray (wpoNames), Array<var> (wpoValues, numElementsInArray (wpoValues))));
  202. }
  203. {
  204. props.add (new BooleanPropertyComponent (shouldLinkIncrementalValue(), "Incremental Linking", "Enable"),
  205. "Enable to avoid linking from scratch for every new build. "
  206. "Disable to ensure that your final release build does not contain padding or thunks.");
  207. }
  208. if (! isDebug())
  209. props.add (new BooleanPropertyComponent (shouldGenerateDebugSymbolsValue(), "Debug Symbols", "Force generation of debug symbols"));
  210. props.add (new TextPropertyComponent (getPrebuildCommand(), "Pre-build Command", 2048, true));
  211. props.add (new TextPropertyComponent (getPostbuildCommand(), "Post-build Command", 2048, true));
  212. props.add (new BooleanPropertyComponent (shouldGenerateManifestValue(), "Manifest", "Generate Manifest"));
  213. {
  214. static const char* characterSetNames[] = { "Default", "MultiByte", "Unicode", nullptr };
  215. const var charSets[] = { var(), "MultiByte", "Unicode", };
  216. props.add (new ChoicePropertyComponent (getCharacterSetValue(), "Character Set",
  217. StringArray (characterSetNames), Array<var> (charSets, numElementsInArray (charSets))));
  218. }
  219. }
  220. String getModuleLibraryArchName() const override
  221. {
  222. String result ("$(Platform)\\");
  223. result += isUsingRuntimeLibDLL() ? "MD" : "MT";
  224. if (isDebug())
  225. result += "d";
  226. return result;
  227. }
  228. };
  229. //==============================================================================
  230. class MSVCTargetBase : public ProjectType::Target
  231. {
  232. public:
  233. MSVCTargetBase (ProjectType::Target::Type targetType, const MSVCProjectExporterBase& exporter)
  234. : ProjectType::Target (targetType), owner (exporter)
  235. {
  236. projectGuid = createGUID (owner.getProject().getProjectUID() + getName());
  237. }
  238. virtual ~MSVCTargetBase() {}
  239. String getProjectVersionString() const { return "10.00"; }
  240. String getProjectFileSuffix() const { return ".vcxproj"; }
  241. String getFiltersFileSuffix() const { return ".vcxproj.filters"; }
  242. String getTopLevelXmlEntity() const { return "Project"; }
  243. //==============================================================================
  244. void fillInProjectXml (XmlElement& projectXml) const
  245. {
  246. projectXml.setAttribute ("DefaultTargets", "Build");
  247. projectXml.setAttribute ("ToolsVersion", getOwner().getToolsVersion());
  248. projectXml.setAttribute ("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
  249. {
  250. XmlElement* configsGroup = projectXml.createNewChildElement ("ItemGroup");
  251. configsGroup->setAttribute ("Label", "ProjectConfigurations");
  252. for (ConstConfigIterator i (owner); i.next();)
  253. {
  254. const MSVCBuildConfiguration& config = dynamic_cast<const MSVCBuildConfiguration&> (*i);
  255. XmlElement* e = configsGroup->createNewChildElement ("ProjectConfiguration");
  256. e->setAttribute ("Include", config.createMSVCConfigName());
  257. e->createNewChildElement ("Configuration")->addTextElement (config.getName());
  258. e->createNewChildElement ("Platform")->addTextElement (config.is64Bit() ? config.get64BitArchName()
  259. : config.get32BitArchName());
  260. }
  261. }
  262. {
  263. XmlElement* globals = projectXml.createNewChildElement ("PropertyGroup");
  264. globals->setAttribute ("Label", "Globals");
  265. globals->createNewChildElement ("ProjectGuid")->addTextElement (getProjectGuid());
  266. }
  267. {
  268. XmlElement* imports = projectXml.createNewChildElement ("Import");
  269. imports->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
  270. }
  271. for (ConstConfigIterator i (owner); i.next();)
  272. {
  273. const MSVCBuildConfiguration& config = dynamic_cast<const MSVCBuildConfiguration&> (*i);
  274. XmlElement* e = projectXml.createNewChildElement ("PropertyGroup");
  275. setConditionAttribute (*e, config);
  276. e->setAttribute ("Label", "Configuration");
  277. e->createNewChildElement ("ConfigurationType")->addTextElement (getProjectType());
  278. e->createNewChildElement ("UseOfMfc")->addTextElement ("false");
  279. const String charSet (config.getCharacterSet());
  280. if (charSet.isNotEmpty())
  281. e->createNewChildElement ("CharacterSet")->addTextElement (charSet);
  282. if (! (config.isDebug() || config.shouldDisableWholeProgramOpt()))
  283. e->createNewChildElement ("WholeProgramOptimization")->addTextElement ("true");
  284. if (config.shouldLinkIncremental())
  285. e->createNewChildElement ("LinkIncremental")->addTextElement ("true");
  286. if (config.is64Bit())
  287. e->createNewChildElement ("PlatformToolset")->addTextElement (getOwner().getPlatformToolset());
  288. }
  289. {
  290. XmlElement* e = projectXml.createNewChildElement ("Import");
  291. e->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
  292. }
  293. {
  294. XmlElement* e = projectXml.createNewChildElement ("ImportGroup");
  295. e->setAttribute ("Label", "ExtensionSettings");
  296. }
  297. {
  298. XmlElement* e = projectXml.createNewChildElement ("ImportGroup");
  299. e->setAttribute ("Label", "PropertySheets");
  300. XmlElement* p = e->createNewChildElement ("Import");
  301. p->setAttribute ("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props");
  302. p->setAttribute ("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')");
  303. p->setAttribute ("Label", "LocalAppDataPlatform");
  304. }
  305. {
  306. XmlElement* e = projectXml.createNewChildElement ("PropertyGroup");
  307. e->setAttribute ("Label", "UserMacros");
  308. }
  309. {
  310. XmlElement* props = projectXml.createNewChildElement ("PropertyGroup");
  311. props->createNewChildElement ("_ProjectFileVersion")->addTextElement ("10.0.30319.1");
  312. props->createNewChildElement ("TargetExt")->addTextElement (getTargetSuffix());
  313. for (ConstConfigIterator i (owner); i.next();)
  314. {
  315. const MSVCBuildConfiguration& config = dynamic_cast<const MSVCBuildConfiguration&> (*i);
  316. if (getConfigTargetPath (config).isNotEmpty())
  317. {
  318. XmlElement* outdir = props->createNewChildElement ("OutDir");
  319. setConditionAttribute (*outdir, config);
  320. outdir->addTextElement (FileHelpers::windowsStylePath (getConfigTargetPath (config)) + "\\");
  321. }
  322. {
  323. XmlElement* intdir = props->createNewChildElement("IntDir");
  324. setConditionAttribute (*intdir, config);
  325. String intermediatesPath = getIntermediatesPath (config);
  326. if (! intermediatesPath.endsWithChar (L'\\'))
  327. intermediatesPath += L'\\';
  328. intdir->addTextElement (FileHelpers::windowsStylePath (intermediatesPath));
  329. }
  330. {
  331. XmlElement* targetName = props->createNewChildElement ("TargetName");
  332. setConditionAttribute (*targetName, config);
  333. targetName->addTextElement (config.getOutputFilename ("", false));
  334. }
  335. {
  336. XmlElement* manifest = props->createNewChildElement ("GenerateManifest");
  337. setConditionAttribute (*manifest, config);
  338. manifest->addTextElement (config.shouldGenerateManifest() ? "true" : "false");
  339. }
  340. const StringArray librarySearchPaths (getLibrarySearchPaths (config));
  341. if (librarySearchPaths.size() > 0)
  342. {
  343. XmlElement* libPath = props->createNewChildElement ("LibraryPath");
  344. setConditionAttribute (*libPath, config);
  345. libPath->addTextElement ("$(LibraryPath);" + librarySearchPaths.joinIntoString (";"));
  346. }
  347. }
  348. }
  349. for (ConstConfigIterator i (owner); i.next();)
  350. {
  351. const MSVCBuildConfiguration& config = dynamic_cast<const MSVCBuildConfiguration&> (*i);
  352. const bool isDebug = config.isDebug();
  353. XmlElement* group = projectXml.createNewChildElement ("ItemDefinitionGroup");
  354. setConditionAttribute (*group, config);
  355. {
  356. XmlElement* midl = group->createNewChildElement ("Midl");
  357. midl->createNewChildElement ("PreprocessorDefinitions")->addTextElement (isDebug ? "_DEBUG;%(PreprocessorDefinitions)"
  358. : "NDEBUG;%(PreprocessorDefinitions)");
  359. midl->createNewChildElement ("MkTypLibCompatible")->addTextElement ("true");
  360. midl->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  361. midl->createNewChildElement ("TargetEnvironment")->addTextElement ("Win32");
  362. midl->createNewChildElement ("HeaderFileName");
  363. }
  364. bool isUsingEditAndContinue = false;
  365. {
  366. XmlElement* cl = group->createNewChildElement ("ClCompile");
  367. cl->createNewChildElement ("Optimization")->addTextElement (getOptimisationLevelString (config.getOptimisationLevelInt()));
  368. if (isDebug && config.getOptimisationLevelInt() <= optimisationOff)
  369. {
  370. isUsingEditAndContinue = ! config.is64Bit();
  371. cl->createNewChildElement ("DebugInformationFormat")
  372. ->addTextElement (isUsingEditAndContinue ? "EditAndContinue"
  373. : "ProgramDatabase");
  374. }
  375. StringArray includePaths (getOwner().getHeaderSearchPaths (config));
  376. includePaths.addArray (getExtraSearchPaths());
  377. includePaths.add ("%(AdditionalIncludeDirectories)");
  378. cl->createNewChildElement ("AdditionalIncludeDirectories")->addTextElement (includePaths.joinIntoString (";"));
  379. cl->createNewChildElement ("PreprocessorDefinitions")->addTextElement (getPreprocessorDefs (config, ";") + ";%(PreprocessorDefinitions)");
  380. const bool runtimeDLL = shouldUseRuntimeDLL (config);
  381. cl->createNewChildElement ("RuntimeLibrary")->addTextElement (runtimeDLL ? (isDebug ? "MultiThreadedDebugDLL" : "MultiThreadedDLL")
  382. : (isDebug ? "MultiThreadedDebug" : "MultiThreaded"));
  383. cl->createNewChildElement ("RuntimeTypeInfo")->addTextElement ("true");
  384. cl->createNewChildElement ("PrecompiledHeader");
  385. cl->createNewChildElement ("AssemblerListingLocation")->addTextElement ("$(IntDir)\\");
  386. cl->createNewChildElement ("ObjectFileName")->addTextElement ("$(IntDir)\\");
  387. cl->createNewChildElement ("ProgramDataBaseFileName")->addTextElement ("$(IntDir)\\");
  388. cl->createNewChildElement ("WarningLevel")->addTextElement ("Level" + String (config.getWarningLevel()));
  389. cl->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  390. cl->createNewChildElement ("MultiProcessorCompilation")->addTextElement ("true");
  391. if (config.isFastMathEnabled())
  392. cl->createNewChildElement ("FloatingPointModel")->addTextElement ("Fast");
  393. const String extraFlags (getOwner().replacePreprocessorTokens (config, getOwner().getExtraCompilerFlagsString()).trim());
  394. if (extraFlags.isNotEmpty())
  395. cl->createNewChildElement ("AdditionalOptions")->addTextElement (extraFlags + " %(AdditionalOptions)");
  396. if (config.areWarningsTreatedAsErrors())
  397. cl->createNewChildElement ("TreatWarningAsError")->addTextElement ("true");
  398. String cppLanguageStandard = getOwner().getCppLanguageStandard();
  399. if (cppLanguageStandard.isNotEmpty())
  400. cl->createNewChildElement ("LanguageStandard")->addTextElement (cppLanguageStandard);
  401. }
  402. {
  403. XmlElement* res = group->createNewChildElement ("ResourceCompile");
  404. res->createNewChildElement ("PreprocessorDefinitions")->addTextElement (isDebug ? "_DEBUG;%(PreprocessorDefinitions)"
  405. : "NDEBUG;%(PreprocessorDefinitions)");
  406. }
  407. {
  408. XmlElement* link = group->createNewChildElement ("Link");
  409. link->createNewChildElement ("OutputFile")->addTextElement (getOutputFilePath (config));
  410. link->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  411. link->createNewChildElement ("IgnoreSpecificDefaultLibraries")->addTextElement (isDebug ? "libcmt.lib; msvcrt.lib;;%(IgnoreSpecificDefaultLibraries)"
  412. : "%(IgnoreSpecificDefaultLibraries)");
  413. link->createNewChildElement ("GenerateDebugInformation")->addTextElement ((isDebug || config.shouldGenerateDebugSymbols()) ? "true" : "false");
  414. link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (getOwner().getIntDirFile (config, config.getOutputFilename (".pdb", true)));
  415. link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp ? "Console" : "Windows");
  416. if (! config.is64Bit())
  417. link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
  418. if (isUsingEditAndContinue)
  419. link->createNewChildElement ("ImageHasSafeExceptionHandlers")->addTextElement ("false");
  420. if (! isDebug)
  421. {
  422. link->createNewChildElement ("OptimizeReferences")->addTextElement ("true");
  423. link->createNewChildElement ("EnableCOMDATFolding")->addTextElement ("true");
  424. }
  425. const StringArray librarySearchPaths (config.getLibrarySearchPaths());
  426. if (librarySearchPaths.size() > 0)
  427. link->createNewChildElement ("AdditionalLibraryDirectories")->addTextElement (getOwner().replacePreprocessorTokens (config, librarySearchPaths.joinIntoString (";"))
  428. + ";%(AdditionalLibraryDirectories)");
  429. link->createNewChildElement ("LargeAddressAware")->addTextElement ("true");
  430. const String externalLibraries (getExternalLibraries (config, getOwner().getExternalLibrariesString()));
  431. if (externalLibraries.isNotEmpty())
  432. link->createNewChildElement ("AdditionalDependencies")->addTextElement (getOwner().replacePreprocessorTokens (config, externalLibraries).trim()
  433. + ";%(AdditionalDependencies)");
  434. String extraLinkerOptions (getOwner().getExtraLinkerFlagsString());
  435. if (extraLinkerOptions.isNotEmpty())
  436. link->createNewChildElement ("AdditionalOptions")->addTextElement (getOwner().replacePreprocessorTokens (config, extraLinkerOptions).trim()
  437. + " %(AdditionalOptions)");
  438. const String delayLoadedDLLs (getDelayLoadedDLLs());
  439. if (delayLoadedDLLs.isNotEmpty())
  440. link->createNewChildElement ("DelayLoadDLLs")->addTextElement (delayLoadedDLLs);
  441. const String moduleDefinitionsFile (getModuleDefinitions (config));
  442. if (moduleDefinitionsFile.isNotEmpty())
  443. link->createNewChildElement ("ModuleDefinitionFile")
  444. ->addTextElement (moduleDefinitionsFile);
  445. }
  446. {
  447. XmlElement* bsc = group->createNewChildElement ("Bscmake");
  448. bsc->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  449. bsc->createNewChildElement ("OutputFile")->addTextElement (getOwner().getIntDirFile (config, config.getOutputFilename (".bsc", true)));
  450. }
  451. const RelativePath& manifestFile = getOwner().getManifestPath();
  452. if (manifestFile.getRoot() != RelativePath::unknown)
  453. {
  454. XmlElement* bsc = group->createNewChildElement ("Manifest");
  455. bsc->createNewChildElement ("AdditionalManifestFiles")
  456. ->addTextElement (manifestFile.rebased (getOwner().getProject().getFile().getParentDirectory(),
  457. getOwner().getTargetFolder(),
  458. RelativePath::buildTargetFolder).toWindowsStyle());
  459. }
  460. if (getTargetFileType() == staticLibrary && ! config.is64Bit())
  461. {
  462. XmlElement* lib = group->createNewChildElement ("Lib");
  463. lib->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
  464. }
  465. const String preBuild = getPreBuildSteps (config);
  466. if (preBuild.isNotEmpty())
  467. group->createNewChildElement ("PreBuildEvent")
  468. ->createNewChildElement ("Command")
  469. ->addTextElement (preBuild);
  470. const String postBuild = getPostBuildSteps (config);
  471. if (postBuild.isNotEmpty())
  472. group->createNewChildElement ("PostBuildEvent")
  473. ->createNewChildElement ("Command")
  474. ->addTextElement (postBuild);
  475. }
  476. ScopedPointer<XmlElement> otherFilesGroup (new XmlElement ("ItemGroup"));
  477. {
  478. XmlElement* cppFiles = projectXml.createNewChildElement ("ItemGroup");
  479. XmlElement* headerFiles = projectXml.createNewChildElement ("ItemGroup");
  480. for (int i = 0; i < getOwner().getAllGroups().size(); ++i)
  481. {
  482. const Project::Item& group = getOwner().getAllGroups().getReference (i);
  483. if (group.getNumChildren() > 0)
  484. addFilesToCompile (group, *cppFiles, *headerFiles, *otherFilesGroup);
  485. }
  486. }
  487. if (getOwner().iconFile != File())
  488. {
  489. XmlElement* e = otherFilesGroup->createNewChildElement ("None");
  490. e->setAttribute ("Include", prependDot (getOwner().iconFile.getFileName()));
  491. }
  492. if (otherFilesGroup->getFirstChildElement() != nullptr)
  493. projectXml.addChildElement (otherFilesGroup.release());
  494. if (getOwner().hasResourceFile())
  495. {
  496. XmlElement* rcGroup = projectXml.createNewChildElement ("ItemGroup");
  497. XmlElement* e = rcGroup->createNewChildElement ("ResourceCompile");
  498. e->setAttribute ("Include", prependDot (getOwner().rcFile.getFileName()));
  499. }
  500. {
  501. XmlElement* e = projectXml.createNewChildElement ("Import");
  502. e->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
  503. }
  504. {
  505. XmlElement* e = projectXml.createNewChildElement ("ImportGroup");
  506. e->setAttribute ("Label", "ExtensionTargets");
  507. }
  508. getOwner().addPlatformToolsetToPropertyGroup (projectXml);
  509. getOwner().addWindowsTargetPlatformVersionToPropertyGroup (projectXml);
  510. getOwner().addIPPSettingToPropertyGroup (projectXml);
  511. }
  512. String getProjectType() const
  513. {
  514. switch (getTargetFileType())
  515. {
  516. case executable:
  517. return "Application";
  518. case staticLibrary:
  519. return "StaticLibrary";
  520. default:
  521. break;
  522. }
  523. return "DynamicLibrary";
  524. }
  525. //==============================================================================
  526. void addFilesToCompile (const Project::Item& projectItem, XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles) const
  527. {
  528. const Type targetType = (getOwner().getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget);
  529. if (projectItem.isGroup())
  530. {
  531. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  532. addFilesToCompile (projectItem.getChild (i), cpps, headers, otherFiles);
  533. }
  534. else if (projectItem.shouldBeAddedToTargetProject()
  535. && getOwner().getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType)
  536. {
  537. const RelativePath path (projectItem.getFile(), getOwner().getTargetFolder(), RelativePath::buildTargetFolder);
  538. jassert (path.getRoot() == RelativePath::buildTargetFolder);
  539. if (path.hasFileExtension (cOrCppFileExtensions) || path.hasFileExtension (asmFileExtensions))
  540. {
  541. if (targetType == SharedCodeTarget || projectItem.shouldBeCompiled())
  542. {
  543. auto* e = cpps.createNewChildElement ("ClCompile");
  544. e->setAttribute ("Include", path.toWindowsStyle());
  545. if (shouldUseStdCall (path))
  546. e->createNewChildElement ("CallingConvention")->addTextElement ("StdCall");
  547. if (! projectItem.shouldBeCompiled())
  548. e->createNewChildElement ("ExcludedFromBuild")->addTextElement ("true");
  549. }
  550. }
  551. else if (path.hasFileExtension (headerFileExtensions))
  552. {
  553. headers.createNewChildElement ("ClInclude")->setAttribute ("Include", path.toWindowsStyle());
  554. }
  555. else if (! path.hasFileExtension (objCFileExtensions))
  556. {
  557. otherFiles.createNewChildElement ("None")->setAttribute ("Include", path.toWindowsStyle());
  558. }
  559. }
  560. }
  561. void setConditionAttribute (XmlElement& xml, const BuildConfiguration& config) const
  562. {
  563. const MSVCBuildConfiguration& msvcConfig = dynamic_cast<const MSVCBuildConfiguration&> (config);
  564. xml.setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + msvcConfig.createMSVCConfigName() + "'");
  565. }
  566. //==============================================================================
  567. void addFilterGroup (XmlElement& groups, const String& path) const
  568. {
  569. XmlElement* e = groups.createNewChildElement ("Filter");
  570. e->setAttribute ("Include", path);
  571. e->createNewChildElement ("UniqueIdentifier")->addTextElement (createGUID (path + "_guidpathsaltxhsdf"));
  572. }
  573. void addFileToFilter (const RelativePath& file, const String& groupPath,
  574. XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles) const
  575. {
  576. XmlElement* e;
  577. if (file.hasFileExtension (headerFileExtensions))
  578. e = headers.createNewChildElement ("ClInclude");
  579. else if (file.hasFileExtension (sourceFileExtensions))
  580. e = cpps.createNewChildElement ("ClCompile");
  581. else
  582. e = otherFiles.createNewChildElement ("None");
  583. jassert (file.getRoot() == RelativePath::buildTargetFolder);
  584. e->setAttribute ("Include", file.toWindowsStyle());
  585. e->createNewChildElement ("Filter")->addTextElement (groupPath);
  586. }
  587. bool addFilesToFilter (const Project::Item& projectItem, const String& path,
  588. XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles, XmlElement& groups) const
  589. {
  590. const Type targetType = (getOwner().getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget);
  591. if (projectItem.isGroup())
  592. {
  593. bool filesWereAdded = false;
  594. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  595. if (addFilesToFilter (projectItem.getChild(i),
  596. (path.isEmpty() ? String() : (path + "\\")) + projectItem.getChild(i).getName(),
  597. cpps, headers, otherFiles, groups))
  598. filesWereAdded = true;
  599. if (filesWereAdded)
  600. addFilterGroup (groups, path);
  601. return filesWereAdded;
  602. }
  603. else if (projectItem.shouldBeAddedToTargetProject())
  604. {
  605. const RelativePath relativePath (projectItem.getFile(), getOwner().getTargetFolder(), RelativePath::buildTargetFolder);
  606. jassert (relativePath.getRoot() == RelativePath::buildTargetFolder);
  607. if (getOwner().getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType
  608. && (targetType == SharedCodeTarget || projectItem.shouldBeCompiled()))
  609. {
  610. addFileToFilter (relativePath, path.upToLastOccurrenceOf ("\\", false, false), cpps, headers, otherFiles);
  611. return true;
  612. }
  613. }
  614. return false;
  615. }
  616. bool addFilesToFilter (const Array<RelativePath>& files, const String& path,
  617. XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles, XmlElement& groups)
  618. {
  619. if (files.size() > 0)
  620. {
  621. addFilterGroup (groups, path);
  622. for (int i = 0; i < files.size(); ++i)
  623. addFileToFilter (files.getReference(i), path, cpps, headers, otherFiles);
  624. return true;
  625. }
  626. return false;
  627. }
  628. void fillInFiltersXml (XmlElement& filterXml) const
  629. {
  630. filterXml.setAttribute ("ToolsVersion", getOwner().getToolsVersion());
  631. filterXml.setAttribute ("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
  632. XmlElement* groupsXml = filterXml.createNewChildElement ("ItemGroup");
  633. XmlElement* cpps = filterXml.createNewChildElement ("ItemGroup");
  634. XmlElement* headers = filterXml.createNewChildElement ("ItemGroup");
  635. ScopedPointer<XmlElement> otherFilesGroup (new XmlElement ("ItemGroup"));
  636. for (int i = 0; i < getOwner().getAllGroups().size(); ++i)
  637. {
  638. const Project::Item& group = getOwner().getAllGroups().getReference(i);
  639. if (group.getNumChildren() > 0)
  640. addFilesToFilter (group, group.getName(), *cpps, *headers, *otherFilesGroup, *groupsXml);
  641. }
  642. if (getOwner().iconFile.exists())
  643. {
  644. XmlElement* e = otherFilesGroup->createNewChildElement ("None");
  645. e->setAttribute ("Include", prependDot (getOwner().iconFile.getFileName()));
  646. e->createNewChildElement ("Filter")->addTextElement (ProjectSaver::getJuceCodeGroupName());
  647. }
  648. if (otherFilesGroup->getFirstChildElement() != nullptr)
  649. filterXml.addChildElement (otherFilesGroup.release());
  650. if (getOwner().hasResourceFile())
  651. {
  652. XmlElement* rcGroup = filterXml.createNewChildElement ("ItemGroup");
  653. XmlElement* e = rcGroup->createNewChildElement ("ResourceCompile");
  654. e->setAttribute ("Include", prependDot (getOwner().rcFile.getFileName()));
  655. e->createNewChildElement ("Filter")->addTextElement (ProjectSaver::getJuceCodeGroupName());
  656. }
  657. }
  658. const MSVCProjectExporterBase& getOwner() const { return owner; }
  659. const String& getProjectGuid() const { return projectGuid; }
  660. //==============================================================================
  661. void writeProjectFile()
  662. {
  663. {
  664. XmlElement projectXml (getTopLevelXmlEntity());
  665. fillInProjectXml (projectXml);
  666. writeXmlOrThrow (projectXml, getVCProjFile(), "UTF-8", 10);
  667. }
  668. {
  669. XmlElement filtersXml (getTopLevelXmlEntity());
  670. fillInFiltersXml (filtersXml);
  671. writeXmlOrThrow (filtersXml, getVCProjFiltersFile(), "UTF-8", 100);
  672. }
  673. }
  674. String getSolutionTargetPath (const BuildConfiguration& config) const
  675. {
  676. const String binaryPath (config.getTargetBinaryRelativePathString().trim());
  677. if (binaryPath.isEmpty())
  678. return "$(SolutionDir)$(Platform)\\$(Configuration)";
  679. RelativePath binaryRelPath (binaryPath, RelativePath::projectFolder);
  680. if (binaryRelPath.isAbsolute())
  681. return binaryRelPath.toWindowsStyle();
  682. return prependDot (binaryRelPath.rebased (getOwner().projectFolder, getOwner().getTargetFolder(), RelativePath::buildTargetFolder)
  683. .toWindowsStyle());
  684. }
  685. String getConfigTargetPath (const BuildConfiguration& config) const
  686. {
  687. String solutionTargetFolder (getSolutionTargetPath (config));
  688. return solutionTargetFolder + String ("\\") + getName();
  689. }
  690. String getIntermediatesPath (const MSVCBuildConfiguration& config) const
  691. {
  692. String intDir = (config.getIntermediatesPath().isNotEmpty() ? config.getIntermediatesPath() : "$(Platform)\\$(Configuration)");
  693. if (! intDir.endsWithChar (L'\\'))
  694. intDir += L'\\';
  695. return intDir + getName();
  696. }
  697. static const char* getOptimisationLevelString (int level)
  698. {
  699. switch (level)
  700. {
  701. case optimiseMaxSpeed: return "Full";
  702. case optimiseMinSize: return "MinSpace";
  703. default: return "Disabled";
  704. }
  705. }
  706. String getTargetSuffix() const
  707. {
  708. const ProjectType::Target::TargetFileType fileType = getTargetFileType();
  709. switch (fileType)
  710. {
  711. case executable: return ".exe";
  712. case staticLibrary: return ".lib";
  713. case sharedLibraryOrDLL: return ".dll";
  714. case pluginBundle:
  715. switch (type)
  716. {
  717. case VST3PlugIn: return ".vst3";
  718. case AAXPlugIn: return ".aaxdll";
  719. case RTASPlugIn: return ".dpm";
  720. default: break;
  721. }
  722. return ".dll";
  723. default:
  724. break;
  725. }
  726. return {};
  727. }
  728. XmlElement* createToolElement (XmlElement& parent, const String& toolName) const
  729. {
  730. XmlElement* const e = parent.createNewChildElement ("Tool");
  731. e->setAttribute ("Name", toolName);
  732. return e;
  733. }
  734. String getPreprocessorDefs (const BuildConfiguration& config, const String& joinString) const
  735. {
  736. StringPairArray defines (getOwner().msvcExtraPreprocessorDefs);
  737. defines.set ("WIN32", "");
  738. defines.set ("_WINDOWS", "");
  739. if (config.isDebug())
  740. {
  741. defines.set ("DEBUG", "");
  742. defines.set ("_DEBUG", "");
  743. }
  744. else
  745. {
  746. defines.set ("NDEBUG", "");
  747. }
  748. defines = mergePreprocessorDefs (defines, getOwner().getAllPreprocessorDefs (config, type));
  749. addExtraPreprocessorDefines (defines);
  750. if (getTargetFileType() == staticLibrary || getTargetFileType() == sharedLibraryOrDLL)
  751. defines.set("_LIB", "");
  752. StringArray result;
  753. for (int i = 0; i < defines.size(); ++i)
  754. {
  755. String def (defines.getAllKeys()[i]);
  756. const String value (defines.getAllValues()[i]);
  757. if (value.isNotEmpty())
  758. def << "=" << value;
  759. result.add (def);
  760. }
  761. return result.joinIntoString (joinString);
  762. }
  763. //==============================================================================
  764. RelativePath getAAXIconFile() const
  765. {
  766. const RelativePath aaxSDK (getOwner().getAAXPathValue().toString(), RelativePath::projectFolder);
  767. const RelativePath projectIcon ("icon.ico", RelativePath::buildTargetFolder);
  768. if (getOwner().getTargetFolder().getChildFile ("icon.ico").existsAsFile())
  769. return projectIcon.rebased (getOwner().getTargetFolder(),
  770. getOwner().getProject().getProjectFolder(),
  771. RelativePath::projectFolder);
  772. else
  773. return aaxSDK.getChildFile ("Utilities").getChildFile ("PlugIn.ico");
  774. }
  775. String getExtraPostBuildSteps (const MSVCBuildConfiguration& config) const
  776. {
  777. if (type == AAXPlugIn)
  778. {
  779. const RelativePath aaxSDK (getOwner().getAAXPathValue().toString(), RelativePath::projectFolder);
  780. const RelativePath aaxLibsFolder = aaxSDK.getChildFile ("Libs");
  781. const RelativePath bundleScript = aaxSDK.getChildFile ("Utilities").getChildFile ("CreatePackage.bat");
  782. const RelativePath iconFilePath = getAAXIconFile();
  783. const bool is64Bit = (config.config [Ids::winArchitecture] == "x64");
  784. const String bundleDir = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", true));
  785. const String bundleContents = bundleDir + "\\Contents";
  786. const String macOSDir = bundleContents + String ("\\") + (is64Bit ? "x64" : "Win32");
  787. const String executable = macOSDir + String ("\\") + config.getOutputFilename (".aaxplugin", true);
  788. return String ("copy /Y \"") + getOutputFilePath (config) + String ("\" \"") + executable + String ("\"\r\ncall ") +
  789. createRebasedPath (bundleScript) + String (" \"") + macOSDir + String ("\" ") + createRebasedPath (iconFilePath);
  790. }
  791. return {};
  792. }
  793. String getExtraPreBuildSteps (const MSVCBuildConfiguration& config) const
  794. {
  795. if (type == AAXPlugIn)
  796. {
  797. String script;
  798. const bool is64Bit = (config.config [Ids::winArchitecture] == "x64");
  799. const String bundleDir = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", false));
  800. const String bundleContents = bundleDir + "\\Contents";
  801. const String macOSDir = bundleContents + String ("\\") + (is64Bit ? "x64" : "Win32");
  802. StringArray folders = {bundleDir.toRawUTF8(), bundleContents.toRawUTF8(), macOSDir.toRawUTF8()};
  803. for (int i = 0; i < folders.size(); ++i)
  804. script += String ("if not exist \"") + folders[i] + String ("\" mkdir \"") + folders[i] + String ("\"\r\n");
  805. return script;
  806. }
  807. return {};
  808. }
  809. String getPostBuildSteps (const MSVCBuildConfiguration& config) const
  810. {
  811. String postBuild = config.getPostbuildCommandString();
  812. const String extraPostBuild = getExtraPostBuildSteps (config);
  813. postBuild += String (postBuild.isNotEmpty() && extraPostBuild.isNotEmpty() ? "\r\n" : "") + extraPostBuild;
  814. return postBuild;
  815. }
  816. String getPreBuildSteps (const MSVCBuildConfiguration& config) const
  817. {
  818. String preBuild = config.getPrebuildCommandString();
  819. const String extraPreBuild = getExtraPreBuildSteps (config);
  820. preBuild += String (preBuild.isNotEmpty() && extraPreBuild.isNotEmpty() ? "\r\n" : "") + extraPreBuild;
  821. return preBuild;
  822. }
  823. void addExtraPreprocessorDefines (StringPairArray& defines) const
  824. {
  825. switch (type)
  826. {
  827. case AAXPlugIn:
  828. {
  829. const RelativePath aaxLibsFolder = RelativePath (getOwner().getAAXPathValue().toString(), RelativePath::projectFolder).getChildFile ("Libs");
  830. defines.set ("JucePlugin_AAXLibs_path", createRebasedPath (aaxLibsFolder));
  831. }
  832. break;
  833. case RTASPlugIn:
  834. {
  835. const RelativePath rtasFolder (getOwner().getRTASPathValue().toString(), RelativePath::projectFolder);
  836. defines.set ("JucePlugin_WinBag_path", createRebasedPath (rtasFolder.getChildFile ("WinBag")));
  837. }
  838. break;
  839. default:
  840. break;
  841. }
  842. }
  843. String getExtraLinkerFlags() const
  844. {
  845. if (type == RTASPlugIn)
  846. return "/FORCE:multiple";
  847. return {};
  848. }
  849. StringArray getExtraSearchPaths() const
  850. {
  851. StringArray searchPaths;
  852. if (type == RTASPlugIn)
  853. {
  854. const RelativePath rtasFolder (getOwner().getRTASPathValue().toString(), RelativePath::projectFolder);
  855. static const char* p[] = { "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses",
  856. "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses",
  857. "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses/Interfaces",
  858. "AlturaPorts/TDMPlugins/PluginLibrary/Utilities",
  859. "AlturaPorts/TDMPlugins/PluginLibrary/RTASP_Adapt",
  860. "AlturaPorts/TDMPlugins/PluginLibrary/CoreClasses",
  861. "AlturaPorts/TDMPlugins/PluginLibrary/Controls",
  862. "AlturaPorts/TDMPlugins/PluginLibrary/Meters",
  863. "AlturaPorts/TDMPlugins/PluginLibrary/ViewClasses",
  864. "AlturaPorts/TDMPlugins/PluginLibrary/DSPClasses",
  865. "AlturaPorts/TDMPlugins/PluginLibrary/Interfaces",
  866. "AlturaPorts/TDMPlugins/common",
  867. "AlturaPorts/TDMPlugins/common/Platform",
  868. "AlturaPorts/TDMPlugins/common/Macros",
  869. "AlturaPorts/TDMPlugins/SignalProcessing/Public",
  870. "AlturaPorts/TDMPlugIns/DSPManager/Interfaces",
  871. "AlturaPorts/SADriver/Interfaces",
  872. "AlturaPorts/DigiPublic/Interfaces",
  873. "AlturaPorts/DigiPublic",
  874. "AlturaPorts/Fic/Interfaces/DAEClient",
  875. "AlturaPorts/NewFileLibs/Cmn",
  876. "AlturaPorts/NewFileLibs/DOA",
  877. "AlturaPorts/AlturaSource/PPC_H",
  878. "AlturaPorts/AlturaSource/AppSupport",
  879. "AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc",
  880. "xplat/AVX/avx2/avx2sdk/inc" };
  881. for (int i = 0; i < numElementsInArray (p); ++i)
  882. searchPaths.add (createRebasedPath (rtasFolder.getChildFile (p[i])));
  883. }
  884. return searchPaths;
  885. }
  886. String getBinaryNameWithSuffix (const MSVCBuildConfiguration& config) const
  887. {
  888. return config.getOutputFilename (getTargetSuffix(), true);
  889. }
  890. String getOutputFilePath (const MSVCBuildConfiguration& config) const
  891. {
  892. return getOwner().getOutDirFile (config, getBinaryNameWithSuffix (config));
  893. }
  894. StringArray getLibrarySearchPaths (const BuildConfiguration& config) const
  895. {
  896. StringArray librarySearchPaths (config.getLibrarySearchPaths());
  897. if (type != SharedCodeTarget)
  898. if (const MSVCTargetBase* shared = getOwner().getSharedCodeTarget())
  899. librarySearchPaths.add (shared->getConfigTargetPath (config));
  900. return librarySearchPaths;
  901. }
  902. String getExternalLibraries (const MSVCBuildConfiguration& config, const String& otherLibs) const
  903. {
  904. StringArray libraries;
  905. if (otherLibs.isNotEmpty())
  906. libraries.add (otherLibs);
  907. StringArray moduleLibs = getOwner().getModuleLibs();
  908. if (! moduleLibs.isEmpty())
  909. libraries.addArray (moduleLibs);
  910. if (type != SharedCodeTarget)
  911. if (const MSVCTargetBase* shared = getOwner().getSharedCodeTarget())
  912. libraries.add (shared->getBinaryNameWithSuffix (config));
  913. return libraries.joinIntoString (";");
  914. }
  915. String getDelayLoadedDLLs() const
  916. {
  917. String delayLoadedDLLs = getOwner().msvcDelayLoadedDLLs;
  918. if (type == RTASPlugIn)
  919. delayLoadedDLLs += "DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; "
  920. "DSPManager.dll; DSPManager.dll; DSPManagerClientLib.dll; RTASClientLib.dll";
  921. return delayLoadedDLLs;
  922. }
  923. String getModuleDefinitions (const MSVCBuildConfiguration& config) const
  924. {
  925. const String& moduleDefinitions = config.config [Ids::msvcModuleDefinitionFile].toString();
  926. if (moduleDefinitions.isNotEmpty())
  927. return moduleDefinitions;
  928. if (type == RTASPlugIn)
  929. {
  930. const ProjectExporter& exp = getOwner();
  931. RelativePath moduleDefPath
  932. = RelativePath (exp.getPathForModuleString ("juce_audio_plugin_client"), RelativePath::projectFolder)
  933. .getChildFile ("juce_audio_plugin_client").getChildFile ("RTAS").getChildFile ("juce_RTAS_WinExports.def");
  934. return prependDot (moduleDefPath.rebased (exp.getProject().getProjectFolder(),
  935. exp.getTargetFolder(),
  936. RelativePath::buildTargetFolder).toWindowsStyle());
  937. }
  938. return {};
  939. }
  940. bool shouldUseRuntimeDLL (const MSVCBuildConfiguration& config) const
  941. {
  942. return (config.config [Ids::useRuntimeLibDLL].isVoid() ? (getOwner().hasTarget (AAXPlugIn) || getOwner().hasTarget (RTASPlugIn))
  943. : config.isUsingRuntimeLibDLL());
  944. }
  945. File getVCProjFile() const { return getOwner().getProjectFile (getProjectFileSuffix(), getName()); }
  946. File getVCProjFiltersFile() const { return getOwner().getProjectFile (getFiltersFileSuffix(), getName()); }
  947. String createRebasedPath (const RelativePath& path) const { return getOwner().createRebasedPath (path); }
  948. protected:
  949. const MSVCProjectExporterBase& owner;
  950. String projectGuid;
  951. };
  952. //==============================================================================
  953. bool usesMMFiles() const override { return false; }
  954. bool canCopeWithDuplicateFiles() override { return false; }
  955. bool supportsUserDefinedConfigurations() const override { return true; }
  956. bool isXcode() const override { return false; }
  957. bool isVisualStudio() const override { return true; }
  958. bool isCodeBlocks() const override { return false; }
  959. bool isMakefile() const override { return false; }
  960. bool isAndroidStudio() const override { return false; }
  961. bool isAndroid() const override { return false; }
  962. bool isWindows() const override { return true; }
  963. bool isLinux() const override { return false; }
  964. bool isOSX() const override { return false; }
  965. bool isiOS() const override { return false; }
  966. bool supportsTargetType (ProjectType::Target::Type type) const override
  967. {
  968. switch (type)
  969. {
  970. case ProjectType::Target::StandalonePlugIn:
  971. case ProjectType::Target::GUIApp:
  972. case ProjectType::Target::ConsoleApp:
  973. case ProjectType::Target::StaticLibrary:
  974. case ProjectType::Target::SharedCodeTarget:
  975. case ProjectType::Target::AggregateTarget:
  976. case ProjectType::Target::VSTPlugIn:
  977. case ProjectType::Target::VST3PlugIn:
  978. case ProjectType::Target::AAXPlugIn:
  979. case ProjectType::Target::RTASPlugIn:
  980. case ProjectType::Target::DynamicLibrary:
  981. return true;
  982. default:
  983. break;
  984. }
  985. return false;
  986. }
  987. //==============================================================================
  988. Value getManifestFile() { return getSetting (Ids::msvcManifestFile); }
  989. RelativePath getManifestPath() const
  990. {
  991. const String& path = settings [Ids::msvcManifestFile].toString();
  992. return path.isEmpty() ? RelativePath() : RelativePath (settings [Ids::msvcManifestFile], RelativePath::projectFolder);
  993. }
  994. //==============================================================================
  995. const String& getProjectName() const { return projectName; }
  996. bool launchProject() override
  997. {
  998. #if JUCE_WINDOWS
  999. return getSLNFile().startAsProcess();
  1000. #else
  1001. return false;
  1002. #endif
  1003. }
  1004. bool canLaunchProject() override
  1005. {
  1006. #if JUCE_WINDOWS
  1007. return true;
  1008. #else
  1009. return false;
  1010. #endif
  1011. }
  1012. void createExporterProperties (PropertyListBuilder& props) override
  1013. {
  1014. props.add(new TextPropertyComponent(getManifestFile(), "Manifest file", 8192, false),
  1015. "Path to a manifest input file which should be linked into your binary (path is relative to jucer file).");
  1016. }
  1017. enum OptimisationLevel
  1018. {
  1019. optimisationOff = 1,
  1020. optimiseMinSize = 2,
  1021. optimiseMaxSpeed = 3
  1022. };
  1023. //==============================================================================
  1024. void addPlatformSpecificSettingsForProjectType (const ProjectType& type) override
  1025. {
  1026. msvcExtraPreprocessorDefs.set ("_CRT_SECURE_NO_WARNINGS", "");
  1027. if (type.isCommandLineApp())
  1028. msvcExtraPreprocessorDefs.set("_CONSOLE", "");
  1029. callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType)
  1030. {
  1031. if (MSVCTargetBase* target = new MSVCTargetBase (targetType, *this))
  1032. {
  1033. if (targetType != ProjectType::Target::AggregateTarget)
  1034. targets.add (target);
  1035. }
  1036. });
  1037. // If you hit this assert, you tried to generate a project for an exporter
  1038. // that does not support any of your targets!
  1039. jassert (targets.size() > 0);
  1040. }
  1041. const MSVCTargetBase* getSharedCodeTarget() const
  1042. {
  1043. for (auto target : targets)
  1044. if (target->type == ProjectType::Target::SharedCodeTarget)
  1045. return target;
  1046. return nullptr;
  1047. }
  1048. bool hasTarget (ProjectType::Target::Type type) const
  1049. {
  1050. for (auto target : targets)
  1051. if (target->type == type)
  1052. return true;
  1053. return false;
  1054. }
  1055. private:
  1056. //==============================================================================
  1057. String createRebasedPath (const RelativePath& path) const
  1058. {
  1059. String rebasedPath = rebaseFromProjectFolderToBuildTarget (path).toWindowsStyle();
  1060. return getVisualStudioVersion() < 10 // (VS10 automatically adds escape characters to the quotes for this definition)
  1061. ? CppTokeniserFunctions::addEscapeChars (rebasedPath.quoted())
  1062. : CppTokeniserFunctions::addEscapeChars (rebasedPath).quoted();
  1063. }
  1064. protected:
  1065. //==============================================================================
  1066. mutable File rcFile, iconFile;
  1067. OwnedArray<MSVCTargetBase> targets;
  1068. File getProjectFile (const String& extension, const String& target) const
  1069. {
  1070. String filename = project.getProjectFilenameRoot();
  1071. if (target.isNotEmpty())
  1072. filename += String ("_") + target.removeCharacters (" ");
  1073. return getTargetFolder().getChildFile (filename).withFileExtension (extension);
  1074. }
  1075. File getSLNFile() const { return getProjectFile (".sln", String()); }
  1076. static String prependIfNotAbsolute (const String& file, const char* prefix)
  1077. {
  1078. if (File::isAbsolutePath (file) || file.startsWithChar ('$'))
  1079. prefix = "";
  1080. return prefix + FileHelpers::windowsStylePath (file);
  1081. }
  1082. String getIntDirFile (const BuildConfiguration& config, const String& file) const { return prependIfNotAbsolute (replacePreprocessorTokens (config, file), "$(IntDir)\\"); }
  1083. String getOutDirFile (const BuildConfiguration& config, const String& file) const { return prependIfNotAbsolute (replacePreprocessorTokens (config, file), "$(OutDir)\\"); }
  1084. void updateOldSettings()
  1085. {
  1086. {
  1087. const String oldStylePrebuildCommand (getSettingString (Ids::prebuildCommand));
  1088. settings.removeProperty (Ids::prebuildCommand, nullptr);
  1089. if (oldStylePrebuildCommand.isNotEmpty())
  1090. for (ConfigIterator config (*this); config.next();)
  1091. dynamic_cast<MSVCBuildConfiguration&> (*config).getPrebuildCommand() = oldStylePrebuildCommand;
  1092. }
  1093. {
  1094. const String oldStyleLibName (getSettingString ("libraryName_Debug"));
  1095. settings.removeProperty ("libraryName_Debug", nullptr);
  1096. if (oldStyleLibName.isNotEmpty())
  1097. for (ConfigIterator config (*this); config.next();)
  1098. if (config->isDebug())
  1099. config->getTargetBinaryName() = oldStyleLibName;
  1100. }
  1101. {
  1102. const String oldStyleLibName (getSettingString ("libraryName_Release"));
  1103. settings.removeProperty ("libraryName_Release", nullptr);
  1104. if (oldStyleLibName.isNotEmpty())
  1105. for (ConfigIterator config (*this); config.next();)
  1106. if (! config->isDebug())
  1107. config->getTargetBinaryName() = oldStyleLibName;
  1108. }
  1109. }
  1110. BuildConfiguration::Ptr createBuildConfig (const ValueTree& v) const override
  1111. {
  1112. return new MSVCBuildConfiguration (project, v, *this);
  1113. }
  1114. StringArray getHeaderSearchPaths (const BuildConfiguration& config) const
  1115. {
  1116. StringArray searchPaths (extraSearchPaths);
  1117. searchPaths.addArray (config.getHeaderSearchPaths());
  1118. return getCleanedStringArray (searchPaths);
  1119. }
  1120. String getSharedCodeGuid() const
  1121. {
  1122. String sharedCodeGuid;
  1123. for (int i = 0; i < targets.size(); ++i)
  1124. if (MSVCTargetBase* target = targets[i])
  1125. if (target->type == ProjectType::Target::SharedCodeTarget)
  1126. return target->getProjectGuid();
  1127. return {};
  1128. }
  1129. //==============================================================================
  1130. void writeProjectDependencies (OutputStream& out) const
  1131. {
  1132. const String sharedCodeGuid = getSharedCodeGuid();
  1133. for (int addingOtherTargets = 0; addingOtherTargets < (sharedCodeGuid.isNotEmpty() ? 2 : 1); ++addingOtherTargets)
  1134. {
  1135. for (int i = 0; i < targets.size(); ++i)
  1136. {
  1137. if (MSVCTargetBase* target = targets[i])
  1138. {
  1139. if (sharedCodeGuid.isEmpty() || (addingOtherTargets != 0) == (target->type != ProjectType::Target::StandalonePlugIn))
  1140. {
  1141. out << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" << projectName << " - "
  1142. << target->getName() << "\", \""
  1143. << target->getVCProjFile().getFileName() << "\", \"" << target->getProjectGuid() << '"' << newLine;
  1144. if (sharedCodeGuid.isNotEmpty() && target->type != ProjectType::Target::SharedCodeTarget)
  1145. out << "\tProjectSection(ProjectDependencies) = postProject" << newLine
  1146. << "\t\t" << sharedCodeGuid << " = " << sharedCodeGuid << newLine
  1147. << "\tEndProjectSection" << newLine;
  1148. out << "EndProject" << newLine;
  1149. }
  1150. }
  1151. }
  1152. }
  1153. }
  1154. void writeSolutionFile (OutputStream& out, const String& versionString, String commentString) const
  1155. {
  1156. if (commentString.isNotEmpty())
  1157. commentString += newLine;
  1158. out << "Microsoft Visual Studio Solution File, Format Version " << versionString << newLine
  1159. << commentString << newLine;
  1160. writeProjectDependencies (out);
  1161. out << "Global" << newLine
  1162. << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution" << newLine;
  1163. for (ConstConfigIterator i (*this); i.next();)
  1164. {
  1165. const MSVCBuildConfiguration& config = dynamic_cast<const MSVCBuildConfiguration&> (*i);
  1166. const String configName = config.createMSVCConfigName();
  1167. out << "\t\t" << configName << " = " << configName << newLine;
  1168. }
  1169. out << "\tEndGlobalSection" << newLine
  1170. << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution" << newLine;
  1171. for (auto& target : targets)
  1172. for (ConstConfigIterator i (*this); i.next();)
  1173. {
  1174. const MSVCBuildConfiguration& config = dynamic_cast<const MSVCBuildConfiguration&> (*i);
  1175. const String configName = config.createMSVCConfigName();
  1176. for (auto& suffix : { "ActiveCfg", "Build.0" })
  1177. out << "\t\t" << target->getProjectGuid() << "." << configName << "." << suffix << " = " << configName << newLine;
  1178. }
  1179. out << "\tEndGlobalSection" << newLine
  1180. << "\tGlobalSection(SolutionProperties) = preSolution" << newLine
  1181. << "\t\tHideSolutionNode = FALSE" << newLine
  1182. << "\tEndGlobalSection" << newLine;
  1183. out << "EndGlobal" << newLine;
  1184. }
  1185. //==============================================================================
  1186. static void writeBMPImage (const Image& image, const int w, const int h, MemoryOutputStream& out)
  1187. {
  1188. const int maskStride = (w / 8 + 3) & ~3;
  1189. out.writeInt (40); // bitmapinfoheader size
  1190. out.writeInt (w);
  1191. out.writeInt (h * 2);
  1192. out.writeShort (1); // planes
  1193. out.writeShort (32); // bits
  1194. out.writeInt (0); // compression
  1195. out.writeInt ((h * w * 4) + (h * maskStride)); // size image
  1196. out.writeInt (0); // x pixels per meter
  1197. out.writeInt (0); // y pixels per meter
  1198. out.writeInt (0); // clr used
  1199. out.writeInt (0); // clr important
  1200. const Image::BitmapData bitmap (image, Image::BitmapData::readOnly);
  1201. const int alphaThreshold = 5;
  1202. int y;
  1203. for (y = h; --y >= 0;)
  1204. {
  1205. for (int x = 0; x < w; ++x)
  1206. {
  1207. const Colour pixel (bitmap.getPixelColour (x, y));
  1208. if (pixel.getAlpha() <= alphaThreshold)
  1209. {
  1210. out.writeInt (0);
  1211. }
  1212. else
  1213. {
  1214. out.writeByte ((char) pixel.getBlue());
  1215. out.writeByte ((char) pixel.getGreen());
  1216. out.writeByte ((char) pixel.getRed());
  1217. out.writeByte ((char) pixel.getAlpha());
  1218. }
  1219. }
  1220. }
  1221. for (y = h; --y >= 0;)
  1222. {
  1223. int mask = 0, count = 0;
  1224. for (int x = 0; x < w; ++x)
  1225. {
  1226. const Colour pixel (bitmap.getPixelColour (x, y));
  1227. mask <<= 1;
  1228. if (pixel.getAlpha() <= alphaThreshold)
  1229. mask |= 1;
  1230. if (++count == 8)
  1231. {
  1232. out.writeByte ((char) mask);
  1233. count = 0;
  1234. mask = 0;
  1235. }
  1236. }
  1237. if (mask != 0)
  1238. out.writeByte ((char) mask);
  1239. for (int i = maskStride - w / 8; --i >= 0;)
  1240. out.writeByte (0);
  1241. }
  1242. }
  1243. static void writeIconFile (const Array<Image>& images, MemoryOutputStream& out)
  1244. {
  1245. out.writeShort (0); // reserved
  1246. out.writeShort (1); // .ico tag
  1247. out.writeShort ((short) images.size());
  1248. MemoryOutputStream dataBlock;
  1249. const int imageDirEntrySize = 16;
  1250. const int dataBlockStart = 6 + images.size() * imageDirEntrySize;
  1251. for (int i = 0; i < images.size(); ++i)
  1252. {
  1253. const size_t oldDataSize = dataBlock.getDataSize();
  1254. const Image& image = images.getReference (i);
  1255. const int w = image.getWidth();
  1256. const int h = image.getHeight();
  1257. if (w >= 256 || h >= 256)
  1258. {
  1259. PNGImageFormat pngFormat;
  1260. pngFormat.writeImageToStream (image, dataBlock);
  1261. }
  1262. else
  1263. {
  1264. writeBMPImage (image, w, h, dataBlock);
  1265. }
  1266. out.writeByte ((char) w);
  1267. out.writeByte ((char) h);
  1268. out.writeByte (0);
  1269. out.writeByte (0);
  1270. out.writeShort (1); // colour planes
  1271. out.writeShort (32); // bits per pixel
  1272. out.writeInt ((int) (dataBlock.getDataSize() - oldDataSize));
  1273. out.writeInt (dataBlockStart + (int) oldDataSize);
  1274. }
  1275. jassert (out.getPosition() == dataBlockStart);
  1276. out << dataBlock;
  1277. }
  1278. bool hasResourceFile() const
  1279. {
  1280. return ! projectType.isStaticLibrary();
  1281. }
  1282. void createResourcesAndIcon() const
  1283. {
  1284. if (hasResourceFile())
  1285. {
  1286. Array<Image> images;
  1287. const int sizes[] = { 16, 32, 48, 256 };
  1288. for (int i = 0; i < numElementsInArray (sizes); ++i)
  1289. {
  1290. Image im (getBestIconForSize (sizes[i], true));
  1291. if (im.isValid())
  1292. images.add (im);
  1293. }
  1294. if (images.size() > 0)
  1295. {
  1296. iconFile = getTargetFolder().getChildFile ("icon.ico");
  1297. MemoryOutputStream mo;
  1298. writeIconFile (images, mo);
  1299. overwriteFileIfDifferentOrThrow (iconFile, mo);
  1300. }
  1301. createRCFile();
  1302. }
  1303. }
  1304. void createRCFile() const
  1305. {
  1306. rcFile = getTargetFolder().getChildFile ("resources.rc");
  1307. const String version (project.getVersionString());
  1308. MemoryOutputStream mo;
  1309. mo << "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine
  1310. << " #include JUCE_USER_DEFINED_RC_FILE" << newLine
  1311. << "#else" << newLine
  1312. << newLine
  1313. << "#undef WIN32_LEAN_AND_MEAN" << newLine
  1314. << "#define WIN32_LEAN_AND_MEAN" << newLine
  1315. << "#include <windows.h>" << newLine
  1316. << newLine
  1317. << "VS_VERSION_INFO VERSIONINFO" << newLine
  1318. << "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine
  1319. << "BEGIN" << newLine
  1320. << " BLOCK \"StringFileInfo\"" << newLine
  1321. << " BEGIN" << newLine
  1322. << " BLOCK \"040904E4\"" << newLine
  1323. << " BEGIN" << newLine;
  1324. writeRCValue (mo, "CompanyName", project.getCompanyName().toString());
  1325. writeRCValue (mo, "FileDescription", project.getTitle());
  1326. writeRCValue (mo, "FileVersion", version);
  1327. writeRCValue (mo, "ProductName", project.getTitle());
  1328. writeRCValue (mo, "ProductVersion", version);
  1329. mo << " END" << newLine
  1330. << " END" << newLine
  1331. << newLine
  1332. << " BLOCK \"VarFileInfo\"" << newLine
  1333. << " BEGIN" << newLine
  1334. << " VALUE \"Translation\", 0x409, 1252" << newLine
  1335. << " END" << newLine
  1336. << "END" << newLine
  1337. << newLine
  1338. << "#endif" << newLine;
  1339. if (iconFile != File())
  1340. mo << newLine
  1341. << "IDI_ICON1 ICON DISCARDABLE " << iconFile.getFileName().quoted()
  1342. << newLine
  1343. << "IDI_ICON2 ICON DISCARDABLE " << iconFile.getFileName().quoted();
  1344. overwriteFileIfDifferentOrThrow (rcFile, mo);
  1345. }
  1346. static void writeRCValue (MemoryOutputStream& mo, const String& name, const String& value)
  1347. {
  1348. if (value.isNotEmpty())
  1349. mo << " VALUE \"" << name << "\", \""
  1350. << CppTokeniserFunctions::addEscapeChars (value) << "\\0\"" << newLine;
  1351. }
  1352. static String getCommaSeparatedVersionNumber (const String& version)
  1353. {
  1354. StringArray versionParts;
  1355. versionParts.addTokens (version, ",.", "");
  1356. versionParts.trim();
  1357. versionParts.removeEmptyStrings();
  1358. while (versionParts.size() < 4)
  1359. versionParts.add ("0");
  1360. return versionParts.joinIntoString (",");
  1361. }
  1362. static String prependDot (const String& filename)
  1363. {
  1364. return FileHelpers::isAbsolutePath (filename) ? filename
  1365. : (".\\" + filename);
  1366. }
  1367. void initialiseDependencyPathValues()
  1368. {
  1369. vst3Path.referTo (Value (new DependencyPathValueSource (getSetting (Ids::vst3Folder),
  1370. Ids::vst3Path,
  1371. TargetOS::windows)));
  1372. aaxPath.referTo (Value (new DependencyPathValueSource (getSetting (Ids::aaxFolder),
  1373. Ids::aaxPath,
  1374. TargetOS::windows)));
  1375. rtasPath.referTo (Value (new DependencyPathValueSource (getSetting (Ids::rtasFolder),
  1376. Ids::rtasPath,
  1377. TargetOS::windows)));
  1378. }
  1379. static bool shouldUseStdCall (const RelativePath& path)
  1380. {
  1381. return path.getFileNameWithoutExtension().startsWithIgnoreCase ("juce_audio_plugin_client_RTAS_");
  1382. }
  1383. StringArray getModuleLibs() const
  1384. {
  1385. StringArray result;
  1386. for (auto& lib : windowsLibs)
  1387. result.add (lib + ".lib");
  1388. return result;
  1389. }
  1390. JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterBase)
  1391. };
  1392. //==============================================================================
  1393. class MSVCProjectExporterVC2013 : public MSVCProjectExporterBase
  1394. {
  1395. public:
  1396. MSVCProjectExporterVC2013 (Project& p, const ValueTree& t)
  1397. : MSVCProjectExporterBase (p, t, "VisualStudio2013")
  1398. {
  1399. name = getName();
  1400. }
  1401. static const char* getName() { return "Visual Studio 2013"; }
  1402. static const char* getValueTreeTypeName() { return "VS2013"; }
  1403. int getVisualStudioVersion() const override { return 12; }
  1404. String getSolutionComment() const override { return "# Visual Studio 2013"; }
  1405. String getToolsVersion() const override { return "12.0"; }
  1406. String getDefaultToolset() const override { return "v120"; }
  1407. String getDefaultWindowsTargetPlatformVersion() const override { return "8.1"; }
  1408. static MSVCProjectExporterVC2013* createForSettings (Project& project, const ValueTree& settings)
  1409. {
  1410. if (settings.hasType (getValueTreeTypeName()))
  1411. return new MSVCProjectExporterVC2013 (project, settings);
  1412. return nullptr;
  1413. }
  1414. void createExporterProperties (PropertyListBuilder& props) override
  1415. {
  1416. MSVCProjectExporterBase::createExporterProperties (props);
  1417. static const char* toolsetNames[] = { "(default)", "v120", "v120_xp", "Windows7.1SDK", "CTP_Nov2013" };
  1418. const var toolsets[] = { var(), "v120", "v120_xp", "Windows7.1SDK", "CTP_Nov2013" };
  1419. addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));
  1420. addIPPLibraryProperty (props);
  1421. addWindowsTargetPlatformProperties (props);
  1422. }
  1423. JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2013)
  1424. };
  1425. //==============================================================================
  1426. class MSVCProjectExporterVC2015 : public MSVCProjectExporterBase
  1427. {
  1428. public:
  1429. MSVCProjectExporterVC2015 (Project& p, const ValueTree& t)
  1430. : MSVCProjectExporterBase (p, t, "VisualStudio2015")
  1431. {
  1432. name = getName();
  1433. }
  1434. static const char* getName() { return "Visual Studio 2015"; }
  1435. static const char* getValueTreeTypeName() { return "VS2015"; }
  1436. int getVisualStudioVersion() const override { return 14; }
  1437. String getSolutionComment() const override { return "# Visual Studio 2015"; }
  1438. String getToolsVersion() const override { return "14.0"; }
  1439. String getDefaultToolset() const override { return "v140"; }
  1440. String getDefaultWindowsTargetPlatformVersion() const override { return "8.1"; }
  1441. static MSVCProjectExporterVC2015* createForSettings (Project& project, const ValueTree& settings)
  1442. {
  1443. if (settings.hasType (getValueTreeTypeName()))
  1444. return new MSVCProjectExporterVC2015 (project, settings);
  1445. return nullptr;
  1446. }
  1447. void createExporterProperties (PropertyListBuilder& props) override
  1448. {
  1449. MSVCProjectExporterBase::createExporterProperties (props);
  1450. static const char* toolsetNames[] = { "(default)", "v140", "v140_xp", "CTP_Nov2013" };
  1451. const var toolsets[] = { var(), "v140", "v140_xp", "CTP_Nov2013" };
  1452. addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));
  1453. addIPPLibraryProperty (props);
  1454. addWindowsTargetPlatformProperties (props);
  1455. }
  1456. JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2015)
  1457. };
  1458. //==============================================================================
  1459. class MSVCProjectExporterVC2017 : public MSVCProjectExporterBase
  1460. {
  1461. public:
  1462. MSVCProjectExporterVC2017 (Project& p, const ValueTree& t)
  1463. : MSVCProjectExporterBase (p, t, "VisualStudio2017")
  1464. {
  1465. name = getName();
  1466. }
  1467. static const char* getName() { return "Visual Studio 2017"; }
  1468. static const char* getValueTreeTypeName() { return "VS2017"; }
  1469. int getVisualStudioVersion() const override { return 15; }
  1470. String getSolutionComment() const override { return "# Visual Studio 2017"; }
  1471. String getToolsVersion() const override { return "15.0"; }
  1472. String getDefaultToolset() const override { return "v141"; }
  1473. String getDefaultWindowsTargetPlatformVersion() const override { return "10.0.15063.0"; }
  1474. static MSVCProjectExporterVC2017* createForSettings (Project& project, const ValueTree& settings)
  1475. {
  1476. if (settings.hasType (getValueTreeTypeName()))
  1477. return new MSVCProjectExporterVC2017 (project, settings);
  1478. return nullptr;
  1479. }
  1480. void createExporterProperties (PropertyListBuilder& props) override
  1481. {
  1482. MSVCProjectExporterBase::createExporterProperties (props);
  1483. static const char* toolsetNames[] = { "(default)", "v140", "v140_xp", "v141", "v141_xp" };
  1484. const var toolsets[] = { var(), "v140", "v140_xp", "v141", "v141_xp" };
  1485. addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));
  1486. addIPPLibraryProperty (props);
  1487. addWindowsTargetPlatformProperties (props);
  1488. static const char* cppStandardNames[] = { "(default)", "C++14", "Latest C++ Standard"};
  1489. const var standards[] = { var(), "stdcpp14", "stdcpplatest" };
  1490. addCppStandardProperty (props, cppStandardNames, standards, numElementsInArray (standards));
  1491. }
  1492. JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2017)
  1493. };