| #!/usr/bin/env python2.7 |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import json |
| import os |
| import shutil |
| import sys |
| |
| SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| FUCHSIA_ROOT = os.path.dirname( # $root |
| os.path.dirname( # build |
| SCRIPT_DIR)) # zircon |
| ZIRCON_PUBLIC = os.path.join(FUCHSIA_ROOT, 'zircon', 'public') |
| EXPORT_TEMPLATE_FILE = os.path.join(SCRIPT_DIR, 'lib_template.gn') |
| TOOL_TEMPLATE_FILE = os.path.join(SCRIPT_DIR, 'tool_template.gn') |
| UNIFICATION_DIR = os.path.join(FUCHSIA_ROOT, 'build', 'unification') |
| MAPPINGS_FILE = os.path.join(UNIFICATION_DIR, 'zircon_library_mappings.json') |
| FORWARD_TEMPLATE_FILE = os.path.join(UNIFICATION_DIR, |
| 'zircon_library_forward.gn') |
| |
| DIRS = { |
| 'lib': True, |
| 'tool': False, |
| } |
| PUBLIC_DIRS = set(DIRS.keys()) |
| |
| MARKER = 'ONLY EDIT IT BY THAT NAME!' |
| |
| |
| def is_template(build_file): |
| with open(build_file, 'r') as file: |
| return MARKER in file.read() |
| |
| |
| def has_sources(top_dir): |
| return DIRS[top_dir] |
| |
| |
| def main(): |
| with open(sys.argv[1]) as f: |
| legacy_dirs = json.load(f) |
| with open(MAPPINGS_FILE, 'r') as f: |
| content = json.load(f) |
| mapped_lib_dirs = dict([('lib/' + i['name'], i['label']) |
| for i in content]) |
| |
| # Verify that we're not trying to create a forwarding target and an exported |
| # library under the same alias. |
| common_dirs = set(mapped_lib_dirs) & set(legacy_dirs) |
| if common_dirs: |
| print('The following paths cannot be both exports from Zircon and ' |
| 'forwarding targets:') |
| for dir in common_dirs: |
| print('//zircon/public/' + dir) |
| return 1 |
| |
| # Create a data structure holding all generated paths. |
| all_dirs = {} |
| for dir in legacy_dirs: |
| top_dir = os.path.dirname(dir) |
| if top_dir == 'tool': |
| all_dirs[dir] = TOOL_TEMPLATE_FILE |
| else: |
| all_dirs[dir] = EXPORT_TEMPLATE_FILE |
| for dir in mapped_lib_dirs: |
| all_dirs[dir] = FORWARD_TEMPLATE_FILE |
| |
| dirs = {} |
| for dir, template in all_dirs.iteritems(): |
| top_dir = os.path.dirname(dir) |
| name = os.path.basename(dir) |
| subdirs, templates = dirs.setdefault(top_dir, ([], {})) |
| templates[name] = template |
| dirs[top_dir] = (subdirs + [name], templates) |
| assert set(dirs.keys()).issubset(PUBLIC_DIRS), ( |
| "%r from JSON should be a subset of %r" % |
| (set(dirs.keys()), PUBLIC_DIRS)) |
| stats = dict([(f, os.lstat(f)) |
| for f in [EXPORT_TEMPLATE_FILE, FORWARD_TEMPLATE_FILE, |
| TOOL_TEMPLATE_FILE]]) |
| for top_dir in dirs: |
| subdirs, templates = dirs[top_dir] |
| top_dir_name = top_dir |
| top_dir = os.path.join(ZIRCON_PUBLIC, top_dir) |
| subdirs = set(subdirs) |
| if not os.path.exists(top_dir): |
| os.mkdir(top_dir) |
| else: |
| # Go over the existing contents of the directory. |
| for existing in os.listdir(top_dir): |
| existing_dir = os.path.join(top_dir, existing) |
| if not os.path.isdir(existing_dir): |
| # Disregard files (e.g. .gitignore). |
| continue |
| build_file = os.path.join(existing_dir, 'BUILD.gn') |
| is_source = (has_sources(top_dir_name) and |
| os.path.exists(build_file) and |
| not is_template(build_file)) |
| if existing in subdirs: |
| if is_source: |
| print('%s cannot be both a source and generated' % |
| existing_dir) |
| return 1 |
| # An existing directory might already have the link. |
| # If the link doesn't exist or doesn't match, make it. |
| template = templates[existing] |
| if not os.path.exists(build_file): |
| os.link(template, build_file) |
| elif not os.path.samestat(os.lstat(build_file), |
| stats[template]): |
| os.remove(build_file) |
| os.link(template, build_file) |
| subdirs.remove(existing) |
| else: |
| if not is_source: |
| # A stale directory that shouldn't exist any more. |
| shutil.rmtree(existing_dir) |
| # Make and populate any directories that don't exist yet. |
| for subdir in subdirs: |
| template = templates[subdir] |
| subdir = os.path.join(top_dir, subdir) |
| os.mkdir(subdir) |
| os.link(template, os.path.join(subdir, 'BUILD.gn')) |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |