1cb93a386Sopenharmony_ci#!/usr/bin/env python
2cb93a386Sopenharmony_ci#
3cb93a386Sopenharmony_ci# Copyright 2015 Google Inc.
4cb93a386Sopenharmony_ci#
5cb93a386Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
6cb93a386Sopenharmony_ci# found in the LICENSE file.
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci# This script does a very rough simulation of BUILD file expansion,
9cb93a386Sopenharmony_ci# mostly to see the effects of glob().
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci# We start by adding some symbols to our namespace that BUILD.public calls.
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ciimport glob
14cb93a386Sopenharmony_ciimport os
15cb93a386Sopenharmony_ciimport pprint
16cb93a386Sopenharmony_ciimport re
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cidef noop(*args, **kwargs):
19cb93a386Sopenharmony_ci  pass
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cidef select_simulator(d):
22cb93a386Sopenharmony_ci  result = []
23cb93a386Sopenharmony_ci  for k in d:
24cb93a386Sopenharmony_ci    result.append("*** BEGIN %s ***" % k)
25cb93a386Sopenharmony_ci    result.extend(d[k])
26cb93a386Sopenharmony_ci    result.append("*** END %s ***" % k)
27cb93a386Sopenharmony_ci  return result
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ciDOUBLE_STAR_RE = re.compile(r'/\*\*/')
30cb93a386Sopenharmony_ciSTAR_RE = re.compile(r'\*')
31cb93a386Sopenharmony_ciDOUBLE_STAR_PLACEHOLDER = "xxxdoublestarxxx"
32cb93a386Sopenharmony_ciSTAR_PLACEHOLDER = "xxxstarxxx"
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci# Returns a set of files that match pattern.
35cb93a386Sopenharmony_cidef BUILD_glob_single(pattern):
36cb93a386Sopenharmony_ci  if pattern.find('**') < 0:
37cb93a386Sopenharmony_ci    # If pattern doesn't include **, glob.glob more-or-less does the right
38cb93a386Sopenharmony_ci    # thing.
39cb93a386Sopenharmony_ci    return glob.glob(pattern)
40cb93a386Sopenharmony_ci  # First transform pattern into a regexp.
41cb93a386Sopenharmony_ci  # Temporarily remove ** and *.
42cb93a386Sopenharmony_ci  pattern2 = DOUBLE_STAR_RE.sub(DOUBLE_STAR_PLACEHOLDER, pattern)
43cb93a386Sopenharmony_ci  pattern3 = STAR_RE.sub(STAR_PLACEHOLDER, pattern2)
44cb93a386Sopenharmony_ci  # Replace any regexp special characters.
45cb93a386Sopenharmony_ci  pattern4 = re.escape(pattern3)
46cb93a386Sopenharmony_ci  # Replace * with [^/]* and ** with .*.
47cb93a386Sopenharmony_ci  pattern5 = pattern4.replace(STAR_PLACEHOLDER, '[^/]*')
48cb93a386Sopenharmony_ci  pattern6 = pattern5.replace(DOUBLE_STAR_PLACEHOLDER, '.*/')
49cb93a386Sopenharmony_ci  # Anchor the match at the beginning and end.
50cb93a386Sopenharmony_ci  pattern7 = "^" + pattern6 + "$"
51cb93a386Sopenharmony_ci  pattern_re = re.compile(pattern7)
52cb93a386Sopenharmony_ci  matches = set()
53cb93a386Sopenharmony_ci  for root, _, files in os.walk('.'):
54cb93a386Sopenharmony_ci    for fname in files:
55cb93a386Sopenharmony_ci      # Remove initial "./".
56cb93a386Sopenharmony_ci      path = os.path.join(root, fname)[2:]
57cb93a386Sopenharmony_ci      if pattern_re.match(path):
58cb93a386Sopenharmony_ci        matches.add(path)
59cb93a386Sopenharmony_ci  return matches
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci# Simulates BUILD file glob().
62cb93a386Sopenharmony_cidef BUILD_glob(include, exclude=()):
63cb93a386Sopenharmony_ci  files = set()
64cb93a386Sopenharmony_ci  for pattern in include:
65cb93a386Sopenharmony_ci    files.update(BUILD_glob_single(pattern))
66cb93a386Sopenharmony_ci  for pattern in exclude:
67cb93a386Sopenharmony_ci    files.difference_update(BUILD_glob_single(pattern))
68cb93a386Sopenharmony_ci  return list(sorted(files))
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci# With these namespaces, we can treat BUILD.public as if it were
71cb93a386Sopenharmony_ci# Python code.  This pulls its variable definitions (SRCS, HDRS,
72cb93a386Sopenharmony_ci# DEFINES, etc.) into local_names.
73cb93a386Sopenharmony_ciglobal_names = {
74cb93a386Sopenharmony_ci  'cc_library': noop,
75cb93a386Sopenharmony_ci  'cc_test': noop,
76cb93a386Sopenharmony_ci  'exports_files': noop,
77cb93a386Sopenharmony_ci  'glob': BUILD_glob,
78cb93a386Sopenharmony_ci  'select': select_simulator,
79cb93a386Sopenharmony_ci  'BASE_DIR': '',
80cb93a386Sopenharmony_ci  'BASE_EXTERNAL_DEPS_ANDROID': [],
81cb93a386Sopenharmony_ci  'BASE_EXTERNAL_DEPS_IOS': [],
82cb93a386Sopenharmony_ci  'BASE_EXTERNAL_DEPS_UNIX': [],
83cb93a386Sopenharmony_ci  'CONDITION_ANDROID': 'CONDITION_ANDROID',
84cb93a386Sopenharmony_ci  'CONDITION_IOS': 'CONDITION_IOS',
85cb93a386Sopenharmony_ci  'DM_EXTERNAL_DEPS': [],
86cb93a386Sopenharmony_ci  'EXTERNAL_DEPS_ALL': [],
87cb93a386Sopenharmony_ci  'EXTERNAL_INCLUDES': [],
88cb93a386Sopenharmony_ci}
89cb93a386Sopenharmony_cilocal_names = {}
90cb93a386Sopenharmony_ciexecfile('BUILD.public', global_names, local_names)
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ciwith open('tools/BUILD.public.expected', 'w') as out:
93cb93a386Sopenharmony_ci  print >>out, "This file is auto-generated by tools/BUILD_simulator.py."
94cb93a386Sopenharmony_ci  print >>out, "It expands BUILD.public to make it easy to see changes."
95cb93a386Sopenharmony_ci  for name, value in sorted(local_names.items()):
96cb93a386Sopenharmony_ci    print >>out, name, '= ',
97cb93a386Sopenharmony_ci    pprint.pprint(value, out)
98