Index: site_scons/site_tools/_Node_MSVS.py |
=================================================================== |
--- site_scons/site_tools/_Node_MSVS.py (revision 7829) |
+++ site_scons/site_tools/_Node_MSVS.py (working copy) |
@@ -39,8 +39,6 @@ |
import SCons.Node.FS |
import SCons.Script |
-from SCons.Debug import Trace |
-TODO = 0 |
# Initialize random number generator |
random.seed() |
@@ -266,7 +264,7 @@ |
class MSVSConfig(object): |
"""Visual Studio configuration.""" |
- def __init__(self, Name, config_type, tools=None, **attrs): |
+ def __init__(self, Name, config_type, tools=[], **attrs): |
"""Initializes the configuration. |
Args: |
@@ -280,12 +278,21 @@ |
ips = ';'.join(ips) |
attrs['InheritedPropertySheets'] = ips.replace('/', '\\') |
+ tools = tools or [] |
+ if not SCons.Util.is_List(tools): |
+ tools = [tools] |
+ tool_objects = [] |
+ for t in tools: |
+ if not isinstance(t, MSVSTool): |
+ t = MSVSTool(t) |
+ tool_objects.append(t) |
+ |
self.Name = Name |
self.config_type = config_type |
- self.tools = tools |
+ self.tools = tool_objects |
self.attrs = attrs |
- def CreateElement(self, doc, project): |
+ def CreateElement(self, doc): |
"""Creates an element for the configuration. |
Args: |
@@ -298,20 +305,8 @@ |
node.setAttribute('Name', self.Name) |
for k, v in self.attrs.items(): |
node.setAttribute(k, v) |
- |
- tools = self.tools |
- if tools is None: |
- tools = project.tools or [] |
- if not SCons.Util.is_List(tools): |
- tools = [tools] |
- tool_objects = [] |
- for t in tools: |
- if not isinstance(t, MSVSTool): |
- t = MSVSTool(t) |
- tool_objects.append(t) |
- for t in tool_objects: |
+ for t in self.tools: |
node.appendChild(t.CreateElement(doc)) |
- |
return node |
@@ -403,18 +398,7 @@ |
node.setAttribute(k, v) |
return node |
- def _format(self): |
- """Formats a tool specification for debug printing""" |
- xml_impl = xml.dom.getDOMImplementation() |
- doc = xml_impl.createDocument(None, 'VisualStudioProject', None) |
- return self.CreateElement(doc).toprettyxml() |
- def diff(self, other): |
- for key, value in self.attrs.items(): |
- if other.attrs[key] == value: |
- del self.attrs[key] |
- |
- |
class MSVSToolFile(object): |
"""Visual Studio tool file specification.""" |
@@ -445,7 +429,6 @@ |
"""Visual Studio project.""" |
entry_type_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' |
- initialized = False |
def initialize(self, env, path, name = None, |
dependencies = None, |
@@ -455,8 +438,7 @@ |
root_namespace = None, |
relative_path_prefix = '', |
tools = None, |
- configurations = None, |
- **attrs): |
+ configurations = None): |
"""Initializes the project. |
Args: |
@@ -482,52 +464,33 @@ |
configurations: A list of MSVSConfig objects representing |
configurations built by this project. |
""" |
+ self.msvs_path = path |
+ self.msvs_node = env.File(path) |
if name is None: |
if buildtargets: |
name = os.path.splitext(buildtargets[0].name)[0] |
else: |
name = os.path.splitext(os.path.basename(path))[0] |
- if not root_namespace: |
- root_namespace or name |
- |
- if self.initialized: |
- # TODO(sgk): fill in |
- if self.msvs_name != name: |
- pass |
- if self.root_namespace != root_namespace: |
- pass |
- if self.relative_path_prefix != relative_path_prefix: |
- pass |
- if self.guid != guid: |
- pass |
- #if self.env != env: |
- # pass |
- else: |
- self.buildtargets = [] |
- self.configurations = [] |
- self.dependencies = [] |
- self.file_configurations = {} |
- self.files = MSVSFiles([]) |
- self.tool_files = [] |
- self.file_lists = [] |
- self.initialized = True |
- |
- self.attrs = attrs |
- self.env = env |
- self.guid = guid |
self.msvs_name = name |
- self.msvs_path = path |
- self.relative_path_prefix = relative_path_prefix |
self.root_namespace = root_namespace or self.msvs_name |
+ self.buildtargets = buildtargets |
+ self.relative_path_prefix = relative_path_prefix |
self.tools = tools |
- self.buildtargets.extend(buildtargets) |
- self.configurations.extend(configurations or []) |
- self.dependencies.extend(list(dependencies or [])) |
- self.AddFiles(files) |
+ self.env = env |
+ self.guid = guid |
- env.Command(self, [], MSVSProjectAction) |
+ self.dependencies = list(dependencies or []) |
+ self.configurations = list(configurations or []) |
+ self.file_configurations = {} |
+ self.tool_files = [] |
+ if not isinstance(files, MSVSFiles): |
+ files = MSVSFiles(self.args2nodes(files)) |
+ self.files = files |
+ |
+ env.Command(self, [], MSVSSolutionAction) |
+ |
def args2nodes(self, entries): |
result = [] |
for entry in entries: |
@@ -542,7 +505,7 @@ |
elif hasattr(entry, 'sources') and entry.sources: |
result.extend(entry.sources) |
else: |
- result.append(entry.srcnode()) |
+ result.append(entry) |
return result |
def FindFile(self, node): |
@@ -560,11 +523,9 @@ |
file_list.extend(f.entries) |
else: |
flat_file_dict[f] = True |
- flat_file_dict[f.srcnode()] = True |
if hasattr(f, 'sources'): |
for s in f.sources: |
flat_file_dict[s] = True |
- flat_file_dict[s.srcnode()] = True |
self.flat_file_dict = flat_file_dict |
return flat_file_dict.get(node) |
@@ -594,7 +555,7 @@ |
return sln.rel_path(self).replace('/', '\\') |
def get_rel_path(self, node): |
- result = self.relative_path_prefix + self.rel_path(node) |
+ result = self.relative_path_prefix + self.msvs_node.rel_path(node) |
return result.replace('/', '\\') |
def AddConfig(self, Name, tools=None, **attrs): |
@@ -609,16 +570,6 @@ |
# No tool list specifically for this configuration, |
# use the Project's as a default. |
tools = self.tools |
- if not attrs.has_key('ConfigurationType'): |
- # No ConfigurationType specifically for this configuration, |
- # use the Project's as a default. |
- try: |
- attrs['ConfigurationType'] = self.attrs['ConfigurationType'] |
- except KeyError: |
- pass |
- if attrs.has_key('InheritedPropertySheets'): |
- ips = attrs['InheritedPropertySheets'] |
- attrs['InheritedPropertySheets'] = self.env.subst(ips) |
c = MSVSConfig(Name, 'Configuration', tools=tools, **attrs) |
self.configurations.append(c) |
@@ -632,36 +583,10 @@ |
later add files to a Filter object which was passed into a previous call |
to AddFiles(), it will not be reflected in this project. |
""" |
- self.file_lists.append(self.args2nodes(files)) |
+ # TODO(rspangler) This also doesn't handle adding files to an existing |
+ # filter. That is, it doesn't merge the trees. |
+ self.files.extend(self.args2nodes(files)) |
- def _FilesToSourceFiles(self, files): |
- file_list = files[:] |
- result = [] |
- while file_list: |
- entry = file_list.pop(0) |
- if not isinstance(entry, (list, UserList.UserList)): |
- entry = [entry] |
- for f in entry: |
- if hasattr(f, 'entries'): |
- self._FilesToSourceFiles(f.entries) |
- result.append(f) |
- else: |
- if f.sources: |
- flist = f.sources |
- else: |
- flist = [f] |
- for x in flist: |
- result.append(x.srcnode()) |
- files[:] = result |
- |
- def _MergeFiles(self, dest_list, src_list): |
- for f in src_list: |
- if f not in dest_list: |
- dest_list.append(f) |
- continue |
- #if hasattr(f, 'entries'): |
- # self._FilesToSourceFiles(f.entries) |
- |
def AddFileConfig(self, path, Name, tools=None, **attrs): |
"""Adds a configuration to a file. |
@@ -674,8 +599,9 @@ |
Raises: |
ValueError: Relative path does not match any file added via AddFiles(). |
""" |
- # Store as the VariantDir node, not as the source node. |
node = self.env.File(path) |
+ if not self.FindFile(node): |
+ raise ValueError('AddFileConfig: file "%s" not in project' % path) |
c = MSVSConfig(Name, 'FileConfiguration', tools=tools, **attrs) |
config_list = self.file_configurations.get(node) |
if config_list is None: |
@@ -729,7 +655,7 @@ |
configs = self.doc.createElement('Configurations') |
root.appendChild(configs) |
for c in self.configurations: |
- configs.appendChild(c.CreateElement(self.doc, self)) |
+ configs.appendChild(c.CreateElement(self.doc)) |
# Add empty References section |
root.appendChild(self.doc.createElement('References')) |
@@ -755,194 +681,10 @@ |
node = self.doc.createElement('File') |
node.setAttribute('RelativePath', self.get_rel_path(file)) |
for c in self.file_configurations.get(file, []): |
- node.appendChild(c.CreateElement(self.doc, self)) |
+ node.appendChild(c.CreateElement(self.doc)) |
return node |
- def VCCLCompilerTool(self, args): |
- default_attrs = { |
- 'BufferSecurityCheck' : "false", |
- 'CompileAs' : 0, # default |
- 'DebugInformationFormat' : 0, # TODO(???) |
- 'DisableSpecificWarnings' : [], |
- 'EnableFiberSafeOptimizations' : "false", |
- 'EnableFunctionLevelLinking' : "false", |
- 'EnableIntrinsicFunctions' : "false", |
- 'FavorSizeOrSpeed' : 0, # favorNone |
- 'InlineFunctionExpansion' : 1, # expandDisable |
- 'MinimalRebuild' : "false", |
- 'OmitFramePointers' : "false", |
- 'Optimization' : 1, # optimizeDisabled TODO(???) |
- 'PreprocessorDefinitions' : [], |
- 'RuntimeLibrary' : TODO, |
- 'RuntimeTypeInfo' : "false", |
- 'StringPooling' : "false", |
- 'SuppressStartupBanner' : "false", |
- 'WarningAsError' : "false", |
- 'WarningLevel' : 1, # warningLevel_1 |
- 'WholeProgramOptimization' : "false", |
- } |
- |
- tool = MSVSTool('VCCLCompilerTool', **default_attrs) |
- attrs = tool.attrs |
- |
- for arg in args: |
- if arg in ('/c',): |
- continue |
- if arg.startswith('/Fo'): |
- continue |
- if arg.startswith('/D'): |
- attrs['PreprocessorDefinitions'].append(arg[2:]) |
- elif arg == '/EH': |
- attrs['ExceptionHandling'] = 0 |
- elif arg == '/GF': |
- attrs['StringPooling'] = "true" |
- elif arg == '/GL': |
- attrs['WholeProgramOptimization'] = "true" |
- elif arg == '/GM': |
- attrs['MinimalRebuild'] = "true" |
- elif arg == '/GR-': |
- attrs['RuntimeTypeInfo'] = "true" |
- elif arg == '/Gs': |
- attrs['BufferSecurityCheck'] = "true" |
- elif arg == '/Gs-': |
- attrs['BufferSecurityCheck'] = "false" |
- elif arg == '/GT': |
- attrs['EnableFiberSafeOptimizations'] = "true" |
- elif arg == '/Gy': |
- attrs['EnableFunctionLevelLinking'] = "true" |
- elif arg == '/MD': |
- attrs['RuntimeLibrary'] = 1 # rtMultiThreadedDebug |
- elif arg == '/MDd': |
- attrs['RuntimeLibrary'] = 2 # rtMultiThreadedDebugDLL |
- elif arg == '/MT': |
- attrs['RuntimeLibrary'] = 0 # rtMultiThreaded |
- elif arg == '/MTd': |
- attrs['RuntimeLibrary'] = 3 # rtMultiThreadedDLL |
- elif arg == '/nologo': |
- attrs['SuppressStartupBanner'] = "true" |
- elif arg == '/O1': |
- attrs['InlineFunctionExpansion'] = 4 # optimizeMinSpace |
- elif arg == '/O2': |
- attrs['InlineFunctionExpansion'] = 3 # optimizeMaxSpeed |
- elif arg == '/Ob1': |
- attrs['InlineFunctionExpansion'] = 2 # expandOnlyInline |
- elif arg == '/Ob2': |
- attrs['InlineFunctionExpansion'] = 0 # expandAnySuitable |
- elif arg == '/Od': |
- attrs['Optimization'] = 0 |
- elif arg == '/Oi': |
- attrs['EnableIntrinsicFunctions'] = "true" |
- elif arg == '/Os': |
- attrs['FavorSizeOrSpeed'] = 1 # favorSize |
- elif arg == '/Ot': |
- attrs['FavorSizeOrSpeed'] = 2 # favorSpeed |
- elif arg == '/Ox': |
- attrs['Optimization'] = 2 # optimizeFull |
- elif arg == '/Oy': |
- attrs['OmitFramePointers'] = "true" |
- elif arg == '/Oy-': |
- attrs['TODO'] = "true" |
- elif arg in ('/Tc', '/TC'): |
- attrs['CompileAs'] = 1 # compileAsC |
- elif arg in ('/Tp', '/TP'): |
- attrs['CompileAs'] = 2 # compileAsCPlusPlus |
- elif arg == '/WX': |
- attrs['WarnAsError'] = "true" |
- elif arg.startswith('/W'): |
- attrs['WarningLevel'] = int(arg[2:]) # 0 through 4 |
- elif arg.startswith('/wd'): |
- attrs['DisableSpecificWarnings'].append(str(arg[3:])) |
- elif arg == '/Z7': |
- attrs['DebugInformationFormat'] = 3 # debugOldSytleInfo TODO(???) |
- elif arg == '/Zd': |
- attrs['DebugInformationFormat'] = 0 # debugDisabled |
- elif arg == '/Zi': |
- attrs['DebugInformationFormat'] = 2 # debugEnabled TODO(???) |
- elif arg == '/ZI': |
- attrs['DebugInformationFormat'] = 1 # debugEditAndContinue TODO(???) |
- |
- cppdefines = attrs['PreprocessorDefinitions'] |
- if cppdefines: |
- attrs['PreprocessorDefinitions'] = ';'.join(cppdefines) |
- warnings = attrs['DisableSpecificWarnings'] |
- if warnings: |
- warnings = SCons.Util.uniquer(warnings) |
- attrs['DisableSpecificWarnings'] = ';'.join(warnings) |
- |
- return tool |
- |
- def VCLibrarianTool(self, args): |
- default_attrs = { |
- 'LinkTimeCodeGeneration' : "false", |
- 'SuppressStartupBanner' : "false", |
- } |
- |
- tool = MSVSTool('VCLibrarianTool', **default_attrs) |
- attrs = tool.attrs |
- |
- for arg in args: |
- if arg.startswith('/OUT'): |
- continue |
- if arg == '/ltcg': |
- attrs['LinkTimeCodeGeneration'] = "true" |
- elif arg == '/nologo': |
- attrs['SuppressStartupBanner'] = "true" |
- |
- return tool |
- |
- def VCLinkerTool(self, args): |
- default_attrs = { |
- 'LinkIncremental' : "false", |
- 'LinkTimeCodeGeneration' : "false", |
- 'EnableCOMDATFolding' : TODO, |
- 'OptimizeForWindows98' : TODO, |
- 'OptimizeReferences' : TODO, |
- 'Profile' : "false", |
- 'SuppressStartupBanner' : "false", |
- } |
- |
- tool = MSVSTool('VCLinkerTool', **default_attrs) |
- attrs = tool.attrs |
- |
- for arg in args: |
- if arg == '': |
- continue |
- if arg == '/INCREMENTAL': |
- attrs['LinkIncremental'] = "true" |
- elif arg == '/INCREMENTAL:NO': |
- attrs['LinkIncremental'] = "false" |
- elif arg == '/LTCG': |
- attrs['LinkTimeCodeGeneration'] = "true" |
- elif arg == '/nologo': |
- attrs['SuppressStartupBanner'] = "true" |
- elif arg == '/OPT:NOICF': |
- attrs['EnableCOMDATFolding'] = 2 # |
- elif arg == '/OPT:NOWIN98': |
- attrs['OptimizeForWindows98'] = 1 # |
- elif arg == '/OPT:REF': |
- attrs['OptimizeReferences'] = 2 # |
- elif arg == '/PROFILE': |
- attrs['Profile'] = "true" |
- |
- return tool |
- |
- command_to_tool_map = { |
- 'cl' : 'VCCLCompilerTool', |
- 'cl.exe' : 'VCCLCompilerTool', |
- 'lib' : 'VCLibrarianTool', |
- 'lib.exe' : 'VCLibrarianTool', |
- 'link' : 'VCLinkerTool', |
- 'link.exe' : 'VCLinkerTool', |
- } |
- |
- def cl_to_tool(self, args): |
- command = os.path.basename(args[0]) |
- method_name = self.command_to_tool_map.get(command) |
- if not method_name: |
- return None |
- return getattr(self, method_name)(args[1:]) |
- |
- def _AddFileConfigurationDifferences(self, target, source, base_env, file_env, name): |
+ def _AddFileConfigurationDifferences(self, target, source, base_env, file_env): |
"""Adds a per-file configuration. |
Args: |
@@ -954,19 +696,8 @@ |
file_env: The construction environment for the target, containing |
the per-target settings. |
""" |
- executor = target.get_executor() |
- base_cl = map(str, base_env.subst_list(executor)[0]) |
- file_cl = map(str, file_env.subst_list(executor)[0]) |
- if base_cl == file_cl: |
- return |
+ pass |
- base_tool = self.cl_to_tool(base_cl) |
- file_tool = self.cl_to_tool(file_cl) |
- |
- file_tool.diff(base_tool) |
- |
- self.AddFileConfig(source, name, tools=[file_tool]) |
- |
def _AddFileConfigurations(self, env): |
"""Adds per-file configurations for the buildtarget's sources. |
@@ -976,53 +707,25 @@ |
if not self.buildtargets: |
return |
- for bt in self.buildtargets: |
- executor = bt.get_executor() |
- build_env = bt.get_build_env() |
- bt_cl = map(str, build_env.subst_list(executor)[0]) |
- tool = self.cl_to_tool(bt_cl) |
- default_tool = self.cl_to_tool([bt_cl[0]]) |
- if default_tool: |
- tool.diff(default_tool) |
- else: |
- print "no tool for %r" % bt_cl[0] |
- for t in bt.sources: |
+ bt = self.buildtargets[0] |
+ additional_files = [] |
+ for t in bt.sources: |
e = t.get_build_env() |
- additional_files = SCons.Util.UniqueList() |
for s in t.sources: |
- s = env.arg2nodes([s])[0].srcnode() |
+ s = env.arg2nodes([s])[0] |
if not self.FindFile(s): |
additional_files.append(s) |
- if not build_env is e: |
- # TODO(sgk): This test may be bogus, but it works for now. |
- # We're trying to figure out if the file configuration |
- # differences need to be added one per build target, or one |
- # per configuration for the entire project. The assumption |
- # is that if the number of buildtargets configured matches |
- # the number of project configurations, that we use those |
- # in preference to the project configurations. |
- if len(self.buildtargets) == len(self.configurations): |
- self._AddFileConfigurationDifferences(t, s, build_env, e, e.subst('$MSVSCONFIGURATIONNAME')) |
- else: |
- for config in self.configurations: |
- self._AddFileConfigurationDifferences(t, s, build_env, e, config.Name) |
- self._MergeFiles(self.files, additional_files) |
+ if not env is e: |
+ self._AddFileConfigurationDifferences(t, s, env, e) |
+ self.AddFiles(additional_files) |
def Write(self, env): |
"""Writes the project file.""" |
- for flist in self.file_lists: |
- self._FilesToSourceFiles(flist) |
- self._MergeFiles(self.files, flist) |
- for k, v in self.file_configurations.items(): |
- self.file_configurations[str(k)] = v |
- k = self.env.File(k).srcnode() |
- self.file_configurations[k] = v |
- self.file_configurations[str(k)] = v |
self._AddFileConfigurations(env) |
self.Create() |
- f = open(str(self), 'wt') |
+ f = open(str(self.msvs_node), 'wt') |
f.write(self.formatMSVSProjectXML(self.doc)) |
f.close() |
@@ -1086,11 +789,6 @@ |
'Tool' : [ |
'Name', |
'DisableSpecificWarnings', |
- |
- 'PreprocessorDefinitions', |
- 'UsePrecompiledHeader', |
- 'PrecompiledHeaderThrough', |
- 'ForcedIncludeFiles', |
], |
'VisualStudioProject' : [ |
'ProjectType', |
@@ -1364,7 +1062,6 @@ |
import __builtin__ |
-__builtin__.MSVSConfig = MSVSConfig |
__builtin__.MSVSFilter = MSVSFilter |
__builtin__.MSVSProject = MSVSProject |
__builtin__.MSVSSolution = MSVSSolution |