2010-11-23 11:47:52 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
2011-04-24 13:33:23 -04:00
# include "config.h"
2010-11-23 11:47:52 +00:00
# include "msbuild.h"
# include <fstream>
# include <algorithm>
namespace CreateProjectTool {
//////////////////////////////////////////////////////////////////////////
// MSBuild Provider (Visual Studio 2010)
//////////////////////////////////////////////////////////////////////////
MSBuildProvider : : MSBuildProvider ( StringList & global_warnings , std : : map < std : : string , StringList > & project_warnings , const int version )
: MSVCProvider ( global_warnings , project_warnings , version ) {
}
const char * MSBuildProvider : : getProjectExtension ( ) {
return " .vcxproj " ;
}
const char * MSBuildProvider : : getPropertiesExtension ( ) {
return " .props " ;
}
int MSBuildProvider : : getVisualStudioVersion ( ) {
2012-07-11 01:08:22 -04:00
if ( _version = = 10 )
return 2010 ;
if ( _version = = 11 )
return 2012 ;
2013-06-29 18:33:50 -04:00
if ( _version = = 12 )
return 2013 ;
2012-07-11 01:08:22 -04:00
error ( " Unsupported version passed to getVisualStudioVersion " ) ;
2010-11-23 11:47:52 +00:00
}
2011-04-28 17:44:17 +02:00
namespace {
inline void outputConfiguration ( std : : ostream & project , const std : : string & config , const std : : string & platform ) {
project < < " \t \t <ProjectConfiguration Include= \" " < < config < < " | " < < platform < < " \" > \n "
" \t \t \t <Configuration> " < < config < < " </Configuration> \n "
" \t \t \t <Platform> " < < platform < < " </Platform> \n "
" \t \t </ProjectConfiguration> \n " ;
}
2012-07-11 01:08:22 -04:00
inline void outputConfigurationType ( const BuildSetup & setup , std : : ostream & project , const std : : string & name , const std : : string & config , int version ) {
2011-04-28 17:44:17 +02:00
project < < " \t <PropertyGroup Condition= \" '$(Configuration)|$(Platform)'==' " < < config < < " ' \" Label= \" Configuration \" > \n "
2011-09-06 16:01:10 -04:00
" \t \t <ConfigurationType> " < < ( ( name = = setup . projectName | | setup . devTools ) ? " Application " : " StaticLibrary " ) < < " </ConfigurationType> \n "
2012-07-14 12:34:12 -04:00
" \t \t <PlatformToolset>v " < < version < < " 0</PlatformToolset> \n "
2011-04-28 17:44:17 +02:00
" \t </PropertyGroup> \n " ;
}
inline void outputProperties ( std : : ostream & project , const std : : string & config , const std : : string & properties ) {
project < < " \t <ImportGroup Condition= \" '$(Configuration)|$(Platform)'==' " < < config < < " ' \" Label= \" PropertySheets \" > \n "
" \t \t <Import Project= \" $(UserRootDir) \\ Microsoft.Cpp.$(Platform).user.props \" Condition= \" exists('$(UserRootDir) \\ Microsoft.Cpp.$(Platform).user.props') \" Label= \" LocalAppDataPlatform \" /> \n "
" \t \t <Import Project= \" " < < properties < < " \" /> \n "
" \t </ImportGroup> \n " ;
}
} // End of anonymous namespace
2010-11-23 11:47:52 +00:00
void MSBuildProvider : : createProjectFile ( const std : : string & name , const std : : string & uuid , const BuildSetup & setup , const std : : string & moduleDir ,
const StringList & includeList , const StringList & excludeList ) {
const std : : string projectFile = setup . outputDir + ' / ' + name + getProjectExtension ( ) ;
std : : ofstream project ( projectFile . c_str ( ) ) ;
if ( ! project )
error ( " Could not open \" " + projectFile + " \" for writing " ) ;
project < < " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \n "
2013-06-29 18:33:50 -04:00
" <Project DefaultTargets= \" Build \" ToolsVersion= \" " < < ( _version > = 12 ? _version : 4 ) < < " .0 \" xmlns= \" http://schemas.microsoft.com/developer/msbuild/2003 \" > \n "
2010-11-23 11:47:52 +00:00
" \t <ItemGroup Label= \" ProjectConfigurations \" > \n " ;
2011-04-28 17:44:17 +02:00
outputConfiguration ( project , " Debug " , " Win32 " ) ;
outputConfiguration ( project , " Debug " , " x64 " ) ;
outputConfiguration ( project , " Analysis " , " Win32 " ) ;
outputConfiguration ( project , " Analysis " , " x64 " ) ;
outputConfiguration ( project , " Release " , " Win32 " ) ;
outputConfiguration ( project , " Release " , " x64 " ) ;
2010-11-23 11:47:52 +00:00
project < < " \t </ItemGroup> \n " ;
// Project name & Guid
project < < " \t <PropertyGroup Label= \" Globals \" > \n "
" \t \t <ProjectGuid>{ " < < uuid < < " }</ProjectGuid> \n "
" \t \t <RootNamespace> " < < name < < " </RootNamespace> \n "
" \t \t <Keyword>Win32Proj</Keyword> \n "
2013-06-29 18:33:50 -04:00
" \t \t <VCTargetsPath Condition= \" '$(VCTargetsPath " < < _version < < " )' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == '' \" >$(VCTargetsPath " < < _version < < " )</VCTargetsPath> \n "
2010-11-23 11:47:52 +00:00
" \t </PropertyGroup> \n " ;
// Shared configuration
project < < " \t <Import Project= \" $(VCTargetsPath) \\ Microsoft.Cpp.Default.props \" /> \n " ;
2012-07-11 01:08:22 -04:00
outputConfigurationType ( setup , project , name , " Release|Win32 " , _version ) ;
outputConfigurationType ( setup , project , name , " Analysis|Win32 " , _version ) ;
outputConfigurationType ( setup , project , name , " Debug|Win32 " , _version ) ;
outputConfigurationType ( setup , project , name , " Release|x64 " , _version ) ;
outputConfigurationType ( setup , project , name , " Analysis|x64 " , _version ) ;
outputConfigurationType ( setup , project , name , " Debug|x64 " , _version ) ;
2010-11-23 11:47:52 +00:00
project < < " \t <Import Project= \" $(VCTargetsPath) \\ Microsoft.Cpp.props \" /> \n "
" \t <ImportGroup Label= \" ExtensionSettings \" > \n "
" \t </ImportGroup> \n " ;
2011-09-06 16:01:10 -04:00
outputProperties ( project , " Release|Win32 " , setup . projectDescription + " _Release.props " ) ;
outputProperties ( project , " Analysis|Win32 " , setup . projectDescription + " _Analysis.props " ) ;
outputProperties ( project , " Debug|Win32 " , setup . projectDescription + " _Debug.props " ) ;
outputProperties ( project , " Release|x64 " , setup . projectDescription + " _Release64.props " ) ;
outputProperties ( project , " Analysis|x64 " , setup . projectDescription + " _Analysis64.props " ) ;
outputProperties ( project , " Debug|x64 " , setup . projectDescription + " _Debug64.props " ) ;
2010-11-23 11:47:52 +00:00
project < < " \t <PropertyGroup Label= \" UserMacros \" /> \n " ;
// Project-specific settings (analysis uses debug properties)
outputProjectSettings ( project , name , setup , false , true , false ) ;
outputProjectSettings ( project , name , setup , false , true , true ) ;
outputProjectSettings ( project , name , setup , true , true , false ) ;
outputProjectSettings ( project , name , setup , false , false , false ) ;
outputProjectSettings ( project , name , setup , false , false , true ) ;
outputProjectSettings ( project , name , setup , true , false , false ) ;
// Files
std : : string modulePath ;
if ( ! moduleDir . compare ( 0 , setup . srcDir . size ( ) , setup . srcDir ) ) {
modulePath = moduleDir . substr ( setup . srcDir . size ( ) ) ;
if ( ! modulePath . empty ( ) & & modulePath . at ( 0 ) = = ' / ' )
modulePath . erase ( 0 , 1 ) ;
}
if ( modulePath . size ( ) )
addFilesToProject ( moduleDir , project , includeList , excludeList , setup . filePrefix + ' / ' + modulePath ) ;
else
addFilesToProject ( moduleDir , project , includeList , excludeList , setup . filePrefix ) ;
2011-04-24 13:33:23 -04:00
// Output references for the main project
2011-09-06 16:01:10 -04:00
if ( name = = setup . projectName )
writeReferences ( setup , project ) ;
2010-11-23 11:47:52 +00:00
project < < " \t <Import Project= \" $(VCTargetsPath) \\ Microsoft.Cpp.targets \" /> \n "
" \t <ImportGroup Label= \" ExtensionTargets \" > \n "
" \t </ImportGroup> \n "
" </Project> \n " ;
// Output filter file if necessary
createFiltersFile ( setup , name ) ;
}
void MSBuildProvider : : createFiltersFile ( const BuildSetup & setup , const std : : string & name ) {
// No filters => no need to create a filter file
if ( _filters . empty ( ) )
return ;
// Sort all list alphabetically
_filters . sort ( ) ;
_compileFiles . sort ( ) ;
_includeFiles . sort ( ) ;
_otherFiles . sort ( ) ;
_resourceFiles . sort ( ) ;
_asmFiles . sort ( ) ;
const std : : string filtersFile = setup . outputDir + ' / ' + name + getProjectExtension ( ) + " .filters " ;
std : : ofstream filters ( filtersFile . c_str ( ) ) ;
if ( ! filters )
error ( " Could not open \" " + filtersFile + " \" for writing " ) ;
filters < < " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \n "
2013-06-29 18:33:50 -04:00
" <Project ToolsVersion= \" " < < ( _version > = 12 ? _version : 4 ) < < " .0 \" xmlns= \" http://schemas.microsoft.com/developer/msbuild/2003 \" > \n " ;
2010-11-23 11:47:52 +00:00
// Output the list of filters
filters < < " \t <ItemGroup> \n " ;
for ( std : : list < std : : string > : : iterator filter = _filters . begin ( ) ; filter ! = _filters . end ( ) ; + + filter ) {
filters < < " \t \t <Filter Include= \" " < < * filter < < " \" > \n "
" \t \t \t <UniqueIdentifier> " < < createUUID ( ) < < " </UniqueIdentifier> \n "
" \t \t </Filter> \n " ;
}
filters < < " \t </ItemGroup> \n " ;
// Output files
2011-04-28 17:44:17 +02:00
outputFilter ( filters , _compileFiles , " ClCompile " ) ;
outputFilter ( filters , _includeFiles , " ClInclude " ) ;
outputFilter ( filters , _otherFiles , " None " ) ;
outputFilter ( filters , _resourceFiles , " ResourceCompile " ) ;
outputFilter ( filters , _asmFiles , " CustomBuild " ) ;
2010-11-23 11:47:52 +00:00
filters < < " </Project> " ;
}
2011-04-28 17:44:17 +02:00
void MSBuildProvider : : outputFilter ( std : : ostream & filters , const FileEntries & files , const std : : string & action ) {
if ( ! files . empty ( ) ) {
filters < < " \t <ItemGroup> \n " ;
for ( FileEntries : : const_iterator entry = files . begin ( ) , end = files . end ( ) ; entry ! = end ; + + entry ) {
if ( ( * entry ) . filter ! = " " ) {
filters < < " \t \t < " < < action < < " Include= \" " < < ( * entry ) . path < < " \" > \n "
" \t \t \t <Filter> " < < ( * entry ) . filter < < " </Filter> \n "
" \t \t </ " < < action < < " > \n " ;
} else {
filters < < " \t \t < " < < action < < " Include= \" " < < ( * entry ) . path < < " \" /> \n " ;
}
}
filters < < " \t </ItemGroup> \n " ;
}
}
2011-09-06 16:01:10 -04:00
void MSBuildProvider : : writeReferences ( const BuildSetup & setup , std : : ofstream & output ) {
2010-11-23 11:47:52 +00:00
output < < " \t <ItemGroup> \n " ;
for ( UUIDMap : : const_iterator i = _uuidMap . begin ( ) ; i ! = _uuidMap . end ( ) ; + + i ) {
2011-09-06 16:01:10 -04:00
if ( i - > first = = setup . projectName )
2010-11-23 11:47:52 +00:00
continue ;
output < < " \t <ProjectReference Include= \" " < < i - > first < < " .vcxproj \" > \n "
" \t \t <Project>{ " < < i - > second < < " }</Project> \n "
" \t </ProjectReference> \n " ;
}
output < < " \t </ItemGroup> \n " ;
}
void MSBuildProvider : : outputProjectSettings ( std : : ofstream & project , const std : : string & name , const BuildSetup & setup , bool isRelease , bool isWin32 , bool enableAnalysis ) {
const std : : string configuration = ( enableAnalysis ? " Analysis " : ( isRelease ? " Release " : " Debug " ) ) ;
// Check for project-specific warnings:
std : : map < std : : string , StringList > : : iterator warningsIterator = _projectWarnings . find ( name ) ;
2012-09-05 07:54:33 -04:00
bool enableLanguageExtensions = find ( _enableLanguageExtensions . begin ( ) , _enableLanguageExtensions . end ( ) , name ) ! = _enableLanguageExtensions . end ( ) ;
bool disableEditAndContinue = find ( _disableEditAndContinue . begin ( ) , _disableEditAndContinue . end ( ) , name ) ! = _disableEditAndContinue . end ( ) ;
2010-11-23 11:47:52 +00:00
// Nothing to add here, move along!
2012-09-05 07:54:33 -04:00
if ( ! setup . devTools & & name ! = setup . projectName & & ! enableLanguageExtensions & & ! disableEditAndContinue & & warningsIterator = = _projectWarnings . end ( ) )
2010-11-23 11:47:52 +00:00
return ;
std : : string warnings = " " ;
if ( warningsIterator ! = _projectWarnings . end ( ) )
for ( StringList : : const_iterator i = warningsIterator - > second . begin ( ) ; i ! = warningsIterator - > second . end ( ) ; + + i )
warnings + = * i + ' ; ' ;
project < < " \t <ItemDefinitionGroup Condition= \" '$(Configuration)|$(Platform)'==' " < < configuration < < " | " < < ( isWin32 ? " Win32 " : " x64 " ) < < " ' \" > \n "
" \t \t <ClCompile> \n " ;
2012-09-05 07:54:33 -04:00
// Language Extensions
if ( setup . devTools | | name = = setup . projectName | | enableLanguageExtensions )
2010-11-23 11:47:52 +00:00
project < < " \t \t \t <DisableLanguageExtensions>false</DisableLanguageExtensions> \n " ;
2012-09-05 07:54:33 -04:00
// Edit and Continue
if ( ( name = = setup . projectName | | disableEditAndContinue ) & & ! isRelease )
project < < " \t \t \t <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> \n " ;
// Warnings
if ( warningsIterator ! = _projectWarnings . end ( ) )
project < < " \t \t \t <DisableSpecificWarnings> " < < warnings < < " ;%(DisableSpecificWarnings)</DisableSpecificWarnings> \n " ;
2010-11-23 11:47:52 +00:00
project < < " \t \t </ClCompile> \n " ;
2011-04-24 13:33:23 -04:00
// Link configuration for main project
2011-09-06 16:01:10 -04:00
if ( name = = setup . projectName | | setup . devTools ) {
2010-11-23 11:47:52 +00:00
std : : string libraries ;
for ( StringList : : const_iterator i = setup . libraries . begin ( ) ; i ! = setup . libraries . end ( ) ; + + i )
libraries + = * i + " .lib; " ;
project < < " \t \t <Link> \n "
2011-09-06 16:01:10 -04:00
" \t \t \t <OutputFile>$(OutDir) " < < ( setup . devTools ? name : setup . projectName ) < < " .exe</OutputFile> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <AdditionalDependencies> " < < libraries < < " %(AdditionalDependencies)</AdditionalDependencies> \n "
" \t \t </Link> \n " ;
2011-09-06 16:01:10 -04:00
if ( ! setup . devTools & & setup . runBuildEvents ) {
2011-04-22 14:10:14 -04:00
project < < " \t \t <PreBuildEvent> \n "
2011-04-24 13:33:23 -04:00
" \t \t \t <Message>Generate revision</Message> \n "
2011-04-22 14:10:14 -04:00
" \t \t \t <Command> " < < getPreBuildEvent ( ) < < " </Command> \n "
" \t \t </PreBuildEvent> \n " ;
2010-11-23 11:47:52 +00:00
// Copy data files to the build folder
project < < " \t \t <PostBuildEvent> \n "
" \t \t \t <Message>Copy data files to the build folder</Message> \n "
2011-04-26 20:10:46 -04:00
" \t \t \t <Command> " < < getPostBuildEvent ( isWin32 , setup . createInstaller ) < < " </Command> \n "
2010-11-23 11:47:52 +00:00
" \t \t </PostBuildEvent> \n " ;
}
}
project < < " \t </ItemDefinitionGroup> \n " ;
}
2011-09-06 16:01:10 -04:00
void MSBuildProvider : : outputGlobalPropFile ( const BuildSetup & setup , std : : ofstream & properties , int bits , const StringList & defines , const std : : string & prefix , bool runBuildEvents ) {
2010-11-23 11:47:52 +00:00
std : : string warnings ;
for ( StringList : : const_iterator i = _globalWarnings . begin ( ) ; i ! = _globalWarnings . end ( ) ; + + i )
warnings + = * i + ' ; ' ;
std : : string definesList ;
for ( StringList : : const_iterator i = defines . begin ( ) ; i ! = defines . end ( ) ; + + i )
definesList + = * i + ' ; ' ;
2011-04-24 12:34:57 -04:00
// Add define to include revision header
if ( runBuildEvents )
2011-04-24 13:33:23 -04:00
definesList + = REVISION_DEFINE " ; " ;
2011-04-24 12:34:57 -04:00
2010-11-23 11:47:52 +00:00
properties < < " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \n "
2013-06-29 18:33:50 -04:00
" <Project DefaultTargets= \" Build \" ToolsVersion= \" " < < ( _version > = 12 ? _version : 4 ) < < " .0 \" xmlns= \" http://schemas.microsoft.com/developer/msbuild/2003 \" > \n "
2010-11-23 11:47:52 +00:00
" \t <PropertyGroup> \n "
2011-09-06 16:01:10 -04:00
" \t \t <_PropertySheetDisplayName> " < < setup . projectDescription < < " _Global</_PropertySheetDisplayName> \n "
2011-04-24 13:33:23 -04:00
" \t \t <ExecutablePath>$( " < < LIBS_DEFINE < < " ) \\ bin;$(ExecutablePath)</ExecutablePath> \n "
" \t \t <LibraryPath>$( " < < LIBS_DEFINE < < " ) \\ lib \\ " < < ( bits = = 32 ? " x86 " : " x64 " ) < < " ;$(LibraryPath)</LibraryPath> \n "
" \t \t <IncludePath>$( " < < LIBS_DEFINE < < " ) \\ include;$(IncludePath)</IncludePath> \n "
2010-11-23 11:47:52 +00:00
" \t \t <OutDir>$(Configuration) " < < bits < < " \\ </OutDir> \n "
" \t \t <IntDir>$(Configuration) " < < bits < < " /$(ProjectName) \\ </IntDir> \n "
" \t </PropertyGroup> \n "
" \t <ItemDefinitionGroup> \n "
" \t \t <ClCompile> \n "
" \t \t \t <DisableLanguageExtensions>true</DisableLanguageExtensions> \n "
" \t \t \t <DisableSpecificWarnings> " < < warnings < < " ;%(DisableSpecificWarnings)</DisableSpecificWarnings> \n "
2011-04-24 13:33:23 -04:00
" \t \t \t <AdditionalIncludeDirectories>$( " < < LIBS_DEFINE < < " ) \\ include; " < < prefix < < " ; " < < prefix < < " \\ engines;$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <PreprocessorDefinitions> " < < definesList < < " %(PreprocessorDefinitions)</PreprocessorDefinitions> \n "
2011-09-06 16:01:10 -04:00
" \t \t \t <ExceptionHandling> " < < ( setup . devTools ? " Sync " : " " ) < < " </ExceptionHandling> \n " ;
2011-04-24 13:33:23 -04:00
# if NEEDS_RTTI
properties < < " \t \t \t <RuntimeTypeInfo>true</RuntimeTypeInfo> \n " ;
# else
properties < < " \t \t \t <RuntimeTypeInfo>false</RuntimeTypeInfo> \n " ;
# endif
properties < < " \t \t \t <WarningLevel>Level4</WarningLevel> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <TreatWarningAsError>false</TreatWarningAsError> \n "
" \t \t \t <CompileAs>Default</CompileAs> \n "
" \t \t </ClCompile> \n "
" \t \t <Link> \n "
" \t \t \t <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries> \n "
2011-09-06 16:01:10 -04:00
" \t \t \t <SubSystem>Console</SubSystem> \n " ;
if ( ! setup . devTools )
properties < < " \t \t \t <EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol> \n " ;
properties < < " \t \t </Link> \n "
2010-11-23 11:47:52 +00:00
" \t \t <ResourceCompile> \n "
" \t \t \t <AdditionalIncludeDirectories> " < < prefix < < " ;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> \n "
" \t \t </ResourceCompile> \n "
" \t </ItemDefinitionGroup> \n "
" </Project> \n " ;
properties . flush ( ) ;
}
void MSBuildProvider : : createBuildProp ( const BuildSetup & setup , bool isRelease , bool isWin32 , bool enableAnalysis ) {
const std : : string outputType = ( enableAnalysis ? " Analysis " : ( isRelease ? " Release " : " Debug " ) ) ;
const std : : string outputBitness = ( isWin32 ? " 32 " : " 64 " ) ;
2011-09-06 16:01:10 -04:00
std : : ofstream properties ( ( setup . outputDir + ' / ' + setup . projectDescription + " _ " + outputType + ( isWin32 ? " " : " 64 " ) + getPropertiesExtension ( ) ) . c_str ( ) ) ;
2010-11-23 11:47:52 +00:00
if ( ! properties )
2011-09-06 16:01:10 -04:00
error ( " Could not open \" " + setup . outputDir + ' / ' + setup . projectDescription + " _ " + outputType + ( isWin32 ? " " : " 64 " ) + getPropertiesExtension ( ) + " \" for writing " ) ;
2010-11-23 11:47:52 +00:00
properties < < " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \n "
2013-06-29 18:33:50 -04:00
" <Project DefaultTargets= \" Build \" ToolsVersion= \" " < < ( _version > = 12 ? _version : 4 ) < < " .0 \" xmlns= \" http://schemas.microsoft.com/developer/msbuild/2003 \" > \n "
2010-11-23 11:47:52 +00:00
" \t <ImportGroup Label= \" PropertySheets \" > \n "
2011-09-06 16:01:10 -04:00
" \t \t <Import Project= \" " < < setup . projectDescription < < " _Global " < < ( isWin32 ? " " : " 64 " ) < < " .props \" /> \n "
2010-11-23 11:47:52 +00:00
" \t </ImportGroup> \n "
" \t <PropertyGroup> \n "
2011-09-06 16:01:10 -04:00
" \t \t <_PropertySheetDisplayName> " < < setup . projectDescription < < " _ " < < outputType < < outputBitness < < " </_PropertySheetDisplayName> \n "
2010-11-23 11:47:52 +00:00
" \t \t <LinkIncremental> " < < ( isRelease ? " false " : " true " ) < < " </LinkIncremental> \n "
" \t </PropertyGroup> \n "
" \t <ItemDefinitionGroup> \n "
" \t \t <ClCompile> \n " ;
if ( isRelease ) {
properties < < " \t \t \t <IntrinsicFunctions>true</IntrinsicFunctions> \n "
" \t \t \t <WholeProgramOptimization>true</WholeProgramOptimization> \n "
2013-07-04 12:06:22 -04:00
" \t \t \t <PreprocessorDefinitions>WIN32;DISABLE_GUI_BUILTIN_THEME;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <StringPooling>true</StringPooling> \n "
" \t \t \t <BufferSecurityCheck>false</BufferSecurityCheck> \n "
" \t \t \t <DebugInformationFormat></DebugInformationFormat> \n "
2011-06-06 13:11:47 -04:00
" \t \t \t <RuntimeLibrary>MultiThreaded</RuntimeLibrary> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <EnablePREfast> " < < ( enableAnalysis ? " true " : " false " ) < < " </EnablePREfast> \n "
" \t \t </ClCompile> \n "
" \t \t <Link> \n "
" \t \t \t <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries> \n "
" \t \t \t <SetChecksum>true</SetChecksum> \n " ;
} else {
properties < < " \t \t \t <Optimization>Disabled</Optimization> \n "
2013-07-04 12:06:22 -04:00
" \t \t \t <PreprocessorDefinitions>WIN32;DISABLE_GUI_BUILTIN_THEME;%(PreprocessorDefinitions)</PreprocessorDefinitions> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <MinimalRebuild>true</MinimalRebuild> \n "
" \t \t \t <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> \n "
" \t \t \t <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> \n "
" \t \t \t <FunctionLevelLinking>true</FunctionLevelLinking> \n "
" \t \t \t <TreatWarningAsError>false</TreatWarningAsError> \n "
" \t \t \t <DebugInformationFormat> " < < ( isWin32 ? " EditAndContinue " : " ProgramDatabase " ) < < " </DebugInformationFormat> \n " // For x64 format Edit and continue is not supported, thus we default to Program Database
" \t \t \t <EnablePREfast> " < < ( enableAnalysis ? " true " : " false " ) < < " </EnablePREfast> \n "
" \t \t </ClCompile> \n "
" \t \t <Link> \n "
" \t \t \t <GenerateDebugInformation>true</GenerateDebugInformation> \n "
2012-07-14 12:34:12 -04:00
" \t \t \t <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> \n "
2010-11-23 11:47:52 +00:00
" \t \t \t <IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries> \n " ;
}
properties < < " \t \t </Link> \n "
" \t </ItemDefinitionGroup> \n "
" </Project> \n " ;
properties . flush ( ) ;
properties . close ( ) ;
}
bool hasEnding ( std : : string const & fullString , std : : string const & ending ) {
if ( fullString . length ( ) > ending . length ( ) ) {
return ( 0 = = fullString . compare ( fullString . length ( ) - ending . length ( ) , ending . length ( ) , ending ) ) ;
} else {
return false ;
}
}
2011-04-28 17:44:17 +02:00
namespace {
inline void outputNasmCommand ( std : : ostream & projectFile , const std : : string & config , const std : : string & prefix ) {
projectFile < < " \t \t \t <Command Condition= \" '$(Configuration)|$(Platform)'==' " < < config < < " |Win32' \" >nasm.exe -f win32 -g -o \" $(IntDir) " < < prefix < < " %(Filename).obj \" \" %(FullPath) \" </Command> \n "
" \t \t \t <Outputs Condition= \" '$(Configuration)|$(Platform)'==' " < < config < < " |Win32' \" >$(IntDir) " < < prefix < < " %(Filename).obj;%(Outputs)</Outputs> \n " ;
}
} // End of anonymous namespace
2010-11-23 11:47:52 +00:00
void MSBuildProvider : : writeFileListToProject ( const FileNode & dir , std : : ofstream & projectFile , const int , const StringList & duplicate ,
const std : : string & objPrefix , const std : : string & filePrefix ) {
// Reset lists
_filters . clear ( ) ;
_compileFiles . clear ( ) ;
_includeFiles . clear ( ) ;
_otherFiles . clear ( ) ;
_resourceFiles . clear ( ) ;
_asmFiles . clear ( ) ;
// Compute the list of files
_filters . push_back ( " " ) ; // init filters
computeFileList ( dir , duplicate , objPrefix , filePrefix ) ;
_filters . pop_back ( ) ; // remove last empty filter
// Output compile files
if ( ! _compileFiles . empty ( ) ) {
projectFile < < " \t <ItemGroup> \n " ;
for ( std : : list < FileEntry > : : const_iterator entry = _compileFiles . begin ( ) ; entry ! = _compileFiles . end ( ) ; + + entry ) {
const bool isDuplicate = ( std : : find ( duplicate . begin ( ) , duplicate . end ( ) , ( * entry ) . name + " .o " ) ! = duplicate . end ( ) ) ;
// Deal with duplicated file names
if ( isDuplicate ) {
projectFile < < " \t \t <ClCompile Include= \" " < < ( * entry ) . path < < " \" > \n "
" \t \t \t <ObjectFileName>$(IntDir) " < < ( * entry ) . prefix < < " %(Filename).obj</ObjectFileName> \n " ;
projectFile < < " \t \t </ClCompile> \n " ;
} else {
projectFile < < " \t \t <ClCompile Include= \" " < < ( * entry ) . path < < " \" /> \n " ;
}
}
projectFile < < " \t </ItemGroup> \n " ;
}
// Output include, other and resource files
2011-04-28 17:44:17 +02:00
outputFiles ( projectFile , _includeFiles , " ClInclude " ) ;
outputFiles ( projectFile , _otherFiles , " None " ) ;
outputFiles ( projectFile , _resourceFiles , " ResourceCompile " ) ;
2010-11-23 11:47:52 +00:00
// Output asm files
if ( ! _asmFiles . empty ( ) ) {
projectFile < < " \t <ItemGroup> \n " ;
for ( std : : list < FileEntry > : : const_iterator entry = _asmFiles . begin ( ) ; entry ! = _asmFiles . end ( ) ; + + entry ) {
const bool isDuplicate = ( std : : find ( duplicate . begin ( ) , duplicate . end ( ) , ( * entry ) . name + " .o " ) ! = duplicate . end ( ) ) ;
projectFile < < " \t \t <CustomBuild Include= \" " < < ( * entry ) . path < < " \" > \n "
" \t \t \t <FileType>Document</FileType> \n " ;
2011-04-28 17:44:17 +02:00
outputNasmCommand ( projectFile , " Debug " , ( isDuplicate ? ( * entry ) . prefix : " " ) ) ;
outputNasmCommand ( projectFile , " Analysis " , ( isDuplicate ? ( * entry ) . prefix : " " ) ) ;
outputNasmCommand ( projectFile , " Release " , ( isDuplicate ? ( * entry ) . prefix : " " ) ) ;
2010-11-23 11:47:52 +00:00
projectFile < < " \t \t </CustomBuild> \n " ;
}
projectFile < < " \t </ItemGroup> \n " ;
}
}
2011-04-28 17:44:17 +02:00
void MSBuildProvider : : outputFiles ( std : : ostream & projectFile , const FileEntries & files , const std : : string & action ) {
if ( ! files . empty ( ) ) {
projectFile < < " \t <ItemGroup> \n " ;
for ( FileEntries : : const_iterator entry = files . begin ( ) , end = files . end ( ) ; entry ! = end ; + + entry ) {
projectFile < < " \t \t < " < < action < < " Include= \" " < < ( * entry ) . path < < " \" /> \n " ;
}
projectFile < < " \t </ItemGroup> \n " ;
}
}
2010-11-23 11:47:52 +00:00
void MSBuildProvider : : computeFileList ( const FileNode & dir , const StringList & duplicate , const std : : string & objPrefix , const std : : string & filePrefix ) {
for ( FileNode : : NodeList : : const_iterator i = dir . children . begin ( ) ; i ! = dir . children . end ( ) ; + + i ) {
const FileNode * node = * i ;
if ( ! node - > children . empty ( ) ) {
// Update filter
std : : string _currentFilter = _filters . back ( ) ;
_filters . back ( ) . append ( ( _filters . back ( ) = = " " ? " " : " \\ " ) + node - > name ) ;
computeFileList ( * node , duplicate , objPrefix + node - > name + ' _ ' , filePrefix + node - > name + ' / ' ) ;
// Reset filter
_filters . push_back ( _currentFilter ) ;
} else {
// Filter files by extension
std : : string name , ext ;
splitFilename ( node - > name , name , ext ) ;
FileEntry entry ;
entry . name = name ;
entry . path = convertPathToWin ( filePrefix + node - > name ) ;
entry . filter = _filters . back ( ) ;
entry . prefix = objPrefix ;
if ( ext = = " cpp " | | ext = = " c " )
_compileFiles . push_back ( entry ) ;
else if ( ext = = " h " )
_includeFiles . push_back ( entry ) ;
else if ( ext = = " rc " )
_resourceFiles . push_back ( entry ) ;
else if ( ext = = " asm " )
_asmFiles . push_back ( entry ) ;
else
_otherFiles . push_back ( entry ) ;
}
}
}
} // End of CreateProjectTool namespace