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