#!/usr/bin/env python
#
# Copyright 2015 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script does a very rough simulation of BUILD file expansion,
# mostly to see the effects of glob().
# We start by adding some symbols to our namespace that BUILD.public calls.
import glob
import os
import pprint
import re
def noop(*args, **kwargs):
pass
def select_simulator(d):
result = []
for k in d:
result.append("*** BEGIN %s ***" % k)
result.extend(d[k])
result.append("*** END %s ***" % k)
return result
DOUBLE_STAR_RE = re.compile(r'/\*\*/')
STAR_RE = re.compile(r'\*')
DOUBLE_STAR_PLACEHOLDER = "xxxdoublestarxxx"
STAR_PLACEHOLDER = "xxxstarxxx"
# Returns a set of files that match pattern.
def BUILD_glob_single(pattern):
if pattern.find('**') < 0:
# If pattern doesn't include **, glob.glob more-or-less does the right
# thing.
return glob.glob(pattern)
# First transform pattern into a regexp.
# Temporarily remove ** and *.
pattern2 = DOUBLE_STAR_RE.sub(DOUBLE_STAR_PLACEHOLDER, pattern)
pattern3 = STAR_RE.sub(STAR_PLACEHOLDER, pattern2)
# Replace any regexp special characters.
pattern4 = re.escape(pattern3)
# Replace * with [^/]* and ** with .*.
pattern5 = pattern4.replace(STAR_PLACEHOLDER, '[^/]*')
pattern6 = pattern5.replace(DOUBLE_STAR_PLACEHOLDER, '.*/')
# Anchor the match at the beginning and end.
pattern7 = "^" + pattern6 + "$"
pattern_re = re.compile(pattern7)
matches = set()
for root, _, files in os.walk('.'):
for fname in files:
# Remove initial "./".
path = os.path.join(root, fname)[2:]
if pattern_re.match(path):
matches.add(path)
return matches
# Simulates BUILD file glob().
def BUILD_glob(include, exclude=()):
files = set()
for pattern in include:
files.update(BUILD_glob_single(pattern))
for pattern in exclude:
files.difference_update(BUILD_glob_single(pattern))
return list(sorted(files))
# With these namespaces, we can treat BUILD.public as if it were
# Python code. This pulls its variable definitions (SRCS, HDRS,
# DEFINES, etc.) into local_names.
global_names = {
'cc_library': noop,
'cc_test': noop,
'exports_files': noop,
'glob': BUILD_glob,
'select': select_simulator,
'BASE_DIR': '',
'BASE_EXTERNAL_DEPS_ANDROID': [],
'BASE_EXTERNAL_DEPS_IOS': [],
'BASE_EXTERNAL_DEPS_UNIX': [],
'CONDITION_ANDROID': 'CONDITION_ANDROID',
'CONDITION_IOS': 'CONDITION_IOS',
'DM_EXTERNAL_DEPS': [],
'EXTERNAL_DEPS_ALL': [],
'EXTERNAL_INCLUDES': [],
}
local_names = {}
execfile('BUILD.public', global_names, local_names)
with open('tools/BUILD.public.expected', 'w') as out:
print >>out, "This file is auto-generated by tools/BUILD_simulator.py."
print >>out, "It expands BUILD.public to make it easy to see changes."
for name, value in sorted(local_names.items()):
print >>out, name, '= ',
pprint.pprint(value, out)