You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
2.9 KiB
97 lines
2.9 KiB
#!/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)
|
|
|