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.

1320 lines
62KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCER_PROJECTEXPORT_MSVC_JUCEHEADER__
  19. #define __JUCER_PROJECTEXPORT_MSVC_JUCEHEADER__
  20. #include "jucer_ProjectExporter.h"
  21. //==============================================================================
  22. class MSVCProjectExporterBase : public ProjectExporter
  23. {
  24. public:
  25. //==============================================================================
  26. MSVCProjectExporterBase (Project& project_, const ValueTree& settings_, const char* const folderName)
  27. : ProjectExporter (project_, settings_)
  28. {
  29. if (getTargetLocation().toString().isEmpty())
  30. getTargetLocation() = getDefaultBuildsRootFolder() + folderName;
  31. if (getVSTFolder().toString().isEmpty())
  32. getVSTFolder() = "c:\\SDKs\\vstsdk2.4";
  33. if (getRTASFolder().toString().isEmpty())
  34. getRTASFolder() = "c:\\SDKs\\PT_80_SDK";
  35. if ((int) getLibraryType().getValue() <= 0)
  36. getLibraryType() = 1;
  37. projectGUID = createGUID (project.getProjectUID());
  38. }
  39. ~MSVCProjectExporterBase() {}
  40. //==============================================================================
  41. bool isPossibleForCurrentProject() { return true; }
  42. bool usesMMFiles() const { return false; }
  43. void createPropertyEditors (Array <PropertyComponent*>& props)
  44. {
  45. ProjectExporter::createPropertyEditors (props);
  46. if (project.isLibrary())
  47. {
  48. const char* const libTypes[] = { "Static Library (.lib)", "Dynamic Library (.dll)", 0 };
  49. const int libTypeValues[] = { 1, 2, 0 };
  50. props.add (new ChoicePropertyComponent (getLibraryType(), "Library Type", StringArray (libTypes), Array<var> (libTypeValues)));
  51. props.add (new TextPropertyComponent (getSetting (Ids::libraryName_Debug), "Library Name (Debug)", 128, false));
  52. props.getLast()->setTooltip ("If set, this name will override the binary name specified in the configuration settings, for a debug build. You must include the .lib or .dll suffix on this filename.");
  53. props.add (new TextPropertyComponent (getSetting (Ids::libraryName_Release), "Library Name (Release)", 128, false));
  54. props.getLast()->setTooltip ("If set, this name will override the binary name specified in the configuration settings, for a release build. You must include the .lib or .dll suffix on this filename.");
  55. }
  56. }
  57. protected:
  58. String projectGUID;
  59. const File getProjectFile (const String& extension) const { return getTargetFolder().getChildFile (project.getProjectFilenameRoot()).withFileExtension (extension); }
  60. Value getLibraryType() const { return getSetting (Ids::libraryType); }
  61. bool isLibraryDLL() const { return project.isLibrary() && getLibraryType() == 2; }
  62. //==============================================================================
  63. const Array<RelativePath> getRTASFilesRequired() const
  64. {
  65. Array<RelativePath> s;
  66. if (isRTAS())
  67. {
  68. static const char* files[] = { "extras/audio plugins/wrapper/RTAS/juce_RTAS_DigiCode1.cpp",
  69. "extras/audio plugins/wrapper/RTAS/juce_RTAS_DigiCode2.cpp",
  70. "extras/audio plugins/wrapper/RTAS/juce_RTAS_DigiCode3.cpp",
  71. "extras/audio plugins/wrapper/RTAS/juce_RTAS_DigiCode_Header.h",
  72. "extras/audio plugins/wrapper/RTAS/juce_RTAS_WinUtilities.cpp",
  73. "extras/audio plugins/wrapper/RTAS/juce_RTAS_Wrapper.cpp" };
  74. for (int i = 0; i < numElementsInArray (files); ++i)
  75. s.add (getJucePathFromTargetFolder().getChildFile (files[i]));
  76. }
  77. return s;
  78. }
  79. const String getIntermediatesPath (const Project::BuildConfiguration& config) const
  80. {
  81. return ".\\" + File::createLegalFileName (config.getName().toString().trim());
  82. }
  83. const String getConfigTargetPath (const Project::BuildConfiguration& config) const
  84. {
  85. const String binaryPath (config.getTargetBinaryRelativePath().toString().trim());
  86. if (binaryPath.isEmpty())
  87. return getIntermediatesPath (config);
  88. return ".\\" + RelativePath (binaryPath, RelativePath::projectFolder)
  89. .rebased (project.getFile().getParentDirectory(), getTargetFolder(), RelativePath::buildTargetFolder)
  90. .toWindowsStyle();
  91. }
  92. const String getTargetBinarySuffix() const
  93. {
  94. if (project.isLibrary())
  95. return ".lib";
  96. else if (isRTAS())
  97. return ".dpm";
  98. else if (project.isAudioPlugin() || project.isBrowserPlugin())
  99. return ".dll";
  100. return ".exe";
  101. }
  102. const String getPreprocessorDefs (const Project::BuildConfiguration& config, const String& joinString) const
  103. {
  104. StringArray defines;
  105. defines.add (getExporterIdentifierMacro());
  106. defines.add ("WIN32");
  107. defines.add ("_WINDOWS");
  108. defines.add (config.isDebug().getValue() ? "_DEBUG" : "NDEBUG");
  109. if (project.isCommandLineApp())
  110. defines.add ("_CONSOLE");
  111. if (project.isLibrary())
  112. defines.add ("_LIB");
  113. if (isRTAS())
  114. {
  115. RelativePath rtasFolder (getRTASFolder().toString(), RelativePath::unknown);
  116. defines.add ("JucePlugin_WinBag_path="
  117. + CodeHelpers::addEscapeChars (rtasFolder.getChildFile ("WinBag")
  118. .toWindowsStyle().quoted()));
  119. }
  120. defines.addArray (config.parsePreprocessorDefs());
  121. defines.addArray (parsePreprocessorDefs());
  122. return defines.joinIntoString (joinString);
  123. }
  124. const StringArray getHeaderSearchPaths (const Project::BuildConfiguration& config) const
  125. {
  126. StringArray searchPaths (config.getHeaderSearchPaths());
  127. if (project.shouldAddVSTFolderToPath() && getVSTFolder().toString().isNotEmpty())
  128. searchPaths.add (RelativePath (getVSTFolder().toString(), RelativePath::projectFolder)
  129. .rebased (project.getFile().getParentDirectory(), getTargetFolder(), RelativePath::buildTargetFolder)
  130. .toWindowsStyle());
  131. if (project.isAudioPlugin())
  132. searchPaths.add (juceWrapperFiles[0].getParentDirectory().toWindowsStyle());
  133. if (isRTAS())
  134. {
  135. static const char* rtasIncludePaths[] = { "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses",
  136. "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses",
  137. "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses/Interfaces",
  138. "AlturaPorts/TDMPlugins/PluginLibrary/Utilities",
  139. "AlturaPorts/TDMPlugins/PluginLibrary/RTASP_Adapt",
  140. "AlturaPorts/TDMPlugins/PluginLibrary/CoreClasses",
  141. "AlturaPorts/TDMPlugins/PluginLibrary/Controls",
  142. "AlturaPorts/TDMPlugins/PluginLibrary/Meters",
  143. "AlturaPorts/TDMPlugins/PluginLibrary/ViewClasses",
  144. "AlturaPorts/TDMPlugins/PluginLibrary/DSPClasses",
  145. "AlturaPorts/TDMPlugins/PluginLibrary/Interfaces",
  146. "AlturaPorts/TDMPlugins/common",
  147. "AlturaPorts/TDMPlugins/common/Platform",
  148. "AlturaPorts/TDMPlugins/SignalProcessing/Public",
  149. "AlturaPorts/TDMPlugIns/DSPManager/Interfaces",
  150. "AlturaPorts/SADriver/Interfaces",
  151. "AlturaPorts/DigiPublic/Interfaces",
  152. "AlturaPorts/Fic/Interfaces/DAEClient",
  153. "AlturaPorts/NewFileLibs/Cmn",
  154. "AlturaPorts/NewFileLibs/DOA",
  155. "AlturaPorts/AlturaSource/PPC_H",
  156. "AlturaPorts/AlturaSource/AppSupport",
  157. "AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc",
  158. "xplat/AVX/avx2/avx2sdk/inc" };
  159. RelativePath sdkFolder (getRTASFolder().toString(), RelativePath::projectFolder);
  160. sdkFolder = sdkFolder.rebased (project.getFile().getParentDirectory(), getTargetFolder(), RelativePath::buildTargetFolder);
  161. for (int i = 0; i < numElementsInArray (rtasIncludePaths); ++i)
  162. searchPaths.add (sdkFolder.getChildFile (rtasIncludePaths[i]).toWindowsStyle());
  163. }
  164. return searchPaths;
  165. }
  166. const String getBinaryFileForConfig (const Project::BuildConfiguration& config) const
  167. {
  168. const String targetBinary (getSetting (config.isDebug().getValue() ? Ids::libraryName_Debug : Ids::libraryName_Release).toString().trim());
  169. if (targetBinary.isNotEmpty())
  170. return targetBinary;
  171. return config.getTargetBinaryName().toString() + getTargetBinarySuffix();
  172. }
  173. static const String createConfigName (const Project::BuildConfiguration& config)
  174. {
  175. return config.getName().toString() + "|Win32";
  176. }
  177. //==============================================================================
  178. void writeSolutionFile (OutputStream& out, const String& versionString, const File& vcProject)
  179. {
  180. out << newLine << "Microsoft Visual Studio Solution File, Format Version " << versionString << newLine
  181. << "Project(\"" << createGUID (project.getProjectName().toString() + "sln_guid") << "\") = \"" << project.getProjectName().toString() << "\", \""
  182. << vcProject.getFileName() << "\", \"" << projectGUID << '"' << newLine
  183. << "EndProject" << newLine
  184. << "Global" << newLine
  185. << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution" << newLine;
  186. int i;
  187. for (i = 0; i < project.getNumConfigurations(); ++i)
  188. {
  189. Project::BuildConfiguration config (project.getConfiguration (i));
  190. out << "\t\t" << createConfigName (config) << " = " << createConfigName (config) << newLine;
  191. }
  192. out << "\tEndGlobalSection" << newLine
  193. << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution" << newLine;
  194. for (i = 0; i < project.getNumConfigurations(); ++i)
  195. {
  196. Project::BuildConfiguration config (project.getConfiguration (i));
  197. out << "\t\t" << projectGUID << "." << createConfigName (config) << ".ActiveCfg = " << createConfigName (config) << newLine;
  198. out << "\t\t" << projectGUID << "." << createConfigName (config) << ".Build.0 = " << createConfigName (config) << newLine;
  199. }
  200. out << "\tEndGlobalSection" << newLine
  201. << "\tGlobalSection(SolutionProperties) = preSolution" << newLine
  202. << "\t\tHideSolutionNode = FALSE" << newLine
  203. << "\tEndGlobalSection" << newLine
  204. << "EndGlobal" << newLine;
  205. }
  206. MSVCProjectExporterBase (const MSVCProjectExporterBase&);
  207. MSVCProjectExporterBase& operator= (const MSVCProjectExporterBase&);
  208. };
  209. //==============================================================================
  210. class MSVCProjectExporterVC2008 : public MSVCProjectExporterBase
  211. {
  212. public:
  213. //==============================================================================
  214. MSVCProjectExporterVC2008 (Project& project_, const ValueTree& settings_, const char* folderName = "VisualStudio2008")
  215. : MSVCProjectExporterBase (project_, settings_, folderName)
  216. {
  217. name = getName();
  218. }
  219. ~MSVCProjectExporterVC2008() {}
  220. static const char* getName() { return "Visual Studio 2008"; }
  221. static const char* getValueTreeTypeName() { return "VS2008"; }
  222. void launchProject() { getSLNFile().startAsProcess(); }
  223. bool isDefaultFormatForCurrentOS()
  224. {
  225. #if JUCE_WINDOWS
  226. return true;
  227. #else
  228. return false;
  229. #endif
  230. }
  231. static MSVCProjectExporterVC2008* createForSettings (Project& project, const ValueTree& settings)
  232. {
  233. if (settings.hasType (getValueTreeTypeName()))
  234. return new MSVCProjectExporterVC2008 (project, settings);
  235. return 0;
  236. }
  237. //==============================================================================
  238. const String create()
  239. {
  240. {
  241. XmlElement projectXml ("VisualStudioProject");
  242. fillInProjectXml (projectXml);
  243. MemoryOutputStream mo;
  244. projectXml.writeToStream (mo, String::empty, false, true, "UTF-8", 10);
  245. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getVCProjFile(), mo))
  246. return "Can't write to the VC project file: " + getVCProjFile().getFullPathName();
  247. }
  248. {
  249. MemoryOutputStream mo;
  250. writeSolutionFile (mo, getSolutionVersionString(), getVCProjFile());
  251. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getSLNFile(), mo))
  252. return "Can't write to the VC solution file: " + getSLNFile().getFullPathName();
  253. }
  254. return String::empty;
  255. }
  256. protected:
  257. virtual const String getProjectVersionString() const { return "9.00"; }
  258. virtual const String getSolutionVersionString() const { return String ("10.00") + newLine + "# Visual C++ Express 2008"; }
  259. const File getVCProjFile() const { return getProjectFile (".vcproj"); }
  260. const File getSLNFile() const { return getProjectFile (".sln"); }
  261. //==============================================================================
  262. void fillInProjectXml (XmlElement& projectXml)
  263. {
  264. projectXml.setAttribute ("ProjectType", "Visual C++");
  265. projectXml.setAttribute ("Version", getProjectVersionString());
  266. projectXml.setAttribute ("Name", project.getProjectName().toString());
  267. projectXml.setAttribute ("ProjectGUID", projectGUID);
  268. projectXml.setAttribute ("TargetFrameworkVersion", "131072");
  269. {
  270. XmlElement* platforms = projectXml.createNewChildElement ("Platforms");
  271. XmlElement* platform = platforms->createNewChildElement ("Platform");
  272. platform->setAttribute ("Name", "Win32");
  273. }
  274. projectXml.createNewChildElement ("ToolFiles");
  275. createConfigs (*projectXml.createNewChildElement ("Configurations"));
  276. projectXml.createNewChildElement ("References");
  277. createFiles (*projectXml.createNewChildElement ("Files"));
  278. projectXml.createNewChildElement ("Globals");
  279. }
  280. //==============================================================================
  281. void addFile (const RelativePath& file, XmlElement& parent, const bool excludeFromBuild, const bool useStdcall)
  282. {
  283. jassert (file.getRoot() == RelativePath::buildTargetFolder);
  284. XmlElement* fileXml = parent.createNewChildElement ("File");
  285. fileXml->setAttribute ("RelativePath", file.toWindowsStyle());
  286. if (excludeFromBuild || useStdcall)
  287. {
  288. for (int i = 0; i < project.getNumConfigurations(); ++i)
  289. {
  290. Project::BuildConfiguration config (project.getConfiguration (i));
  291. XmlElement* fileConfig = fileXml->createNewChildElement ("FileConfiguration");
  292. fileConfig->setAttribute ("Name", createConfigName (config));
  293. if (excludeFromBuild)
  294. fileConfig->setAttribute ("ExcludedFromBuild", "true");
  295. XmlElement* tool = createToolElement (*fileConfig, "VCCLCompilerTool");
  296. if (useStdcall)
  297. tool->setAttribute ("CallingConvention", "2");
  298. }
  299. }
  300. }
  301. XmlElement* createGroup (const String& groupName, XmlElement& parent)
  302. {
  303. XmlElement* filter = parent.createNewChildElement ("Filter");
  304. filter->setAttribute ("Name", groupName);
  305. return filter;
  306. }
  307. void addFiles (const Project::Item& projectItem, XmlElement& parent)
  308. {
  309. if (projectItem.isGroup())
  310. {
  311. XmlElement* filter = createGroup (projectItem.getName().toString(), parent);
  312. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  313. addFiles (projectItem.getChild(i), *filter);
  314. }
  315. else
  316. {
  317. if (projectItem.shouldBeAddedToTargetProject())
  318. {
  319. const RelativePath path (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder);
  320. addFile (path, parent,
  321. projectItem.shouldBeAddedToBinaryResources() || (shouldFileBeCompiledByDefault (path) && ! projectItem.shouldBeCompiled()),
  322. false);
  323. }
  324. }
  325. }
  326. void addGroup (XmlElement& parent, const String& groupName, const Array<RelativePath>& files, const bool useStdcall)
  327. {
  328. if (files.size() > 0)
  329. {
  330. XmlElement* const group = createGroup (groupName, parent);
  331. for (int i = 0; i < files.size(); ++i)
  332. if (files.getReference(i).hasFileExtension ("cpp;c;h"))
  333. addFile (files.getReference(i), *group, false,
  334. useStdcall && shouldFileBeCompiledByDefault (files.getReference(i)));
  335. }
  336. }
  337. void createFiles (XmlElement& files)
  338. {
  339. addFiles (project.getMainGroup(), files);
  340. addGroup (files, project.getJuceCodeGroupName(), juceWrapperFiles, false);
  341. addGroup (files, "Juce VST Wrapper", getVSTFilesRequired(), false);
  342. addGroup (files, "Juce RTAS Wrapper", getRTASFilesRequired(), true);
  343. }
  344. //==============================================================================
  345. XmlElement* createToolElement (XmlElement& parent, const String& toolName) const
  346. {
  347. XmlElement* const e = parent.createNewChildElement ("Tool");
  348. e->setAttribute ("Name", toolName);
  349. return e;
  350. }
  351. void createConfig (XmlElement& xml, const Project::BuildConfiguration& config) const
  352. {
  353. String binariesPath (getConfigTargetPath (config));
  354. String intermediatesPath (getIntermediatesPath (config));
  355. const bool isDebug = (bool) config.isDebug().getValue();
  356. const String binaryName (File::createLegalFileName (config.getTargetBinaryName().toString()));
  357. xml.setAttribute ("Name", createConfigName (config));
  358. xml.setAttribute ("OutputDirectory", FileHelpers::windowsStylePath (binariesPath));
  359. xml.setAttribute ("IntermediateDirectory", FileHelpers::windowsStylePath (intermediatesPath));
  360. xml.setAttribute ("ConfigurationType", (project.isAudioPlugin() || project.isBrowserPlugin() || isLibraryDLL())
  361. ? "2" : (project.isLibrary() ? "4" : "1"));
  362. xml.setAttribute ("UseOfMFC", "0");
  363. xml.setAttribute ("ATLMinimizesCRunTimeLibraryUsage", "false");
  364. xml.setAttribute ("CharacterSet", "2");
  365. if (! isDebug)
  366. xml.setAttribute ("WholeProgramOptimization", "1");
  367. createToolElement (xml, "VCPreBuildEventTool");
  368. XmlElement* customBuild = createToolElement (xml, "VCCustomBuildTool");
  369. if (isRTAS())
  370. {
  371. RelativePath rsrFile (getJucePathFromTargetFolder().getChildFile ("extras/audio plugins/wrapper/RTAS/juce_RTAS_WinResources.rsr"));
  372. customBuild->setAttribute ("CommandLine", "copy /Y \"" + rsrFile.toWindowsStyle() + "\" \"$(TargetPath)\".rsr");
  373. customBuild->setAttribute ("Outputs", "\"$(TargetPath)\".rsr");
  374. }
  375. createToolElement (xml, "VCXMLDataGeneratorTool");
  376. createToolElement (xml, "VCWebServiceProxyGeneratorTool");
  377. if (! project.isLibrary())
  378. {
  379. XmlElement* midl = createToolElement (xml, "VCMIDLTool");
  380. midl->setAttribute ("PreprocessorDefinitions", isDebug ? "_DEBUG" : "NDEBUG");
  381. midl->setAttribute ("MkTypLibCompatible", "true");
  382. midl->setAttribute ("SuppressStartupBanner", "true");
  383. midl->setAttribute ("TargetEnvironment", "1");
  384. midl->setAttribute ("TypeLibraryName", FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".tlb"));
  385. midl->setAttribute ("HeaderFileName", "");
  386. }
  387. {
  388. XmlElement* compiler = createToolElement (xml, "VCCLCompilerTool");
  389. const int optimiseLevel = (int) config.getOptimisationLevel().getValue();
  390. compiler->setAttribute ("Optimization", optimiseLevel <= 1 ? "0" : (optimiseLevel == 2 ? "2" : "3"));
  391. if (isDebug)
  392. {
  393. compiler->setAttribute ("BufferSecurityCheck", "");
  394. compiler->setAttribute ("DebugInformationFormat", project.isLibrary() ? "3" : "4");
  395. }
  396. else
  397. {
  398. compiler->setAttribute ("InlineFunctionExpansion", "1");
  399. compiler->setAttribute ("StringPooling", "true");
  400. }
  401. compiler->setAttribute ("AdditionalIncludeDirectories", getHeaderSearchPaths (config).joinIntoString (";"));
  402. compiler->setAttribute ("PreprocessorDefinitions", getPreprocessorDefs (config, ";"));
  403. compiler->setAttribute ("RuntimeLibrary", isRTAS() ? (isDebug ? 3 : 2) // MT DLL
  404. : (isDebug ? 1 : 0)); // MT static
  405. compiler->setAttribute ("RuntimeTypeInfo", "true");
  406. compiler->setAttribute ("UsePrecompiledHeader", "0");
  407. compiler->setAttribute ("PrecompiledHeaderFile", FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".pch"));
  408. compiler->setAttribute ("AssemblerListingLocation", FileHelpers::windowsStylePath (intermediatesPath + "/"));
  409. compiler->setAttribute ("ObjectFile", FileHelpers::windowsStylePath (intermediatesPath + "/"));
  410. compiler->setAttribute ("ProgramDataBaseFileName", FileHelpers::windowsStylePath (intermediatesPath + "/"));
  411. compiler->setAttribute ("WarningLevel", "4");
  412. compiler->setAttribute ("SuppressStartupBanner", "true");
  413. if (getExtraCompilerFlags().toString().isNotEmpty())
  414. compiler->setAttribute ("AdditionalOptions", getExtraCompilerFlags().toString().trim());
  415. }
  416. createToolElement (xml, "VCManagedResourceCompilerTool");
  417. {
  418. XmlElement* resCompiler = createToolElement (xml, "VCResourceCompilerTool");
  419. resCompiler->setAttribute ("PreprocessorDefinitions", isDebug ? "_DEBUG" : "NDEBUG");
  420. }
  421. createToolElement (xml, "VCPreLinkEventTool");
  422. const String outputFileName (getBinaryFileForConfig (config));
  423. if (! project.isLibrary())
  424. {
  425. XmlElement* linker = createToolElement (xml, "VCLinkerTool");
  426. linker->setAttribute ("OutputFile", FileHelpers::windowsStylePath (binariesPath + "/" + outputFileName));
  427. linker->setAttribute ("SuppressStartupBanner", "true");
  428. if (project.getJuceLinkageMode() == Project::useLinkedJuce)
  429. linker->setAttribute ("AdditionalLibraryDirectories", getJucePathFromTargetFolder().getChildFile ("bin").toWindowsStyle());
  430. linker->setAttribute ("IgnoreDefaultLibraryNames", isDebug ? "libcmt.lib, msvcrt.lib" : "");
  431. linker->setAttribute ("GenerateDebugInformation", isDebug ? "true" : "false");
  432. linker->setAttribute ("ProgramDatabaseFile", FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".pdb"));
  433. linker->setAttribute ("SubSystem", project.isCommandLineApp() ? "1" : "2");
  434. if (! isDebug)
  435. {
  436. linker->setAttribute ("GenerateManifest", "false");
  437. linker->setAttribute ("OptimizeReferences", "2");
  438. linker->setAttribute ("EnableCOMDATFolding", "2");
  439. }
  440. linker->setAttribute ("TargetMachine", "1"); // (64-bit build = 5)
  441. String extraLinkerOptions (getExtraLinkerFlags().toString());
  442. if (isRTAS())
  443. {
  444. extraLinkerOptions += " /FORCE:multiple";
  445. linker->setAttribute ("DelayLoadDLLs", "DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; DSPManager.dll");
  446. linker->setAttribute ("ModuleDefinitionFile", getJucePathFromTargetFolder()
  447. .getChildFile ("extras/audio plugins/wrapper/RTAS/juce_RTAS_WinExports.def")
  448. .toWindowsStyle());
  449. }
  450. if (extraLinkerOptions.isNotEmpty())
  451. linker->setAttribute ("AdditionalOptions", extraLinkerOptions.trim());
  452. }
  453. else
  454. {
  455. if (isLibraryDLL())
  456. {
  457. XmlElement* linker = createToolElement (xml, "VCLinkerTool");
  458. String extraLinkerOptions (getExtraLinkerFlags().toString());
  459. extraLinkerOptions << " /IMPLIB:" << FileHelpers::windowsStylePath (binariesPath + "/" + outputFileName.upToLastOccurrenceOf (".", false, false) + ".lib");
  460. linker->setAttribute ("AdditionalOptions", extraLinkerOptions.trim());
  461. linker->setAttribute ("OutputFile", FileHelpers::windowsStylePath (binariesPath + "/" + outputFileName));
  462. linker->setAttribute ("IgnoreDefaultLibraryNames", isDebug ? "libcmt.lib, msvcrt.lib" : "");
  463. }
  464. else
  465. {
  466. XmlElement* librarian = createToolElement (xml, "VCLibrarianTool");
  467. librarian->setAttribute ("OutputFile", FileHelpers::windowsStylePath (binariesPath + "/" + outputFileName));
  468. librarian->setAttribute ("IgnoreDefaultLibraryNames", isDebug ? "libcmt.lib, msvcrt.lib" : "");
  469. }
  470. }
  471. createToolElement (xml, "VCALinkTool");
  472. createToolElement (xml, "VCManifestTool");
  473. createToolElement (xml, "VCXDCMakeTool");
  474. {
  475. XmlElement* bscMake = createToolElement (xml, "VCBscMakeTool");
  476. bscMake->setAttribute ("SuppressStartupBanner", "true");
  477. bscMake->setAttribute ("OutputFile", FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".bsc"));
  478. }
  479. createToolElement (xml, "VCFxCopTool");
  480. if (! project.isLibrary())
  481. createToolElement (xml, "VCAppVerifierTool");
  482. createToolElement (xml, "VCPostBuildEventTool");
  483. }
  484. void createConfigs (XmlElement& configs)
  485. {
  486. for (int i = 0; i < project.getNumConfigurations(); ++i)
  487. {
  488. Project::BuildConfiguration config (project.getConfiguration (i));
  489. createConfig (*configs.createNewChildElement ("Configuration"), config);
  490. }
  491. }
  492. //==============================================================================
  493. MSVCProjectExporterVC2008 (const MSVCProjectExporterVC2008&);
  494. MSVCProjectExporterVC2008& operator= (const MSVCProjectExporterVC2008&);
  495. };
  496. //==============================================================================
  497. class MSVCProjectExporterVC2005 : public MSVCProjectExporterVC2008
  498. {
  499. public:
  500. MSVCProjectExporterVC2005 (Project& project_, const ValueTree& settings_)
  501. : MSVCProjectExporterVC2008 (project_, settings_, "VisualStudio2005")
  502. {
  503. name = getName();
  504. }
  505. ~MSVCProjectExporterVC2005() {}
  506. static const char* getName() { return "Visual Studio 2005"; }
  507. static const char* getValueTreeTypeName() { return "VS2005"; }
  508. bool isDefaultFormatForCurrentOS() { return false; }
  509. static MSVCProjectExporterVC2005* createForSettings (Project& project, const ValueTree& settings)
  510. {
  511. if (settings.hasType (getValueTreeTypeName()))
  512. return new MSVCProjectExporterVC2005 (project, settings);
  513. return 0;
  514. }
  515. protected:
  516. const String getProjectVersionString() const { return "8.00"; }
  517. const String getSolutionVersionString() const { return String ("8.00") + newLine + "# Visual C++ Express 2005"; }
  518. MSVCProjectExporterVC2005 (const MSVCProjectExporterVC2005&);
  519. MSVCProjectExporterVC2005& operator= (const MSVCProjectExporterVC2005&);
  520. };
  521. //==============================================================================
  522. class MSVCProjectExporterVC6 : public MSVCProjectExporterBase
  523. {
  524. public:
  525. //==============================================================================
  526. MSVCProjectExporterVC6 (Project& project_, const ValueTree& settings_)
  527. : MSVCProjectExporterBase (project_, settings_, "MSVC6")
  528. {
  529. name = getName();
  530. }
  531. ~MSVCProjectExporterVC6() {}
  532. static const char* getName() { return "Visual C++ 6.0"; }
  533. static const char* getValueTreeTypeName() { return "MSVC6"; }
  534. bool isDefaultFormatForCurrentOS() { return false; }
  535. void launchProject() { getDSWFile().startAsProcess(); }
  536. static MSVCProjectExporterVC6* createForSettings (Project& project, const ValueTree& settings)
  537. {
  538. if (settings.hasType (getValueTreeTypeName()))
  539. return new MSVCProjectExporterVC6 (project, settings);
  540. return 0;
  541. }
  542. //==============================================================================
  543. const String create()
  544. {
  545. {
  546. MemoryOutputStream mo;
  547. writeProject (mo);
  548. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getDSPFile(), mo))
  549. return "Can't write to the VC project file: " + getDSPFile().getFullPathName();
  550. }
  551. {
  552. MemoryOutputStream mo;
  553. writeDSWFile (mo);
  554. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getDSWFile(), mo))
  555. return "Can't write to the VC solution file: " + getDSWFile().getFullPathName();
  556. }
  557. return String::empty;
  558. }
  559. private:
  560. const File getDSPFile() const { return getProjectFile (".dsp"); }
  561. const File getDSWFile() const { return getProjectFile (".dsw"); }
  562. //==============================================================================
  563. const String createConfigName (const Project::BuildConfiguration& config) const
  564. {
  565. return project.getProjectName().toString() + " - Win32 " + config.getName().toString();
  566. }
  567. void writeProject (OutputStream& out)
  568. {
  569. const String defaultConfigName (createConfigName (project.getConfiguration (0)));
  570. const bool isDLL = project.isAudioPlugin() || project.isBrowserPlugin();
  571. String targetType, targetCode;
  572. if (isDLL) { targetType = "\"Win32 (x86) Dynamic-Link Library\""; targetCode = "0x0102"; }
  573. else if (project.isLibrary()) { targetType = "\"Win32 (x86) Static Library\""; targetCode = "0x0104"; }
  574. else if (project.isCommandLineApp()) { targetType = "\"Win32 (x86) Console Application\""; targetCode = "0x0103"; }
  575. else { targetType = "\"Win32 (x86) Application\""; targetCode = "0x0101"; }
  576. out << "# Microsoft Developer Studio Project File - Name=\"" << project.getProjectName()
  577. << "\" - Package Owner=<4>" << newLine
  578. << "# Microsoft Developer Studio Generated Build File, Format Version 6.00" << newLine
  579. << "# ** DO NOT EDIT **" << newLine
  580. << "# TARGTYPE " << targetType << " " << targetCode << newLine
  581. << "CFG=" << defaultConfigName << newLine
  582. << "!MESSAGE This is not a valid makefile. To build this project using NMAKE," << newLine
  583. << "!MESSAGE use the Export Makefile command and run" << newLine
  584. << "!MESSAGE " << newLine
  585. << "!MESSAGE NMAKE /f \"" << project.getProjectName() << ".mak.\"" << newLine
  586. << "!MESSAGE " << newLine
  587. << "!MESSAGE You can specify a configuration when running NMAKE" << newLine
  588. << "!MESSAGE by defining the macro CFG on the command line. For example:" << newLine
  589. << "!MESSAGE " << newLine
  590. << "!MESSAGE NMAKE /f \"" << project.getProjectName() << ".mak\" CFG=\"" << defaultConfigName << '"' << newLine
  591. << "!MESSAGE " << newLine
  592. << "!MESSAGE Possible choices for configuration are:" << newLine
  593. << "!MESSAGE " << newLine;
  594. int i;
  595. for (i = 0; i < project.getNumConfigurations(); ++i)
  596. out << "!MESSAGE \"" << createConfigName (project.getConfiguration (i)) << "\" (based on " << targetType << ")" << newLine;
  597. out << "!MESSAGE " << newLine
  598. << "# Begin Project" << newLine
  599. << "# PROP AllowPerConfigDependencies 0" << newLine
  600. << "# PROP Scc_ProjName \"\"" << newLine
  601. << "# PROP Scc_LocalPath \"\"" << newLine
  602. << "CPP=cl.exe" << newLine
  603. << "MTL=midl.exe" << newLine
  604. << "RSC=rc.exe" << newLine;
  605. String targetList;
  606. for (i = 0; i < project.getNumConfigurations(); ++i)
  607. {
  608. const Project::BuildConfiguration config (project.getConfiguration (i));
  609. const String configName (createConfigName (config));
  610. targetList << "# Name \"" << configName << '"' << newLine;
  611. const String binariesPath (getConfigTargetPath (config));
  612. const String targetBinary (FileHelpers::windowsStylePath (binariesPath + "/" + getBinaryFileForConfig (config)));
  613. const String optimisationFlag (((int) config.getOptimisationLevel().getValue() <= 1) ? "Od" : (config.getOptimisationLevel() == 2 ? "O2" : "O3"));
  614. const String defines (getPreprocessorDefs (config, " /D "));
  615. const bool isDebug = (bool) config.isDebug().getValue();
  616. const String extraDebugFlags (isDebug ? "/Gm /ZI /GZ" : "");
  617. out << (i == 0 ? "!IF" : "!ELSEIF") << " \"$(CFG)\" == \"" << configName << '"' << newLine
  618. << "# PROP BASE Use_MFC 0" << newLine
  619. << "# PROP BASE Use_Debug_Libraries " << (isDebug ? "1" : "0") << newLine
  620. << "# PROP BASE Output_Dir \"" << binariesPath << '"' << newLine
  621. << "# PROP BASE Intermediate_Dir \"" << getIntermediatesPath (config) << '"' << newLine
  622. << "# PROP BASE Target_Dir \"\"" << newLine
  623. << "# PROP Use_MFC 0" << newLine
  624. << "# PROP Use_Debug_Libraries " << (isDebug ? "1" : "0") << newLine
  625. << "# PROP Output_Dir \"" << binariesPath << '"' << newLine
  626. << "# PROP Intermediate_Dir \"" << getIntermediatesPath (config) << '"' << newLine
  627. << "# PROP Ignore_Export_Lib 0" << newLine
  628. << "# PROP Target_Dir \"\"" << newLine
  629. << "# ADD BASE CPP /nologo /W3 /GX /" << optimisationFlag << " /D " << defines
  630. << " /YX /FD /c " << extraDebugFlags << " /Zm1024" << newLine
  631. << "# ADD CPP /nologo " << (isDebug ? "/MTd" : "/MT") << " /W3 /GR /GX /" << optimisationFlag
  632. << " /I " << getHeaderSearchPaths (config).joinIntoString (" /I ")
  633. << " /D " << defines << " /D \"_UNICODE\" /D \"UNICODE\" /FD /c /Zm1024 " << extraDebugFlags
  634. << " " << getExtraCompilerFlags().toString().trim() << newLine;
  635. if (! isDebug)
  636. out << "# SUBTRACT CPP /YX" << newLine;
  637. if (! project.isLibrary())
  638. out << "# ADD BASE MTL /nologo /D " << defines << " /mktyplib203 /win32" << newLine
  639. << "# ADD MTL /nologo /D " << defines << " /mktyplib203 /win32" << newLine;
  640. out << "# ADD BASE RSC /l 0x40c /d " << defines << newLine
  641. << "# ADD RSC /l 0x40c /d " << defines << newLine
  642. << "BSC32=bscmake.exe" << newLine
  643. << "# ADD BASE BSC32 /nologo" << newLine
  644. << "# ADD BSC32 /nologo" << newLine;
  645. if (project.isLibrary())
  646. {
  647. out << "LIB32=link.exe -lib" << newLine
  648. << "# ADD BASE LIB32 /nologo" << newLine
  649. << "# ADD LIB32 /nologo /out:\"" << targetBinary << '"' << newLine;
  650. }
  651. else
  652. {
  653. out << "LINK32=link.exe" << newLine
  654. << "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386" << newLine
  655. << "# ADD LINK32 \"C:\\Program Files\\Microsoft Visual Studio\\VC98\\LIB\\shell32.lib\" " // This is avoid debug information corruption when mixing Platform SDK
  656. << "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "
  657. << (isDebug ? " /debug" : "")
  658. << " /nologo /machine:I386 /out:\"" << targetBinary << "\" "
  659. << (isDLL ? "/dll" : (project.isCommandLineApp() ? "/subsystem:console "
  660. : "/subsystem:windows "))
  661. << getExtraLinkerFlags().toString().trim() << newLine;
  662. }
  663. }
  664. out << "!ENDIF" << newLine
  665. << "# Begin Target" << newLine
  666. << targetList;
  667. writeFiles (out, project.getMainGroup());
  668. writeGroup (out, project.getJuceCodeGroupName(), juceWrapperFiles);
  669. writeGroup (out, "Juce VST Wrapper", getVSTFilesRequired());
  670. out << "# End Target" << newLine
  671. << "# End Project" << newLine;
  672. }
  673. void writeFile (OutputStream& out, const RelativePath& file, const bool excludeFromBuild)
  674. {
  675. jassert (file.getRoot() == RelativePath::buildTargetFolder);
  676. out << "# Begin Source File" << newLine
  677. << "SOURCE=" << file.toWindowsStyle().quoted() << newLine;
  678. if (excludeFromBuild)
  679. out << "# PROP Exclude_From_Build 1" << newLine;
  680. out << "# End Source File" << newLine;
  681. }
  682. void writeFiles (OutputStream& out, const Project::Item& projectItem)
  683. {
  684. if (projectItem.isGroup())
  685. {
  686. out << "# Begin Group \"" << projectItem.getName() << '"' << newLine
  687. << "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"" << newLine;
  688. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  689. writeFiles (out, projectItem.getChild (i));
  690. out << "# End Group" << newLine;
  691. }
  692. else if (projectItem.shouldBeAddedToTargetProject())
  693. {
  694. const RelativePath path (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder);
  695. writeFile (out, path, projectItem.shouldBeAddedToBinaryResources() || (shouldFileBeCompiledByDefault (path) && ! projectItem.shouldBeCompiled()));
  696. }
  697. }
  698. void writeGroup (OutputStream& out, const String& groupName, const Array<RelativePath>& files)
  699. {
  700. if (files.size() > 0)
  701. {
  702. out << "# Begin Group \"" << groupName << '"' << newLine;
  703. for (int i = 0; i < files.size(); ++i)
  704. if (files.getReference(i).hasFileExtension ("cpp;c;h"))
  705. writeFile (out, files.getReference(i), false);
  706. out << "# End Group" << newLine;
  707. }
  708. }
  709. void writeDSWFile (OutputStream& out)
  710. {
  711. out << "Microsoft Developer Studio Workspace File, Format Version 6.00 " << newLine;
  712. if (! project.isUsingWrapperFiles())
  713. {
  714. out << "Project: \"JUCE\"= ..\\JUCE.dsp - Package Owner=<4>" << newLine
  715. << "Package=<5>" << newLine
  716. << "{{{" << newLine
  717. << "}}}" << newLine
  718. << "Package=<4>" << newLine
  719. << "{{{" << newLine
  720. << "}}}" << newLine;
  721. }
  722. out << "Project: \"" << project.getProjectName() << "\" = .\\" << getDSPFile().getFileName() << " - Package Owner=<4>" << newLine
  723. << "Package=<5>" << newLine
  724. << "{{{" << newLine
  725. << "}}}" << newLine
  726. << "Package=<4>" << newLine
  727. << "{{{" << newLine;
  728. if (! project.isUsingWrapperFiles())
  729. {
  730. out << " Begin Project Dependency" << newLine
  731. << " Project_Dep_Name JUCE" << newLine
  732. << " End Project Dependency" << newLine;
  733. }
  734. out << "}}}" << newLine
  735. << "Global:" << newLine
  736. << "Package=<5>" << newLine
  737. << "{{{" << newLine
  738. << "}}}" << newLine
  739. << "Package=<3>" << newLine
  740. << "{{{" << newLine
  741. << "}}}" << newLine;
  742. }
  743. MSVCProjectExporterVC6 (const MSVCProjectExporterVC6&);
  744. MSVCProjectExporterVC6& operator= (const MSVCProjectExporterVC6&);
  745. };
  746. //==============================================================================
  747. class MSVCProjectExporterVC2010 : public MSVCProjectExporterBase
  748. {
  749. public:
  750. MSVCProjectExporterVC2010 (Project& project_, const ValueTree& settings_)
  751. : MSVCProjectExporterBase (project_, settings_, "VisualStudio2010")
  752. {
  753. name = getName();
  754. }
  755. ~MSVCProjectExporterVC2010() {}
  756. static const char* getName() { return "Visual Studio 2010"; }
  757. static const char* getValueTreeTypeName() { return "VS2010"; }
  758. bool isDefaultFormatForCurrentOS() { return false; }
  759. void launchProject() { getSLNFile().startAsProcess(); }
  760. static MSVCProjectExporterVC2010* createForSettings (Project& project, const ValueTree& settings)
  761. {
  762. if (settings.hasType (getValueTreeTypeName()))
  763. return new MSVCProjectExporterVC2010 (project, settings);
  764. return 0;
  765. }
  766. //==============================================================================
  767. const String create()
  768. {
  769. {
  770. XmlElement projectXml ("Project");
  771. fillInProjectXml (projectXml);
  772. MemoryOutputStream mo;
  773. projectXml.writeToStream (mo, String::empty, false, true, "utf-8", 100);
  774. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getVCProjFile(), mo))
  775. return "Can't write to the VC project file: " + getVCProjFile().getFullPathName();
  776. }
  777. {
  778. XmlElement filtersXml ("Project");
  779. fillInFiltersXml (filtersXml);
  780. MemoryOutputStream mo;
  781. filtersXml.writeToStream (mo, String::empty, false, true, "utf-8", 100);
  782. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getVCProjFiltersFile(), mo))
  783. return "Can't write to the VC project file: " + getVCProjFiltersFile().getFullPathName();
  784. }
  785. {
  786. MemoryOutputStream mo;
  787. writeSolutionFile (mo, "11.00", getVCProjFile());
  788. if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getSLNFile(), mo))
  789. return "Can't write to the VC solution file: " + getSLNFile().getFullPathName();
  790. }
  791. return String::empty;
  792. }
  793. protected:
  794. const File getVCProjFile() const { return getProjectFile (".vcxproj"); }
  795. const File getVCProjFiltersFile() const { return getProjectFile (".vcxproj.filters"); }
  796. const File getSLNFile() const { return getProjectFile (".sln"); }
  797. static const String createConfigName (const Project::BuildConfiguration& config)
  798. {
  799. return config.getName().toString() + "|Win32";
  800. }
  801. //==============================================================================
  802. void fillInProjectXml (XmlElement& projectXml)
  803. {
  804. projectXml.setAttribute ("DefaultTargets", "Build");
  805. projectXml.setAttribute ("ToolsVersion", "4.0");
  806. projectXml.setAttribute ("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
  807. {
  808. XmlElement* configsGroup = projectXml.createNewChildElement ("ItemGroup");
  809. configsGroup->setAttribute ("Label", "ProjectConfigurations");
  810. for (int i = 0; i < project.getNumConfigurations(); ++i)
  811. {
  812. Project::BuildConfiguration config (project.getConfiguration (i));
  813. XmlElement* e = configsGroup->createNewChildElement ("ProjectConfiguration");
  814. e->setAttribute ("Include", createConfigName (config));
  815. e->createNewChildElement ("Configuration")->addTextElement (config.getName().toString());
  816. e->createNewChildElement ("Platform")->addTextElement ("Win32");
  817. }
  818. }
  819. {
  820. XmlElement* globals = projectXml.createNewChildElement ("PropertyGroup");
  821. globals->setAttribute ("Label", "Globals");
  822. globals->createNewChildElement ("ProjectGuid")->addTextElement (projectGUID);
  823. }
  824. {
  825. XmlElement* imports = projectXml.createNewChildElement ("Import");
  826. imports->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
  827. }
  828. for (int i = 0; i < project.getNumConfigurations(); ++i)
  829. {
  830. Project::BuildConfiguration config (project.getConfiguration (i));
  831. XmlElement* e = projectXml.createNewChildElement ("PropertyGroup");
  832. e->setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + createConfigName (config) + "'");
  833. e->setAttribute ("Label", "Configuration");
  834. e->createNewChildElement ("ConfigurationType")->addTextElement (getProjectType());
  835. e->createNewChildElement ("UseOfMfc")->addTextElement ("false");
  836. e->createNewChildElement ("CharacterSet")->addTextElement ("MultiByte");
  837. if (! config.isDebug().getValue())
  838. e->createNewChildElement ("WholeProgramOptimization")->addTextElement ("true");
  839. }
  840. {
  841. XmlElement* e = projectXml.createNewChildElement ("Import");
  842. e->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
  843. }
  844. {
  845. XmlElement* e = projectXml.createNewChildElement ("ImportGroup");
  846. e->setAttribute ("Label", "ExtensionSettings");
  847. }
  848. {
  849. XmlElement* e = projectXml.createNewChildElement ("ImportGroup");
  850. e->setAttribute ("Label", "PropertySheets");
  851. XmlElement* p = e->createNewChildElement ("Import");
  852. p->setAttribute ("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props");
  853. p->setAttribute ("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')");
  854. p->setAttribute ("Label", "LocalAppDataPlatform");
  855. }
  856. {
  857. XmlElement* e = projectXml.createNewChildElement ("PropertyGroup");
  858. e->setAttribute ("Label", "UserMacros");
  859. }
  860. {
  861. XmlElement* props = projectXml.createNewChildElement ("PropertyGroup");
  862. props->createNewChildElement ("_ProjectFileVersion")->addTextElement ("10.0.30319.1");
  863. for (int i = 0; i < project.getNumConfigurations(); ++i)
  864. {
  865. Project::BuildConfiguration config (project.getConfiguration (i));
  866. XmlElement* outdir = props->createNewChildElement ("OutDir");
  867. outdir->setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + createConfigName (config) + "'");
  868. outdir->addTextElement (getConfigTargetPath (config) + "\\");
  869. XmlElement* intdir = props->createNewChildElement ("IntDir");
  870. intdir->setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + createConfigName (config) + "'");
  871. intdir->addTextElement (getConfigTargetPath (config) + "\\");
  872. XmlElement* name = props->createNewChildElement ("TargetName");
  873. name->setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + createConfigName (config) + "'");
  874. name->addTextElement (getBinaryFileForConfig (config).upToLastOccurrenceOf (".", false, false));
  875. }
  876. }
  877. for (int i = 0; i < project.getNumConfigurations(); ++i)
  878. {
  879. Project::BuildConfiguration config (project.getConfiguration (i));
  880. String binariesPath (getConfigTargetPath (config));
  881. String intermediatesPath (getIntermediatesPath (config));
  882. const bool isDebug = (bool) config.isDebug().getValue();
  883. const String binaryName (File::createLegalFileName (config.getTargetBinaryName().toString()));
  884. const String outputFileName (getBinaryFileForConfig (config));
  885. XmlElement* group = projectXml.createNewChildElement ("ItemDefinitionGroup");
  886. group->setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + createConfigName (config) + "'");
  887. XmlElement* midl = group->createNewChildElement ("Midl");
  888. midl->createNewChildElement ("PreprocessorDefinitions")->addTextElement (isDebug ? "_DEBUG;%(PreprocessorDefinitions)"
  889. : "NDEBUG;%(PreprocessorDefinitions)");
  890. midl->createNewChildElement ("MkTypLibCompatible")->addTextElement ("true");
  891. midl->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  892. midl->createNewChildElement ("TargetEnvironment")->addTextElement ("Win32");
  893. //midl->createNewChildElement ("TypeLibraryName")->addTextElement ("");
  894. midl->createNewChildElement ("HeaderFileName");
  895. XmlElement* cl = group->createNewChildElement ("ClCompile");
  896. cl->createNewChildElement ("Optimization")->addTextElement (isDebug ? "Disabled" : "MaxSpeed");
  897. if (isDebug)
  898. cl->createNewChildElement ("DebugInformationFormat")->addTextElement ("EditAndContinue");
  899. StringArray includePaths (getHeaderSearchPaths (config));
  900. includePaths.add ("%(AdditionalIncludeDirectories)");
  901. cl->createNewChildElement ("AdditionalIncludeDirectories")->addTextElement (includePaths.joinIntoString (";"));
  902. cl->createNewChildElement ("PreprocessorDefinitions")->addTextElement (getPreprocessorDefs (config, ";") + ";%(PreprocessorDefinitions)");
  903. cl->createNewChildElement ("RuntimeLibrary")->addTextElement (isRTAS() ? (isDebug ? "MultiThreadedDLLDebug" : "MultiThreadedDLL")
  904. : (isDebug ? "MultiThreadedDebug" : "MultiThreaded"));
  905. cl->createNewChildElement ("RuntimeTypeInfo")->addTextElement ("true");
  906. cl->createNewChildElement ("PrecompiledHeader");
  907. cl->createNewChildElement ("AssemblerListingLocation")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath + "/"));
  908. cl->createNewChildElement ("ObjectFileName")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath + "/"));
  909. cl->createNewChildElement ("ProgramDataBaseFileName")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath + "/"));
  910. cl->createNewChildElement ("WarningLevel")->addTextElement ("Level4");
  911. cl->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  912. XmlElement* res = group->createNewChildElement ("ResourceCompile");
  913. res->createNewChildElement ("PreprocessorDefinitions")->addTextElement (isDebug ? "_DEBUG;%(PreprocessorDefinitions)"
  914. : "NDEBUG;%(PreprocessorDefinitions)");
  915. XmlElement* link = group->createNewChildElement ("Link");
  916. link->createNewChildElement ("OutputFile")->addTextElement (FileHelpers::windowsStylePath (binariesPath + "/" + outputFileName));
  917. link->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  918. link->createNewChildElement ("IgnoreSpecificDefaultLibraries")->addTextElement (isDebug ? "libcmt.lib; msvcrt.lib;;%(IgnoreSpecificDefaultLibraries)"
  919. : "%(IgnoreSpecificDefaultLibraries)");
  920. link->createNewChildElement ("GenerateDebugInformation")->addTextElement (isDebug ? "true" : "false");
  921. link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".pdb"));
  922. link->createNewChildElement ("SubSystem")->addTextElement (project.isCommandLineApp() ? "Console" : "Windows");
  923. link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
  924. if (! isDebug)
  925. {
  926. link->createNewChildElement ("OptimizeReferences")->addTextElement ("true");
  927. link->createNewChildElement ("EnableCOMDATFolding")->addTextElement ("true");
  928. }
  929. XmlElement* bsc = group->createNewChildElement ("Bscmake");
  930. bsc->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
  931. bsc->createNewChildElement ("OutputFile")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".bsc"));
  932. }
  933. {
  934. XmlElement* cppFiles = projectXml.createNewChildElement ("ItemGroup");
  935. XmlElement* headerFiles = projectXml.createNewChildElement ("ItemGroup");
  936. addFilesToCompile (project.getMainGroup(), *cppFiles, *headerFiles);
  937. addFilesToCompile (juceWrapperFiles, *cppFiles, *headerFiles, false);
  938. addFilesToCompile (getVSTFilesRequired(), *cppFiles, *headerFiles, false);
  939. addFilesToCompile (getRTASFilesRequired(), *cppFiles, *headerFiles, true);
  940. }
  941. {
  942. XmlElement* e = projectXml.createNewChildElement ("Import");
  943. e->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
  944. }
  945. {
  946. XmlElement* e = projectXml.createNewChildElement ("ImportGroup");
  947. e->setAttribute ("Label", "ExtensionTargets");
  948. }
  949. }
  950. const String getProjectType() const
  951. {
  952. if (project.isGUIApplication())
  953. return "Application";
  954. else if (project.isAudioPlugin() || project.isBrowserPlugin())
  955. return "DynamicLibrary";
  956. else if (project.isLibrary())
  957. return "StaticLibrary";
  958. jassertfalse;
  959. return String::empty;
  960. }
  961. //==============================================================================
  962. void addFileToCompile (const RelativePath& file, XmlElement& cpps, XmlElement& headers, const bool excludeFromBuild, const bool useStdcall)
  963. {
  964. jassert (file.getRoot() == RelativePath::buildTargetFolder);
  965. if (file.hasFileExtension ("cpp;c"))
  966. {
  967. XmlElement* e = cpps.createNewChildElement ("ClCompile");
  968. e->setAttribute ("Include", file.toWindowsStyle());
  969. if (excludeFromBuild)
  970. e->createNewChildElement ("ExcludedFromBuild")->addTextElement ("true");
  971. if (useStdcall)
  972. {
  973. jassertfalse;
  974. }
  975. }
  976. else if (file.hasFileExtension ("h"))
  977. {
  978. headers.createNewChildElement ("ClInclude")->setAttribute ("Include", file.toWindowsStyle());
  979. }
  980. }
  981. void addFilesToCompile (const Array<RelativePath>& files, XmlElement& cpps, XmlElement& headers, bool useStdCall)
  982. {
  983. for (int i = 0; i < files.size(); ++i)
  984. addFileToCompile (files.getReference(i), cpps, headers, false,
  985. useStdCall && shouldFileBeCompiledByDefault (files.getReference(i)));
  986. }
  987. void addFilesToCompile (const Project::Item& projectItem, XmlElement& cpps, XmlElement& headers)
  988. {
  989. if (projectItem.isGroup())
  990. {
  991. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  992. addFilesToCompile (projectItem.getChild(i), cpps, headers);
  993. }
  994. else
  995. {
  996. if (projectItem.shouldBeAddedToTargetProject())
  997. {
  998. const RelativePath path (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder);
  999. if (path.hasFileExtension ("h") || (path.hasFileExtension ("cpp;c") && projectItem.shouldBeCompiled()))
  1000. addFileToCompile (path, cpps, headers, false, false);
  1001. }
  1002. }
  1003. }
  1004. //==============================================================================
  1005. void addFilterGroup (XmlElement& groups, const String& path)
  1006. {
  1007. XmlElement* e = groups.createNewChildElement ("Filter");
  1008. e->setAttribute ("Include", path);
  1009. e->createNewChildElement ("UniqueIdentifier")->addTextElement (createGUID (path + "_guidpathsaltxhsdf"));
  1010. }
  1011. void addFileToFilter (const RelativePath& file, const String& groupPath, XmlElement& cpps, XmlElement& headers)
  1012. {
  1013. XmlElement* e;
  1014. if (file.hasFileExtension ("h"))
  1015. e = headers.createNewChildElement ("ClInclude");
  1016. else
  1017. e = cpps.createNewChildElement ("ClCompile");
  1018. jassert (file.getRoot() == RelativePath::buildTargetFolder);
  1019. e->setAttribute ("Include", file.toWindowsStyle());
  1020. e->createNewChildElement ("Filter")->addTextElement (groupPath);
  1021. }
  1022. void addFilesToFilter (const Project::Item& projectItem, const String& path, XmlElement& cpps, XmlElement& headers, XmlElement& groups)
  1023. {
  1024. if (projectItem.isGroup())
  1025. {
  1026. addFilterGroup (groups, path);
  1027. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  1028. addFilesToFilter (projectItem.getChild(i),
  1029. (path.isEmpty() ? String::empty : (path + "\\")) + projectItem.getChild(i).getName().toString(),
  1030. cpps, headers, groups);
  1031. }
  1032. else
  1033. {
  1034. if (projectItem.shouldBeAddedToTargetProject())
  1035. {
  1036. addFileToFilter (RelativePath (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder),
  1037. path.upToLastOccurrenceOf ("\\", false, false), cpps, headers);
  1038. }
  1039. }
  1040. }
  1041. void addFilesToFilter (const Array<RelativePath>& files, const String& path, XmlElement& cpps, XmlElement& headers, XmlElement& groups)
  1042. {
  1043. if (files.size() > 0)
  1044. {
  1045. addFilterGroup (groups, path);
  1046. for (int i = 0; i < files.size(); ++i)
  1047. addFileToFilter (files.getReference(i), path, cpps, headers);
  1048. }
  1049. }
  1050. void fillInFiltersXml (XmlElement& filterXml)
  1051. {
  1052. filterXml.setAttribute ("ToolsVersion", "4.0");
  1053. filterXml.setAttribute ("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
  1054. XmlElement* groups = filterXml.createNewChildElement ("ItemGroup");
  1055. XmlElement* cpps = filterXml.createNewChildElement ("ItemGroup");
  1056. XmlElement* headers = filterXml.createNewChildElement ("ItemGroup");
  1057. addFilesToFilter (project.getMainGroup(), project.getProjectName().toString(), *cpps, *headers, *groups);
  1058. addFilesToFilter (juceWrapperFiles, project.getJuceCodeGroupName(), *cpps, *headers, *groups);
  1059. addFilesToFilter (getVSTFilesRequired(), "Juce VST Wrapper", *cpps, *headers, *groups);
  1060. addFilesToFilter (getRTASFilesRequired(), "Juce RTAS Wrapper", *cpps, *headers, *groups);
  1061. }
  1062. //==============================================================================
  1063. MSVCProjectExporterVC2010 (const MSVCProjectExporterVC2010&);
  1064. MSVCProjectExporterVC2010& operator= (const MSVCProjectExporterVC2010&);
  1065. };
  1066. #endif // __JUCER_PROJECTEXPORT_MSVC_JUCEHEADER__