Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Unified Diff: site_scons/site_tools/component_targets_msvs.py

Issue 42667: Remove Hammer files.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « site_scons/site_tools/component_targets.py ('k') | site_scons/site_tools/component_targets_xml.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: site_scons/site_tools/component_targets_msvs.py
===================================================================
--- site_scons/site_tools/component_targets_msvs.py (revision 12583)
+++ site_scons/site_tools/component_targets_msvs.py (working copy)
@@ -1,997 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Visual Studio solution output of component targets for SCons."""
-
-import copy
-import md5
-import os
-import sys
-import xml.dom
-import xml.dom.minidom
-import SCons
-
-
-#------------------------------------------------------------------------------
-
-
-def MakeGuid(name, seed='component_targets_msvs'):
- """Returns a GUID for the specified target name.
-
- Args:
- name: Target name.
- seed: Seed for MD5 hash.
- Returns:
- A GUID-line string calculated from the name and seed.
-
- This generates something which looks like a GUID, but depends only on the
- name and seed. This means the same name/seed will always generate the same
- GUID, so that projects and solutions which refer to each other can explicitly
- determine the GUID to refer to explicitly. It also means that the GUID will
- not change when the project for a target is rebuilt.
- """
- # Calculate a MD5 signature for the seed and name.
- d = md5.new(str(seed) + str(name)).hexdigest().upper()
- # Convert most of the signature to GUID form (discard the rest)
- guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20]
- + '-' + d[20:32] + '}')
- return guid
-
-#------------------------------------------------------------------------------
-
-
-def GetGuidAndNameFromVSProject(project_path):
- """Reads the GUID from a Visual Studio project file.
-
- Args:
- project_path: Path to the Visual Studio project file.
-
- Returns:
- The GUID string from the file.
- The project name from the file.
- """
- doc = xml.dom.minidom.parse(project_path)
- try:
- n_root = doc.documentElement
- if n_root.nodeName != 'VisualStudioProject':
- raise SCons.Errors.UserError('%s is not a Visual Studio project.' %
- project_path)
- return (
- str(n_root.attributes['ProjectGUID'].nodeValue),
- str(n_root.attributes['Name'].nodeValue),
- )
- finally:
- # Clean up doc
- doc.unlink()
-
-#------------------------------------------------------------------------------
-
-
-class VSProjectWriter(object):
- """Visual Studio XML project writer."""
-
- def __init__(self, project_path):
- """Initializes the project.
-
- Args:
- project_path: Path to the project file.
- """
- self.project_path = project_path
- self.doc = None
-
- def Create(self, name):
- """Creates the project document.
-
- Args:
- name: Name of the project.
- """
- self.name = name
- self.guid = MakeGuid(name)
-
- # Create XML doc
- xml_impl = xml.dom.getDOMImplementation()
- self.doc = xml_impl.createDocument(None, 'VisualStudioProject', None)
-
- # Add attributes to root element
- self.n_root = self.doc.documentElement
- self.n_root.setAttribute('ProjectType', 'Visual C++')
- self.n_root.setAttribute('Version', '8.00')
- self.n_root.setAttribute('Name', self.name)
- self.n_root.setAttribute('ProjectGUID', self.guid)
- self.n_root.setAttribute('RootNamespace', self.name)
- self.n_root.setAttribute('Keyword', 'MakeFileProj')
-
- # Add platform list
- n_platform = self.doc.createElement('Platforms')
- self.n_root.appendChild(n_platform)
- n = self.doc.createElement('Platform')
- n.setAttribute('Name', 'Win32')
- n_platform.appendChild(n)
-
- # Add empty ToolFiles section
- self.n_root.appendChild(self.doc.createElement('ToolFiles'))
-
- # Add configurations section
- self.n_configs = self.doc.createElement('Configurations')
- self.n_root.appendChild(self.n_configs)
-
- # Add files section
- self.n_files = self.doc.createElement('Files')
- self.n_root.appendChild(self.n_files)
-
- # Add empty Globals section
- self.n_root.appendChild(self.doc.createElement('Globals'))
-
- def AddConfig(self, name, attrs, tool_attrs):
- """Adds a configuration to the project.
-
- Args:
- name: Configuration name.
- attrs: Dict of configuration attributes.
- tool_attrs: Dict of tool attributes.
- """
- # Add configuration node
- n_config = self.doc.createElement('Configuration')
- n_config.setAttribute('Name', '%s|Win32' % name)
- n_config.setAttribute('ConfigurationType', '0')
- for k, v in attrs.items():
- n_config.setAttribute(k, v)
- self.n_configs.appendChild(n_config)
-
- # Add tool node
- n_tool = self.doc.createElement('Tool')
- n_tool.setAttribute('Name', 'VCNMakeTool')
- n_tool.setAttribute('IncludeSearchPath', '')
- n_tool.setAttribute('ForcedIncludes', '')
- n_tool.setAttribute('AssemblySearchPath', '')
- n_tool.setAttribute('ForcedUsingAssemblies', '')
- n_tool.setAttribute('CompileAsManaged', '')
- n_tool.setAttribute('PreprocessorDefinitions', '')
- for k, v in tool_attrs.items():
- n_tool.setAttribute(k, v)
- n_config.appendChild(n_tool)
-
- def _WalkFolders(self, folder_dict, parent):
- """Recursively walks the folder tree.
-
- Args:
- folder_dict: Dict of folder entries. Entry is
- either subdir_name:subdir_dict or relative_path_to_file:None.
- parent: Parent node (folder node for that dict)
- """
- entries = folder_dict.keys()
- entries.sort()
- for e in entries:
- if folder_dict[e]:
- # Folder
- n_subfolder = self.doc.createElement('Filter')
- n_subfolder.setAttribute('Name', e)
- parent.appendChild(n_subfolder)
- self._WalkFolders(folder_dict[e], n_subfolder)
- else:
- # File
- n_file = self.doc.createElement('File')
- n_file.setAttribute('RelativePath', e)
- parent.appendChild(n_file)
-
- def AddFiles(self, name, files_dict):
- """Adds files to the project.
-
- Args:
- name: Name of the folder. If None, files/folders will be added directly
- to the files list.
- files_dict: A dict of files / folders.
-
- Within the files_dict:
- * A file entry is relative_path:None
- * A folder entry is folder_name:files_dict, where files_dict is another
- dict of this form.
- """
- # Create subfolder if necessary
- if name:
- n_folder = self.doc.createElement('Filter')
- n_folder.setAttribute('Name', name)
- self.n_files.appendChild(n_folder)
- else:
- n_folder = self.n_files
-
- # Recursively add files to the folder
- self._WalkFolders(files_dict, n_folder)
-
- def Write(self):
- """Writes the project file."""
- f = open(self.project_path, 'wt')
- self.doc.writexml(f, encoding='Windows-1252', addindent=' ', newl='\n')
- f.close()
-
-#------------------------------------------------------------------------------
-
-
-def ComponentVSProjectBuilder(target, source, env):
- """Visual Studio project builder.
-
- Args:
- target: Destination file.
- source: List of sources to be added to the target.
- env: Environment context.
-
- Returns:
- Zero if successful.
- """
- source = source # Silence gpylint
-
- target_name = env['TARGET_NAME']
- project_file = target[0].path
- project_to_main = env.RelativePath(target[0].dir, env.Dir('$MAIN_DIR'),
- sep='/')
-
- env_hammer_bat = env.Clone(VS_PROJECT_TO_MAIN_DIR=project_to_main)
- hammer_bat = env_hammer_bat.subst('$COMPONENT_VS_PROJECT_SCRIPT_PATH', raw=1)
-
- vsp = VSProjectWriter(project_file)
- vsp.Create(target_name)
-
- # Add configuration per build mode supported by this target
- target_path = env['TARGET_PATH']
- for mode, path in target_path.items():
- attrs = {}
- attrs['OutputDirectory'] = '$(ProjectDir)/%s/%s/out' % (mode, target_name)
- attrs['IntermediateDirectory'] = ('$(ProjectDir)/%s/%s/tmp' %
- (mode, target_name))
-
- tool_attrs = {}
- if path:
- tool_attrs['Output'] = env.RelativePath(target[0].dir,
- env.Entry(path), sep='/')
- build_cmd = '%s --mode=%s %s' % (hammer_bat, mode, target_name)
- clean_cmd = '%s --mode=%s -c %s' % (hammer_bat, mode, target_name)
- tool_attrs['BuildCommandLine'] = build_cmd
- tool_attrs['CleanCommandLine'] = clean_cmd
- tool_attrs['ReBuildCommandLine'] = clean_cmd + ' && ' + build_cmd
-
- vsp.AddConfig(mode, attrs, tool_attrs)
-
- # TODO(rspangler): Fill in files - at least, the .scons file invoking the
- # target.
-
- # Write project
- vsp.Write()
- return 0
-
-
-def ComponentVSProject(self, target_name, **kwargs):
- """Visual Studio project pseudo-builder for the specified target.
-
- Args:
- self: Environment context.
- target_name: Name of the target.
- kwargs: Optional keyword arguments override environment variables in the
- derived environment used to create the project.
-
- Returns:
- A list of output nodes.
- """
- # Builder only works on Windows
- if sys.platform not in ('win32', 'cygwin'):
- return []
-
- # Clone environment and add keyword args
- env = self.Clone()
- for k, v in kwargs.items():
- env[k] = v
-
- # Save the target name
- env['TARGET_NAME'] = target_name
-
- # Extract the target properties and save in the environment for use by the
- # real builder.
- t = GetTargets().get(target_name)
- env['TARGET_PATH'] = {}
- if t:
- for mode, mode_properties in t.mode_properties.items():
- # Since the target path is what Visual Studio will run, use the EXE
- # property in preference to TARGET_PATH.
- target_path = mode_properties.get('EXE',
- mode_properties.get('TARGET_PATH'))
- env.Append(TARGET_PATH={mode: target_path})
- else:
- # No modes declared for this target. Could be a custom alias created by
- # a SConscript, rather than a component builder. Assume it can be built in
- # all modes, but produces no output.
- for mode in GetTargetModes():
- env.Append(TARGET_PATH={mode: None})
-
- # Call the real builder
- return env.ComponentVSProjectBuilder(
- '$COMPONENT_VS_PROJECT_DIR/${TARGET_NAME}', [])
-
-#------------------------------------------------------------------------------
-
-
-class SourceWalker(object):
- """Iterator for walking a node tree and collecting sources.
-
- This is depth-first, children are visited before the parent. The object
- can be initialized with any node, and returns the next node on the descent
- with each Next() call.
-
- This class does not get caught in node cycles caused, for example, by C
- header file include loops.
-
- Based on SCons.Node.Walker.
- """
-
- def __init__(self, node, seen, print_interval = 1000):
- """Initializes the source walker.
-
- Args:
- node: Node to start walk from.
- seen: Set to add seen nodes to, if not None.
- print_interval: Interval in nodes examined at which to print a progress
- indicator.
- """
- self.interval = print_interval
- # Put node on stack
- self.stack = [node]
- # Scan for node's children, then copy them to node.wkids
- node.wkids = copy.copy(node.children(scan=1))
- # Keep track of nodes we've seen (returned)
- if seen is None:
- seen = set()
- self.seen = seen
- # Add node to history for cycle detection
- self.history = set()
- self.history.add(node)
- # We've seen one node now
- self.nodes_examined = 1
- self.unique_nodes = 1
-
-
- def Next(self):
- """Get the next node for this walk of the tree.
-
- Returns:
- The next node, or None if no more nodes.
-
- This function is intentionally iterative, not recursive, to sidestep any
- issues of stack size limitations.
- """
- while self.stack:
- if self.stack[-1].wkids:
- # Node has children we haven't examined, so iterate into the first
- # child
- node = self.stack[-1].wkids.pop(0)
- if not self.stack[-1].wkids:
- # No more children of this node
- self.stack[-1].wkids = None
- self.nodes_examined += 1
- if self.interval and not self.nodes_examined % self.interval:
- self.PrintProgress()
- if (node not in self.history) and (node not in self.seen):
- # Haven't hit a cycle or a node we've already seen
- node.wkids = copy.copy(node.children(scan=1))
- self.stack.append(node)
- self.history.add(node)
- else:
- # Coming back from iterating, so return the next node on the stack.
- node = self.stack.pop()
- self.history.remove(node)
- self.seen.add(node)
- self.unique_nodes += 1
- return node
- return None
-
- def PrintProgress(self):
- """Prints a progress indicator."""
- print ' Examined %d nodes, found %d unique...' % (
- self.nodes_examined, self.unique_nodes)
-
- def WalkAll(self):
- """Walks all nodes in the the tree."""
- while self.Next():
- pass
- if self.interval:
- self.PrintProgress()
-
-
-def ComponentVSSourceProjectBuilder(target, source, env):
- """Visual Studio source project builder.
-
- Args:
- target: Destination file.
- source: List of sources to be added to the target.
- env: Environment context.
-
- Returns:
- Zero if successful.
- """
- source = source # Silence gpylint
-
- target_name = env['PROJECT_NAME']
- project_file = target[0].path
- project_dir = target[0].dir
-
- # Get list of suffixes to include
- suffixes = env.SubstList2('$COMPONENT_VS_SOURCE_SUFFIXES')
-
- # Convert source folders to absolute paths
- folders = []
- for f in env['COMPONENT_VS_SOURCE_FOLDERS']:
- # (folder name, folder abspath, dict of contents)
- folders.append((f[0], env.Dir(f[1]).abspath, {}))
-
- # TODO(rspangler): Additional enhancements:
- # * Should be able to specify paths in folder name (i.e., foo/bar) and
- # create the nested folder nodes ('foo' and 'bar')
- # * Should be tolerant of a folder being specified more than once with
- # the same name (probably necessary to support nested folder nodes anyway)
- # Can probably accomplish both of those by creating a parent fodler dict and
- # calling WalkFolders() only once.
- # Create a temporary solution alias to point to all the targets, so we can
- # make a single call to SourceWalker()
- tmp_alias = env.Alias('vs_source_project_' + target_name,
- map(env.Alias, env['COMPONENT_VS_SOURCE_TARGETS']))
-
- # Scan all targets and add unique nodes to set of sources
- print ' Scanning dependency tree ...'
- all_srcs = set()
- walker = SourceWalker(tmp_alias[0], all_srcs)
- walker.WalkAll()
-
- # Walk all sources and build directory trees
- print ' Building source tree...'
- for n in all_srcs:
- if not hasattr(n, 'isfile') or not n.isfile():
- continue # Not a file
- if n.has_builder():
- continue # Not a leaf node
- if n.suffix not in suffixes:
- continue # Not a file type we include
-
- path = n.rfile().abspath
- for f in folders:
- if path.startswith(f[1]):
- if f[0] is None:
- # Folder name of None is a filter
- break
- relpath = path[len(f[1]) + 1:].split(os.sep)
- folder_dict = f[2]
- # Recursively add subdirs
- for pathseg in relpath[:-1]:
- if pathseg not in folder_dict:
- folder_dict[pathseg] = {}
- folder_dict = folder_dict[pathseg]
- # Add file to last subdir. No dict, since this isn't a subdir
- folder_dict[env.RelativePath(project_dir, path)] = None
- break
-
- print ' Writing project file...'
-
- vsp = VSProjectWriter(project_file)
- vsp.Create(target_name)
-
- # One configuration for all build modes
- vsp.AddConfig('all', {}, {})
-
- # Add files
- for f in folders:
- if f[0] is None:
- continue # Skip filters
- vsp.AddFiles(f[0], f[2])
-
- vsp.Write()
- return 0
-
-
-def ComponentVSSourceProject(self, project_name, target_names, **kwargs):
- """Visual Studio source project pseudo-builder.
-
- Args:
- self: Environment context.
- project_name: Name of the project.
- target_names: List of target names to include source for.
- kwargs: Optional keyword arguments override environment variables in the
- derived environment used to create the project.
-
- Returns:
- A list of output nodes.
- """
- # Builder only works on Windows
- if sys.platform not in ('win32', 'cygwin'):
- return []
-
- # Clone environment and add keyword args
- env = self.Clone()
- for k, v in kwargs.items():
- env[k] = v
-
- # Save the project name and targets
- env['PROJECT_NAME'] = project_name
- env['COMPONENT_VS_SOURCE_TARGETS'] = target_names
-
- # Call the real builder
- return env.ComponentVSSourceProjectBuilder(
- '$COMPONENT_VS_PROJECT_DIR/${PROJECT_NAME}', [])
-
-#------------------------------------------------------------------------------
-
-
-def FindSources(env, dest, source, suffixes=None):
- """Recursively finds sources and adds them to the destination set.
-
- Args:
- env: Environment context.
- dest: Set to add source nodes to.
- source: Source file(s) to find. May be a string, Node, or a list of
- mixed strings or Nodes. Strings will be passed through env.Glob() to
- evaluate wildcards. If a source evaluates to a directory, the entire
- directory will be recursively added.
- suffixes: List of suffixes to include. If not None, only files with these
- suffixes will be added to dest.
- """
- for source_entry in env.Flatten(source):
- if type(source_entry) == str:
- # Search for matches for each source entry
- source_nodes = env.Glob(source_entry)
- else:
- # Source entry is already a file or directory node; no need to glob it
- source_nodes = [source_entry]
- for s in source_nodes:
- if str(s.__class__) == 'SCons.Node.FS.Dir':
- # Recursively search subdir. Since glob('*') doesn't match dot files,
- # also glob('.*').
- FindSources(env, dest, [s.abspath + '/*', s.abspath + '/.*'], suffixes)
- elif suffixes and s.suffix in suffixes:
- dest.add(s)
-
-
-def ComponentVSDirProjectBuilder(target, source, env):
- """Visual Studio directory project builder.
-
- Args:
- target: Destination file.
- source: List of sources to be added to the target.
- env: Environment context.
-
- Returns:
- Zero if successful.
- """
- source = source # Silence gpylint
-
- target_name = env['PROJECT_NAME']
- project_file = target[0].path
- project_dir = target[0].dir
-
- # Convert source folders to absolute paths
- folders = []
- for f in env['COMPONENT_VS_SOURCE_FOLDERS']:
- # (folder name, folder abspath, dict of contents)
- folders.append((f[0], env.Dir(f[1]).abspath, {}))
-
- # Recursively scan source directories
- print ' Scanning directories for source...'
- all_srcs = set()
- FindSources(env, all_srcs, env['PROJECT_SOURCES'],
- suffixes=env.SubstList2('$COMPONENT_VS_SOURCE_SUFFIXES'))
-
- # Walk all sources and build directory trees
- print ' Building source tree...'
- for n in all_srcs:
- # Map addRepository'd source to its real location.
- path = n.rfile().abspath
- for f in folders:
- if path.startswith(f[1]):
- if f[0] is None:
- # Folder name of None is a filter
- break
- relpath = path[len(f[1]) + 1:].split(os.sep)
- folder_dict = f[2]
- # Recursively add subdirs
- for pathseg in relpath[:-1]:
- if pathseg not in folder_dict:
- folder_dict[pathseg] = {}
- folder_dict = folder_dict[pathseg]
- # Add file to last subdir. No dict, since this isn't a subdir
- folder_dict[env.RelativePath(project_dir, path)] = None
- break
-
- print ' Writing project file...'
-
- vsp = VSProjectWriter(project_file)
- vsp.Create(target_name)
-
- # One configuration for all build modes
- vsp.AddConfig('all', {}, {})
-
- # Add files
- for f in folders:
- if f[0] is None:
- continue # Skip filters
- vsp.AddFiles(f[0], f[2])
-
- vsp.Write()
- return 0
-
-
-def ComponentVSDirProject(self, project_name, source, **kwargs):
- """Visual Studio directory project pseudo-builder.
-
- Args:
- self: Environment context.
- project_name: Name of the project.
- source: List of source files and/or directories.
- kwargs: Optional keyword arguments override environment variables in the
- derived environment used to create the project.
-
- Returns:
- A list of output nodes.
- """
- # Builder only works on Windows
- if sys.platform not in ('win32', 'cygwin'):
- return []
-
- # Clone environment and add keyword args
- env = self.Clone()
- for k, v in kwargs.items():
- env[k] = v
-
- # Save the project name and sources
- env['PROJECT_NAME'] = project_name
- env['PROJECT_SOURCES'] = source
-
- # Call the real builder
- return env.ComponentVSDirProjectBuilder(
- '$COMPONENT_VS_PROJECT_DIR/${PROJECT_NAME}', [])
-
-#------------------------------------------------------------------------------
-
-
-def ComponentVSSolutionBuilder(target, source, env):
- """Visual Studio solution builder.
-
- Args:
- target: Destination file.
- source: List of sources to be added to the target.
- env: Environment context.
-
- Returns:
- Zero if successful.
- """
- source = source # Silence gpylint
-
- solution_file = target[0].path
- projects = env['SOLUTION_PROJECTS']
- folders = env['SOLUTION_FOLDERS']
-
- # Scan externally-generated projects
- external_projects = []
- for p in source:
- guid, name = GetGuidAndNameFromVSProject(p.abspath)
- external_projects.append((p, name, guid))
-
- f = open(solution_file, 'wt')
- f.write('Microsoft Visual Studio Solution File, Format Version 9.00\n')
- f.write('# Visual Studio 2005\n')
-
- # Projects generated by ComponentVSSolution()
- for p in projects:
- project_file = env.File(
- '$COMPONENT_VS_PROJECT_DIR/%s$COMPONENT_VS_PROJECT_SUFFIX' % p)
- f.write('Project("%s") = "%s", "%s", "%s"\nEndProject\n' % (
- '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}', # External makefile GUID
- p, # Project name
- env.RelativePath(target[0].dir, project_file), # Path to project file
- MakeGuid(p), # Project GUID
- ))
-
- # Projects generated elsewhere
- for p, name, guid in external_projects:
- f.write('Project("%s") = "%s", "%s", "%s"\nEndProject\n' % (
- # TODO(rspangler): What if this project isn't type external makefile?
- # How to tell what type it is?
- '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}', # External makefile GUID
- name, # Project name
- env.RelativePath(target[0].dir, p), # Path to project file
- guid, # Project GUID
- ))
-
- # Folders from build groups
- # TODO(rspangler): Currently no way to add external project (specified in
- # sources) to a solution folder.
- for folder in folders:
- f.write('Project("%s") = "%s", "%s", "%s"\nEndProject\n' % (
- '{2150E333-8FDC-42A3-9474-1A3956D46DE8}', # Solution folder GUID
- folder, # Folder name
- folder, # Folder name (again)
- # Use a different seed so the folder won't get the same GUID as a
- # project.
- MakeGuid(folder, seed='folder'), # Project GUID
- ))
-
- f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
- for mode in GetTargetModes():
- f.write('\t\t%s|Win32 = %s|Win32\n' % (mode, mode))
- f.write('\tEndGlobalSection\n')
-
- # Determine which projects should be enabled
- # TODO(rspangler): This is somewhat clunky. DEFAULT_TARGETS is global, and
- # what we really need is something mode-specific. In theory we could make
- # this a mode-specific dict rather than a list, but that'd also be a pain to
- # populate.
- # These variable names are also getting REALLY long. Perhaps we should
- # define shorter ones (with the default value redirecting to the longer
- # ones for legacy compatibility).
- enable_projects = env.SubstList2('$COMPONENT_VS_ENABLED_PROJECTS')
-
- f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
-
- # Projects generated by ComponentVSSolution()
- for p in projects:
- for mode in GetTargetModes():
- f.write('\t\t%s.%s|Win32.ActiveCfg = %s|Win32\n' % (
- MakeGuid(p), # Project GUID
- mode, # Solution build configuration
- mode, # Project build config for that solution config
- ))
-
- t = GetTargets().get(p)
-
- # Determine if project should be enabled in this mode
- enabled = t and mode in t.mode_properties
- if enable_projects and p not in enable_projects:
- # Enable list specified, but target isn't in it
- # TODO(rspangler): Since we env.Default(scons-out) elsewhere, this
- # likely causes all projects to be disabled by default. But that's
- # realistically better than enabling them all...
- enabled = False
-
- if enabled:
- # Target can be built in this mode
- f.write('\t\t%s.%s|Win32.Build.0 = %s|Win32\n' % (
- MakeGuid(p), # Project GUID
- mode, # Solution build configuration
- mode, # Project build config for that solution config
- ))
-
- # Projects generated elsewhere
- for p, name, guid in external_projects:
- for mode in GetTargetModes():
- f.write('\t\t%s.%s|Win32.ActiveCfg = %s|Win32\n' % (
- guid, # Project GUID
- mode, # Solution build configuration
- mode, # Project build config for that solution config
- ))
-
- if name in enable_projects or not enable_projects:
- # Build target in this mode
- f.write('\t\t%s.%s|Win32.Build.0 = %s|Win32\n' % (
- guid, # Project GUID
- mode, # Solution build configuration
- mode, # Project build config for that solution config
- ))
-
- f.write('\tEndGlobalSection\n')
-
- f.write('\tGlobalSection(SolutionProperties) = preSolution\n')
- f.write('\t\tHideSolutionNode = FALSE\n')
- f.write('\tEndGlobalSection\n')
-
- if folders:
- f.write('\tGlobalSection(NestedProjects) = preSolution\n')
- for p, folder in projects.items():
- f.write('\t\t%s = %s\n' % (MakeGuid(p), MakeGuid(folder, seed='folder')))
- f.write('\tEndGlobalSection\n')
-
- f.write('EndGlobal\n')
- f.close()
-
- return 0
-
-
-def ComponentVSSolution(self, solution_name, target_names, projects=None,
- **kwargs):
- """Visual Studio solution pseudo-builder.
-
- Args:
- self: Environment context.
- solution_name: Name of the solution.
- target_names: Names of targets or target groups to include in the solution.
- This will automatically build projects for them.
- projects: List of aditional projects not generated by this solution to
- include in the solution.
- kwargs: Optional keyword arguments override environment variables in the
- derived environment used to create the solution.
-
- Returns:
- The list of output nodes.
- """
- # TODO(rspangler): Should have option to build source project also. Perhaps
- # select using a --source_project option, since it needs to use gather_inputs
- # to scan the DAG and will blow up the null build time.
- # TODO(rspangler): Should also have autobuild_projects option. If false,
- # don't build them.
- # TODO(rspangler): Should also be able to specify a target group directly
- # (i.e. 'run_all_tests')
-
- # Builder only works on Windows
- if sys.platform not in ('win32', 'cygwin'):
- return []
-
- # Clone environment and add keyword args
- env = self.Clone()
- for k, v in kwargs.items():
- env[k] = v
-
- # Save the target name
- env['SOLUTION_NAME'] = solution_name
-
- # Get list of targets to make projects for. At this point we haven't
- # determined whether they're groups or targets.
- target_names = env.SubstList2(target_names)
- env['SOLUTION_TARGETS'] = target_names
-
- # Save the default targets list as an environment variable
- env['COMPONENT_VS_SCONS_DEFAULT_TARGETS'] = SCons.Script.DEFAULT_TARGETS
-
- # Expand target_names into project names, and create project-to-folder
- # mappings
- project_names = {}
- folders = []
- if target_names:
- # Expand target_names into project names
- for target in target_names:
- if target in GetTargetGroups():
- # Add target to folders
- folders.append(target)
- # Add all project_names in the group
- for t in GetTargetGroups()[target].GetTargetNames():
- project_names[t] = target
- elif target in GetTargets():
- # Just a target name
- project_names[target] = None
- else:
- print 'Warning: ignoring unknown target "%s"' % target
- else:
- # No target names specified, so use all projects
- for t in GetTargets():
- project_names[t] = None
-
- env['SOLUTION_FOLDERS'] = folders
- env['SOLUTION_PROJECTS'] = project_names
-
- # Call the real builder
- out_nodes = env.ComponentVSSolutionBuilder(
- '$COMPONENT_VS_SOLUTION_DIR/${SOLUTION_NAME}', projects or [])
-
- # Call the real builder for the projects we generate
- for p in project_names:
- out_nodes += env.ComponentVSProject(p)
-
- # Add the solution target
- # TODO(rspangler): Should really defer the rest of the work above, since
- # otherwise we can't build a solution which has a target to rebuild itself.
- env.Alias('all_solutions', env.Alias(solution_name, out_nodes))
-
- # TODO(rspangler): To rebuild the solution properly, need to override its
- # project configuration so it only has '--mode=all' (or some other way of
- # setting the subset of modes which it should use to rebuild itself).
- # Rebuilding with the property below will strip it down to just the current
- # build mode, which isn't what we want.
- # Let component_targets know this target is available in the current mode
- #self.SetTargetProperty(solution_name, TARGET_PATH=out_nodes[0])
-
- return out_nodes
-
-#------------------------------------------------------------------------------
-
-
-def generate(env):
- # NOTE: SCons requires the use of this name, which fails gpylint.
- """SCons entry point for this tool."""
-
- # Add pseudo-builders to set up the project and solution builders. These
- # need to be available on all platforms so that SConscripts which reference
- # them will work.
- env.AddMethod(ComponentVSDirProject)
- env.AddMethod(ComponentVSProject)
- env.AddMethod(ComponentVSSolution)
- env.AddMethod(ComponentVSSourceProject)
-
- # If not on Windows, don't do anything else
- if sys.platform not in ('win32', 'cygwin'):
- return
-
- # Include tools we need
- env.Tool('gather_inputs')
-
- env.SetDefault(
- COMPONENT_VS_PROJECT_DIR='$COMPONENT_VS_SOLUTION_DIR/projects',
- COMPONENT_VS_PROJECT_SCRIPT_NAME = 'hammer.bat',
- COMPONENT_VS_PROJECT_SCRIPT_PATH = (
- '$$(ProjectDir)/$VS_PROJECT_TO_MAIN_DIR/'
- '$COMPONENT_VS_PROJECT_SCRIPT_NAME'),
- COMPONENT_VS_PROJECT_SUFFIX='.vcproj',
-
- COMPONENT_VS_SOLUTION_DIR='$DESTINATION_ROOT/solution',
- COMPONENT_VS_SOLUTION_SUFFIX='.sln',
- COMPONENT_VS_ENABLED_PROJECTS=['$COMPONENT_VS_SCONS_DEFAULT_TARGETS'],
-
- COMPONENT_VS_SOURCE_SUFFIXES=['$CPPSUFFIXES', '.rc', '.scons'],
- COMPONENT_VS_SOURCE_FOLDERS=[('source', '$MAIN_DIR')],
- )
-
- AddTargetGroup('all_solutions', 'solutions can be built')
-
- # Add builders
- vcprojaction = SCons.Script.Action(ComponentVSProjectBuilder, varlist=[
- 'COMPONENT_VS_PROJECT_SCRIPT_PATH',
- 'TARGET_NAME',
- 'TARGET_PATH',
- ])
- vcprojbuilder = SCons.Script.Builder(
- action=vcprojaction,
- suffix='$COMPONENT_VS_PROJECT_SUFFIX')
-
- source_vcproj_action = SCons.Script.Action(
- ComponentVSSourceProjectBuilder, varlist=[
- 'COMPONENT_VS_SOURCE_FOLDERS',
- 'COMPONENT_VS_SOURCE_SUFFIXES',
- 'COMPONENT_VS_SOURCE_TARGETS',
- ])
- source_vcproj_builder = SCons.Script.Builder(
- action=source_vcproj_action,
- suffix='$COMPONENT_VS_PROJECT_SUFFIX')
-
- dir_vcproj_action = SCons.Script.Action(
- ComponentVSDirProjectBuilder, varlist=[
- 'COMPONENT_VS_SOURCE_FOLDERS',
- 'COMPONENT_VS_SOURCE_SUFFIXES',
- 'PROJECT_SOURCES',
- ])
- dir_vcproj_builder = SCons.Script.Builder(
- action=dir_vcproj_action,
- suffix='$COMPONENT_VS_PROJECT_SUFFIX')
-
- slnaction = SCons.Script.Action(ComponentVSSolutionBuilder, varlist=[
- 'COMPONENT_VS_ENABLED_PROJECTS',
- 'SOLUTION_FOLDERS',
- 'SOLUTION_PROJECTS',
- 'SOLUTION_TARGETS',
- ])
- slnbuilder = SCons.Script.Builder(
- action=slnaction,
- suffix='$COMPONENT_VS_SOLUTION_SUFFIX')
-
- env.Append(BUILDERS={
- 'ComponentVSDirProjectBuilder': dir_vcproj_builder,
- 'ComponentVSProjectBuilder': vcprojbuilder,
- 'ComponentVSSolutionBuilder': slnbuilder,
- 'ComponentVSSourceProjectBuilder': source_vcproj_builder,
- })
« no previous file with comments | « site_scons/site_tools/component_targets.py ('k') | site_scons/site_tools/component_targets_xml.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698