| Viewing file:  MSVSProject.py (6.24 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
# Copyright (c) 2012 Google Inc. All rights reserved.# Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 """Visual Studio project reader/writer."""
 
 import gyp.common
 import gyp.easy_xml as easy_xml
 
 #------------------------------------------------------------------------------
 
 
 class Tool(object):
 """Visual Studio tool."""
 
 def __init__(self, name, attrs=None):
 """Initializes the tool.
 
 Args:
 name: Tool name.
 attrs: Dict of tool attributes; may be None.
 """
 self._attrs = attrs or {}
 self._attrs['Name'] = name
 
 def _GetSpecification(self):
 """Creates an element for the tool.
 
 Returns:
 A new xml.dom.Element for the tool.
 """
 return ['Tool', self._attrs]
 
 class Filter(object):
 """Visual Studio filter - that is, a virtual folder."""
 
 def __init__(self, name, contents=None):
 """Initializes the folder.
 
 Args:
 name: Filter (folder) name.
 contents: List of filenames and/or Filter objects contained.
 """
 self.name = name
 self.contents = list(contents or [])
 
 
 #------------------------------------------------------------------------------
 
 
 class Writer(object):
 """Visual Studio XML project writer."""
 
 def __init__(self, project_path, version, name, guid=None, platforms=None):
 """Initializes the project.
 
 Args:
 project_path: Path to the project file.
 version: Format version to emit.
 name: Name of the project.
 guid: GUID to use for project, if not None.
 platforms: Array of string, the supported platforms.  If null, ['Win32']
 """
 self.project_path = project_path
 self.version = version
 self.name = name
 self.guid = guid
 
 # Default to Win32 for platforms.
 if not platforms:
 platforms = ['Win32']
 
 # Initialize the specifications of the various sections.
 self.platform_section = ['Platforms']
 for platform in platforms:
 self.platform_section.append(['Platform', {'Name': platform}])
 self.tool_files_section = ['ToolFiles']
 self.configurations_section = ['Configurations']
 self.files_section = ['Files']
 
 # Keep a dict keyed on filename to speed up access.
 self.files_dict = dict()
 
 def AddToolFile(self, path):
 """Adds a tool file to the project.
 
 Args:
 path: Relative path from project to tool file.
 """
 self.tool_files_section.append(['ToolFile', {'RelativePath': path}])
 
 def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
 """Returns the specification for a configuration.
 
 Args:
 config_type: Type of configuration node.
 config_name: Configuration name.
 attrs: Dict of configuration attributes; may be None.
 tools: List of tools (strings or Tool objects); may be None.
 Returns:
 """
 # Handle defaults
 if not attrs:
 attrs = {}
 if not tools:
 tools = []
 
 # Add configuration node and its attributes
 node_attrs = attrs.copy()
 node_attrs['Name'] = config_name
 specification = [config_type, node_attrs]
 
 # Add tool nodes and their attributes
 if tools:
 for t in tools:
 if isinstance(t, Tool):
 specification.append(t._GetSpecification())
 else:
 specification.append(Tool(t)._GetSpecification())
 return specification
 
 
 def AddConfig(self, name, attrs=None, tools=None):
 """Adds a configuration to the project.
 
 Args:
 name: Configuration name.
 attrs: Dict of configuration attributes; may be None.
 tools: List of tools (strings or Tool objects); may be None.
 """
 spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools)
 self.configurations_section.append(spec)
 
 def _AddFilesToNode(self, parent, files):
 """Adds files and/or filters to the parent node.
 
 Args:
 parent: Destination node
 files: A list of Filter objects and/or relative paths to files.
 
 Will call itself recursively, if the files list contains Filter objects.
 """
 for f in files:
 if isinstance(f, Filter):
 node = ['Filter', {'Name': f.name}]
 self._AddFilesToNode(node, f.contents)
 else:
 node = ['File', {'RelativePath': f}]
 self.files_dict[f] = node
 parent.append(node)
 
 def AddFiles(self, files):
 """Adds files to the project.
 
 Args:
 files: A list of Filter objects and/or relative paths to files.
 
 This makes a copy of the file/filter tree at the time of this call.  If you
 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._AddFilesToNode(self.files_section, files)
 # TODO(rspangler) This also doesn't handle adding files to an existing
 # filter.  That is, it doesn't merge the trees.
 
 def AddFileConfig(self, path, config, attrs=None, tools=None):
 """Adds a configuration to a file.
 
 Args:
 path: Relative path to the file.
 config: Name of configuration to add.
 attrs: Dict of configuration attributes; may be None.
 tools: List of tools (strings or Tool objects); may be None.
 
 Raises:
 ValueError: Relative path does not match any file added via AddFiles().
 """
 # Find the file node with the right relative path
 parent = self.files_dict.get(path)
 if not parent:
 raise ValueError('AddFileConfig: file "%s" not in project.' % path)
 
 # Add the config to the file node
 spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs,
 tools)
 parent.append(spec)
 
 def WriteIfChanged(self):
 """Writes the project file."""
 # First create XML content definition
 content = [
 'VisualStudioProject',
 {'ProjectType': 'Visual C++',
 'Version': self.version.ProjectVersion(),
 'Name': self.name,
 'ProjectGUID': self.guid,
 'RootNamespace': self.name,
 'Keyword': 'Win32Proj'
 },
 self.platform_section,
 self.tool_files_section,
 self.configurations_section,
 ['References'],  # empty section
 self.files_section,
 ['Globals']  # empty section
 ]
 easy_xml.WriteXmlIfChanged(content, self.project_path,
 encoding="Windows-1252")
 
 |