mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
298 lines
9.0 KiB
Python
Executable File
298 lines
9.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2013 The Flutter Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Utility for dart_pkg and dart_pkg_app rules"""
|
|
|
|
import argparse
|
|
import errno
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
USE_LINKS = sys.platform != "win32"
|
|
|
|
DART_ANALYZE = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
"dart_analyze.py")
|
|
|
|
def dart_filter(path):
|
|
if os.path.isdir(path):
|
|
return True
|
|
_, ext = os.path.splitext(path)
|
|
# .dart includes '.mojom.dart'
|
|
return ext == '.dart'
|
|
|
|
|
|
def ensure_dir_exists(path):
|
|
abspath = os.path.abspath(path)
|
|
if not os.path.exists(abspath):
|
|
os.makedirs(abspath)
|
|
|
|
|
|
def has_pubspec_yaml(paths):
|
|
for path in paths:
|
|
_, filename = os.path.split(path)
|
|
if 'pubspec.yaml' == filename:
|
|
return True
|
|
return False
|
|
|
|
|
|
def link(from_root, to_root):
|
|
ensure_dir_exists(os.path.dirname(to_root))
|
|
try:
|
|
os.unlink(to_root)
|
|
except OSError as e:
|
|
if e.errno == errno.ENOENT:
|
|
pass
|
|
|
|
try:
|
|
os.symlink(from_root, to_root)
|
|
except OSError as e:
|
|
if e.errno == errno.EEXIST:
|
|
pass
|
|
|
|
|
|
def copy(from_root, to_root, filter_func=None):
|
|
if not os.path.exists(from_root):
|
|
return
|
|
if os.path.isfile(from_root):
|
|
ensure_dir_exists(os.path.dirname(to_root))
|
|
shutil.copy(from_root, to_root)
|
|
return
|
|
|
|
ensure_dir_exists(to_root)
|
|
|
|
for root, dirs, files in os.walk(from_root):
|
|
# filter_func expects paths not names, so wrap it to make them absolute.
|
|
wrapped_filter = None
|
|
if filter_func:
|
|
wrapped_filter = lambda name: filter_func(os.path.join(root, name))
|
|
|
|
for name in filter(wrapped_filter, files):
|
|
from_path = os.path.join(root, name)
|
|
root_rel_path = os.path.relpath(from_path, from_root)
|
|
to_path = os.path.join(to_root, root_rel_path)
|
|
to_dir = os.path.dirname(to_path)
|
|
if not os.path.exists(to_dir):
|
|
os.makedirs(to_dir)
|
|
shutil.copy(from_path, to_path)
|
|
|
|
dirs[:] = filter(wrapped_filter, dirs)
|
|
|
|
|
|
def copy_or_link(from_root, to_root, filter_func=None):
|
|
if USE_LINKS:
|
|
link(from_root, to_root)
|
|
else:
|
|
copy(from_root, to_root, filter_func)
|
|
|
|
|
|
def link_if_possible(from_root, to_root):
|
|
if USE_LINKS:
|
|
link(from_root, to_root)
|
|
|
|
|
|
def remove_if_exists(path):
|
|
try:
|
|
os.remove(path)
|
|
except OSError as e:
|
|
if e.errno != errno.ENOENT:
|
|
raise
|
|
|
|
|
|
def list_files(from_root, filter_func=None):
|
|
file_list = []
|
|
for root, dirs, files in os.walk(from_root):
|
|
# filter_func expects paths not names, so wrap it to make them absolute.
|
|
wrapped_filter = None
|
|
if filter_func:
|
|
wrapped_filter = lambda name: filter_func(os.path.join(root, name))
|
|
for name in filter(wrapped_filter, files):
|
|
path = os.path.join(root, name)
|
|
file_list.append(path)
|
|
dirs[:] = filter(wrapped_filter, dirs)
|
|
return file_list
|
|
|
|
|
|
def remove_broken_symlink(path):
|
|
if not USE_LINKS:
|
|
return
|
|
try:
|
|
link_path = os.readlink(path)
|
|
except OSError as e:
|
|
# Path was not a symlink.
|
|
if e.errno == errno.EINVAL:
|
|
pass
|
|
else:
|
|
if not os.path.exists(link_path):
|
|
remove_if_exists(path)
|
|
|
|
|
|
def remove_broken_symlinks(root_dir):
|
|
if not USE_LINKS:
|
|
return
|
|
for current_dir, _, child_files in os.walk(root_dir):
|
|
for filename in child_files:
|
|
path = os.path.join(current_dir, filename)
|
|
remove_broken_symlink(path)
|
|
|
|
|
|
def analyze_entrypoints(dart_sdk, package_root, entrypoints):
|
|
cmd = [ "python", DART_ANALYZE ]
|
|
cmd.append("--dart-sdk")
|
|
cmd.append(dart_sdk)
|
|
cmd.append("--entrypoints")
|
|
cmd.extend(entrypoints)
|
|
cmd.append("--package-root")
|
|
cmd.append(package_root)
|
|
cmd.append("--no-hints")
|
|
try:
|
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
except subprocess.CalledProcessError as e:
|
|
print('Failed analyzing %s' % entrypoints)
|
|
print(e.output)
|
|
return e.returncode
|
|
return 0
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='Generate a dart-pkg')
|
|
parser.add_argument('--dart-sdk',
|
|
action='store',
|
|
metavar='dart_sdk',
|
|
help='Path to the Dart SDK.')
|
|
parser.add_argument('--package-name',
|
|
action='store',
|
|
metavar='package_name',
|
|
help='Name of package',
|
|
required=True)
|
|
parser.add_argument('--pkg-directory',
|
|
metavar='pkg_directory',
|
|
help='Directory where dart_pkg should go',
|
|
required=True)
|
|
parser.add_argument('--package-root',
|
|
metavar='package_root',
|
|
help='packages/ directory',
|
|
required=True)
|
|
parser.add_argument('--stamp-file',
|
|
metavar='stamp_file',
|
|
help='timestamp file',
|
|
required=True)
|
|
parser.add_argument('--entries-file',
|
|
metavar='entries_file',
|
|
help='script entries file',
|
|
required=True)
|
|
parser.add_argument('--package-sources',
|
|
metavar='package_sources',
|
|
help='Package sources',
|
|
nargs='+')
|
|
parser.add_argument('--package-entrypoints',
|
|
metavar='package_entrypoints',
|
|
help='Package entry points for analyzer',
|
|
nargs='*',
|
|
default=[])
|
|
parser.add_argument('--sdk-ext-directories',
|
|
metavar='sdk_ext_directories',
|
|
help='Directory containing .dart sources',
|
|
nargs='*',
|
|
default=[])
|
|
parser.add_argument('--sdk-ext-files',
|
|
metavar='sdk_ext_files',
|
|
help='List of .dart files that are part of of sdk_ext.',
|
|
nargs='*',
|
|
default=[])
|
|
parser.add_argument('--sdk-ext-mappings',
|
|
metavar='sdk_ext_mappings',
|
|
help='Mappings for SDK extension libraries.',
|
|
nargs='*',
|
|
default=[])
|
|
parser.add_argument('--read_only',
|
|
action='store_true',
|
|
dest='read_only',
|
|
help='Package is a read only package.',
|
|
default=False)
|
|
args = parser.parse_args()
|
|
|
|
# We must have a pubspec.yaml.
|
|
assert has_pubspec_yaml(args.package_sources)
|
|
|
|
target_dir = os.path.join(args.pkg_directory, args.package_name)
|
|
target_packages_dir = os.path.join(target_dir, 'packages')
|
|
lib_path = os.path.join(target_dir, "lib")
|
|
ensure_dir_exists(lib_path)
|
|
|
|
mappings = {}
|
|
for mapping in args.sdk_ext_mappings:
|
|
library, path = mapping.split(',', 1)
|
|
mappings[library] = '../sdk_ext/%s' % path
|
|
|
|
sdkext_path = os.path.join(lib_path, '_sdkext')
|
|
if mappings:
|
|
with open(sdkext_path, 'w') as stream:
|
|
json.dump(mappings, stream, sort_keys=True,
|
|
indent=2, separators=(',', ': '))
|
|
else:
|
|
remove_if_exists(sdkext_path)
|
|
|
|
# Copy or symlink package sources into pkg directory.
|
|
common_source_prefix = os.path.dirname(os.path.commonprefix(
|
|
args.package_sources))
|
|
for source in args.package_sources:
|
|
relative_source = os.path.relpath(source, common_source_prefix)
|
|
target = os.path.join(target_dir, relative_source)
|
|
copy_or_link(source, target)
|
|
|
|
entrypoint_targets = []
|
|
for source in args.package_entrypoints:
|
|
relative_source = os.path.relpath(source, common_source_prefix)
|
|
target = os.path.join(target_dir, relative_source)
|
|
copy_or_link(source, target)
|
|
entrypoint_targets.append(target)
|
|
|
|
# Copy sdk-ext sources into pkg directory
|
|
sdk_ext_dir = os.path.join(target_dir, 'sdk_ext')
|
|
for directory in args.sdk_ext_directories:
|
|
sdk_ext_sources = list_files(directory, dart_filter)
|
|
common_prefix = os.path.commonprefix(sdk_ext_sources)
|
|
for source in sdk_ext_sources:
|
|
relative_source = os.path.relpath(source, common_prefix)
|
|
target = os.path.join(sdk_ext_dir, relative_source)
|
|
copy_or_link(source, target)
|
|
|
|
common_source_prefix = os.path.dirname(os.path.commonprefix(
|
|
args.sdk_ext_files))
|
|
for source in args.sdk_ext_files:
|
|
relative_source = os.path.relpath(source, common_source_prefix)
|
|
target = os.path.join(sdk_ext_dir, relative_source)
|
|
copy_or_link(source, target)
|
|
|
|
# Symlink packages/
|
|
package_path = os.path.join(args.package_root, args.package_name)
|
|
copy_or_link(lib_path, package_path)
|
|
|
|
# Link dart-pkg/$package/packages to dart-pkg/packages
|
|
link_if_possible(args.package_root, target_packages_dir)
|
|
|
|
# Remove any broken symlinks in target_dir and package root.
|
|
remove_broken_symlinks(target_dir)
|
|
remove_broken_symlinks(args.package_root)
|
|
|
|
# If any entrypoints are defined, write them to disk so that the analyzer
|
|
# test can find them.
|
|
with open(args.entries_file, 'w') as f:
|
|
for entrypoint in entrypoint_targets:
|
|
f.write(entrypoint + '\n')
|
|
|
|
# Write stamp file.
|
|
with open(args.stamp_file, 'w'):
|
|
pass
|
|
|
|
return 0
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|