for i in `find $DIRS -name '*.py'`; do
ed $i <<EOF
/^__revision__ = /s/= .*/= "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"/p
-/Copyright (c) 2001.*SCons Foundation/s/.*/__COPYRIGHT__/p
+/Copyright (c) 2001.*SCons Foundation.*/s//__COPYRIGHT__/p
w
q
EOF
for i in `find $DIRS -name '*.txt'`; do
ed $i <<EOF
/# [^ ]* 0.96.[CD][0-9]* [0-9\/]* [0-9:]* knight$/s/.*/# __FILE__ __REVISION__ __DATE__ __DEVELOPER__/p
-/Copyright (c) 2001.*SCons Foundation/s/.*/__COPYRIGHT__/p
+/Copyright (c) 2001.*SCons Foundation.*/s//__COPYRIGHT__/p
w
q
EOF
.fi
.RE
..
-.TH SCONS 1 "January 2005"
+.TH SCONS 1 "October 2005"
.SH NAME
scons \- a software construction tool
.SH SYNOPSIS
'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.IP MSVSProject()
.IP env.MSVSProject()
-Builds Microsoft Visual Studio project files.
+Builds a Microsoft Visual Studio project file,
+and by default builds a solution file as well.
+
This builds a Visual Studio project file, based on the version of
Visual Studio that is configured (either the latest installed version,
-or the version set by
+or the version specified by
.B MSVS_VERSION
-in the Environment constructor).
-For VS 6, it will generate
+in the construction environment).
+For Visual Studio 6, it will generate a
.B .dsp
-and
-.B .dsw
-files, for VS 7, it will
-generate
+file.
+For Visual Studio 7 (.NET), it will
+generate a
.B .vcproj
-and
+file.
+
+By default,
+this also generates a solution file
+for the specified project,
+a
+.B .dsw
+file for Visual Studio 6
+or a
.B .sln
-files.
+file for Visual Studio 7 (.NET).
+This behavior may be disabled by specifying
+.B auto_build_solution=0
+when you call
+.BR MSVSProject (),
+in which case you presumably want to
+build the solution file(s)
+by calling the
+.BR MSVSSolution ()
+Builder (see below).
It takes several lists of filenames to be placed into the project
-file, currently these are limited to
-.B srcs, incs, localincs, resources,
+file.
+These are currently limited to
+.BR srcs ,
+.BR incs ,
+.BR localincs ,
+.BR resources ,
and
-.B misc.
-These are pretty self explanatory, but it
-should be noted that the 'srcs' list is NOT added to the $SOURCES
-environment variable. This is because it represents a list of files
-to be added to the project file, not the source used to build the
-project file (in this case, the 'source' is the SConscript file used
-to call MSVSProject).
-
-In addition to these values (which are all optional, although not
-specifying any of them results in an empty project file), the
-following values must be specified:
-
-target: The name of the target .dsp or .vcproj file. The correct
-suffix for the version of Visual Studio must be used, but the value
-
-env['MSVSPROJECTSUFFIX']
-
+.BR misc .
+These are pretty self-explanatory, but it should be noted that these
+lists are added to the $SOURCES construction variable as strings,
+NOT as SCons File Nodes. This is because they represent file
+names to be added to the project file, not the source files used to
+build the project file.
+
+In addition to the above lists of values (which are all optional,
+although not specifying any of them results in an empty project file),
+the following values may be specified:
+
+.BR target :
+The name of the target
+.B .dsp
+or
+.B .vcproj
+file.
+The correct
+suffix for the version of Visual Studio must be used, but the
+.B env['MSVSPROJECTSUFFIX']
+construction variable
will be defined to the correct value (see example below).
-variant: The name of this particular variant. These are typically
-things like "Debug" or "Release", but really can be anything you want.
-Multiple calls to MSVSProject with different variants are allowed: all
-variants will be added to the project file with their appropriate
+.BR variant :
+The name of this particular variant.
+For Visual Studio 7 projects,
+this can also be a list of variant names.
+These are typically things like "Debug" or "Release", but really
+can be anything you want.
+For Visual Studio 7 projects,
+they may also specify a target platform
+separated from the variant name by a
+.B |
+(vertical pipe)
+character:
+.BR Debug|Xbox .
+The default target platform is Win32.
+Multiple calls to
+.BR MSVSProject ()
+with different variants are allowed;
+all variants will be added to the project file with their appropriate
build targets and sources.
-buildtarget: A list of SCons.Node.FS objects which is returned from
-the command which builds the target. This is used to tell SCons what
-to build when the 'build' button is pressed inside of the IDE.
+.BR buildtarget :
+An optional string, node, or list of strings or nodes
+(one per build variant), to tell the Visual Studio debugger
+what output target to use in what build variant.
+The number of
+.B buildtarget
+entries must match the number of
+.B variant
+entries.
Example Usage:
variant = 'Release')
.EE
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.IP MSVSSolution()
+.IP env.MSVSSolution()
+Builds a Microsoft Visual Studio solution file.
+
+This builds a Visual Studio solution file,
+based on the version of Visual Studio that is configured
+(either the latest installed version,
+or the version specified by
+.B MSVS_VERSION
+in the construction environment).
+For Visual Studio 6, it will generate a
+.B .dsw
+file.
+For Visual Studio 7 (.NET), it will
+generate a
+.B .sln
+file.
+
+The following values must be specified:
+
+.BR target :
+The name of the target .dsw or .sln file. The correct
+suffix for the version of Visual Studio must be used, but the value
+.B env['MSVSSOLUTIONSUFFIX']
+will be defined to the correct value (see example below).
+
+.BR variant :
+The name of this particular variant, or a list of variant
+names (the latter is only supported for MSVS 7 solutions). These are
+typically things like "Debug" or "Release", but really can be anything
+you want. For MSVS 7 they may also specify target platform, like this
+"Debug|Xbox". Default platform is Win32.
+
+.BR projects :
+A list of project file names, or Project nodes returned by calls to the
+.BR MSVSProject ()
+Builder,
+to be placed into the solution file.
+(NOTE: Currently only one project is supported per solution.)
+It should be noted that these file names are NOT added to the $SOURCES
+environment variable in form of files, but rather as strings. This
+is because they represent file names to be added to the solution file,
+not the source files used to build the solution file.
+
+Example Usage:
+
+.ES
+ local.MSVSSolution(target = 'Bar' + env['MSVSSOLUTIONSUFFIX'],
+ projects = ['bar' + env['MSVSPROJECTSUFFIX']],
+ variant = 'Release')
+.EE
+
'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.IP Object()
.IP env.Object()
Sets the preferred version of MSVS to use.
SCons will (by default) select the latest version of MSVS
-installed on your machine. So, if you have version 6 and version 7
-(MSVS .NET) installed, it will prefer version 7. You can override this by
+installed on your machine.
+So, if you have version 6 and version 7 (MSVS .NET) installed,
+it will prefer version 7.
+You can override this by
specifying the
.B MSVS_VERSION
variable in the Environment initialization, setting it to the
appropriate version ('6.0' or '7.0', for example).
If the given version isn't installed, tool initialization will fail.
+.IP MSVSBUILDCOM
+The build command line placed in
+a generated Microsoft Visual Studio project file.
+The default is to have Visual Studio invoke SCons with any specified
+build targets.
+
+.IP MSVSCLEANCOM
+The clean command line placed in
+a generated Microsoft Visual Studio project file.
+The default is to have Visual Studio invoke SCons with the -c option
+to remove any specified targets.
+
+.IP MSVSENCODING
+The encoding string placed in
+a generated Microsoft Visual Studio project file.
+The default is encoding
+.BR Windows-1252 .
+
.IP MSVSPROJECTCOM
-The action used to generate Microsoft Visual Studio
-project and solution files.
+The action used to generate Microsoft Visual Studio project files.
.IP MSVSPROJECTSUFFIX
The suffix used for Microsoft Visual Studio project (DSP) files.
.B .dsp
when using earlier versions of Visual Studio.
+.IP MSVSREBUILDCOM
+The rebuild command line placed in
+a generated Microsoft Visual Studio project file.
+The default is to have Visual Studio invoke SCons with any specified
+rebuild targets.
+
+.IP MSVSSCONS
+The SCons used in generated Microsoft Visual Studio project files.
+The default is the version of SCons being
+used to generate the project file.
+
+.IP MSVSSCONSFLAGS
+The SCons flags used in generated Microsoft Visual Studio
+project files.
+
+.IP MSVSSCONSCOM
+The default SCons command used in generated Microsoft Visual Studio
+project files.
+
+.IP MSVSSCONSCRIPT
+The sconscript file
+(that is,
+.B SConstruct
+or
+.B SConscript
+file)
+that will be invoked by Visual Studio
+project files
+(through the
+.B MSVSSCONSCOM
+variable).
+The default is the same sconscript file
+that contains the call to
+.BR MSVSProject ()
+to build the project file.
+
+.IP MSVSSOLUTIONCOM
+The action used to generate Microsoft Visual Studio solution files.
+
.IP MSVSSOLUTIONSUFFIX
The suffix used for Microsoft Visual Studio solution (DSW) files.
The default value is
- Allow SConscript files to modify BUILD_TARGETS.
+ - Add a separate MSVSSolution() Builder, with support for the
+ following new construction variables: $MSVSBUILDCOM, $MSVSCLEANCOM,
+ $MSVSENCODING, $MSVSREBUILDCOM, $MSVSSCONS, $MSVSSCONSCOM,
+ $MSVSSCONSFLAGS, $MSVSSCONSCRIPT and $MSVSSOLUTIONCOM.
+
From Timothee Besset:
- Add support for Objective C/C++ .m and .mm file suffixes (for
import re
import string
import sys
-import types
import SCons.Builder
import SCons.Node.FS
import SCons.Platform.win32
-import SCons.Script
+import SCons.Script.SConscript
import SCons.Util
import SCons.Warnings
# the MSVS Project file invoke SCons the same way that scons.bat does,
# which works regardless of how we were invoked.
exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()"
-exec_script_main_xml = string.replace(exec_script_main, "'", "'")
# The string for the Python executable we tell the Project file to use
# is either sys.executable or, if an external PYTHON_ROOT environment
except KeyError:
python_executable = sys.executable
else:
- python_executable = os.path.join('$(PYTHON_ROOT)',
+ python_executable = os.path.join('$$(PYTHON_ROOT)',
os.path.split(sys.executable)[1])
class Config:
pass
+def splitFully(path):
+ dir, base = os.path.split(path)
+ if dir and dir != '' and dir != path:
+ return splitFully(dir)+[base]
+ if base == '':
+ return []
+ return [base]
+
+def makeHierarchy(sources):
+ '''Break a list of files into a hierarchy; for each value, if it is a string,
+ then it is a file. If it is a dictionary, it is a folder. The string is
+ the original path of the file.'''
+
+ hierarchy = {}
+ for file in sources:
+ path = splitFully(file)
+ if len(path):
+ dict = hierarchy
+ for part in path[:-1]:
+ if not dict.has_key(part):
+ dict[part] = {}
+ dict = dict[part]
+ dict[path[-1]] = file
+ #else:
+ # print 'Warning: failed to decompose path for '+str(file)
+ return hierarchy
+
class _DSPGenerator:
""" Base class for DSP generators """
+
+ srcargs = [
+ 'srcs',
+ 'incs',
+ 'localincs',
+ 'resources',
+ 'misc']
+
def __init__(self, dspfile, source, env):
- if type(dspfile) == types.StringType:
+ if SCons.Util.is_String(dspfile):
self.dspfile = os.path.abspath(dspfile)
else:
self.dspfile = dspfile.get_abspath()
- try:
- self.conspath = source[0].attributes.sconstruct.get_abspath()
- except KeyError:
- raise SCons.Errors.InternalError, \
- "Unable to determine where the SConstruct is"
-
- self.config = Config()
- if env.has_key('variant'):
- self.config.variant = env['variant'].capitalize()
- else:
+ if not env.has_key('variant'):
raise SCons.Errors.InternalError, \
"You must specify a 'variant' argument (i.e. 'Debug' or " +\
"'Release') to create an MSVSProject."
-
- if env.has_key('buildtarget'):
- if type(env['buildtarget']) == types.StringType:
- self.config.buildtarget = os.path.abspath(env['buildtarget'])
- elif type(env['buildtarget']) == types.ListType:
- self.config.buildtarget = env['buildtarget'][0].get_abspath()
- else:
- self.config.buildtarget = env['buildtarget'].get_abspath()
+ elif SCons.Util.is_String(env['variant']):
+ variants = [env['variant']]
+ elif SCons.Util.is_List(env['variant']):
+ variants = env['variant']
+
+ if not env.has_key('buildtarget') or env['buildtarget'] == None:
+ buildtarget = ['']
+ elif SCons.Util.is_String(env['buildtarget']):
+ buildtarget = [env['buildtarget']]
+ elif SCons.Util.is_List(env['buildtarget']):
+ if len(env['buildtarget']) != len(variants):
+ raise SCons.Errors.InternalError, \
+ "Sizes of 'buildtarget' and 'variant' lists must be the same."
+ buildtarget = []
+ for bt in env['buildtarget']:
+ if SCons.Util.is_String(bt):
+ buildtarget.append(bt)
+ else:
+ buildtarget.append(bt.get_abspath())
else:
- raise SCons.Errors.InternalError, \
- "You must specify a target 'buildtarget' file argument (such as the target" +\
- " executable) to create an MSVSProject."
-
- self.config.outdir = os.path.dirname(self.config.buildtarget)
-
- if type(source[0]) == types.StringType:
- self.source = os.path.abspath(source[0])
+ buildtarget = [env['buildtarget'].get_abspath()]
+ if len(buildtarget) == 1:
+ bt = buildtarget[0]
+ buildtarget = []
+ for v in variants:
+ buildtarget.append(bt)
+
+ if not env.has_key('outdir') or env['outdir'] == None:
+ outdir = ['']
+ elif SCons.Util.is_String(env['outdir']):
+ outdir = [env['outdir']]
+ elif SCons.Util.is_List(env['outdir']):
+ if len(env['outdir']) != len(variants):
+ raise SCons.Errors.InternalError, \
+ "Sizes of 'outdir' and 'variant' lists must be the same."
+ outdir = []
+ for s in env['outdir']:
+ if SCons.Util.is_String(s):
+ outdir.append(s)
+ else:
+ outdir.append(s.get_abspath())
else:
- self.source = source[0].get_abspath()
+ outdir = [env['outdir'].get_abspath()]
+ if len(outdir) == 1:
+ s = outdir[0]
+ outdir = []
+ for v in variants:
+ outdir.append(s)
+
+ self.sconscript = env['MSVSSCONSCRIPT']
self.env = env
else:
self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0])
- print "Adding '" + self.name + ' - ' + self.config.variant + "' to Visual Studio Project '" + str(dspfile) + "'"
-
sourcenames = [
- ' Source Files',
+ 'Source Files',
'Header Files',
'Local Headers',
'Resource Files',
'Other Files']
- srcargs = [
- 'srcs',
- 'incs',
- 'localincs',
- 'resources',
- 'misc']
-
self.sources = {}
for n in sourcenames:
self.sources[n] = []
self.configs = {}
- if os.path.exists(self.dspfile):
+ self.nokeep = 0
+ if env.has_key('nokeep') and env['variant'] != 0:
+ self.nokeep = 1
+
+ if self.nokeep == 0 and os.path.exists(self.dspfile):
self.Parse()
- for t in zip(sourcenames,srcargs):
+ for t in zip(sourcenames,self.srcargs):
if self.env.has_key(t[1]):
- if type(self.env[t[1]]) == types.ListType:
+ if SCons.Util.is_List(self.env[t[1]]):
for i in self.env[t[1]]:
if not i in self.sources[t[0]]:
self.sources[t[0]].append(i)
self.sources[t[0]].append(self.env[t[1]])
for n in sourcenames:
- self.sources[n].sort()
+ self.sources[n].sort(lambda a, b: cmp(a.lower(), b.lower()))
+
+ def AddConfig(variant, buildtarget, outdir):
+ config = Config()
+ config.buildtarget = buildtarget
+ config.outdir = outdir
- self.configs[self.config.variant] = self.config
+ match = re.match('(.*)\|(.*)', variant)
+ if match:
+ config.variant = match.group(1)
+ config.platform = match.group(2)
+ else:
+ config.variant = variant
+ config.platform = 'Win32';
+
+ self.configs[variant] = config
+ print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'"
+
+ for i in range(len(variants)):
+ AddConfig(variants[i], buildtarget[i], outdir[i])
+
+ self.platforms = []
+ for key in self.configs.keys():
+ platform = self.configs[key].platform
+ if not platform in self.platforms:
+ self.platforms.append(platform)
def Build(self):
pass
else:
self.file.write('\n!ELSEIF "$(CFG)" == "%s - Win32 %s"\n\n' % (name, kind))
+ env_has_buildtarget = self.env.has_key('MSVSBUILDTARGET')
+ if not env_has_buildtarget:
+ self.env['MSVSBUILDTARGET'] = buildtarget
+
# have to write this twice, once with the BASE settings, and once without
for base in ("BASE ",""):
self.file.write('# PROP %sUse_MFC 0\n'
self.file.write('1\n')
self.file.write('# PROP %sOutput_Dir "%s"\n'
'# PROP %sIntermediate_Dir "%s"\n' % (base,outdir,base,outdir))
- (d,c) = os.path.split(str(self.conspath))
- cmd = 'echo Starting SCons && "%s" -c "%s" -C %s -f %s %s'
- cmd = cmd % (python_executable, exec_script_main, d, c, buildtarget)
- self.file.write('# PROP %sCmd_Line "%s"\n'
+ cmd = 'echo Starting SCons && ' + self.env.subst('$MSVSBUILDCOM', 1)
+ self.file.write('# PROP %sCmd_Line "%s"\n'
'# PROP %sRebuild_Opt "-c && %s"\n'
'# PROP %sTarget_File "%s"\n'
'# PROP %sBsc_Name ""\n'
'# PROP %sTarget_Dir ""\n'\
%(base,cmd,base,cmd,base,buildtarget,base,base))
+ if not env_has_buildtarget:
+ del self.env['MSVSBUILDTARGET']
+
self.file.write('\n!ENDIF\n\n'
'# Begin Target\n\n')
for kind in confkeys:
self.file.write('# End Target\n'
'# End Project\n')
- # now we pickle some data and add it to the file -- MSDEV will ignore it.
- pdata = pickle.dumps(self.configs,1)
- pdata = base64.encodestring(pdata)
- self.file.write(pdata + '\n')
- pdata = pickle.dumps(self.sources,1)
- pdata = base64.encodestring(pdata)
- self.file.write(pdata + '\n')
+ if self.nokeep == 0:
+ # now we pickle some data and add it to the file -- MSDEV will ignore it.
+ pdata = pickle.dumps(self.configs,1)
+ pdata = base64.encodestring(pdata)
+ self.file.write(pdata + '\n')
+ pdata = pickle.dumps(self.sources,1)
+ pdata = base64.encodestring(pdata)
+ self.file.write(pdata + '\n')
def PrintSourceFiles(self):
- categories = {' Source Files': 'cpp|c|cxx|l|y|def|odl|idl|hpj|bat',
+ categories = {'Source Files': 'cpp|c|cxx|l|y|def|odl|idl|hpj|bat',
'Header Files': 'h|hpp|hxx|hm|inl',
'Local Headers': 'h|hpp|hxx|hm|inl',
'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe',
'Other Files': ''}
cats = categories.keys()
- cats.sort()
+ cats.sort(lambda a, b: cmp(a.lower(), b.lower()))
for kind in cats:
if not self.sources[kind]:
continue # skip empty groups
'# End Source File\n')
self.file.write('# End Group\n')
- # add the Conscript file outside of the groups
+ # add the SConscript file outside of the groups
self.file.write('# Begin Source File\n\n'
- 'SOURCE="' + str(self.source) + '"\n'
+ 'SOURCE="' + str(self.sconscript) + '"\n'
'# End Source File\n')
def Parse(self):
self.file.close()
V7DSPHeader = """\
-<?xml version="1.0" encoding = "Windows-1252"?>
+<?xml version="1.0" encoding = "%(encoding)s"?>
<VisualStudioProject
\tProjectType="Visual C++"
\tVersion="%(versionstr)s"
\tSccProjectName=""
\tSccLocalPath=""
\tKeyword="MakeFileProj">
-\t<Platforms>
-\t\t<Platform
-\t\t\tName="Win32"/>
-\t</Platforms>
"""
V7DSPConfiguration = """\
\t\t<Configuration
-\t\t\tName="%(capitalized_kind)s|Win32"
+\t\t\tName="%(variant)s|Win32"
\t\t\tOutputDirectory="%(outdir)s"
\t\t\tIntermediateDirectory="%(outdir)s"
\t\t\tConfigurationType="0"
\t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE">
\t\t\t<Tool
\t\t\t\tName="VCNMakeTool"
-\t\t\t\tBuildCommandLine="%(cmd)s"
+\t\t\t\tBuildCommandLine="%(buildcmd)s"
\t\t\t\tCleanCommandLine="%(cleancmd)s"
-\t\t\t\tRebuildCommandLine="%(cmd)s"
+\t\t\t\tRebuildCommandLine="%(rebuildcmd)s"
\t\t\t\tOutput="%(buildtarget)s"/>
\t\t</Configuration>
"""
self.versionstr = '7.10'
def PrintHeader(self):
- self.file.write(V7DSPHeader % self.__dict__)
+ versionstr = self.versionstr
+ name = self.name
+ encoding = self.env.subst('$MSVSENCODING')
+
+ self.file.write(V7DSPHeader % locals())
+
+ self.file.write('\t<Platforms>\n')
+ for platform in self.platforms:
+ self.file.write(
+ '\t\t<Platform\n'
+ '\t\t\tName="%s"/>\n' % platform)
+ self.file.write('\t</Platforms>\n')
def PrintProject(self):
self.file.write('\t<Configurations>\n')
confkeys = self.configs.keys()
confkeys.sort()
for kind in confkeys:
- capitalized_kind = kind.capitalize()
+ variant = self.configs[kind].variant
+ platform = self.configs[kind].platform
outdir = self.configs[kind].outdir
buildtarget = self.configs[kind].buildtarget
- (d,c) = os.path.split(str(self.conspath))
- fmt = 'echo Starting SCons && "%s" -c "%s" -C %s -f %s%s %s'
- cmd = fmt % (python_executable, exec_script_main_xml,
- d, c, '', buildtarget)
- cleancmd = fmt % (python_executable, exec_script_main_xml,
- d, c, ' -c', buildtarget)
+ def xmlify(cmd):
+ cmd = string.replace(cmd, "&", "&") # do this first
+ cmd = string.replace(cmd, "'", "'")
+ cmd = string.replace(cmd, '"', """)
+ return cmd
+
+ env_has_buildtarget = self.env.has_key('MSVSBUILDTARGET')
+ if not env_has_buildtarget:
+ self.env['MSVSBUILDTARGET'] = buildtarget
+
+ starting = 'echo Starting SCons && '
+ buildcmd = xmlify(starting + self.env.subst('$MSVSBUILDCOM', 1))
+ rebuildcmd = xmlify(starting + self.env.subst('$MSVSREBUILDCOM', 1))
+ cleancmd = xmlify(starting + self.env.subst('$MSVSCLEANCOM', 1))
+
+ if not env_has_buildtarget:
+ del self.env['MSVSBUILDTARGET']
self.file.write(V7DSPConfiguration % locals())
self.file.write('\t</Configurations>\n')
if self.version >= 7.1:
- self.file.write('\t<References>\n'
+ self.file.write('\t<References>\n'
'\t</References>\n')
self.PrintSourceFiles()
self.file.write('</VisualStudioProject>\n')
- # now we pickle some data and add it to the file -- MSDEV will ignore it.
- pdata = pickle.dumps(self.configs,1)
- pdata = base64.encodestring(pdata)
- self.file.write('<!-- SCons Data:\n' + pdata + '\n')
- pdata = pickle.dumps(self.sources,1)
- pdata = base64.encodestring(pdata)
- self.file.write(pdata + '-->\n')
+ if self.nokeep == 0:
+ # now we pickle some data and add it to the file -- MSDEV will ignore it.
+ pdata = pickle.dumps(self.configs,1)
+ pdata = base64.encodestring(pdata)
+ self.file.write('<!-- SCons Data:\n' + pdata + '\n')
+ pdata = pickle.dumps(self.sources,1)
+ pdata = base64.encodestring(pdata)
+ self.file.write(pdata + '-->\n')
def PrintSourceFiles(self):
- categories = {' Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat',
+ categories = {'Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat',
'Header Files': 'h;hpp;hxx;hm;inl',
'Local Headers': 'h;hpp;hxx;hm;inl',
'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe',
self.file.write('\t<Files>\n')
cats = categories.keys()
- cats.sort()
+ cats.sort(lambda a, b: cmp(a.lower(), b.lower()))
+ cats = filter(lambda k, s=self: s.sources[k], cats)
for kind in cats:
- if not self.sources[kind]:
- continue # skip empty groups
-
- self.file.write('\t\t<Filter\n'
- '\t\t\tName="%s"\n'
- '\t\t\tFilter="%s">\n' % (kind, categories[kind]))
-
- for file in self.sources[kind]:
- file = os.path.normpath(file)
- self.file.write('\t\t\t<File\n'
- '\t\t\t\tRelativePath="%s">\n'
- '\t\t\t</File>\n' % file)
-
- self.file.write('\t\t</Filter>\n')
-
- # add the Conscript file outside of the groups
+ if len(cats) > 1:
+ self.file.write('\t\t<Filter\n'
+ '\t\t\tName="%s"\n'
+ '\t\t\tFilter="%s">\n' % (kind, categories[kind]))
+
+
+ def printSources(hierarchy):
+ sorteditems = hierarchy.items()
+ sorteditems.sort(lambda a, b: cmp(a[0].lower(), b[0].lower()))
+
+ # First folders, then files
+ for key, value in sorteditems:
+ if SCons.Util.is_Dict(value):
+ self.file.write('\t\t\t<Filter\n'
+ '\t\t\t\tName="%s"\n'
+ '\t\t\t\tFilter="">\n' % (key))
+ printSources(value)
+ self.file.write('\t\t\t</Filter>\n')
+
+ for key, value in sorteditems:
+ if SCons.Util.is_String(value):
+ file = value
+ if commonprefix:
+ file = os.path.join(commonprefix, value)
+ file = os.path.normpath(file)
+ self.file.write('\t\t\t<File\n'
+ '\t\t\t\tRelativePath="%s">\n'
+ '\t\t\t</File>\n' % (file))
+
+ sources = self.sources[kind]
+
+ # First remove any common prefix
+ commonprefix = None
+ if len(sources) > 1:
+ commonprefix = os.path.commonprefix(sources)
+ prefixlen = len(commonprefix)
+ if prefixlen:
+ sources = map(lambda s, p=prefixlen: s[p:], sources)
+
+ hierarchy = makeHierarchy(sources)
+ printSources(hierarchy)
+
+ if len(cats)>1:
+ self.file.write('\t\t</Filter>\n')
+
+ # add the SConscript file outside of the groups
self.file.write('\t\t<File\n'
'\t\t\tRelativePath="%s">\n'
- '\t\t</File>\n'
- '\t</Files>\n' % str(self.source))
+ '\t\t</File>\n' % str(self.sconscript))
- self.file.write('\t<Globals>\n'
+ self.file.write('\t</Files>\n'
+ '\t<Globals>\n'
'\t</Globals>\n')
def Parse(self):
class _DSWGenerator:
""" Base class for DSW generators """
- def __init__(self, dswfile, dspfile, source, env):
+ def __init__(self, dswfile, source, env):
self.dswfile = os.path.normpath(str(dswfile))
- self.dspfile = os.path.abspath(str(dspfile))
self.env = env
+ if not env.has_key('projects'):
+ raise SCons.Errors.UserError, \
+ "You must specify a 'projects' argument to create an MSVSSolution."
+ projects = env['projects']
+ if not SCons.Util.is_List(projects):
+ raise SCons.Errors.InternalError, \
+ "The 'projects' argument must be a list of nodes."
+ projects = SCons.Util.flatten(projects)
+ if len(projects) < 1:
+ raise SCons.Errors.UserError, \
+ "You must specify at least one project to create an MSVSSolution."
+ if len(projects) > 1:
+ raise SCons.Errors.UserError, \
+ "Currently you can specify at most one project to create an MSVSSolution."
+ self.dspfile = str(projects[0])
+
if self.env.has_key('name'):
self.name = self.env['name']
else:
class _GenerateV7DSW(_DSWGenerator):
"""Generates a Solution file for MSVS .NET"""
- def __init__(self, dswfile, dspfile, source, env):
- _DSWGenerator.__init__(self, dswfile, dspfile, source, env)
+ def __init__(self, dswfile, source, env):
+ _DSWGenerator.__init__(self, dswfile, source, env)
self.version = float(self.env['MSVS_VERSION'])
self.versionstr = '7.00'
else:
self.slnguid = _generateGUID(dswfile, self.name)
- self.config = Config()
- if env.has_key('variant'):
- self.config.variant = env['variant'].capitalize()
- else:
- raise SCons.Errors.InternalError, \
- "You must specify a 'variant' argument (i.e. 'Debug' or " +\
- "'Release') to create an MSVS Solution File."
-
self.configs = {}
- if os.path.exists(self.dswfile):
+ self.nokeep = 0
+ if env.has_key('nokeep') and env['variant'] != 0:
+ self.nokeep = 1
+
+ if self.nokeep == 0 and os.path.exists(self.dswfile):
self.Parse()
- self.configs[self.config.variant] = self.config
+ def AddConfig(variant):
+ config = Config()
+
+ match = re.match('(.*)\|(.*)', variant)
+ if match:
+ config.variant = match.group(1)
+ config.platform = match.group(2)
+ else:
+ config.variant = variant
+ config.platform = 'Win32';
+
+ self.configs[variant] = config
+ print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'"
+
+ if not env.has_key('variant'):
+ raise SCons.Errors.InternalError, \
+ "You must specify a 'variant' argument (i.e. 'Debug' or " +\
+ "'Release') to create an MSVS Solution File."
+ elif SCons.Util.is_String(env['variant']):
+ AddConfig(env['variant'])
+ elif SCons.Util.is_List(env['variant']):
+ for variant in env['variant']:
+ AddConfig(variant)
+
+ self.platforms = []
+ for key in self.configs.keys():
+ platform = self.configs[key].platform
+ if not platform in self.platforms:
+ self.platforms.append(platform)
def Parse(self):
try:
confkeys.sort()
cnt = 0
for name in confkeys:
- self.file.write('\t\tConfigName.%d = %s\n' % (cnt, name.capitalize()))
+ variant = self.configs[name].variant
+ self.file.write('\t\tConfigName.%d = %s\n' % (cnt, variant))
cnt = cnt + 1
self.file.write('\tEndGlobalSection\n')
if self.version < 7.1:
'\tEndGlobalSection\n')
self.file.write('\tGlobalSection(ProjectConfiguration) = postSolution\n')
for name in confkeys:
- name = name.capitalize()
- self.file.write('\t\t%s.%s.ActiveCfg = %s|Win32\n'
- '\t\t%s.%s.Build.0 = %s|Win32\n' %(self.slnguid,name,name,self.slnguid,name,name))
+ name = name
+ variant = self.configs[name].variant
+ platform = self.configs[name].platform
+ self.file.write('\t\t%s.%s.ActiveCfg = %s|%s\n'
+ '\t\t%s.%s.Build.0 = %s|%s\n' %(self.slnguid,variant,variant,platform,self.slnguid,variant,variant,platform))
self.file.write('\tEndGlobalSection\n'
'\tGlobalSection(ExtensibilityGlobals) = postSolution\n'
'\tEndGlobalSection\n'
'\tGlobalSection(ExtensibilityAddIns) = postSolution\n'
'\tEndGlobalSection\n'
'EndGlobal\n')
- pdata = pickle.dumps(self.configs,1)
- pdata = base64.encodestring(pdata)
- self.file.write(pdata + '\n')
+ if self.nokeep == 0:
+ pdata = pickle.dumps(self.configs,1)
+ pdata = base64.encodestring(pdata)
+ self.file.write(pdata + '\n')
def Build(self):
try:
def PrintWorkspace(self):
""" writes a DSW file """
- self.file.write(V6DSWHeader % self.__dict__)
+ name = self.name
+ dspfile = self.dspfile
+ self.file.write(V6DSWHeader % locals())
def Build(self):
try:
g = _GenerateV6DSP(dspfile, source, env)
g.Build()
-def GenerateDSW(dswfile, dspfile, source, env):
+def GenerateDSW(dswfile, source, env):
"""Generates a Solution/Workspace file based on the version of MSVS that is being used"""
if env.has_key('MSVS_VERSION') and float(env['MSVS_VERSION']) >= 7.0:
- g = _GenerateV7DSW(dswfile, dspfile, source, env)
+ g = _GenerateV7DSW(dswfile, source, env)
g.Build()
else:
- g = _GenerateV6DSW(dswfile, dspfile, source, env)
+ g = _GenerateV6DSW(dswfile, source, env)
g.Build()
version = '6.0'
versions = [version]
- if not env.has_key('MSVS') or type(env['MSVS']) != types.DictType:
+ if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']):
env['MSVS'] = {}
if env.has_key('MSVS_VERSION'):
def GenerateProject(target, source, env):
# generate the dsp file, according to the version of MSVS.
builddspfile = target[0]
- builddswfile = target[1]
- dswfile = builddswfile.srcnode()
dspfile = builddspfile.srcnode()
-# print "SConscript :",str(source[0])
-# print "DSW file :",dswfile
-# print "DSP file :",dspfile
-# print "Build DSW file:",builddswfile
-# print "Build DSP file:",builddspfile
-
# this detects whether or not we're using a BuildDir
- if os.path.abspath(os.path.normcase(str(dspfile))) != \
- os.path.abspath(os.path.normcase(str(builddspfile))):
+ if not dspfile is builddspfile:
try:
bdsp = open(str(builddspfile), "w+")
except IOError, detail:
bdsp.write("This is just a placeholder file.\nThe real project file is here:\n%s\n" % dspfile.get_abspath())
- try:
- bdsw = open(str(builddswfile), "w+")
- except IOError, detail:
- print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n'
- raise
+ GenerateDSP(dspfile, source, env)
- bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath())
+ if env.get('auto_build_solution', 1):
+ builddswfile = target[1]
+ dswfile = builddswfile.srcnode()
- GenerateDSP(dspfile, source, env)
- GenerateDSW(dswfile, dspfile, source, env)
+ if not dswfile is builddswfile:
+
+ try:
+ bdsw = open(str(builddswfile), "w+")
+ except IOError, detail:
+ print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n'
+ raise
+
+ bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath())
+
+ GenerateDSW(dswfile, source, env)
+
+def GenerateSolution(target, source, env):
+ GenerateDSW(target[0], source, env)
def projectEmitter(target, source, env):
- """Sets up the DSP and DSW dependencies for an SConscript file."""
+ """Sets up the DSP dependencies."""
+ # todo: Not sure what sets source to what user has passed as target,
+ # but this is what happens. When that is fixed, we also won't have
+ # to make the user always append env['MSVSPROJECTSUFFIX'] to target.
if source[0] == target[0]:
source = []
suff = env.subst('$MSVSPROJECTSUFFIX')
target[0] = base + suff
- dspfile = env.File(target[0]).srcnode()
- dswfile = env.File(SCons.Util.splitext(str(dspfile))[0] + env.subst('$MSVSSOLUTIONSUFFIX'))
+ if not source:
+ source = 'prj_inputs:'
+ source = source + env.subst('$MSVSSCONSCOM', 1)
+ source = source + env.subst('$MSVSENCODING', 1)
+
+ if env.has_key('buildtarget') and env['buildtarget'] != None:
+ if SCons.Util.is_String(env['buildtarget']):
+ source = source + ' "%s"' % env['buildtarget']
+ elif SCons.Util.is_List(env['buildtarget']):
+ for bt in env['buildtarget']:
+ if SCons.Util.is_String(bt):
+ source = source + ' "%s"' % bt
+ else:
+ try: source = source + ' "%s"' % bt.get_abspath()
+ except AttributeError: raise SCons.Errors.InternalError, \
+ "buildtarget can be a string, a node, a list of strings or nodes, or None"
+ else:
+ try: source = source + ' "%s"' % env['buildtarget'].get_abspath()
+ except AttributeError: raise SCons.Errors.InternalError, \
+ "buildtarget can be a string, a node, a list of strings or nodes, or None"
+
+ if env.has_key('outdir') and env['outdir'] != None:
+ if SCons.Util.is_String(env['outdir']):
+ source = source + ' "%s"' % env['outdir']
+ elif SCons.Util.is_List(env['outdir']):
+ for s in env['outdir']:
+ if SCons.Util.is_String(s):
+ source = source + ' "%s"' % s
+ else:
+ try: source = source + ' "%s"' % s.get_abspath()
+ except AttributeError: raise SCons.Errors.InternalError, \
+ "outdir can be a string, a node, a list of strings or nodes, or None"
+ else:
+ try: source = source + ' "%s"' % env['outdir'].get_abspath()
+ except AttributeError: raise SCons.Errors.InternalError, \
+ "outdir can be a string, a node, a list of strings or nodes, or None"
+
+ if env.has_key('name'):
+ if SCons.Util.is_String(env['name']):
+ source = source + ' "%s"' % env['name']
+ else:
+ raise SCons.Errors.InternalError, "name must be a string"
+
+ if env.has_key('variant'):
+ if SCons.Util.is_String(env['variant']):
+ source = source + ' "%s"' % env['variant']
+ elif SCons.Util.is_List(env['variant']):
+ for variant in env['variant']:
+ if SCons.Util.is_String(variant):
+ source = source + ' "%s"' % variant
+ else:
+ raise SCons.Errors.InternalError, "name must be a string or a list of strings"
+ else:
+ raise SCons.Errors.InternalError, "variant must be a string or a list of strings"
+ else:
+ raise SCons.Errors.InternalError, "variant must be specified"
+
+ for s in _DSPGenerator.srcargs:
+ if env.has_key(s):
+ if SCons.Util.is_String(env[s]):
+ source = source + ' "%s' % env[s]
+ elif SCons.Util.is_List(env[s]):
+ for t in env[s]:
+ if SCons.Util.is_String(t):
+ source = source + ' "%s"' % t
+ else:
+ raise SCons.Errors.InternalError, s + " must be a string or a list of strings"
+ else:
+ raise SCons.Errors.InternalError, s + " must be a string or a list of strings"
+
+ source = source + ' "%s"' % str(target[0])
+ source = [SCons.Node.Python.Value(source)]
+
+ targetlist = [target[0]]
+ sourcelist = source
+
+ if env.get('auto_build_solution', 1):
+ env['projects'] = targetlist
+ t, s = solutionEmitter(target, target, env)
+ targetlist = targetlist + t
+
+ return (targetlist, sourcelist)
+
+def solutionEmitter(target, source, env):
+ """Sets up the DSW dependencies."""
+
+ # todo: Not sure what sets source to what user has passed as target,
+ # but this is what happens. When that is fixed, we also won't have
+ # to make the user always append env['MSVSSOLUTIONSUFFIX'] to target.
+ if source[0] == target[0]:
+ source = []
+
+ # make sure the suffix is correct for the version of MSVS we're running.
+ (base, suff) = SCons.Util.splitext(str(target[0]))
+ suff = env.subst('$MSVSSOLUTIONSUFFIX')
+ target[0] = base + suff
- # XXX Need to find a way to abstract this; the build engine
- # shouldn't depend on anything in SCons.Script.
- stack = SCons.Script.call_stack
if not source:
- source = [stack[-1].sconscript.srcnode()]
- source[0].attributes.sconstruct = stack[0].sconscript
+ source = 'sln_inputs:'
- bdswpath = SCons.Util.splitext(str(target[0]))[0] + env.subst('$MSVSSOLUTIONSUFFIX')
- bdswfile = env.File(bdswpath)
+ if env.has_key('name'):
+ if SCons.Util.is_String(env['name']):
+ source = source + ' "%s"' % env['name']
+ else:
+ raise SCons.Errors.InternalError, "name must be a string"
- # only make these side effects if they're
- # not the same file.
- if os.path.abspath(os.path.normcase(str(dspfile))) != \
- os.path.abspath(os.path.normcase(str(target[0]))):
- env.SideEffect(dspfile, target[0])
- env.Precious(dspfile)
- # dswfile isn't precious -- it can be blown away and rewritten each time.
- env.SideEffect(dswfile, target[0])
+ if env.has_key('variant'):
+ if SCons.Util.is_String(env['variant']):
+ source = source + ' "%s"' % env['variant']
+ elif SCons.Util.is_List(env['variant']):
+ for variant in env['variant']:
+ if SCons.Util.is_String(variant):
+ source = source + ' "%s"' % variant
+ else:
+ raise SCons.Errors.InternalError, "name must be a string or a list of strings"
+ else:
+ raise SCons.Errors.InternalError, "variant must be a string or a list of strings"
+ else:
+ raise SCons.Errors.InternalError, "variant must be specified"
- return ([target[0],bdswfile], source)
+ if env.has_key('slnguid'):
+ if SCons.Util.is_String(env['slnguid']):
+ source = source + ' "%s"' % env['slnguid']
+ else:
+ raise SCons.Errors.InternalError, "slnguid must be a string"
+
+ if env.has_key('projects'):
+ if SCons.Util.is_String(env['projects']):
+ source = source + ' "%s"' % env['projects']
+ elif SCons.Util.is_List(env['projects']):
+ for t in env['projects']:
+ if SCons.Util.is_String(t):
+ source = source + ' "%s"' % t
+
+ source = source + ' "%s"' % str(target[0])
+ source = [SCons.Node.Python.Value(source)]
+
+ return ([target[0]], source)
-projectGeneratorAction = SCons.Action.Action(GenerateProject, None)
+projectAction = SCons.Action.Action(GenerateProject, None)
+
+solutionAction = SCons.Action.Action(GenerateSolution, None)
projectBuilder = SCons.Builder.Builder(action = '$MSVSPROJECTCOM',
suffix = '$MSVSPROJECTSUFFIX',
emitter = projectEmitter)
+solutionBuilder = SCons.Builder.Builder(action = '$MSVSSOLUTIONCOM',
+ suffix = '$MSVSSOLUTIONSUFFIX',
+ emitter = solutionEmitter)
+
def generate(env):
"""Add Builders and construction variables for Microsoft Visual
Studio project files to an Environment."""
except KeyError:
env['BUILDERS']['MSVSProject'] = projectBuilder
- env['MSVSPROJECTCOM'] = projectGeneratorAction
+ try:
+ env['BUILDERS']['MSVSSolution']
+ except KeyError:
+ env['BUILDERS']['MSVSSolution'] = solutionBuilder
+
+ env['MSVSPROJECTCOM'] = projectAction
+ env['MSVSSOLUTIONCOM'] = solutionAction
+
+ if SCons.Script.call_stack:
+ # XXX Need to find a way to abstract this; the build engine
+ # shouldn't depend on anything in SCons.Script.
+ env['MSVSSCONSCRIPT'] = SCons.Script.call_stack[0].sconscript
+ else:
+ env['MSVSSCONSCRIPT'] = env.File('SConstruct')
+
+ env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, exec_script_main)
+ env['MSVSSCONSFLAGS'] = '-C ${MSVSSCONSCRIPT.dir.abspath} -f ${MSVSSCONSCRIPT.name}'
+ env['MSVSSCONSCOM'] = '$MSVSSCONS $MSVSSCONSFLAGS'
+ env['MSVSBUILDCOM'] = '$MSVSSCONSCOM $MSVSBUILDTARGET'
+ env['MSVSREBUILDCOM'] = '$MSVSSCONSCOM $MSVSBUILDTARGET'
+ env['MSVSCLEANCOM'] = '$MSVSSCONSCOM -c $MSVSBUILDTARGET'
+ env['MSVSENCODING'] = 'Windows-1252'
try:
version = get_default_visualstudio_version(env)
else:
# there's at least one version of MSVS installed.
return 1
-
<builder name ="MSVSProject">
<summary>
-Builds Microsoft Visual Studio project files.
+Builds a Microsoft Visual Studio project file,
+and by default builds a solution file as well.
+
This builds a Visual Studio project file, based on the version of
Visual Studio that is configured (either the latest installed version,
-or the version set by
+or the version specified by
&cv-MSVS_VERSION;
in the Environment constructor).
-For VS 6, it will generate
+For Visual Studio 6, it will generate a
<filename>.dsp</filename>
-and
+file.
+For Visual Studio 7 (.NET), it will generate a
+<filename>.dsp</filename>
+file.
+
+By default,
+this also generates a solution file
+for the specified project,
+a
<filename>.dsw</filename>
-files, for VS 7, it will
-generate
-<filename>.vcproj</filename>
-and
+file for Visual Studio 6
+or a
<filename>.sln</filename>
-files.
+file for Visual Studio 7 (.NET).
+This behavior may be disabled by specifying
+<literal>auto_build_solution=0</literal>
+when you call
+&b-MSVSProject;,
+in which case you presumably want to
+build the solution file(s)
+by calling the
+&b-MSVSSolution;
+Builder (see below).
It takes several lists of filenames to be placed into the project
-file, currently these are limited to
+file.
+These are currently these are limited to
<literal>srcs</literal>,
<literal>incs</literal>,
<literal>localincs</literal>,
<literal>resources</literal>,
and
<literal>misc</literal>.
-These are pretty self explanatory, but it
-should be noted that the <literal>srcs</literal> list
-is NOT added to the &cv-SOURCES;
-construction variable. This is because it represents a list of files
-to be added to the project file, not the source used to build the
-project file (in this case, the "source" is the &SConscript; file used
-to call MSVSProject).
-
-In addition to these values (which are all optional, although not
-specifying any of them results in an empty project file), the
-following values must be specified:
-
-target: The name of the target
+These are pretty self-explanatory, but it should be noted that these
+lists are added to the &cv-SOURCES; construction variable as strings,
+NOT as SCons File Nodes. This is because they represent file
+names to be added to the project file, not the source files used to
+build the project file.
+
+In addition to the above lists of values (which are all optional,
+although not specifying any of them results in an empty project file),
+the following values may be specified:
+
+<literal>target</literal>: The name of the target
<filename>.dsp</filename>
or
<filename>.vcproj</filename>
-file. The correct
-suffix for the version of Visual Studio must be used, but the
+file.
+The correct
+suffix for the version of Visual Studio must be used,
+but the
&cv-MSVSPROJECTSUFFIX;
-construction value
+construction variable
will be defined to the correct value (see example below).
-variant: The name of this particular variant. These are typically
-things like "Debug" or "Release", but really can be anything you want.
-Multiple calls to MSVSProject with different variants are allowed: all
-variants will be added to the project file with their appropriate
+<literal>variant</literal>:
+The name of this particular variant.
+For Visual Studio 7 projects,
+this can also be a list of variant names.
+These are typically things like "Debug" or "Release", but really
+can be anything you want.
+For Visual Studio 7 projects,
+they may also specify a target platform
+separated from the variant name by a
+<literal>|</literal>
+(vertical pipe)
+character:
+<literal>Debug|Xbox</literal>.
+The default target platform is Win32.
+Multiple calls to
+&b-MSVSProject;
+ with different variants are allowed;
+all variants will be added to the project file with their appropriate
build targets and sources.
-buildtarget: A list of SCons.Node.FS objects which is returned from
-the command which builds the target. This is used to tell SCons what
-to build when the 'build' button is pressed inside of the IDE.
+<literal>buildtarget</literal>:
+An optional string, node, or list of strings or nodes
+(one per build variant), to tell the Visual Studio debugger
+what output target to use in what build variant.
+The number of
+<literal>buildtarget</literal>
+entries must match the number of
+<literal>variant</literal>
+entries.
Example usage:
</summary>
</builder>
+<builder name ="MSVSSolution">
+<summary>
+Builds a Microsoft Visual Studio solution file.
+
+This builds a Visual Studio solution file,
+based on the version of Visual Studio that is configured
+(either the latest installed version,
+or the version specified by
+&cv-MSVS_VERSION;
+in the construction environment).
+For Visual Studio 6, it will generate a
+<filename>dsw</filename>
+file.
+For Visual Studio 7 (.NET), it will
+generate a
+<filename>sln</filename>
+file.
+
+The following values must be specified:
+
+<literal>target</literal>:
+The name of the target .dsw or .sln file. The correct
+suffix for the version of Visual Studio must be used, but the value
+&cv-MSVSSOLUTIONSUFFIX;
+will be defined to the correct value (see example below).
+
+<literal>variant</literal>:
+The name of this particular variant, or a list of variant
+names (the latter is only supported for MSVS 7 solutions). These are
+typically things like "Debug" or "Release", but really can be anything
+you want. For MSVS 7 they may also specify target platform, like this
+"Debug|Xbox". Default platform is Win32.
+
+<literal>projects</literal>:
+A list of project file names, or Project nodes returned by calls to the
+&b-MSVSProject;
+Builder,
+to be placed into the solution file.
+(NOTE: Currently only one project is supported per solution.)
+It should be noted that these file names are NOT added to the $SOURCES
+environment variable in form of files, but rather as strings. This
+is because they represent file names to be added to the solution file,
+not the source files used to build the solution file.
+
+Example Usage:
+
+<example>
+local.MSVSSolution(target = 'Bar' + env['MSVSSOLUTIONSUFFIX'],
+ projects = ['bar' + env['MSVSPROJECTSUFFIX']],
+ variant = 'Release')
+</example>
+</summary>
+</builder>
+
<cvar name="MSVS">
<summary>
When the Microsoft Visual Studio tools are initialized, they set up
Sets the preferred version of MSVS to use.
SCons will (by default) select the latest version of MSVS
-installed on your machine. So, if you have version 6 and version 7
-(MSVS .NET) installed, it will prefer version 7. You can override this by
+installed on your machine.
+So, if you have version 6 and version 7 (MSVS .NET) installed,
+it will prefer version 7.
+You can override this by
specifying the
<envar>MSVS_VERSION</envar>
variable in the Environment initialization, setting it to the
</summary>
</cvar>
+<cvar name="MSVSBUILDCOM">
+<summary>
+The build command line placed in
+a generated Microsoft Visual Studio project file.
+The default is to have Visual Studio invoke SCons with any specified
+build targets.
+</summary>
+</cvar>
+
+<cvar name="MSVSCLEANCOM">
+<summary>
+The clean command line placed in
+a generated Microsoft Visual Studio project file.
+The default is to have Visual Studio invoke SCons with the -c option
+to remove any specified targets.
+</summary>
+</cvar>
+
+<cvar name="MSVSENCODING">
+<summary>
+The encoding string placed in
+a generated Microsoft Visual Studio project file.
+The default is encoding
+<literal>Windows-1252</literal>.
+</summary>
+</cvar>
+
<cvar name="MSVSPROJECTCOM">
<summary>
-The action used to generate Microsoft Visual Studio
-project and solution files.
+The action used to generate Microsoft Visual Studio project files.
</summary>
</cvar>
</summary>
</cvar>
+<cvar name="MSVSREBUILDCOM">
+<summary>
+The rebuild command line placed in
+a generated Microsoft Visual Studio project file.
+The default is to have Visual Studio invoke SCons with any specified
+rebuild targets.
+</summary>
+</cvar>
+
+<cvar name="MSVSSCONS">
+<summary>
+The SCons used in generated Microsoft Visual Studio project files.
+The default is the version of SCons being
+used to generate the project file.
+</summary>
+</cvar>
+
+<cvar name="MSVSSCONSFLAGS">
+<summary>
+The SCons flags used in generated Microsoft Visual Studio
+project files.
+</summary>
+</cvar>
+
+<cvar name="MSVSSCONSCOM">
+<summary>
+The default SCons command used in generated Microsoft Visual Studio
+project files.
+</summary>
+</cvar>
+
+<cvar name="MSVSSCONSCRIPT">
+<summary>
+The sconscript file
+(that is,
+&SConstruct;
+or
+&SConscript;
+file)
+that will be invoked by Visual Studio
+project files
+(through the
+&cv-MSVSSCONSCOM;
+variable).
+The default is the same sconscript file
+that contains the call to
+&b-MSVSProject;
+to build the project file.
+</summary>
+</cvar>
+
+<cvar name="MSVSSOLUTIONCOM">
+<summary>
+The action used to generate Microsoft Visual Studio solution files.
+</summary>
+</cvar>
+
<cvar name="MSVSSOLUTIONSUFFIX">
<summary>
The suffix used for Microsoft Visual Studio solution (DSW) files.
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "<WORKPATH>"
-# PROP BASE Intermediate_Dir "<WORKPATH>"
-# PROP BASE Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP BASE Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP BASE Target_File "<WORKPATH>\Test.exe"
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct Test.exe"
+# PROP BASE Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct Test.exe"
+# PROP BASE Target_File "Test.exe"
# PROP BASE Bsc_Name ""
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "<WORKPATH>"
-# PROP Intermediate_Dir "<WORKPATH>"
-# PROP Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP Target_File "<WORKPATH>\Test.exe"
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct Test.exe"
+# PROP Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct Test.exe"
+# PROP Target_File "Test.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""
!ENDIF
-# Begin Group " Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;l;y;def;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="test.c"
-# End Source File
-# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
SOURCE="test.rc"
# End Source File
# End Group
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;l;y;def;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="test.c"
+# End Source File
+# End Group
# Begin Source File
SOURCE="<SCONSCRIPT>"
###############################################################################
-Project: "Test"="<WORKPATH>\Test.dsp" - Package Owner=<4>
+Project: "Test"="Test.dsp" - Package Owner=<4>
Package=<5>
{{{
test.must_exist(test.workpath('work1', 'Test.dsp'))
dsp = test.read(['work1', 'Test.dsp'], 'r')
-expect = test.msvs_substitute(expected_dspfile, '6.0', 'work1',
- test.workpath('work1', 'SConstruct'))
+expect = test.msvs_substitute(expected_dspfile, '6.0', 'work1', 'SConstruct')
# don't compare the pickled data
assert dsp[:len(expect)] == expect, test.diff_substr(expect, dsp)
test.must_exist(test.workpath('work1', 'Test.dsw'))
dsw = test.read(['work1', 'Test.dsw'], 'r')
-expect = test.msvs_substitute(expected_dswfile, '6.0', 'work1',
- test.workpath('work1', 'SConstruct'))
+expect = test.msvs_substitute(expected_dswfile, '6.0', 'work1', 'SConstruct')
assert dsw == expect, test.diff_substr(expect, dsw)
test.run(chdir='work1', arguments='-c .')
test.run(chdir='work2', arguments=".")
+dsp = test.read(['work2', 'src', 'Test.dsp'], 'r')
+expect = test.msvs_substitute(expected_dspfile, '6.0', 'work2', 'SConstruct')
+# don't compare the pickled data
+assert dsp[:len(expect)] == expect, test.diff_substr(expect, dsp)
+
+test.must_exist(test.workpath('work2', 'src', 'Test.dsw'))
+dsw = test.read(['work2', 'src', 'Test.dsw'], 'r')
+expect = test.msvs_substitute(expected_dswfile, '6.0',
+ os.path.join('work2', 'src'))
+assert dsw == expect, test.diff_substr(expect, dsw)
+
test.must_match(['work2', 'build', 'Test.dsp'], """\
This is just a placeholder file.
The real project file is here:
""" % test.workpath('work2', 'src', 'Test.dsp'),
mode='r')
-dsp = test.read(['work2', 'src', 'Test.dsp'], 'r')
-expect = test.msvs_substitute(expected_dspfile, '6.0', 'work2',
- test.workpath('work2', 'src', 'SConscript'))
-# don't compare the pickled data
-assert dsp[:len(expect)] == expect, test.diff_substr(expect, dsp)
-
test.must_match(['work2', 'build', 'Test.dsw'], """\
This is just a placeholder file.
The real workspace file is here:
""" % test.workpath('work2', 'src', 'Test.dsw'),
mode='r')
-test.must_exist(test.workpath('work2', 'src', 'Test.dsw'))
-dsw = test.read(['work2', 'src', 'Test.dsw'], 'r')
-expect = test.msvs_substitute(expected_dswfile, '6.0', 'work2\\src')
+
+
+test.subdir('work3')
+
+test.write(['work3', 'SConstruct'], """\
+env=Environment(MSVS_VERSION = '6.0')
+
+testsrc = ['test.c']
+testincs = ['sdk.h']
+testlocalincs = ['test.h']
+testresources = ['test.rc']
+testmisc = ['readme.txt']
+
+p = env.MSVSProject(target = 'Test.dsp',
+ srcs = testsrc,
+ incs = testincs,
+ localincs = testlocalincs,
+ resources = testresources,
+ misc = testmisc,
+ buildtarget = 'Test.exe',
+ variant = 'Release',
+ auto_build_solution = 0)
+
+env.MSVSSolution(target = 'Test.dsw',
+ slnguid = '{SLNGUID}',
+ projects = [p],
+ variant = 'Release')
+""")
+
+test.run(chdir='work3', arguments=".")
+
+test.must_exist(test.workpath('work3', 'Test.dsp'))
+dsp = test.read(['work3', 'Test.dsp'], 'r')
+expect = test.msvs_substitute(expected_dspfile, '6.0', 'work3', 'SConstruct')
+# don't compare the pickled data
+assert dsp[:len(expect)] == expect, test.diff_substr(expect, dsp)
+
+test.must_exist(test.workpath('work3', 'Test.dsw'))
+dsw = test.read(['work3', 'Test.dsw'], 'r')
+expect = test.msvs_substitute(expected_dswfile, '6.0', 'work3', 'SConstruct')
assert dsw == expect, test.diff_substr(expect, dsw)
+test.run(chdir='work3', arguments='-c .')
+
+test.must_not_exist(test.workpath('work3', 'Test.dsp'))
+test.must_not_exist(test.workpath('work3', 'Test.dsw'))
+
+test.run(chdir='work3', arguments='.')
+
+test.must_exist(test.workpath('work3', 'Test.dsp'))
+test.must_exist(test.workpath('work3', 'Test.dsw'))
+
+test.run(chdir='work3', arguments='-c Test.dsw')
+
+test.must_exist(test.workpath('work3', 'Test.dsp'))
+test.must_not_exist(test.workpath('work3', 'Test.dsw'))
+
+test.run(chdir='work3', arguments='-c Test.dsp')
+
+test.must_not_exist(test.workpath('work3', 'Test.dsp'))
+
test.pass_test()
\t<Configurations>
\t\t<Configuration
\t\t\tName="Release|Win32"
-\t\t\tOutputDirectory="<WORKPATH>"
-\t\t\tIntermediateDirectory="<WORKPATH>"
+\t\t\tOutputDirectory=""
+\t\t\tIntermediateDirectory=""
\t\t\tConfigurationType="0"
\t\t\tUseOfMFC="0"
\t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE">
\t\t\t<Tool
\t\t\t\tName="VCNMakeTool"
-\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
-\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-\t\t\t\tOutput="<WORKPATH>\Test.exe"/>
+\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct Test.exe"
+\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c Test.exe"
+\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct Test.exe"
+\t\t\t\tOutput="Test.exe"/>
\t\t</Configuration>
\t</Configurations>
\t<Files>
\t\t<Filter
-\t\t\tName=" Source Files"
-\t\t\tFilter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
-\t\t\t<File
-\t\t\t\tRelativePath="test.cpp">
-\t\t\t</File>
-\t\t</Filter>
-\t\t<Filter
\t\t\tName="Header Files"
\t\t\tFilter="h;hpp;hxx;hm;inl">
\t\t\t<File
\t\t\t\tRelativePath="test.rc">
\t\t\t</File>
\t\t</Filter>
+\t\t<Filter
+\t\t\tName="Source Files"
+\t\t\tFilter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
+\t\t\t<File
+\t\t\t\tRelativePath="test.cpp">
+\t\t\t</File>
+\t\t</Filter>
\t\t<File
\t\t\tRelativePath="<SCONSCRIPT>">
\t\t</File>
test.must_exist(test.workpath('work1', 'Test.vcproj'))
vcproj = test.read(['work1', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work1',
- test.workpath('work1', 'SConstruct'))
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work1', 'SConstruct')
# don't compare the pickled data
assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
test.must_exist(test.workpath('work1', 'Test.sln'))
sln = test.read(['work1', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '7.0', 'work1',
- test.workpath('work1', 'SConstruct'))
+expect = test.msvs_substitute(expected_slnfile, '7.0', 'work1', 'SConstruct')
# don't compare the pickled data
assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
test.must_exist(test.workpath('work1', 'Test.vcproj'))
vcproj = test.read(['work1', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work1',
- test.workpath('work1', 'SConstruct'),
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work1', 'SConstruct',
python=python)
# don't compare the pickled data
assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
test.run(chdir='work2', arguments=".")
+vcproj = test.read(['work2', 'src', 'Test.vcproj'], 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work2', 'SConstruct')
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+
+test.must_exist(test.workpath('work2', 'src', 'Test.sln'))
+sln = test.read(['work2', 'src', 'Test.sln'], 'r')
+expect = test.msvs_substitute(expected_slnfile, '7.0',
+ os.path.join('work2', 'src'))
+# don't compare the pickled data
+assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
+
test.must_match(['work2', 'build', 'Test.vcproj'], """\
This is just a placeholder file.
The real project file is here:
""" % test.workpath('work2', 'src', 'Test.vcproj'),
mode='r')
-vcproj = test.read(['work2', 'src', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work2',
- test.workpath('work2', 'src', 'SConscript'))
-# don't compare the pickled data
-assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
-
test.must_match(['work2', 'build', 'Test.sln'], """\
This is just a placeholder file.
The real workspace file is here:
""" % test.workpath('work2', 'src', 'Test.sln'),
mode='r')
-test.must_exist(test.workpath('work2', 'src', 'Test.sln'))
-sln = test.read(['work2', 'src', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '7.0', 'work2\\src')
+
+
+test.subdir('work3')
+
+test.write(['work3', 'SConstruct'], """\
+env=Environment(MSVS_VERSION = '7.0')
+
+testsrc = ['test.cpp']
+testincs = ['sdk.h']
+testlocalincs = ['test.h']
+testresources = ['test.rc']
+testmisc = ['readme.txt']
+
+p = env.MSVSProject(target = 'Test.vcproj',
+ srcs = testsrc,
+ incs = testincs,
+ localincs = testlocalincs,
+ resources = testresources,
+ misc = testmisc,
+ buildtarget = 'Test.exe',
+ variant = 'Release',
+ auto_build_solution = 0)
+
+env.MSVSSolution(target = 'Test.sln',
+ slnguid = '{SLNGUID}',
+ projects = [p],
+ variant = 'Release')
+""")
+
+test.run(chdir='work3', arguments=".")
+
+test.must_exist(test.workpath('work3', 'Test.vcproj'))
+vcproj = test.read(['work3', 'Test.vcproj'], 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work3', 'SConstruct')
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+
+test.must_exist(test.workpath('work3', 'Test.sln'))
+sln = test.read(['work3', 'Test.sln'], 'r')
+expect = test.msvs_substitute(expected_slnfile, '7.0', 'work3', 'SConstruct')
# don't compare the pickled data
assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
+test.run(chdir='work3', arguments='-c .')
+
+test.must_not_exist(test.workpath('work3', 'Test.vcproj'))
+test.must_not_exist(test.workpath('work3', 'Test.sln'))
+
+test.run(chdir='work3', arguments='.')
+
+test.must_exist(test.workpath('work3', 'Test.vcproj'))
+test.must_exist(test.workpath('work3', 'Test.sln'))
+
+test.run(chdir='work3', arguments='-c Test.sln')
+
+test.must_exist(test.workpath('work3', 'Test.vcproj'))
+test.must_not_exist(test.workpath('work3', 'Test.sln'))
+
+test.run(chdir='work3', arguments='-c Test.vcproj')
+
+test.must_not_exist(test.workpath('work3', 'Test.vcproj'))
+
test.pass_test()
\t<Configurations>
\t\t<Configuration
\t\t\tName="Release|Win32"
-\t\t\tOutputDirectory="<WORKPATH>"
-\t\t\tIntermediateDirectory="<WORKPATH>"
+\t\t\tOutputDirectory=""
+\t\t\tIntermediateDirectory=""
\t\t\tConfigurationType="0"
\t\t\tUseOfMFC="0"
\t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE">
\t\t\t<Tool
\t\t\t\tName="VCNMakeTool"
-\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
-\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-\t\t\t\tOutput="<WORKPATH>\Test.exe"/>
+\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct Test.exe"
+\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c Test.exe"
+\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct Test.exe"
+\t\t\t\tOutput="Test.exe"/>
\t\t</Configuration>
\t</Configurations>
\t<References>
\t</References>
\t<Files>
\t\t<Filter
-\t\t\tName=" Source Files"
-\t\t\tFilter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
-\t\t\t<File
-\t\t\t\tRelativePath="test.cpp">
-\t\t\t</File>
-\t\t</Filter>
-\t\t<Filter
\t\t\tName="Header Files"
\t\t\tFilter="h;hpp;hxx;hm;inl">
\t\t\t<File
\t\t\t\tRelativePath="test.rc">
\t\t\t</File>
\t\t</Filter>
+\t\t<Filter
+\t\t\tName="Source Files"
+\t\t\tFilter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
+\t\t\t<File
+\t\t\t\tRelativePath="test.cpp">
+\t\t\t</File>
+\t\t</Filter>
\t\t<File
\t\t\tRelativePath="<SCONSCRIPT>">
\t\t</File>
test.must_exist(test.workpath('work1', 'Test.vcproj'))
vcproj = test.read(['work1', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.1', 'work1',
- test.workpath('work1', 'SConstruct'))
+expect = test.msvs_substitute(expected_vcprojfile, '7.1', 'work1', 'SConstruct')
# don't compare the pickled data
assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
test.must_exist(test.workpath('work1', 'Test.sln'))
sln = test.read(['work1', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '7.1', 'work1',
- test.workpath('work1', 'SConstruct'))
+expect = test.msvs_substitute(expected_slnfile, '7.1', 'work1', 'SConstruct')
# don't compare the pickled data
assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
test.must_exist(test.workpath('work1', 'Test.vcproj'))
vcproj = test.read(['work1', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.1', 'work1',
- test.workpath('work1', 'SConstruct'),
+expect = test.msvs_substitute(expected_vcprojfile, '7.1', 'work1', 'SConstruct',
python=python)
# don't compare the pickled data
assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
test.run(chdir='work2', arguments=".")
+vcproj = test.read(['work2', 'src', 'Test.vcproj'], 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work2', 'SConstruct')
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+
+test.must_exist(test.workpath('work2', 'src', 'Test.sln'))
+sln = test.read(['work2', 'src', 'Test.sln'], 'r')
+expect = test.msvs_substitute(expected_slnfile, '7.0',
+ os.path.join('work2', 'src'))
+# don't compare the pickled data
+assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
+
test.must_match(['work2', 'build', 'Test.vcproj'], """\
This is just a placeholder file.
The real project file is here:
""" % test.workpath('work2', 'src', 'Test.vcproj'),
mode='r')
-vcproj = test.read(['work2', 'src', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.0', 'work2',
- test.workpath('work2', 'src', 'SConscript'))
-# don't compare the pickled data
-assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
-
test.must_match(['work2', 'build', 'Test.sln'], """\
This is just a placeholder file.
The real workspace file is here:
""" % test.workpath('work2', 'src', 'Test.sln'),
mode='r')
-test.must_exist(test.workpath('work2', 'src', 'Test.sln'))
-sln = test.read(['work2', 'src', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '7.0', 'work2\\src')
+
+
+test.subdir('work3')
+
+test.write(['work3', 'SConstruct'], """\
+env=Environment(MSVS_VERSION = '7.1')
+
+testsrc = ['test.cpp']
+testincs = ['sdk.h']
+testlocalincs = ['test.h']
+testresources = ['test.rc']
+testmisc = ['readme.txt']
+
+p = env.MSVSProject(target = 'Test.vcproj',
+ srcs = testsrc,
+ incs = testincs,
+ localincs = testlocalincs,
+ resources = testresources,
+ misc = testmisc,
+ buildtarget = 'Test.exe',
+ variant = 'Release',
+ auto_build_solution = 0)
+
+env.MSVSSolution(target = 'Test.sln',
+ slnguid = '{SLNGUID}',
+ projects = [p],
+ variant = 'Release')
+""")
+
+test.run(chdir='work3', arguments=".")
+
+test.must_exist(test.workpath('work3', 'Test.vcproj'))
+vcproj = test.read(['work3', 'Test.vcproj'], 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.1', 'work3', 'SConstruct')
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
+
+test.must_exist(test.workpath('work3', 'Test.sln'))
+sln = test.read(['work3', 'Test.sln'], 'r')
+expect = test.msvs_substitute(expected_slnfile, '7.1', 'work3', 'SConstruct')
# don't compare the pickled data
assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
+test.run(chdir='work3', arguments='-c .')
+
+test.must_not_exist(test.workpath('work3', 'Test.vcproj'))
+test.must_not_exist(test.workpath('work3', 'Test.sln'))
+
+test.run(chdir='work3', arguments='.')
+
+test.must_exist(test.workpath('work3', 'Test.vcproj'))
+test.must_exist(test.workpath('work3', 'Test.sln'))
+
+test.run(chdir='work3', arguments='-c Test.sln')
+
+test.must_exist(test.workpath('work3', 'Test.vcproj'))
+test.must_not_exist(test.workpath('work3', 'Test.sln'))
+
+test.run(chdir='work3', arguments='-c Test.vcproj')
+
+test.must_not_exist(test.workpath('work3', 'Test.vcproj'))
+
test.pass_test()