summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-01-15 13:28:43 (GMT)
committerSteven Knight <knight@baldmt.com>2004-01-15 13:28:43 (GMT)
commitecd9231176b6cd74395ffc5b8836eaa450fccb7d (patch)
treea3cd7f007df34f31576c99f9650d35d5893872b3
parent9cc5ac377415fc2404265c614f9cf76b877fece2 (diff)
downloadSCons-ecd9231176b6cd74395ffc5b8836eaa450fccb7d.zip
SCons-ecd9231176b6cd74395ffc5b8836eaa450fccb7d.tar.gz
SCons-ecd9231176b6cd74395ffc5b8836eaa450fccb7d.tar.bz2
Fix MSVS Project file invocation when running scons.bat.
-rw-r--r--src/CHANGES.txt4
-rw-r--r--src/engine/SCons/Tool/msvs.py63
-rw-r--r--test/msvs.py96
3 files changed, 102 insertions, 61 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index d567560..45b9df3 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -122,6 +122,10 @@ RELEASE 0.95 - XXX
- Supply meaningful error messages, not stack traces, if we try to add
a non-Node as a source, dependency, or ignored dependency of a Node.
+ - Generate MSVS Project files that re-invoke SCons properly regardless
+ of whether the file was built via scons.bat or scons.py.
+ (Thanks to Niall Douglas for contributing code and testing.)
+
From Vincent Risi:
- Add support for the bcc32, ilink32 and tlib Borland tools.
diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py
index ee860e3..e4272c3 100644
--- a/src/engine/SCons/Tool/msvs.py
+++ b/src/engine/SCons/Tool/msvs.py
@@ -77,6 +77,29 @@ def _generateGUID(slnfile, name):
solution = "{" + solution[:8] + "-" + solution[8:12] + "-" + solution[12:16] + "-" + solution[16:28] + "}"
return solution
+# This is how we re-invoke SCons from inside MSVS Project files.
+# The problem is that we might have been invoked as either scons.bat
+# or scons.py. If we were invoked directly as scons.py, then we could
+# use sys.argv[0] to find the SCons "executable," but that doesn't work
+# if we were invoked as scons.bat, which uses "python -c" to execute
+# things and ends up with "-c" as sys.argv[0]. Consequently, we have
+# 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, "'", "&apos;")
+
+# The string for the Python executable we tell the Project file to use
+# is either sys.executable or, if an external PYTHON_ROOT environment
+# variable exists, $(PYTHON)ROOT\\python.exe (generalized a little to
+# pluck the actual executable name from sys.executable).
+try:
+ python_root = os.environ['PYTHON_ROOT']
+except KeyError:
+ python_executable = sys.executable
+else:
+ python_executable = os.path.join('$(PYTHON_ROOT)',
+ os.path.split(sys.executable)[1])
+
class Config:
pass
@@ -233,7 +256,9 @@ class _GenerateV6DSP(_DSPGenerator):
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 = '%s %s -C %s -f %s %s' % (sys.executable, os.path.normpath(sys.argv[0]), d, c, buildtarget)
+ cmd = '%s -c "%s" -C %s -f %s %s' % (python_executable,
+ exec_script_main,
+ d, c, buildtarget)
self.file.write('# PROP %sCmd_Line "%s"\n'
'# PROP %sRebuild_Opt "-c && %s"\n'
'# PROP %sTarget_File "%s"\n'
@@ -356,11 +381,16 @@ class _GenerateV6DSP(_DSPGenerator):
class _GenerateV7DSP(_DSPGenerator):
"""Generates a Project file for MSVS .NET"""
+ def __init__(self, dspfile, source, env, version):
+ _DSPGenerator.__init__(self, dspfile, source, env)
+ if version==7.0: self.version="7.00"
+ else: self.version="7.10"
+
def PrintHeader(self):
self.file.write('<?xml version="1.0" encoding = "Windows-1252"?>\n'
'<VisualStudioProject\n'
' ProjectType="Visual C++"\n'
- ' Version="7.00"\n'
+ ' Version="%s"\n'
' Name="%s"\n'
' SccProjectName=""\n'
' SccLocalPath=""\n'
@@ -368,7 +398,7 @@ class _GenerateV7DSP(_DSPGenerator):
' <Platforms>\n'
' <Platform\n'
' Name="Win32"/>\n'
- ' </Platforms>\n' % self.name)
+ ' </Platforms>\n' % (self.version, self.name))
def PrintProject(self):
@@ -383,13 +413,13 @@ class _GenerateV7DSP(_DSPGenerator):
buildtarget = self.configs[kind].buildtarget
(d,c) = os.path.split(str(self.conspath))
- cmd = '%s %s -C %s -f %s %s\n' % (sys.executable,\
- os.path.normpath(sys.argv[0]),\
- d,c,buildtarget)
+ cmd = '%s -c &quot;%s&quot; -C %s -f %s %s' % (python_executable,
+ exec_script_main_xml,
+ d, c, buildtarget)
- cleancmd = '%s %s -C %s -f %s -c %s' % (sys.executable,\
- os.path.normpath(sys.argv[0]),\
- d,c,buildtarget)
+ cleancmd = '%s -c &quot;%s&quot; -C %s -f %s -c %s' % (python_executable,
+ exec_script_main_xml,
+ d, c, buildtarget)
self.file.write(' <Configuration\n'
' Name="%s|Win32"\n'
@@ -530,8 +560,11 @@ class _DSWGenerator:
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, dspfile, source, env, version):
+ _DSWGenerator.__init__(self, dswfile, dspfile, source, env)
+
+ if version==7.0: self.version="7.00"
+ else: self.version="8.00"
if env.has_key('slnguid') and env['slnguid']:
self.slnguid = env['slnguid']
@@ -584,13 +617,13 @@ class _GenerateV7DSW(_DSWGenerator):
def PrintSolution(self):
"""Writes a solution file"""
- self.file.write('Microsoft Visual Studio Solution File, Format Version 7.00\n'
+ self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n'
# the next line has the GUID for an external makefile project.
'Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "%s", "%s", "%s"\n'
'EndProject\n'
'Global\n'
' GlobalSection(SolutionConfiguration) = preSolution\n'\
- % (self.name, os.path.basename(self.dspfile), self.slnguid))
+ % (self.version, self.name, os.path.basename(self.dspfile), self.slnguid))
confkeys = self.configs.keys()
confkeys.sort()
cnt = 0
@@ -673,7 +706,7 @@ def GenerateDSP(dspfile, source, env):
"""Generates a Project 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 = _GenerateV7DSP(dspfile, source, env)
+ g = _GenerateV7DSP(dspfile, source, env, float(env['MSVS_VERSION']))
g.Build()
else:
g = _GenerateV6DSP(dspfile, source, env)
@@ -683,7 +716,7 @@ def GenerateDSW(dswfile, dspfile, 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, dspfile, source, env, float(env['MSVS_VERSION']))
g.Build()
else:
g = _GenerateV6DSW(dswfile, dspfile, source, env)
diff --git a/test/msvs.py b/test/msvs.py
index 03f08cb..e447cb0 100644
--- a/test/msvs.py
+++ b/test/msvs.py
@@ -24,14 +24,16 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import TestSCons
-import sys
-import re
-import os.path
import os
-import TestCmd
+import os.path
+import re
+import string
+import sys
import time
+import TestCmd
+import TestSCons
+
expected_dspfile = '''\
# Microsoft Developer Studio Project File - Name="Test" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
@@ -66,8 +68,8 @@ CFG=Test - Win32 Release
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "<WORKPATH>"
# PROP BASE Intermediate_Dir "<WORKPATH>"
-# PROP BASE Cmd_Line "<PYTHON> <SCONS> -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP BASE Rebuild_Opt "-c && <PYTHON> <SCONS> -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP BASE Cmd_Line "<PYTHON> -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP BASE Rebuild_Opt "-c && <PYTHON> -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
# PROP BASE Target_File "<WORKPATH>\Test.exe"
# PROP BASE Bsc_Name ""
# PROP BASE Target_Dir ""
@@ -75,8 +77,8 @@ CFG=Test - Win32 Release
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "<WORKPATH>"
# PROP Intermediate_Dir "<WORKPATH>"
-# PROP Cmd_Line "<PYTHON> <SCONS> -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP Rebuild_Opt "-c && <PYTHON> <SCONS> -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP Cmd_Line "<PYTHON> -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP Rebuild_Opt "-c && <PYTHON> -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
# PROP Target_File "<WORKPATH>\Test.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""
@@ -214,10 +216,10 @@ expected_vcprojfile = '''\
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCNMakeTool"
- BuildCommandLine="<PYTHON> <SCONS> -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe
+ BuildCommandLine="<PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe
"
- CleanCommandLine="<PYTHON> <SCONS> -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
- RebuildCommandLine="<PYTHON> <SCONS> -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe
+ CleanCommandLine="<PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
+ RebuildCommandLine="<PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe
"
Output="<WORKPATH>\Test.exe"/>
</Configuration>
@@ -272,6 +274,16 @@ test = TestSCons.TestSCons(match = TestCmd.match_re)
if sys.platform != 'win32':
test.pass_test()
+exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-0.94'), join(sys.prefix, 'scons-0.94'), 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, "'", "&apos;")
+
+def substitute(input, workpath=test.workpath(), python=sys.executable):
+ result = string.replace(input, r'<WORKPATH>', workpath)
+ result = string.replace(result, r'<PYTHON>', python)
+ result = string.replace(result, r'<SCONS_SCRIPT_MAIN>', exec_script_main)
+ result = string.replace(result, r'<SCONS_SCRIPT_MAIN_XML>', exec_script_main_xml)
+ return result
+
####
# Determine which environments are installed on the test machine.
test.write('SConstruct','''
@@ -312,25 +324,15 @@ env.MSVSProject(target = 'Test.dsp',
test.run(arguments="Test.dsp")
test.fail_test(not os.path.exists(test.workpath('Test.dsp')))
- test.fail_test(not os.path.exists(test.workpath('Test.dsw')))
-
- # check to see that we got what we expected:
- expected_dspfile = expected_dspfile.replace(r'<WORKPATH>',test.workpath())
- expected_dspfile = expected_dspfile.replace(r'<PYTHON>',sys.executable)
- expected_dspfile = expected_dspfile.replace(r'<SCONS>',os.path.join(os.environ['SCONS_SCRIPT_DIR'],'scons.py'))
- expected_dswfile = expected_dswfile.replace(r'<WORKPATH>',test.workpath())
-
- f = open(test.workpath('Test.dsp'))
- dsp = f.read()
- f.close()
-
+ dsp = test.read('Test.dsp', 'r')
+ expect = substitute(expected_dspfile)
# don't compare the pickled data
- assert dsp[:len(expected_dspfile)] == expected_dspfile
+ assert dsp[:len(expect)] == expect
- f = open(test.workpath('Test.dsw'))
- dsw = f.read()
- f.close()
- assert dsw == expected_dswfile
+ test.fail_test(not os.path.exists(test.workpath('Test.dsw')))
+ dsw = test.read('Test.dsw', 'r')
+ expect = substitute(expected_dswfile)
+ assert dsw == expect
test.run(arguments='-c .')
@@ -374,23 +376,16 @@ env.MSVSProject(target = 'Test.vcproj',
test.run(arguments="Test.vcproj")
test.fail_test(not os.path.exists(test.workpath('Test.vcproj')))
- test.fail_test(not os.path.exists(test.workpath('Test.sln')))
-
- f = open(test.workpath('Test.vcproj'))
- vcproj = f.read()
- f.close()
- expected_vcprojfile = expected_vcprojfile.replace(r'<WORKPATH>',test.workpath())
- expected_vcprojfile = expected_vcprojfile.replace(r'<PYTHON>',sys.executable)
- expected_vcprojfile = expected_vcprojfile.replace(r'<SCONS>',os.path.join(os.environ['SCONS_SCRIPT_DIR'],'scons.py'))
-
+ test.read('Test.vcproj', 'r')
+ expect = substitute(expected_vcprojfile)
# don't compare the pickled data
- assert vcproj[:len(expected_vcprojfile)] == expected_vcprojfile
+ assert vcproj[:len(expect)] == expect
- f = open(test.workpath('Test.sln'))
- sln = f.read()
- f.close()
-
- assert sln[:len(expected_slnfile)] == expected_slnfile
+ test.fail_test(not os.path.exists(test.workpath('Test.sln')))
+ sln = test.read('Test.sln', 'r')
+ expect = substitute(expected_slnfile)
+ # don't compare the pickled data
+ assert sln[:len(expect)] == expect
test.run(arguments='-c .')
@@ -407,9 +402,18 @@ env.MSVSProject(target = 'Test.vcproj',
test.fail_test(os.path.exists(test.workpath('Test.vcproj')))
test.fail_test(os.path.exists(test.workpath('Test.sln')))
-test.pass_test()
-
+ # Test that running SCons with $PYTHON_ROOT in the environment
+ # changes the .vcproj output as expected.
+ os.environ['PYTHON_ROOT'] = 'xyzzy'
+ test.run(arguments='Test.vcproj')
+ python = os.path.join('$(PYTHON_ROOT)', os.path.split(sys.executable)[1])
+ test.fail_test(not os.path.exists(test.workpath('Test.vcproj')))
+ test.read('Test.vcproj', 'r')
+ expect = substitute(expected_vcprojfile, python=python)
+ # don't compare the pickled data
+ assert vcproj[:len(expect)] == expect
+test.pass_test()