2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-10 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCER_PROJECTEXPORT_MSVC_JUCEHEADER__
27 #define __JUCER_PROJECTEXPORT_MSVC_JUCEHEADER__
29 #include "jucer_ProjectExporter.h"
32 //==============================================================================
33 class MSVCProjectExporterBase
: public ProjectExporter
36 //==============================================================================
37 MSVCProjectExporterBase (Project
& project_
, const ValueTree
& settings_
, const char* const folderName
)
38 : ProjectExporter (project_
, settings_
), hasIcon (false)
40 if (getTargetLocation().toString().isEmpty())
41 getTargetLocation() = getDefaultBuildsRootFolder() + folderName
;
43 if (getVSTFolder().toString().isEmpty())
44 getVSTFolder() = "c:\\SDKs\\vstsdk2.4";
46 if (getRTASFolder().toString().isEmpty())
47 getRTASFolder() = "c:\\SDKs\\PT_80_SDK";
49 if ((int) getLibraryType().getValue() <= 0)
52 projectGUID
= createGUID (project
.getProjectUID());
55 //==============================================================================
56 bool isPossibleForCurrentProject() { return true; }
57 bool usesMMFiles() const { return false; }
59 void createPropertyEditors (Array
<PropertyComponent
*>& props
)
61 ProjectExporter::createPropertyEditors (props
);
63 if (project
.isLibrary())
65 const char* const libTypes
[] = { "Static Library (.lib)", "Dynamic Library (.dll)", 0 };
66 const int libTypeValues
[] = { 1, 2, 0 };
67 props
.add (new ChoicePropertyComponent (getLibraryType(), "Library Type", StringArray (libTypes
), Array
<var
> (libTypeValues
)));
69 props
.add (new TextPropertyComponent (getSetting (Ids::libraryName_Debug
), "Library Name (Debug)", 128, false));
70 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.");
72 props
.add (new TextPropertyComponent (getSetting (Ids::libraryName_Release
), "Library Name (Release)", 128, false));
73 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.");
79 File rcFile
, iconFile
;
82 const File
getProjectFile (const String
& extension
) const { return getTargetFolder().getChildFile (project
.getProjectFilenameRoot()).withFileExtension (extension
); }
84 Value
getLibraryType() const { return getSetting (Ids::libraryType
); }
85 bool isLibraryDLL() const { return project
.isLibrary() && getLibraryType() == 2; }
87 //==============================================================================
88 const Array
<RelativePath
> getRTASFilesRequired() const
90 Array
<RelativePath
> s
;
94 static const char* files
[] = { JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_DigiCode1.cpp",
95 JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_DigiCode2.cpp",
96 JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_DigiCode3.cpp",
97 JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_DigiCode_Header.h",
98 JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_WinUtilities.cpp",
99 JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_Wrapper.cpp" };
101 for (int i
= 0; i
< numElementsInArray (files
); ++i
)
102 s
.add (getJucePathFromTargetFolder().getChildFile (files
[i
]));
108 const String
getIntermediatesPath (const Project::BuildConfiguration
& config
) const
110 return ".\\" + File::createLegalFileName (config
.getName().toString().trim());
113 const String
getConfigTargetPath (const Project::BuildConfiguration
& config
) const
115 const String
binaryPath (config
.getTargetBinaryRelativePath().toString().trim());
116 if (binaryPath
.isEmpty())
117 return getIntermediatesPath (config
);
119 return ".\\" + RelativePath (binaryPath
, RelativePath::projectFolder
)
120 .rebased (project
.getFile().getParentDirectory(), getTargetFolder(), RelativePath::buildTargetFolder
)
124 const String
getTargetBinarySuffix() const
126 if (project
.isLibrary())
130 else if (project
.isAudioPlugin() || project
.isBrowserPlugin())
136 const String
getPreprocessorDefs (const Project::BuildConfiguration
& config
, const String
& joinString
) const
138 StringPairArray defines
;
139 defines
.set ("WIN32", "");
140 defines
.set ("_WINDOWS", "");
142 if (config
.isDebug().getValue())
144 defines
.set ("DEBUG", "");
145 defines
.set ("_DEBUG", "");
149 defines
.set ("NDEBUG", "");
152 if (project
.isCommandLineApp())
153 defines
.set ("_CONSOLE", "");
155 if (project
.isLibrary())
156 defines
.set ("_LIB", "");
160 RelativePath
rtasFolder (getRTASFolder().toString(), RelativePath::unknown
);
161 defines
.set ("JucePlugin_WinBag_path", CodeHelpers::addEscapeChars (rtasFolder
.getChildFile ("WinBag")
162 .toWindowsStyle().quoted()));
165 defines
= mergePreprocessorDefs (defines
, getAllPreprocessorDefs (config
));
169 for (int i
= 0; i
< defines
.size(); ++i
)
171 String
def (defines
.getAllKeys()[i
]);
172 const String
value (defines
.getAllValues()[i
]);
173 if (value
.isNotEmpty())
179 return result
.joinIntoString (joinString
);
182 const StringArray
getHeaderSearchPaths (const Project::BuildConfiguration
& config
) const
184 StringArray
searchPaths (config
.getHeaderSearchPaths());
186 if (project
.shouldAddVSTFolderToPath() && getVSTFolder().toString().isNotEmpty())
187 searchPaths
.add (rebaseFromProjectFolderToBuildTarget (RelativePath (getVSTFolder().toString(), RelativePath::projectFolder
)).toWindowsStyle());
189 if (project
.isAudioPlugin())
190 searchPaths
.add (juceWrapperFolder
.toWindowsStyle());
194 static const char* rtasIncludePaths
[] = { "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses",
195 "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses",
196 "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses/Interfaces",
197 "AlturaPorts/TDMPlugins/PluginLibrary/Utilities",
198 "AlturaPorts/TDMPlugins/PluginLibrary/RTASP_Adapt",
199 "AlturaPorts/TDMPlugins/PluginLibrary/CoreClasses",
200 "AlturaPorts/TDMPlugins/PluginLibrary/Controls",
201 "AlturaPorts/TDMPlugins/PluginLibrary/Meters",
202 "AlturaPorts/TDMPlugins/PluginLibrary/ViewClasses",
203 "AlturaPorts/TDMPlugins/PluginLibrary/DSPClasses",
204 "AlturaPorts/TDMPlugins/PluginLibrary/Interfaces",
205 "AlturaPorts/TDMPlugins/common",
206 "AlturaPorts/TDMPlugins/common/Platform",
207 "AlturaPorts/TDMPlugins/SignalProcessing/Public",
208 "AlturaPorts/TDMPlugIns/DSPManager/Interfaces",
209 "AlturaPorts/SADriver/Interfaces",
210 "AlturaPorts/DigiPublic/Interfaces",
211 "AlturaPorts/Fic/Interfaces/DAEClient",
212 "AlturaPorts/NewFileLibs/Cmn",
213 "AlturaPorts/NewFileLibs/DOA",
214 "AlturaPorts/AlturaSource/PPC_H",
215 "AlturaPorts/AlturaSource/AppSupport",
216 "AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc",
217 "xplat/AVX/avx2/avx2sdk/inc" };
219 RelativePath
sdkFolder (getRTASFolder().toString(), RelativePath::projectFolder
);
221 for (int i
= 0; i
< numElementsInArray (rtasIncludePaths
); ++i
)
222 searchPaths
.add (rebaseFromProjectFolderToBuildTarget (sdkFolder
.getChildFile (rtasIncludePaths
[i
])).toWindowsStyle());
228 const String
getBinaryFileForConfig (const Project::BuildConfiguration
& config
) const
230 const String
targetBinary (getSetting (config
.isDebug().getValue() ? Ids::libraryName_Debug
: Ids::libraryName_Release
).toString().trim());
231 if (targetBinary
.isNotEmpty())
234 return config
.getTargetBinaryName().toString() + getTargetBinarySuffix();
237 static const String
createConfigName (const Project::BuildConfiguration
& config
)
239 return config
.getName().toString() + "|Win32";
242 //==============================================================================
243 void writeSolutionFile (OutputStream
& out
, const String
& versionString
, const File
& vcProject
)
245 out
<< "Microsoft Visual Studio Solution File, Format Version " << versionString
<< newLine
246 << "Project(\"" << createGUID (project
.getProjectName().toString() + "sln_guid") << "\") = \"" << project
.getProjectName().toString() << "\", \""
247 << vcProject
.getFileName() << "\", \"" << projectGUID
<< '"' << newLine
248 << "EndProject" << newLine
249 << "Global" << newLine
250 << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution" << newLine
;
253 for (i
= 0; i
< project
.getNumConfigurations(); ++i
)
255 Project::BuildConfiguration
config (project
.getConfiguration (i
));
256 out
<< "\t\t" << createConfigName (config
) << " = " << createConfigName (config
) << newLine
;
259 out
<< "\tEndGlobalSection" << newLine
260 << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution" << newLine
;
262 for (i
= 0; i
< project
.getNumConfigurations(); ++i
)
264 Project::BuildConfiguration
config (project
.getConfiguration (i
));
265 out
<< "\t\t" << projectGUID
<< "." << createConfigName (config
) << ".ActiveCfg = " << createConfigName (config
) << newLine
;
266 out
<< "\t\t" << projectGUID
<< "." << createConfigName (config
) << ".Build.0 = " << createConfigName (config
) << newLine
;
269 out
<< "\tEndGlobalSection" << newLine
270 << "\tGlobalSection(SolutionProperties) = preSolution" << newLine
271 << "\t\tHideSolutionNode = FALSE" << newLine
272 << "\tEndGlobalSection" << newLine
273 << "EndGlobal" << newLine
;
276 //==============================================================================
277 static bool writeRCFile (const File
& file
, const File
& iconFile
)
279 return file
.deleteFile()
280 && file
.appendText ("IDI_ICON1 ICON DISCARDABLE "
281 + iconFile
.getFileName().quoted(), false, false);
284 static void writeIconFile (const Array
<Image
>& images
, OutputStream
& out
)
286 out
.writeShort (0); // reserved
287 out
.writeShort (1); // .ico tag
288 out
.writeShort ((short) images
.size());
290 MemoryOutputStream dataBlock
;
292 const int imageDirEntrySize
= 16;
293 const int dataBlockStart
= 6 + images
.size() * imageDirEntrySize
;
295 for (int i
= 0; i
< images
.size(); ++i
)
297 const Image
& image
= images
.getReference (i
);
298 const int w
= image
.getWidth();
299 const int h
= image
.getHeight();
300 const int maskStride
= (w
/ 8 + 3) & ~3;
302 const size_t oldDataSize
= dataBlock
.getDataSize();
303 dataBlock
.writeInt (40); // bitmapinfoheader size
304 dataBlock
.writeInt (w
);
305 dataBlock
.writeInt (h
* 2);
306 dataBlock
.writeShort (1); // planes
307 dataBlock
.writeShort (32); // bits
308 dataBlock
.writeInt (0); // compression
309 dataBlock
.writeInt ((h
* w
* 4) + (h
* maskStride
)); // size image
310 dataBlock
.writeInt (0); // x pixels per meter
311 dataBlock
.writeInt (0); // y pixels per meter
312 dataBlock
.writeInt (0); // clr used
313 dataBlock
.writeInt (0); // clr important
315 const Image::BitmapData
bitmap (image
, Image::BitmapData::readOnly
);
316 const int alphaThreshold
= 5;
319 for (y
= h
; --y
>= 0;)
321 for (int x
= 0; x
< w
; ++x
)
323 const Colour
pixel (bitmap
.getPixelColour (x
, y
));
325 if (pixel
.getAlpha() <= alphaThreshold
)
327 dataBlock
.writeInt (0);
331 dataBlock
.writeByte ((char) pixel
.getBlue());
332 dataBlock
.writeByte ((char) pixel
.getGreen());
333 dataBlock
.writeByte ((char) pixel
.getRed());
334 dataBlock
.writeByte ((char) pixel
.getAlpha());
339 for (y
= h
; --y
>= 0;)
341 int mask
= 0, count
= 0;
343 for (int x
= 0; x
< w
; ++x
)
345 const Colour
pixel (bitmap
.getPixelColour (x
, y
));
348 if (pixel
.getAlpha() <= alphaThreshold
)
353 dataBlock
.writeByte ((char) mask
);
360 dataBlock
.writeByte ((char) mask
);
362 for (int i
= maskStride
- w
/ 8; --i
>= 0;)
363 dataBlock
.writeByte (0);
366 out
.writeByte ((char) w
);
367 out
.writeByte ((char) h
);
370 out
.writeShort (1); // colour planes
371 out
.writeShort (32); // bits per pixel
372 out
.writeInt ((int) (dataBlock
.getDataSize() - oldDataSize
));
373 out
.writeInt (dataBlockStart
+ oldDataSize
);
376 jassert (out
.getPosition() == dataBlockStart
);
380 bool createIconFile()
384 Image
im (project
.getBestIconForSize (16, true));
388 im
= project
.getBestIconForSize (32, true);
392 im
= project
.getBestIconForSize (48, true);
396 im
= project
.getBestIconForSize (128, true);
400 if (images
.size() == 0)
403 MemoryOutputStream mo
;
404 writeIconFile (images
, mo
);
406 iconFile
= getTargetFolder().getChildFile ("icon.ico");
407 rcFile
= getTargetFolder().getChildFile ("resources.rc");
409 hasIcon
= FileHelpers::overwriteFileWithNewDataIfDifferent (iconFile
, mo
)
410 && writeRCFile (rcFile
, iconFile
);
414 JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterBase
);
418 //==============================================================================
419 class MSVCProjectExporterVC2008
: public MSVCProjectExporterBase
422 //==============================================================================
423 MSVCProjectExporterVC2008 (Project
& project_
, const ValueTree
& settings_
, const char* folderName
= "VisualStudio2008")
424 : MSVCProjectExporterBase (project_
, settings_
, folderName
)
429 static const char* getName() { return "Visual Studio 2008"; }
430 static const char* getValueTreeTypeName() { return "VS2008"; }
432 void launchProject() { getSLNFile().startAsProcess(); }
434 bool isDefaultFormatForCurrentOS()
443 static MSVCProjectExporterVC2008
* createForSettings (Project
& project
, const ValueTree
& settings
)
445 if (settings
.hasType (getValueTreeTypeName()))
446 return new MSVCProjectExporterVC2008 (project
, settings
);
451 //==============================================================================
458 juceWrapperFiles
.add (RelativePath (iconFile
.getFileName(), RelativePath::buildTargetFolder
));
459 juceWrapperFiles
.add (RelativePath (rcFile
.getFileName(), RelativePath::buildTargetFolder
));
463 XmlElement
projectXml ("VisualStudioProject");
464 fillInProjectXml (projectXml
);
465 writeXmlOrThrow (projectXml
, getVCProjFile(), "UTF-8", 10);
469 MemoryOutputStream mo
;
470 writeSolutionFile (mo
, getSolutionVersionString(), getVCProjFile());
472 overwriteFileIfDifferentOrThrow (getSLNFile(), mo
);
477 virtual const String
getProjectVersionString() const { return "9.00"; }
478 virtual const String
getSolutionVersionString() const { return "10.00" + newLine
+ "# Visual C++ Express 2008"; }
480 const File
getVCProjFile() const { return getProjectFile (".vcproj"); }
481 const File
getSLNFile() const { return getProjectFile (".sln"); }
483 //==============================================================================
484 void fillInProjectXml (XmlElement
& projectXml
)
486 projectXml
.setAttribute ("ProjectType", "Visual C++");
487 projectXml
.setAttribute ("Version", getProjectVersionString());
488 projectXml
.setAttribute ("Name", project
.getProjectName().toString());
489 projectXml
.setAttribute ("ProjectGUID", projectGUID
);
490 projectXml
.setAttribute ("TargetFrameworkVersion", "131072");
493 XmlElement
* platforms
= projectXml
.createNewChildElement ("Platforms");
494 XmlElement
* platform
= platforms
->createNewChildElement ("Platform");
495 platform
->setAttribute ("Name", "Win32");
498 projectXml
.createNewChildElement ("ToolFiles");
499 createConfigs (*projectXml
.createNewChildElement ("Configurations"));
500 projectXml
.createNewChildElement ("References");
501 createFiles (*projectXml
.createNewChildElement ("Files"));
502 projectXml
.createNewChildElement ("Globals");
505 //==============================================================================
506 void addFile (const RelativePath
& file
, XmlElement
& parent
, const bool excludeFromBuild
, const bool useStdcall
)
508 jassert (file
.getRoot() == RelativePath::buildTargetFolder
);
510 XmlElement
* fileXml
= parent
.createNewChildElement ("File");
511 fileXml
->setAttribute ("RelativePath", file
.toWindowsStyle());
513 if (excludeFromBuild
|| useStdcall
)
515 for (int i
= 0; i
< project
.getNumConfigurations(); ++i
)
517 Project::BuildConfiguration
config (project
.getConfiguration (i
));
519 XmlElement
* fileConfig
= fileXml
->createNewChildElement ("FileConfiguration");
520 fileConfig
->setAttribute ("Name", createConfigName (config
));
522 if (excludeFromBuild
)
523 fileConfig
->setAttribute ("ExcludedFromBuild", "true");
525 XmlElement
* tool
= createToolElement (*fileConfig
, "VCCLCompilerTool");
528 tool
->setAttribute ("CallingConvention", "2");
533 XmlElement
* createGroup (const String
& groupName
, XmlElement
& parent
)
535 XmlElement
* filter
= parent
.createNewChildElement ("Filter");
536 filter
->setAttribute ("Name", groupName
);
540 void addFiles (const Project::Item
& projectItem
, XmlElement
& parent
)
542 if (projectItem
.isGroup())
544 XmlElement
* filter
= createGroup (projectItem
.getName().toString(), parent
);
546 for (int i
= 0; i
< projectItem
.getNumChildren(); ++i
)
547 addFiles (projectItem
.getChild(i
), *filter
);
551 if (projectItem
.shouldBeAddedToTargetProject())
553 const RelativePath
path (projectItem
.getFile(), getTargetFolder(), RelativePath::buildTargetFolder
);
555 addFile (path
, parent
,
556 projectItem
.shouldBeAddedToBinaryResources() || (shouldFileBeCompiledByDefault (path
) && ! projectItem
.shouldBeCompiled()),
562 void addGroup (XmlElement
& parent
, const String
& groupName
, const Array
<RelativePath
>& files
, const bool useStdcall
)
564 if (files
.size() > 0)
566 XmlElement
* const group
= createGroup (groupName
, parent
);
568 for (int i
= 0; i
< files
.size(); ++i
)
569 if (files
.getReference(i
).hasFileExtension ("cpp;c;cc;cxx;h;hpp;hxx;rc;ico"))
570 addFile (files
.getReference(i
), *group
, false,
571 useStdcall
&& shouldFileBeCompiledByDefault (files
.getReference(i
)));
575 void createFiles (XmlElement
& files
)
577 addFiles (project
.getMainGroup(), files
);
579 addGroup (files
, project
.getJuceCodeGroupName(), juceWrapperFiles
, false);
580 addGroup (files
, "Juce VST Wrapper", getVSTFilesRequired(), false);
581 addGroup (files
, "Juce RTAS Wrapper", getRTASFilesRequired(), true);
584 //==============================================================================
585 XmlElement
* createToolElement (XmlElement
& parent
, const String
& toolName
) const
587 XmlElement
* const e
= parent
.createNewChildElement ("Tool");
588 e
->setAttribute ("Name", toolName
);
592 void createConfig (XmlElement
& xml
, const Project::BuildConfiguration
& config
) const
594 String
binariesPath (getConfigTargetPath (config
));
595 String
intermediatesPath (getIntermediatesPath (config
));
596 const bool isDebug
= (bool) config
.isDebug().getValue();
597 const String
binaryName (File::createLegalFileName (config
.getTargetBinaryName().toString()));
599 xml
.setAttribute ("Name", createConfigName (config
));
600 xml
.setAttribute ("OutputDirectory", FileHelpers::windowsStylePath (binariesPath
));
601 xml
.setAttribute ("IntermediateDirectory", FileHelpers::windowsStylePath (intermediatesPath
));
602 xml
.setAttribute ("ConfigurationType", (project
.isAudioPlugin() || project
.isBrowserPlugin() || isLibraryDLL())
603 ? "2" : (project
.isLibrary() ? "4" : "1"));
604 xml
.setAttribute ("UseOfMFC", "0");
605 xml
.setAttribute ("ATLMinimizesCRunTimeLibraryUsage", "false");
606 xml
.setAttribute ("CharacterSet", "2");
609 xml
.setAttribute ("WholeProgramOptimization", "1");
611 createToolElement (xml
, "VCPreBuildEventTool");
613 XmlElement
* customBuild
= createToolElement (xml
, "VCCustomBuildTool");
617 RelativePath
rsrFile (getJucePathFromTargetFolder().getChildFile (JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_WinResources.rsr"));
619 customBuild
->setAttribute ("CommandLine", "copy /Y \"" + rsrFile
.toWindowsStyle() + "\" \"$(TargetPath)\".rsr");
620 customBuild
->setAttribute ("Outputs", "\"$(TargetPath)\".rsr");
623 createToolElement (xml
, "VCXMLDataGeneratorTool");
624 createToolElement (xml
, "VCWebServiceProxyGeneratorTool");
626 if (! project
.isLibrary())
628 XmlElement
* midl
= createToolElement (xml
, "VCMIDLTool");
629 midl
->setAttribute ("PreprocessorDefinitions", isDebug
? "_DEBUG" : "NDEBUG");
630 midl
->setAttribute ("MkTypLibCompatible", "true");
631 midl
->setAttribute ("SuppressStartupBanner", "true");
632 midl
->setAttribute ("TargetEnvironment", "1");
633 midl
->setAttribute ("TypeLibraryName", FileHelpers::windowsStylePath (intermediatesPath
+ "/" + binaryName
+ ".tlb"));
634 midl
->setAttribute ("HeaderFileName", "");
638 XmlElement
* compiler
= createToolElement (xml
, "VCCLCompilerTool");
640 const int optimiseLevel
= (int) config
.getOptimisationLevel().getValue();
641 compiler
->setAttribute ("Optimization", optimiseLevel
<= 1 ? "0" : (optimiseLevel
== 2 ? "2" : "3"));
645 compiler
->setAttribute ("BufferSecurityCheck", "");
646 compiler
->setAttribute ("DebugInformationFormat", project
.isLibrary() ? "3" : "4");
650 compiler
->setAttribute ("InlineFunctionExpansion", "1");
651 compiler
->setAttribute ("StringPooling", "true");
654 compiler
->setAttribute ("AdditionalIncludeDirectories", replacePreprocessorTokens (config
, getHeaderSearchPaths (config
).joinIntoString (";")));
655 compiler
->setAttribute ("PreprocessorDefinitions", getPreprocessorDefs (config
, ";"));
656 compiler
->setAttribute ("RuntimeLibrary", isRTAS() ? (isDebug
? 3 : 2) // MT DLL
657 : (isDebug
? 1 : 0)); // MT static
658 compiler
->setAttribute ("RuntimeTypeInfo", "true");
659 compiler
->setAttribute ("UsePrecompiledHeader", "0");
660 compiler
->setAttribute ("PrecompiledHeaderFile", FileHelpers::windowsStylePath (intermediatesPath
+ "/" + binaryName
+ ".pch"));
661 compiler
->setAttribute ("AssemblerListingLocation", FileHelpers::windowsStylePath (intermediatesPath
+ "/"));
662 compiler
->setAttribute ("ObjectFile", FileHelpers::windowsStylePath (intermediatesPath
+ "/"));
663 compiler
->setAttribute ("ProgramDataBaseFileName", FileHelpers::windowsStylePath (intermediatesPath
+ "/"));
664 compiler
->setAttribute ("WarningLevel", "4");
665 compiler
->setAttribute ("SuppressStartupBanner", "true");
667 const String
extraFlags (replacePreprocessorTokens (config
, getExtraCompilerFlags().toString()).trim());
668 if (extraFlags
.isNotEmpty())
669 compiler
->setAttribute ("AdditionalOptions", extraFlags
);
672 createToolElement (xml
, "VCManagedResourceCompilerTool");
675 XmlElement
* resCompiler
= createToolElement (xml
, "VCResourceCompilerTool");
676 resCompiler
->setAttribute ("PreprocessorDefinitions", isDebug
? "_DEBUG" : "NDEBUG");
679 createToolElement (xml
, "VCPreLinkEventTool");
681 const String
outputFileName (getBinaryFileForConfig (config
));
683 if (! project
.isLibrary())
685 XmlElement
* linker
= createToolElement (xml
, "VCLinkerTool");
687 linker
->setAttribute ("OutputFile", FileHelpers::windowsStylePath (binariesPath
+ "/" + outputFileName
));
688 linker
->setAttribute ("SuppressStartupBanner", "true");
690 if (project
.getJuceLinkageMode() == Project::useLinkedJuce
)
691 linker
->setAttribute ("AdditionalLibraryDirectories", getJucePathFromTargetFolder().getChildFile ("bin").toWindowsStyle());
693 linker
->setAttribute ("IgnoreDefaultLibraryNames", isDebug
? "libcmt.lib, msvcrt.lib" : "");
694 linker
->setAttribute ("GenerateDebugInformation", isDebug
? "true" : "false");
695 linker
->setAttribute ("ProgramDatabaseFile", FileHelpers::windowsStylePath (intermediatesPath
+ "/" + binaryName
+ ".pdb"));
696 linker
->setAttribute ("SubSystem", project
.isCommandLineApp() ? "1" : "2");
700 linker
->setAttribute ("GenerateManifest", "false");
701 linker
->setAttribute ("OptimizeReferences", "2");
702 linker
->setAttribute ("EnableCOMDATFolding", "2");
705 linker
->setAttribute ("TargetMachine", "1"); // (64-bit build = 5)
707 String
extraLinkerOptions (getExtraLinkerFlags().toString());
711 extraLinkerOptions
+= " /FORCE:multiple";
712 linker
->setAttribute ("DelayLoadDLLs", "DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; DSPManager.dll");
713 linker
->setAttribute ("ModuleDefinitionFile", getJucePathFromTargetFolder()
714 .getChildFile (JUCE_PLUGINS_PATH_RTAS
"juce_RTAS_WinExports.def")
718 if (extraLinkerOptions
.isNotEmpty())
719 linker
->setAttribute ("AdditionalOptions", replacePreprocessorTokens (config
, extraLinkerOptions
).trim());
725 XmlElement
* linker
= createToolElement (xml
, "VCLinkerTool");
727 String
extraLinkerOptions (getExtraLinkerFlags().toString());
728 extraLinkerOptions
<< " /IMPLIB:" << FileHelpers::windowsStylePath (binariesPath
+ "/" + outputFileName
.upToLastOccurrenceOf (".", false, false) + ".lib");
729 linker
->setAttribute ("AdditionalOptions", replacePreprocessorTokens (config
, extraLinkerOptions
).trim());
731 linker
->setAttribute ("OutputFile", FileHelpers::windowsStylePath (binariesPath
+ "/" + outputFileName
));
732 linker
->setAttribute ("IgnoreDefaultLibraryNames", isDebug
? "libcmt.lib, msvcrt.lib" : "");
736 XmlElement
* librarian
= createToolElement (xml
, "VCLibrarianTool");
738 librarian
->setAttribute ("OutputFile", FileHelpers::windowsStylePath (binariesPath
+ "/" + outputFileName
));
739 librarian
->setAttribute ("IgnoreDefaultLibraryNames", isDebug
? "libcmt.lib, msvcrt.lib" : "");
743 createToolElement (xml
, "VCALinkTool");
744 createToolElement (xml
, "VCManifestTool");
745 createToolElement (xml
, "VCXDCMakeTool");
748 XmlElement
* bscMake
= createToolElement (xml
, "VCBscMakeTool");
749 bscMake
->setAttribute ("SuppressStartupBanner", "true");
750 bscMake
->setAttribute ("OutputFile", FileHelpers::windowsStylePath (intermediatesPath
+ "/" + binaryName
+ ".bsc"));
753 createToolElement (xml
, "VCFxCopTool");
755 if (! project
.isLibrary())
756 createToolElement (xml
, "VCAppVerifierTool");
758 createToolElement (xml
, "VCPostBuildEventTool");
761 void createConfigs (XmlElement
& configs
)
763 for (int i
= 0; i
< project
.getNumConfigurations(); ++i
)
765 Project::BuildConfiguration
config (project
.getConfiguration (i
));
766 createConfig (*configs
.createNewChildElement ("Configuration"), config
);
770 //==============================================================================
771 JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2008
);
775 //==============================================================================
776 class MSVCProjectExporterVC2005
: public MSVCProjectExporterVC2008
779 MSVCProjectExporterVC2005 (Project
& project_
, const ValueTree
& settings_
)
780 : MSVCProjectExporterVC2008 (project_
, settings_
, "VisualStudio2005")
785 static const char* getName() { return "Visual Studio 2005"; }
786 static const char* getValueTreeTypeName() { return "VS2005"; }
788 bool isDefaultFormatForCurrentOS() { return false; }
790 static MSVCProjectExporterVC2005
* createForSettings (Project
& project
, const ValueTree
& settings
)
792 if (settings
.hasType (getValueTreeTypeName()))
793 return new MSVCProjectExporterVC2005 (project
, settings
);
799 const String
getProjectVersionString() const { return "8.00"; }
800 const String
getSolutionVersionString() const { return "8.00" + newLine
+ "# Visual C++ Express 2005"; }
802 JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2005
);
806 //==============================================================================
807 class MSVCProjectExporterVC6
: public MSVCProjectExporterBase
810 //==============================================================================
811 MSVCProjectExporterVC6 (Project
& project_
, const ValueTree
& settings_
)
812 : MSVCProjectExporterBase (project_
, settings_
, "MSVC6")
817 static const char* getName() { return "Visual C++ 6.0"; }
818 static const char* getValueTreeTypeName() { return "MSVC6"; }
820 bool isDefaultFormatForCurrentOS() { return false; }
821 void launchProject() { getDSWFile().startAsProcess(); }
823 static MSVCProjectExporterVC6
* createForSettings (Project
& project
, const ValueTree
& settings
)
825 if (settings
.hasType (getValueTreeTypeName()))
826 return new MSVCProjectExporterVC6 (project
, settings
);
831 //==============================================================================
835 MemoryOutputStream mo
;
837 overwriteFileIfDifferentOrThrow (getDSPFile(), mo
);
841 MemoryOutputStream mo
;
843 overwriteFileIfDifferentOrThrow (getDSWFile(), mo
);
848 const File
getDSPFile() const { return getProjectFile (".dsp"); }
849 const File
getDSWFile() const { return getProjectFile (".dsw"); }
851 //==============================================================================
852 const String
createConfigName (const Project::BuildConfiguration
& config
) const
854 return project
.getProjectName().toString() + " - Win32 " + config
.getName().toString();
857 void writeProject (OutputStream
& out
)
859 const String
defaultConfigName (createConfigName (project
.getConfiguration (0)));
861 const bool isDLL
= project
.isAudioPlugin() || project
.isBrowserPlugin();
862 String targetType
, targetCode
;
864 if (isDLL
) { targetType
= "\"Win32 (x86) Dynamic-Link Library\""; targetCode
= "0x0102"; }
865 else if (project
.isLibrary()) { targetType
= "\"Win32 (x86) Static Library\""; targetCode
= "0x0104"; }
866 else if (project
.isCommandLineApp()) { targetType
= "\"Win32 (x86) Console Application\""; targetCode
= "0x0103"; }
867 else { targetType
= "\"Win32 (x86) Application\""; targetCode
= "0x0101"; }
869 out
<< "# Microsoft Developer Studio Project File - Name=\"" << project
.getProjectName()
870 << "\" - Package Owner=<4>" << newLine
871 << "# Microsoft Developer Studio Generated Build File, Format Version 6.00" << newLine
872 << "# ** DO NOT EDIT **" << newLine
873 << "# TARGTYPE " << targetType
<< " " << targetCode
<< newLine
874 << "CFG=" << defaultConfigName
<< newLine
875 << "!MESSAGE This is not a valid makefile. To build this project using NMAKE," << newLine
876 << "!MESSAGE use the Export Makefile command and run" << newLine
877 << "!MESSAGE " << newLine
878 << "!MESSAGE NMAKE /f \"" << project
.getProjectName() << ".mak.\"" << newLine
879 << "!MESSAGE " << newLine
880 << "!MESSAGE You can specify a configuration when running NMAKE" << newLine
881 << "!MESSAGE by defining the macro CFG on the command line. For example:" << newLine
882 << "!MESSAGE " << newLine
883 << "!MESSAGE NMAKE /f \"" << project
.getProjectName() << ".mak\" CFG=\"" << defaultConfigName
<< '"' << newLine
884 << "!MESSAGE " << newLine
885 << "!MESSAGE Possible choices for configuration are:" << newLine
886 << "!MESSAGE " << newLine
;
889 for (i
= 0; i
< project
.getNumConfigurations(); ++i
)
890 out
<< "!MESSAGE \"" << createConfigName (project
.getConfiguration (i
)) << "\" (based on " << targetType
<< ")" << newLine
;
892 out
<< "!MESSAGE " << newLine
893 << "# Begin Project" << newLine
894 << "# PROP AllowPerConfigDependencies 0" << newLine
895 << "# PROP Scc_ProjName \"\"" << newLine
896 << "# PROP Scc_LocalPath \"\"" << newLine
897 << "CPP=cl.exe" << newLine
898 << "MTL=midl.exe" << newLine
899 << "RSC=rc.exe" << newLine
;
903 for (i
= 0; i
< project
.getNumConfigurations(); ++i
)
905 const Project::BuildConfiguration
config (project
.getConfiguration (i
));
906 const String
configName (createConfigName (config
));
907 targetList
<< "# Name \"" << configName
<< '"' << newLine
;
909 const String
binariesPath (getConfigTargetPath (config
));
910 const String
targetBinary (FileHelpers::windowsStylePath (binariesPath
+ "/" + getBinaryFileForConfig (config
)));
911 const String
optimisationFlag (((int) config
.getOptimisationLevel().getValue() <= 1) ? "Od" : (config
.getOptimisationLevel() == 2 ? "O2" : "O3"));
912 const String
defines (getPreprocessorDefs (config
, " /D "));
913 const bool isDebug
= (bool) config
.isDebug().getValue();
914 const String
extraDebugFlags (isDebug
? "/Gm /ZI /GZ" : "");
916 out
<< (i
== 0 ? "!IF" : "!ELSEIF") << " \"$(CFG)\" == \"" << configName
<< '"' << newLine
917 << "# PROP BASE Use_MFC 0" << newLine
918 << "# PROP BASE Use_Debug_Libraries " << (isDebug
? "1" : "0") << newLine
919 << "# PROP BASE Output_Dir \"" << binariesPath
<< '"' << newLine
920 << "# PROP BASE Intermediate_Dir \"" << getIntermediatesPath (config
) << '"' << newLine
921 << "# PROP BASE Target_Dir \"\"" << newLine
922 << "# PROP Use_MFC 0" << newLine
923 << "# PROP Use_Debug_Libraries " << (isDebug
? "1" : "0") << newLine
924 << "# PROP Output_Dir \"" << binariesPath
<< '"' << newLine
925 << "# PROP Intermediate_Dir \"" << getIntermediatesPath (config
) << '"' << newLine
926 << "# PROP Ignore_Export_Lib 0" << newLine
927 << "# PROP Target_Dir \"\"" << newLine
928 << "# ADD BASE CPP /nologo /W3 /GX /" << optimisationFlag
<< " /D " << defines
929 << " /YX /FD /c " << extraDebugFlags
<< " /Zm1024" << newLine
930 << "# ADD CPP /nologo " << (isDebug
? "/MTd" : "/MT") << " /W3 /GR /GX /" << optimisationFlag
931 << " /I " << replacePreprocessorTokens (config
, getHeaderSearchPaths (config
).joinIntoString (" /I "))
932 << " /D " << defines
<< " /D \"_UNICODE\" /D \"UNICODE\" /FD /c /Zm1024 " << extraDebugFlags
933 << " " << replacePreprocessorTokens (config
, getExtraCompilerFlags().toString()).trim() << newLine
;
936 out
<< "# SUBTRACT CPP /YX" << newLine
;
938 if (! project
.isLibrary())
939 out
<< "# ADD BASE MTL /nologo /D " << defines
<< " /mktyplib203 /win32" << newLine
940 << "# ADD MTL /nologo /D " << defines
<< " /mktyplib203 /win32" << newLine
;
942 out
<< "# ADD BASE RSC /l 0x40c /d " << defines
<< newLine
943 << "# ADD RSC /l 0x40c /d " << defines
<< newLine
944 << "BSC32=bscmake.exe" << newLine
945 << "# ADD BASE BSC32 /nologo" << newLine
946 << "# ADD BSC32 /nologo" << newLine
;
948 if (project
.isLibrary())
950 out
<< "LIB32=link.exe -lib" << newLine
951 << "# ADD BASE LIB32 /nologo" << newLine
952 << "# ADD LIB32 /nologo /out:\"" << targetBinary
<< '"' << newLine
;
956 out
<< "LINK32=link.exe" << newLine
957 << "# 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
958 << "# ADD LINK32 \"C:\\Program Files\\Microsoft Visual Studio\\VC98\\LIB\\shell32.lib\" " // This is avoid debug information corruption when mixing Platform SDK
959 << "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "
960 << (isDebug
? " /debug" : "")
961 << " /nologo /machine:I386 /out:\"" << targetBinary
<< "\" "
962 << (isDLL
? "/dll" : (project
.isCommandLineApp() ? "/subsystem:console "
963 : "/subsystem:windows "))
964 << replacePreprocessorTokens (config
, getExtraLinkerFlags().toString()).trim() << newLine
;
968 out
<< "!ENDIF" << newLine
969 << "# Begin Target" << newLine
972 writeFiles (out
, project
.getMainGroup());
973 writeGroup (out
, project
.getJuceCodeGroupName(), juceWrapperFiles
);
974 writeGroup (out
, "Juce VST Wrapper", getVSTFilesRequired());
976 out
<< "# End Target" << newLine
977 << "# End Project" << newLine
;
980 void writeFile (OutputStream
& out
, const RelativePath
& file
, const bool excludeFromBuild
)
982 jassert (file
.getRoot() == RelativePath::buildTargetFolder
);
984 out
<< "# Begin Source File" << newLine
985 << "SOURCE=" << file
.toWindowsStyle().quoted() << newLine
;
987 if (excludeFromBuild
)
988 out
<< "# PROP Exclude_From_Build 1" << newLine
;
990 out
<< "# End Source File" << newLine
;
993 void writeFiles (OutputStream
& out
, const Project::Item
& projectItem
)
995 if (projectItem
.isGroup())
997 out
<< "# Begin Group \"" << projectItem
.getName() << '"' << newLine
998 << "# PROP Default_Filter \"cpp;c;cc;cxx;rc;def;r;odl;idl;hpj;bat\"" << newLine
;
1000 for (int i
= 0; i
< projectItem
.getNumChildren(); ++i
)
1001 writeFiles (out
, projectItem
.getChild (i
));
1003 out
<< "# End Group" << newLine
;
1005 else if (projectItem
.shouldBeAddedToTargetProject())
1007 const RelativePath
path (projectItem
.getFile(), getTargetFolder(), RelativePath::buildTargetFolder
);
1008 writeFile (out
, path
, projectItem
.shouldBeAddedToBinaryResources() || (shouldFileBeCompiledByDefault (path
) && ! projectItem
.shouldBeCompiled()));
1012 void writeGroup (OutputStream
& out
, const String
& groupName
, const Array
<RelativePath
>& files
)
1014 if (files
.size() > 0)
1016 out
<< "# Begin Group \"" << groupName
<< '"' << newLine
;
1017 for (int i
= 0; i
< files
.size(); ++i
)
1018 if (files
.getReference(i
).hasFileExtension ("cpp;cc;c;cxx;h;hpp;hxx"))
1019 writeFile (out
, files
.getReference(i
), false);
1021 out
<< "# End Group" << newLine
;
1025 void writeDSWFile (OutputStream
& out
)
1027 out
<< "Microsoft Developer Studio Workspace File, Format Version 6.00 " << newLine
;
1029 if (! project
.isUsingWrapperFiles())
1031 out
<< "Project: \"JUCE\"= ..\\JUCE.dsp - Package Owner=<4>" << newLine
1032 << "Package=<5>" << newLine
1035 << "Package=<4>" << newLine
1037 << "}}}" << newLine
;
1040 out
<< "Project: \"" << project
.getProjectName() << "\" = .\\" << getDSPFile().getFileName() << " - Package Owner=<4>" << newLine
1041 << "Package=<5>" << newLine
1044 << "Package=<4>" << newLine
1045 << "{{{" << newLine
;
1047 if (! project
.isUsingWrapperFiles())
1049 out
<< " Begin Project Dependency" << newLine
1050 << " Project_Dep_Name JUCE" << newLine
1051 << " End Project Dependency" << newLine
;
1054 out
<< "}}}" << newLine
1055 << "Global:" << newLine
1056 << "Package=<5>" << newLine
1059 << "Package=<3>" << newLine
1061 << "}}}" << newLine
;
1064 JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC6
);
1068 //==============================================================================
1069 class MSVCProjectExporterVC2010
: public MSVCProjectExporterBase
1072 MSVCProjectExporterVC2010 (Project
& project_
, const ValueTree
& settings_
)
1073 : MSVCProjectExporterBase (project_
, settings_
, "VisualStudio2010")
1078 static const char* getName() { return "Visual Studio 2010"; }
1079 static const char* getValueTreeTypeName() { return "VS2010"; }
1081 bool isDefaultFormatForCurrentOS() { return false; }
1082 void launchProject() { getSLNFile().startAsProcess(); }
1084 static MSVCProjectExporterVC2010
* createForSettings (Project
& project
, const ValueTree
& settings
)
1086 if (settings
.hasType (getValueTreeTypeName()))
1087 return new MSVCProjectExporterVC2010 (project
, settings
);
1092 //==============================================================================
1098 XmlElement
projectXml ("Project");
1099 fillInProjectXml (projectXml
);
1100 writeXmlOrThrow (projectXml
, getVCProjFile(), "utf-8", 100);
1104 XmlElement
filtersXml ("Project");
1105 fillInFiltersXml (filtersXml
);
1106 writeXmlOrThrow (filtersXml
, getVCProjFiltersFile(), "utf-8", 100);
1110 MemoryOutputStream mo
;
1111 writeSolutionFile (mo
, "11.00", getVCProjFile());
1113 overwriteFileIfDifferentOrThrow (getSLNFile(), mo
);
1118 const File
getVCProjFile() const { return getProjectFile (".vcxproj"); }
1119 const File
getVCProjFiltersFile() const { return getProjectFile (".vcxproj.filters"); }
1120 const File
getSLNFile() const { return getProjectFile (".sln"); }
1122 static const String
createConfigName (const Project::BuildConfiguration
& config
)
1124 return config
.getName().toString() + "|Win32";
1127 static void setConditionAttribute (XmlElement
& xml
, const Project::BuildConfiguration
& config
)
1129 xml
.setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + createConfigName (config
) + "'");
1132 //==============================================================================
1133 void fillInProjectXml (XmlElement
& projectXml
)
1135 projectXml
.setAttribute ("DefaultTargets", "Build");
1136 projectXml
.setAttribute ("ToolsVersion", "4.0");
1137 projectXml
.setAttribute ("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
1140 XmlElement
* configsGroup
= projectXml
.createNewChildElement ("ItemGroup");
1141 configsGroup
->setAttribute ("Label", "ProjectConfigurations");
1143 for (int i
= 0; i
< project
.getNumConfigurations(); ++i
)
1145 Project::BuildConfiguration
config (project
.getConfiguration (i
));
1147 XmlElement
* e
= configsGroup
->createNewChildElement ("ProjectConfiguration");
1148 e
->setAttribute ("Include", createConfigName (config
));
1149 e
->createNewChildElement ("Configuration")->addTextElement (config
.getName().toString());
1150 e
->createNewChildElement ("Platform")->addTextElement ("Win32");
1155 XmlElement
* globals
= projectXml
.createNewChildElement ("PropertyGroup");
1156 globals
->setAttribute ("Label", "Globals");
1157 globals
->createNewChildElement ("ProjectGuid")->addTextElement (projectGUID
);
1161 XmlElement
* imports
= projectXml
.createNewChildElement ("Import");
1162 imports
->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
1165 for (int i
= 0; i
< project
.getNumConfigurations(); ++i
)
1167 Project::BuildConfiguration
config (project
.getConfiguration (i
));
1169 XmlElement
* e
= projectXml
.createNewChildElement ("PropertyGroup");
1170 setConditionAttribute (*e
, config
);
1171 e
->setAttribute ("Label", "Configuration");
1172 e
->createNewChildElement ("ConfigurationType")->addTextElement (getProjectType());
1173 e
->createNewChildElement ("UseOfMfc")->addTextElement ("false");
1174 e
->createNewChildElement ("CharacterSet")->addTextElement ("MultiByte");
1176 if (! config
.isDebug().getValue())
1177 e
->createNewChildElement ("WholeProgramOptimization")->addTextElement ("true");
1181 XmlElement
* e
= projectXml
.createNewChildElement ("Import");
1182 e
->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
1186 XmlElement
* e
= projectXml
.createNewChildElement ("ImportGroup");
1187 e
->setAttribute ("Label", "ExtensionSettings");
1191 XmlElement
* e
= projectXml
.createNewChildElement ("ImportGroup");
1192 e
->setAttribute ("Label", "PropertySheets");
1193 XmlElement
* p
= e
->createNewChildElement ("Import");
1194 p
->setAttribute ("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props");
1195 p
->setAttribute ("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')");
1196 p
->setAttribute ("Label", "LocalAppDataPlatform");
1200 XmlElement
* e
= projectXml
.createNewChildElement ("PropertyGroup");
1201 e
->setAttribute ("Label", "UserMacros");
1205 XmlElement
* props
= projectXml
.createNewChildElement ("PropertyGroup");
1206 props
->createNewChildElement ("_ProjectFileVersion")->addTextElement ("10.0.30319.1");
1208 for (int i
= 0; i
< project
.getNumConfigurations(); ++i
)
1210 Project::BuildConfiguration
config (project
.getConfiguration (i
));
1212 XmlElement
* outdir
= props
->createNewChildElement ("OutDir");
1213 setConditionAttribute (*outdir
, config
);
1214 outdir
->addTextElement (getConfigTargetPath (config
) + "\\");
1216 XmlElement
* intdir
= props
->createNewChildElement ("IntDir");
1217 setConditionAttribute (*intdir
, config
);
1218 intdir
->addTextElement (getConfigTargetPath (config
) + "\\");
1220 XmlElement
* name
= props
->createNewChildElement ("TargetName");
1221 setConditionAttribute (*name
, config
);
1222 name
->addTextElement (getBinaryFileForConfig (config
).upToLastOccurrenceOf (".", false, false));
1226 for (int i
= 0; i
< project
.getNumConfigurations(); ++i
)
1228 Project::BuildConfiguration
config (project
.getConfiguration (i
));
1229 String
binariesPath (getConfigTargetPath (config
));
1230 String
intermediatesPath (getIntermediatesPath (config
));
1231 const bool isDebug
= (bool) config
.isDebug().getValue();
1232 const String
binaryName (File::createLegalFileName (config
.getTargetBinaryName().toString()));
1233 const String
outputFileName (getBinaryFileForConfig (config
));
1235 XmlElement
* group
= projectXml
.createNewChildElement ("ItemDefinitionGroup");
1236 setConditionAttribute (*group
, config
);
1238 XmlElement
* midl
= group
->createNewChildElement ("Midl");
1239 midl
->createNewChildElement ("PreprocessorDefinitions")->addTextElement (isDebug
? "_DEBUG;%(PreprocessorDefinitions)"
1240 : "NDEBUG;%(PreprocessorDefinitions)");
1241 midl
->createNewChildElement ("MkTypLibCompatible")->addTextElement ("true");
1242 midl
->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
1243 midl
->createNewChildElement ("TargetEnvironment")->addTextElement ("Win32");
1244 //midl->createNewChildElement ("TypeLibraryName")->addTextElement ("");
1245 midl
->createNewChildElement ("HeaderFileName");
1247 XmlElement
* cl
= group
->createNewChildElement ("ClCompile");
1248 cl
->createNewChildElement ("Optimization")->addTextElement (isDebug
? "Disabled" : "MaxSpeed");
1251 cl
->createNewChildElement ("DebugInformationFormat")->addTextElement ("EditAndContinue");
1253 StringArray
includePaths (getHeaderSearchPaths (config
));
1254 includePaths
.add ("%(AdditionalIncludeDirectories)");
1255 cl
->createNewChildElement ("AdditionalIncludeDirectories")->addTextElement (includePaths
.joinIntoString (";"));
1256 cl
->createNewChildElement ("PreprocessorDefinitions")->addTextElement (getPreprocessorDefs (config
, ";") + ";%(PreprocessorDefinitions)");
1257 cl
->createNewChildElement ("RuntimeLibrary")->addTextElement (isRTAS() ? (isDebug
? "MultiThreadedDLLDebug" : "MultiThreadedDLL")
1258 : (isDebug
? "MultiThreadedDebug" : "MultiThreaded"));
1259 cl
->createNewChildElement ("RuntimeTypeInfo")->addTextElement ("true");
1260 cl
->createNewChildElement ("PrecompiledHeader");
1261 cl
->createNewChildElement ("AssemblerListingLocation")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath
+ "/"));
1262 cl
->createNewChildElement ("ObjectFileName")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath
+ "/"));
1263 cl
->createNewChildElement ("ProgramDataBaseFileName")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath
+ "/"));
1264 cl
->createNewChildElement ("WarningLevel")->addTextElement ("Level4");
1265 cl
->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
1267 XmlElement
* res
= group
->createNewChildElement ("ResourceCompile");
1268 res
->createNewChildElement ("PreprocessorDefinitions")->addTextElement (isDebug
? "_DEBUG;%(PreprocessorDefinitions)"
1269 : "NDEBUG;%(PreprocessorDefinitions)");
1271 XmlElement
* link
= group
->createNewChildElement ("Link");
1272 link
->createNewChildElement ("OutputFile")->addTextElement (FileHelpers::windowsStylePath (binariesPath
+ "/" + outputFileName
));
1273 link
->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
1274 link
->createNewChildElement ("IgnoreSpecificDefaultLibraries")->addTextElement (isDebug
? "libcmt.lib; msvcrt.lib;;%(IgnoreSpecificDefaultLibraries)"
1275 : "%(IgnoreSpecificDefaultLibraries)");
1276 link
->createNewChildElement ("GenerateDebugInformation")->addTextElement (isDebug
? "true" : "false");
1277 link
->createNewChildElement ("ProgramDatabaseFile")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath
+ "/" + binaryName
+ ".pdb"));
1278 link
->createNewChildElement ("SubSystem")->addTextElement (project
.isCommandLineApp() ? "Console" : "Windows");
1279 link
->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
1283 link
->createNewChildElement ("OptimizeReferences")->addTextElement ("true");
1284 link
->createNewChildElement ("EnableCOMDATFolding")->addTextElement ("true");
1287 String
extraLinkerOptions (getExtraLinkerFlags().toString());
1288 if (extraLinkerOptions
.isNotEmpty())
1289 link
->createNewChildElement ("AdditionalOptions")->addTextElement (replacePreprocessorTokens (config
, extraLinkerOptions
).trim()
1290 + " %(AdditionalOptions)");
1292 XmlElement
* bsc
= group
->createNewChildElement ("Bscmake");
1293 bsc
->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true");
1294 bsc
->createNewChildElement ("OutputFile")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath
+ "/" + binaryName
+ ".bsc"));
1298 XmlElement
* cppFiles
= projectXml
.createNewChildElement ("ItemGroup");
1299 XmlElement
* headerFiles
= projectXml
.createNewChildElement ("ItemGroup");
1301 addFilesToCompile (project
.getMainGroup(), *cppFiles
, *headerFiles
);
1302 addFilesToCompile (juceWrapperFiles
, *cppFiles
, *headerFiles
, false);
1303 addFilesToCompile (getVSTFilesRequired(), *cppFiles
, *headerFiles
, false);
1304 addFilesToCompile (getRTASFilesRequired(), *cppFiles
, *headerFiles
, true);
1310 XmlElement
* iconGroup
= projectXml
.createNewChildElement ("ItemGroup");
1311 XmlElement
* e
= iconGroup
->createNewChildElement ("None");
1312 e
->setAttribute ("Include", ".\\" + iconFile
.getFileName());
1316 XmlElement
* rcGroup
= projectXml
.createNewChildElement ("ItemGroup");
1317 XmlElement
* e
= rcGroup
->createNewChildElement ("ResourceCompile");
1318 e
->setAttribute ("Include", ".\\" + rcFile
.getFileName());
1323 XmlElement
* e
= projectXml
.createNewChildElement ("Import");
1324 e
->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
1328 XmlElement
* e
= projectXml
.createNewChildElement ("ImportGroup");
1329 e
->setAttribute ("Label", "ExtensionTargets");
1333 const String
getProjectType() const
1335 if (project
.isGUIApplication() || project
.isCommandLineApp())
1336 return "Application";
1337 else if (project
.isAudioPlugin() || project
.isBrowserPlugin())
1338 return "DynamicLibrary";
1339 else if (project
.isLibrary())
1340 return "StaticLibrary";
1343 return String::empty
;
1346 //==============================================================================
1347 void addFileToCompile (const RelativePath
& file
, XmlElement
& cpps
, XmlElement
& headers
, const bool excludeFromBuild
, const bool useStdcall
)
1349 jassert (file
.getRoot() == RelativePath::buildTargetFolder
);
1351 if (file
.hasFileExtension ("cpp;cc;cxx;c"))
1353 XmlElement
* e
= cpps
.createNewChildElement ("ClCompile");
1354 e
->setAttribute ("Include", file
.toWindowsStyle());
1356 if (excludeFromBuild
)
1357 e
->createNewChildElement ("ExcludedFromBuild")->addTextElement ("true");
1364 else if (file
.hasFileExtension (headerFileExtensions
))
1366 headers
.createNewChildElement ("ClInclude")->setAttribute ("Include", file
.toWindowsStyle());
1370 void addFilesToCompile (const Array
<RelativePath
>& files
, XmlElement
& cpps
, XmlElement
& headers
, bool useStdCall
)
1372 for (int i
= 0; i
< files
.size(); ++i
)
1373 addFileToCompile (files
.getReference(i
), cpps
, headers
, false,
1374 useStdCall
&& shouldFileBeCompiledByDefault (files
.getReference(i
)));
1377 void addFilesToCompile (const Project::Item
& projectItem
, XmlElement
& cpps
, XmlElement
& headers
)
1379 if (projectItem
.isGroup())
1381 for (int i
= 0; i
< projectItem
.getNumChildren(); ++i
)
1382 addFilesToCompile (projectItem
.getChild(i
), cpps
, headers
);
1386 if (projectItem
.shouldBeAddedToTargetProject())
1388 const RelativePath
path (projectItem
.getFile(), getTargetFolder(), RelativePath::buildTargetFolder
);
1390 if (path
.hasFileExtension (headerFileExtensions
) || (path
.hasFileExtension ("cpp;cc;c;cxx") && projectItem
.shouldBeCompiled()))
1391 addFileToCompile (path
, cpps
, headers
, false, false);
1396 //==============================================================================
1397 void addFilterGroup (XmlElement
& groups
, const String
& path
)
1399 XmlElement
* e
= groups
.createNewChildElement ("Filter");
1400 e
->setAttribute ("Include", path
);
1401 e
->createNewChildElement ("UniqueIdentifier")->addTextElement (createGUID (path
+ "_guidpathsaltxhsdf"));
1404 void addFileToFilter (const RelativePath
& file
, const String
& groupPath
, XmlElement
& cpps
, XmlElement
& headers
)
1408 if (file
.hasFileExtension (headerFileExtensions
))
1409 e
= headers
.createNewChildElement ("ClInclude");
1411 e
= cpps
.createNewChildElement ("ClCompile");
1413 jassert (file
.getRoot() == RelativePath::buildTargetFolder
);
1414 e
->setAttribute ("Include", file
.toWindowsStyle());
1415 e
->createNewChildElement ("Filter")->addTextElement (groupPath
);
1418 void addFilesToFilter (const Project::Item
& projectItem
, const String
& path
, XmlElement
& cpps
, XmlElement
& headers
, XmlElement
& groups
)
1420 if (projectItem
.isGroup())
1422 addFilterGroup (groups
, path
);
1424 for (int i
= 0; i
< projectItem
.getNumChildren(); ++i
)
1425 addFilesToFilter (projectItem
.getChild(i
),
1426 (path
.isEmpty() ? String::empty
: (path
+ "\\")) + projectItem
.getChild(i
).getName().toString(),
1427 cpps
, headers
, groups
);
1431 if (projectItem
.shouldBeAddedToTargetProject())
1433 addFileToFilter (RelativePath (projectItem
.getFile(), getTargetFolder(), RelativePath::buildTargetFolder
),
1434 path
.upToLastOccurrenceOf ("\\", false, false), cpps
, headers
);
1439 void addFilesToFilter (const Array
<RelativePath
>& files
, const String
& path
, XmlElement
& cpps
, XmlElement
& headers
, XmlElement
& groups
)
1441 if (files
.size() > 0)
1443 addFilterGroup (groups
, path
);
1445 for (int i
= 0; i
< files
.size(); ++i
)
1446 addFileToFilter (files
.getReference(i
), path
, cpps
, headers
);
1450 void fillInFiltersXml (XmlElement
& filterXml
)
1452 filterXml
.setAttribute ("ToolsVersion", "4.0");
1453 filterXml
.setAttribute ("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
1455 XmlElement
* groups
= filterXml
.createNewChildElement ("ItemGroup");
1456 XmlElement
* cpps
= filterXml
.createNewChildElement ("ItemGroup");
1457 XmlElement
* headers
= filterXml
.createNewChildElement ("ItemGroup");
1459 addFilesToFilter (project
.getMainGroup(), project
.getProjectName().toString(), *cpps
, *headers
, *groups
);
1461 addFilesToFilter (juceWrapperFiles
, project
.getJuceCodeGroupName(), *cpps
, *headers
, *groups
);
1462 addFilesToFilter (getVSTFilesRequired(), "Juce VST Wrapper", *cpps
, *headers
, *groups
);
1463 addFilesToFilter (getRTASFilesRequired(), "Juce RTAS Wrapper", *cpps
, *headers
, *groups
);
1465 if (iconFile
.exists())
1468 XmlElement
* iconGroup
= filterXml
.createNewChildElement ("ItemGroup");
1469 XmlElement
* e
= iconGroup
->createNewChildElement ("None");
1470 e
->setAttribute ("Include", ".\\" + iconFile
.getFileName());
1471 e
->createNewChildElement ("Filter")->addTextElement (project
.getJuceCodeGroupName());
1475 XmlElement
* rcGroup
= filterXml
.createNewChildElement ("ItemGroup");
1476 XmlElement
* e
= rcGroup
->createNewChildElement ("ResourceCompile");
1477 e
->setAttribute ("Include", ".\\" + rcFile
.getFileName());
1478 e
->createNewChildElement ("Filter")->addTextElement (project
.getJuceCodeGroupName());
1483 //==============================================================================
1484 JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2010
);
1488 #endif // __JUCER_PROJECTEXPORT_MSVC_JUCEHEADER__