blob: bd4a832b7ba5b0e3f17798750549f9e5e0ecf203 [file] [log] [blame]
mtkleindf5b7602015-08-17 15:02:57 -07001#!/usr/bin/env python
2#
3# Copyright 2015 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8# This script does a very rough simulation of BUILD file expansion,
9# mostly to see the effects of glob().
10
11# We start by adding some symbols to our namespace that BUILD.public calls.
12
halcanarybf3dde22015-08-18 08:35:45 -070013import glob
benjaminwagner6f6bef82015-10-15 08:09:44 -070014import os
halcanarybf3dde22015-08-18 08:35:45 -070015import pprint
benjaminwagner6f6bef82015-10-15 08:09:44 -070016import re
halcanarybf3dde22015-08-18 08:35:45 -070017
18def noop(*args, **kwargs):
mtkleindf5b7602015-08-17 15:02:57 -070019 pass
20
benjaminwagner6f6bef82015-10-15 08:09:44 -070021DOUBLE_STAR_RE = re.compile(r'/\*\*/')
22STAR_RE = re.compile(r'\*')
23DOUBLE_STAR_PLACEHOLDER = "xxxdoublestarxxx"
24STAR_PLACEHOLDER = "xxxstarxxx"
25
26# Returns a set of files that match pattern.
27def BUILD_glob_single(pattern):
28 if pattern.find('**') < 0:
29 # If pattern doesn't include **, glob.glob more-or-less does the right
30 # thing.
31 return glob.glob(pattern)
32 # First transform pattern into a regexp.
33 # Temporarily remove ** and *.
34 pattern2 = DOUBLE_STAR_RE.sub(DOUBLE_STAR_PLACEHOLDER, pattern)
35 pattern3 = STAR_RE.sub(STAR_PLACEHOLDER, pattern2)
36 # Replace any regexp special characters.
37 pattern4 = re.escape(pattern3)
38 # Replace * with [^/]* and ** with .*.
39 pattern5 = pattern4.replace(STAR_PLACEHOLDER, '[^/]*')
40 pattern6 = pattern5.replace(DOUBLE_STAR_PLACEHOLDER, '.*/')
41 # Anchor the match at the beginning and end.
42 pattern7 = "^" + pattern6 + "$"
43 pattern_re = re.compile(pattern7)
44 matches = set()
45 for root, _, files in os.walk('.'):
46 for fname in files:
47 # Remove initial "./".
48 path = os.path.join(root, fname)[2:]
49 if pattern_re.match(path):
50 matches.add(path)
51 return matches
52
mtkleindf5b7602015-08-17 15:02:57 -070053# Simulates BUILD file glob().
halcanarybf3dde22015-08-18 08:35:45 -070054def BUILD_glob(include, exclude=()):
mtkleindf5b7602015-08-17 15:02:57 -070055 files = set()
56 for pattern in include:
benjaminwagner6f6bef82015-10-15 08:09:44 -070057 files.update(BUILD_glob_single(pattern))
mtkleindf5b7602015-08-17 15:02:57 -070058 for pattern in exclude:
benjaminwagner6f6bef82015-10-15 08:09:44 -070059 files.difference_update(BUILD_glob_single(pattern))
mtkleindf5b7602015-08-17 15:02:57 -070060 return list(sorted(files))
61
halcanarybf3dde22015-08-18 08:35:45 -070062# With these namespaces, we can treat BUILD.public as if it were
63# Python code. This pulls its variable definitions (SRCS, HDRS,
64# DEFINES, etc.) into local_names.
65global_names = {
66 'exports_files': noop,
benjaminwagner6f6bef82015-10-15 08:09:44 -070067 'cc_library': noop,
68 'cc_test': noop,
halcanarybf3dde22015-08-18 08:35:45 -070069 'glob': BUILD_glob,
benjaminwagner6f6bef82015-10-15 08:09:44 -070070 'EXTERNAL_DEPS': [],
71 'BASE_DIR': "",
72 'DM_EXTERNAL_DEPS': [],
halcanarybf3dde22015-08-18 08:35:45 -070073}
74local_names = {}
75execfile('BUILD.public', global_names, local_names)
mtkleindf5b7602015-08-17 15:02:57 -070076
mtkleindf5b7602015-08-17 15:02:57 -070077with open('tools/BUILD.public.expected', 'w') as out:
78 print >>out, "This file is auto-generated by tools/BUILD_simulator.py."
79 print >>out, "It expands BUILD.public to make it easy to see changes."
halcanarybf3dde22015-08-18 08:35:45 -070080 for name, value in sorted(local_names.items()):
81 print >>out, name, '= ',
82 pprint.pprint(value, out)