blob: 6964beedecbfc756daabfe183812f9bc78e889dc [file] [log] [blame]
#!/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.
"""Input gathering tool for SCons."""
import re
import SCons.Script
def GatherInputs(env, target, groups=['.*'], exclude_pattern=None):
"""Find all (non-generated) input files used for a target.
Args:
target: a target node to find source files for
For example: File('bob.exe')
groups: a list of patterns to use as categories
For example: ['.*\\.c$', '.*\\.h$']
exclude_pattern: a pattern to exclude from the search
For example: '.*third_party.*'
Returns:
A list of lists of files for each category.
Each file will be placed in the first category which matches,
even if categories overlap.
For example:
[['bob.c', 'jim.c'], ['bob.h', 'jim.h']]
"""
# Compile exclude pattern if any
if exclude_pattern:
exclude_pattern = re.compile(exclude_pattern)
def _FindSources(ptrns, tgt, all):
"""Internal Recursive function to find all pattern matches."""
# Recursively process lists
if SCons.Util.is_List(tgt):
for t in tgt:
_FindSources(ptrns, t, all)
else:
# Get key to use for tracking whether we've seen this node
target_abspath = None
if hasattr(tgt, 'abspath'):
# Use target's absolute path as the key
target_abspath = tgt.abspath
target_key = target_abspath
else:
# Hope node's representation is unique enough (the default repr
# contains a pointer to the target as a string). This works for
# Alias() nodes.
target_key = repr(tgt)
# Skip if we have been here before
if target_key in all: return
# Note that we have been here
all[target_key] = True
# Skip ones that match an exclude pattern, if we have one.
if (exclude_pattern and target_abspath
and exclude_pattern.match(target_abspath)):
return
# Handle non-leaf nodes recursively
lst = tgt.children(scan=1)
if lst:
_FindSources(ptrns, lst, all)
return
# Get real file (backed by repositories).
rfile = tgt.rfile()
rfile_is_file = rfile.isfile()
# See who it matches
for pattern, lst in ptrns.items():
# Add files to the list for the first pattern that matches (implicitly,
# don't add directories).
if rfile_is_file and pattern.match(rfile.path):
lst.append(rfile.abspath)
break
# Prepare a group for each pattern.
patterns = {}
for g in groups:
patterns[re.compile(g, re.IGNORECASE)] = []
# Do the search.
_FindSources(patterns, target, {})
return patterns.values()
def generate(env):
# NOTE: SCons requires the use of this name, which fails gpylint.
"""SCons entry point for this tool."""
# Add a method to gather all inputs needed by a target.
env.AddMethod(GatherInputs, 'GatherInputs')