Index: tools/licenses.py |
diff --git a/tools/licenses.py b/tools/licenses.py |
index 0da272cc874aecf95cebedfad98b73a8377b2518..13f24d1f98b55d7ff5ad238541eb4b93ca21e691 100755 |
--- a/tools/licenses.py |
+++ b/tools/licenses.py |
@@ -18,8 +18,10 @@ Commands: |
import argparse |
import cgi |
import os |
+import shutil |
import subprocess |
import sys |
+import tempfile |
# TODO(agrieve): Move build_utils.WriteDepFile into a non-android directory. |
_REPOSITORY_ROOT = os.path.dirname(os.path.dirname(__file__)) |
@@ -482,9 +484,22 @@ def FindThirdPartyDeps(gn_out_dir, gn_target): |
if not gn_out_dir: |
raise RuntimeError("--gn-out-dir is required if --gn-target is used.") |
- gn_deps = subprocess.check_output([_GnBinary(), "desc", gn_out_dir, |
- gn_target, |
- "deps", "--as=buildfile", "--all"]) |
+ # Generate gn project in temp directory and use it to find dependencies. |
+ # Current gn directory cannot be used when we run this script in a gn action |
+ # rule, because gn doesn't allow recursive invocations due to potential side |
+ # effects. |
+ tmp_dir = None |
+ try: |
+ tmp_dir = tempfile.mkdtemp(dir = gn_out_dir) |
+ shutil.copy(os.path.join(gn_out_dir, "args.gn"), tmp_dir) |
+ subprocess.check_output([_GnBinary(), "gen", tmp_dir]) |
+ gn_deps = subprocess.check_output([ |
+ _GnBinary(), "desc", tmp_dir, gn_target, |
+ "deps", "--as=buildfile", "--all"]) |
+ finally: |
+ if tmp_dir and os.path.exists(tmp_dir): |
+ shutil.rmtree(tmp_dir) |
+ |
third_party_deps = set() |
for build_dep in gn_deps.split(): |
if ("third_party" in build_dep and |
@@ -614,6 +629,53 @@ def GenerateCredits( |
return True |
+def _ReadFile(path): |
+ """Reads a file from disk. |
+ Args: |
+ path: The path of the file to read, relative to the root of the |
+ repository. |
+ Returns: |
+ The contents of the file as a string. |
+ """ |
+ with open(os.path.join(_REPOSITORY_ROOT, path), 'rb') as f: |
+ return f.read() |
+ |
+ |
+def GenerateLicenseFile(output_file, gn_out_dir, gn_target): |
+ """Generate a plain-text LICENSE file which can be used when you ship a part |
+ of Chromium code (specified by gn_target) as a stand-alone library |
+ (e.g., //ios/web_view). |
+ |
+ The LICENSE file contains licenses of both Chromium and third-party |
+ libraries which gn_target depends on. """ |
+ |
+ third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target) |
+ |
+ # Start with Chromium's LICENSE file. |
+ content = [_ReadFile('LICENSE')] |
+ |
+ # Add necessary third_party. |
+ for directory in sorted(third_party_dirs): |
+ metadata = ParseDir( |
+ directory, _REPOSITORY_ROOT, require_license_file=True) |
+ content.append('-' * 20) |
+ content.append(directory.split('/')[-1]) |
+ content.append('-' * 20) |
+ license_file = metadata['License File'] |
+ if license_file and license_file != NOT_SHIPPED: |
+ content.append(_ReadFile(license_file)) |
+ |
+ content_text = '\n'.join(content) |
+ |
+ if output_file: |
+ with open(output_file, 'w') as output: |
+ output.write(content_text) |
+ else: |
+ print content_text |
+ |
+ return True |
+ |
+ |
def main(): |
parser = argparse.ArgumentParser() |
parser.add_argument('--file-template', |
@@ -626,7 +688,8 @@ def main(): |
help='GN output directory for scanning dependencies.') |
parser.add_argument('--gn-target', |
help='GN target to scan for dependencies.') |
- parser.add_argument('command', choices=['help', 'scan', 'credits']) |
+ parser.add_argument('command', |
+ choices=['help', 'scan', 'credits', 'license_file']) |
parser.add_argument('output_file', nargs='?') |
build_utils.AddDepfileOption(parser) |
args = parser.parse_args() |
@@ -639,6 +702,10 @@ def main(): |
args.output_file, args.target_os, |
args.gn_out_dir, args.gn_target, args.depfile): |
return 1 |
+ elif args.command == 'license_file': |
+ if not GenerateLicenseFile( |
+ args.output_file, args.gn_out_dir, args.gn_target): |
+ return 1 |
else: |
print __doc__ |
return 1 |