blob: c548ac8f2b2d7858d3991713a133c9e61623f5a9 [file] [log] [blame]
[email protected]cb155a82011-11-29 17:25:341#!/usr/bin/env python
[email protected]9aaa0a52012-01-31 18:42:412# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]957082a02010-03-18 21:55:243# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
[email protected]54ce7262010-04-17 00:02:556"""Utility for checking and processing licensing information in third_party
[email protected]957082a02010-03-18 21:55:247directories.
[email protected]54ce7262010-04-17 00:02:558
9Usage: licenses.py <command>
10
11Commands:
12 scan scan third_party directories, verifying that we have licensing info
13 credits generate about:credits on stdout
14
15(You can also import this as a module.)
[email protected]957082a02010-03-18 21:55:2416"""
Eli Ribble63a757b2019-07-15 18:28:4217from __future__ import print_function
[email protected]957082a02010-03-18 21:55:2418
jamiewalch6275de52015-06-17 23:25:3419import argparse
Eli Ribble63a757b2019-07-15 18:28:4220import codecs
Nicolas Dossou-gbeteb1b678fa2018-01-31 14:38:0521import json
[email protected]957082a02010-03-18 21:55:2422import os
ichikawacc4ae12d2017-04-11 05:03:1623import shutil
ichikawabaea0822017-04-19 05:24:0224import re
lambroslambrou04a2ae1702017-02-28 19:07:5525import subprocess
[email protected]54ce7262010-04-17 00:02:5526import sys
ichikawacc4ae12d2017-04-11 05:03:1627import tempfile
[email protected]957082a02010-03-18 21:55:2428
Raul Tambre3bc99332019-10-15 06:19:3929if sys.version_info.major == 2:
30 import cgi as html
31else:
32 import html
33
agrievebe961802017-02-15 18:48:2034# TODO(agrieve): Move build_utils.WriteDepFile into a non-android directory.
Hiroshi Ichikawa3c5e1dfb2018-01-19 08:40:1135_REPOSITORY_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
Raul Tambre33ead3322019-04-09 15:42:5336sys.path.insert(0, os.path.join(_REPOSITORY_ROOT, 'build/android/gyp'))
37from util import build_utils
agrievebe961802017-02-15 18:48:2038
39
[email protected]e64b3d82010-03-19 00:46:1840# Paths from the root of the tree to directories to skip.
41PRUNE_PATHS = set([
[email protected]16575432012-08-07 11:21:0642 # Placeholder directory only, not third-party code.
[email protected]946cbf752011-01-16 06:07:2943 os.path.join('third_party','adobe'),
[email protected]25395492010-04-15 15:29:4444
Yun Liuf483471c2019-07-02 02:44:5545 # Will remove it once converted private sdk using cipd.
46 os.path.join('third_party','android_tools_internal'),
47
[email protected]2f5dc572012-10-06 18:44:4948 # Build files only, not third-party code.
49 os.path.join('third_party','widevine'),
50
[email protected]f52832292010-12-15 00:43:1651 # Only binaries, used during development.
[email protected]946cbf752011-01-16 06:07:2952 os.path.join('third_party','valgrind'),
[email protected]f52832292010-12-15 00:43:1653
[email protected]946cbf752011-01-16 06:07:2954 # Used for development and test, not in the shipping product.
[email protected]26688b86e2014-06-19 13:14:2655 os.path.join('build','secondary'),
[email protected]7472d1e02012-11-29 23:05:3756 os.path.join('third_party','bison'),
[email protected]c48b9d72014-06-10 21:06:5957 os.path.join('third_party','blanketjs'),
agrievec11f4b9a2016-05-03 17:38:4958 os.path.join('third_party','chromite'),
[email protected]946cbf752011-01-16 06:07:2959 os.path.join('third_party','cygwin'),
mnaganov8754c6f92015-05-27 15:44:5860 os.path.join('third_party','gles2_conform'),
[email protected]7472d1e02012-11-29 23:05:3761 os.path.join('third_party','gnu_binutils'),
[email protected]b07806c12012-02-03 22:44:5962 os.path.join('third_party','gold'),
[email protected]7472d1e02012-11-29 23:05:3763 os.path.join('third_party','gperf'),
[email protected]946cbf752011-01-16 06:07:2964 os.path.join('third_party','lighttpd'),
[email protected]7472d1e02012-11-29 23:05:3765 os.path.join('third_party','llvm'),
66 os.path.join('third_party','llvm-build'),
[email protected]946cbf752011-01-16 06:07:2967 os.path.join('third_party','mingw-w64'),
[email protected]7472d1e02012-11-29 23:05:3768 os.path.join('third_party','nacl_sdk_binaries'),
[email protected]946cbf752011-01-16 06:07:2969 os.path.join('third_party','pefile'),
[email protected]7472d1e02012-11-29 23:05:3770 os.path.join('third_party','perl'),
71 os.path.join('third_party','psyco_win32'),
agrievec11f4b9a2016-05-03 17:38:4972 os.path.join('third_party','pyelftools'),
[email protected]7472d1e02012-11-29 23:05:3773 os.path.join('third_party','pylib'),
[email protected]51e3e3d2012-08-21 02:27:4474 os.path.join('third_party','pywebsocket'),
[email protected]7472d1e02012-11-29 23:05:3775 os.path.join('third_party','syzygy'),
76
raphael.kubo.da.costa982d27b2016-11-01 07:39:5277 # Chromium code.
[email protected]10d8ac32013-10-31 13:34:3178 os.path.join('tools', 'swarming_client'),
[email protected]946cbf752011-01-16 06:07:2979
[email protected]fe33b982011-02-05 04:10:0580 # Stuff pulled in from chrome-internal for official builds/tools.
81 os.path.join('third_party', 'clear_cache'),
82 os.path.join('third_party', 'gnu'),
83 os.path.join('third_party', 'googlemac'),
84 os.path.join('third_party', 'pcre'),
85 os.path.join('third_party', 'psutils'),
86 os.path.join('third_party', 'sawbuck'),
mnaganov8754c6f92015-05-27 15:44:5887 # See crbug.com/350472
88 os.path.join('chrome', 'browser', 'resources', 'chromeos', 'quickoffice'),
89 # Chrome for Android proprietary code.
90 os.path.join('clank'),
[email protected]fe33b982011-02-05 04:10:0591
[email protected]946cbf752011-01-16 06:07:2992 # Redistribution does not require attribution in documentation.
93 os.path.join('third_party','directxsdk'),
mnaganov8754c6f92015-05-27 15:44:5894
95 # For testing only, presents on some bots.
96 os.path.join('isolate_deps_dir'),
hichris1236175da82016-01-13 12:37:3097
Raphael Kubo da Costa14835ad2018-01-29 19:48:2998 # Mock test data.
99 os.path.join('tools', 'binary_size', 'libsupersize', 'testdata'),
100
hichris1236175da82016-01-13 12:37:30101 # Overrides some WebRTC files, same license. Skip this one.
102 os.path.join('third_party', 'webrtc_overrides'),
[email protected]e64b3d82010-03-19 00:46:18103])
104
105# Directories we don't scan through.
[email protected]d065fb72013-05-14 23:17:05106VCS_METADATA_DIRS = ('.svn', '.git')
Andrew Grieve914ce0a72020-06-26 16:02:45107PRUNE_DIRS = VCS_METADATA_DIRS + ('layout_tests', ) # lots of subdirs
[email protected]957082a02010-03-18 21:55:24108
Nicolas Dossou-gbeteb1b678fa2018-01-31 14:38:05109# A third_party directory can define this file, containing a list of
Raphael Kubo da Costaa984c002019-06-12 14:09:17110# subdirectories to process in addition to itself. Intended for directories
111# that contain multiple others as transitive dependencies.
Nicolas Dossou-gbeteb1b678fa2018-01-31 14:38:05112ADDITIONAL_PATHS_FILENAME = 'additional_readme_paths.json'
113
Justin DeWitte8d65802020-06-26 00:43:45114# A list of paths that contain license information but that would otherwise
115# not be included. Possible reasons include:
116# - Third party directories in //clank which are considered to be Google-owned
117# - Directories that are directly checked out from upstream, and thus
118# don't have a README.chromium
119# - Directories that contain example code, or build tooling.
120# - Nested third_party code inside other third_party libraries.
[email protected]e32bfad2010-10-22 01:34:32121ADDITIONAL_PATHS = (
[email protected]e4598592012-08-09 15:47:21122 os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'),
123 os.path.join('chrome', 'test', 'chromeos', 'autotest'),
124 os.path.join('chrome', 'test', 'data'),
Justin DeWitte8d65802020-06-26 00:43:45125 os.path.join('clank', 'third_party', 'elements'),
[email protected]e4598592012-08-09 15:47:21126 os.path.join('native_client'),
[email protected]e4598592012-08-09 15:47:21127 os.path.join('testing', 'gmock'),
piman5623da42016-07-21 03:03:15128 os.path.join('testing', 'gtest'),
David Benjamin1f13273c2018-01-11 15:14:08129 os.path.join('third_party', 'boringssl', 'src', 'third_party', 'fiat'),
[email protected]e4598592012-08-09 15:47:21130 os.path.join('tools', 'gyp'),
131 os.path.join('tools', 'page_cycler', 'acid3'),
[email protected]f9682112013-08-12 05:01:49132 os.path.join('url', 'third_party', 'mozilla'),
[email protected]e4598592012-08-09 15:47:21133 os.path.join('v8'),
yangguo6459a752015-05-07 14:47:54134 # Fake directories to include the strongtalk and fdlibm licenses.
[email protected]9aaa0a52012-01-31 18:42:41135 os.path.join('v8', 'strongtalk'),
yangguo6459a752015-05-07 14:47:54136 os.path.join('v8', 'fdlibm'),
[email protected]e32bfad2010-10-22 01:34:32137)
138
139
[email protected]e657bfc2010-03-22 23:56:19140# Directories where we check out directly from upstream, and therefore
141# can't provide a README.chromium. Please prefer a README.chromium
142# wherever possible.
143SPECIAL_CASES = {
[email protected]e4598592012-08-09 15:47:21144 os.path.join('native_client'): {
145 "Name": "native client",
146 "URL": "http://code.google.com/p/nativeclient",
147 "License": "BSD",
148 },
[email protected]e4598592012-08-09 15:47:21149 os.path.join('testing', 'gmock'): {
150 "Name": "gmock",
151 "URL": "http://code.google.com/p/googlemock",
152 "License": "BSD",
[email protected]7472d1e02012-11-29 23:05:37153 "License File": "NOT_SHIPPED",
[email protected]e4598592012-08-09 15:47:21154 },
piman5623da42016-07-21 03:03:15155 os.path.join('testing', 'gtest'): {
[email protected]e4598592012-08-09 15:47:21156 "Name": "gtest",
157 "URL": "http://code.google.com/p/googletest",
158 "License": "BSD",
[email protected]7472d1e02012-11-29 23:05:37159 "License File": "NOT_SHIPPED",
[email protected]e4598592012-08-09 15:47:21160 },
[email protected]878cbc72010-05-03 14:22:28161 os.path.join('third_party', 'angle'): {
[email protected]dd4f0602010-04-29 21:50:58162 "Name": "Almost Native Graphics Layer Engine",
163 "URL": "http://code.google.com/p/angleproject/",
[email protected]31eac5b2012-08-01 15:50:29164 "License": "BSD",
[email protected]dd4f0602010-04-29 21:50:58165 },
[email protected]abb1b862012-07-27 01:52:11166 os.path.join('third_party', 'cros_system_api'): {
167 "Name": "Chromium OS system API",
168 "URL": "http://www.chromium.org/chromium-os",
169 "License": "BSD",
170 # Absolute path here is resolved as relative to the source root.
171 "License File": "/LICENSE.chromium_os",
172 },
Stephen Roe108ce9d2020-11-20 22:59:06173 os.path.join('third_party', 'devtools-frontend'): {
174 # TODO(crbug.com/1151057): Remove this special case when issue is fixed.
175 "Name": "Devtools-Frontend",
176 "URL": "https://chromium.googlesource.com/devtools/devtools-frontend",
177 "License": "BSD",
178 "License File": "src/LICENSE",
179 },
[email protected]07c75d52010-10-05 19:02:35180 os.path.join('third_party', 'lss'): {
181 "Name": "linux-syscall-support",
[email protected]7472d1e02012-11-29 23:05:37182 "URL": "http://code.google.com/p/linux-syscall-support/",
[email protected]e4598592012-08-09 15:47:21183 "License": "BSD",
184 "License File": "/LICENSE",
[email protected]07c75d52010-10-05 19:02:35185 },
Stephen Roe108ce9d2020-11-20 22:59:06186 os.path.join('third_party', 'openscreen', 'src', 'third_party', 'abseil'): {
187 "Name": "abseil",
188 "URL": "https://github.com/abseil/abseil-cpp/",
189 "License": "Apache 2.0",
190 "License File": "/third_party/abseil-cpp/LICENSE",
191 },
192 os.path.join('third_party', 'openscreen', 'src', 'third_party',
193 'boringssl'):
194 {
195 "Name": "BoringSSL",
196 "URL": "https://boringssl.googlesource.com/boringssl/",
197 "License": "BSDish",
198 "License File": "/third_party/boringssl/src/LICENSE",
199 },
200 os.path.join('third_party', 'openscreen', 'src', 'third_party', 'jsoncpp'):
201 {
202 "Name": "jsoncpp",
203 "URL": "https://github.com/open-source-parsers/jsoncpp",
204 "License": "MIT",
205 "License File": "/third_party/jsoncpp/LICENSE",
206 },
207 os.path.join('third_party', 'openscreen', 'src', 'third_party', 'mozilla'):
208 {
209 "Name": "mozilla",
210 "URL": "https://github.com/mozilla",
211 "License": "MPL 1.1/GPL 2.0/LGPL 2.1",
212 "License File": "LICENSE.txt",
213 },
[email protected]21aa33682014-05-19 19:47:36214 os.path.join('third_party', 'pdfium'): {
[email protected]d6a2e88f12014-05-19 19:27:03215 "Name": "PDFium",
216 "URL": "http://code.google.com/p/pdfium/",
217 "License": "BSD",
218 },
[email protected]c4826852010-09-10 21:32:40219 os.path.join('third_party', 'ppapi'): {
220 "Name": "ppapi",
221 "URL": "http://code.google.com/p/ppapi/",
222 },
[email protected]abb1b862012-07-27 01:52:11223 os.path.join('third_party', 'scons-2.0.1'): {
224 "Name": "scons-2.0.1",
225 "URL": "http://www.scons.org",
226 "License": "MIT",
[email protected]7472d1e02012-11-29 23:05:37227 "License File": "NOT_SHIPPED",
[email protected]25395492010-04-15 15:29:44228 },
sullivan0cf87672015-08-04 17:10:32229 os.path.join('third_party', 'catapult'): {
230 "Name": "catapult",
231 "URL": "https://github.com/catapult-project/catapult",
[email protected]abb1b862012-07-27 01:52:11232 "License": "BSD",
[email protected]7472d1e02012-11-29 23:05:37233 "License File": "NOT_SHIPPED",
[email protected]946cbf752011-01-16 06:07:29234 },
Stephen Roe108ce9d2020-11-20 22:59:06235 os.path.join('third_party', 'crashpad', 'crashpad', 'third_party', 'lss'): {
Joshua Peraza8ca9deb2019-04-10 01:28:07236 "Name": "linux-syscall-support",
237 "URL": "https://chromium.googlesource.com/linux-syscall-support/",
238 "License": "BSD",
239 "License File": "NOT_SHIPPED",
240 },
241 os.path.join('third_party', 'crashpad', 'crashpad', 'third_party',
Stephen Roe108ce9d2020-11-20 22:59:06242 'mini_chromium'):
243 {
Joshua Perazaf076c742018-12-03 03:41:54244 "Name": "mini_chromium",
245 "URL": "https://chromium.googlesource.com/chromium/mini_chromium/",
246 "License": "BSD",
247 "License File": "NOT_SHIPPED",
248 },
Scott Grahamd16fde52019-03-15 01:08:55249 os.path.join('third_party', 'crashpad', 'crashpad', 'third_party', 'xnu'): {
250 "Name": "xnu",
251 "URL": "https://opensource.apple.com/source/xnu/",
252 "License": "Apple Public Source License 2.0",
253 "License File": "APPLE_LICENSE",
254 },
Stephen Roe108ce9d2020-11-20 22:59:06255 os.path.join('third_party', 'crashpad', 'crashpad', 'third_party', 'zlib'):
256 {
Joshua Perazaf076c742018-12-03 03:41:54257 "Name": "zlib",
258 "URL": "https://zlib.net/",
259 "License": "zlib",
260 "License File": "NOT_SHIPPED",
261 },
[email protected]38acf472012-03-19 13:15:36262 os.path.join('third_party', 'v8-i18n'): {
263 "Name": "Internationalization Library for v8",
264 "URL": "http://code.google.com/p/v8-i18n/",
[email protected]484de3a2012-11-12 13:43:06265 "License": "Apache 2.0",
[email protected]38acf472012-03-19 13:15:36266 },
Kevin Marshall8f688b5f2018-08-10 16:56:59267 os.path.join('third_party', 'blink'): {
Kent Tamura65f56d32018-11-27 05:20:49268 # about:credits doesn't show "Blink" but "WebKit".
269 # Blink is a fork of WebKit, and Chromium project has maintained it
270 # since the fork. about:credits needs to mention the code before
271 # the fork.
[email protected]abb1b862012-07-27 01:52:11272 "Name": "WebKit",
273 "URL": "http://webkit.org/",
kai.koehne70fdcea2017-01-17 12:22:47274 "License": "BSD and LGPL v2 and LGPL v2.1",
[email protected]abb1b862012-07-27 01:52:11275 # Absolute path here is resolved as relative to the source root.
Kent Tamura65f56d32018-11-27 05:20:49276 "License File": "/third_party/blink/LICENSE_FOR_ABOUT_CREDITS",
[email protected]abb1b862012-07-27 01:52:11277 },
[email protected]506a85f2014-05-02 19:21:28278 os.path.join('third_party', 'webpagereplay'): {
[email protected]abb1b862012-07-27 01:52:11279 "Name": "webpagereplay",
280 "URL": "http://code.google.com/p/web-page-replay",
281 "License": "Apache 2.0",
[email protected]7472d1e02012-11-29 23:05:37282 "License File": "NOT_SHIPPED",
[email protected]abb1b862012-07-27 01:52:11283 },
[email protected]e4598592012-08-09 15:47:21284 os.path.join('tools', 'gyp'): {
285 "Name": "gyp",
286 "URL": "http://code.google.com/p/gyp",
287 "License": "BSD",
[email protected]7472d1e02012-11-29 23:05:37288 "License File": "NOT_SHIPPED",
[email protected]e4598592012-08-09 15:47:21289 },
290 os.path.join('v8'): {
[email protected]2d765fc22012-08-16 13:58:28291 "Name": "V8 JavaScript Engine",
[email protected]e4598592012-08-09 15:47:21292 "URL": "http://code.google.com/p/v8",
293 "License": "BSD",
294 },
[email protected]9aaa0a52012-01-31 18:42:41295 os.path.join('v8', 'strongtalk'): {
296 "Name": "Strongtalk",
297 "URL": "http://www.strongtalk.org/",
[email protected]31eac5b2012-08-01 15:50:29298 "License": "BSD",
[email protected]abb1b862012-07-27 01:52:11299 # Absolute path here is resolved as relative to the source root.
[email protected]9aaa0a52012-01-31 18:42:41300 "License File": "/v8/LICENSE.strongtalk",
301 },
yangguo6459a752015-05-07 14:47:54302 os.path.join('v8', 'fdlibm'): {
[email protected]0bdf8032014-08-05 13:07:07303 "Name": "fdlibm",
304 "URL": "http://www.netlib.org/fdlibm/",
305 "License": "Freely Distributable",
306 # Absolute path here is resolved as relative to the source root.
Stephen Roe108ce9d2020-11-20 22:59:06307 "License File": "/v8/LICENSE.fdlibm",
308 "License Android Compatible": "yes",
[email protected]0bdf8032014-08-05 13:07:07309 },
kbra348ef0b2014-11-13 01:50:17310 os.path.join('third_party', 'khronos_glcts'): {
311 # These sources are not shipped, are not public, and it isn't
312 # clear why they're tripping the license check.
313 "Name": "khronos_glcts",
314 "URL": "http://no-public-url",
315 "License": "Khronos",
316 "License File": "NOT_SHIPPED",
317 },
sergiyb9bf925472015-02-06 17:58:17318 os.path.join('tools', 'telemetry', 'third_party', 'gsutil'): {
319 "Name": "gsutil",
320 "URL": "https://cloud.google.com/storage/docs/gsutil",
321 "License": "Apache 2.0",
322 "License File": "NOT_SHIPPED",
323 },
capnd37d6682016-08-15 21:57:02324 os.path.join('third_party', 'swiftshader'): {
325 "Name": "SwiftShader",
326 "URL": "https://swiftshader.googlesource.com/SwiftShader",
327 "License": "Apache 2.0 and compatible licenses",
328 "License Android Compatible": "yes",
329 "License File": "/third_party/swiftshader/LICENSE.txt",
330 },
[email protected]e657bfc2010-03-22 23:56:19331}
332
[email protected]e4598592012-08-09 15:47:21333# Special value for 'License File' field used to indicate that the license file
334# should not be used in about:credits.
335NOT_SHIPPED = "NOT_SHIPPED"
336
sdefresned13d15b2016-02-17 18:06:54337# Paths for libraries that we have checked are not shipped on iOS. These are
338# left out of the licenses file primarily because we don't want to cause a
339# firedrill due to someone thinking that Chrome for iOS is using LGPL code
340# when it isn't.
341# This is a temporary hack; the real solution is crbug.com/178215
342KNOWN_NON_IOS_LIBRARIES = set([
343 os.path.join('base', 'third_party', 'symbolize'),
344 os.path.join('base', 'third_party', 'xdg_mime'),
345 os.path.join('base', 'third_party', 'xdg_user_dirs'),
Misha Efimov45ca19d2019-03-21 15:53:15346 os.path.join('buildtools', 'third_party', 'libc++'),
347 os.path.join('buildtools', 'third_party', 'libc++abi'),
sdefresned13d15b2016-02-17 18:06:54348 os.path.join('chrome', 'installer', 'mac', 'third_party', 'bsdiff'),
349 os.path.join('chrome', 'installer', 'mac', 'third_party', 'xz'),
350 os.path.join('chrome', 'test', 'data', 'third_party', 'kraken'),
351 os.path.join('chrome', 'test', 'data', 'third_party', 'spaceport'),
sdefresned13d15b2016-02-17 18:06:54352 os.path.join('chrome', 'third_party', 'mozilla_security_manager'),
sdefresned13d15b2016-02-17 18:06:54353 os.path.join('third_party', 'angle'),
354 os.path.join('third_party', 'apple_apsl'),
355 os.path.join('third_party', 'apple_sample_code'),
356 os.path.join('third_party', 'ashmem'),
Kent Tamura1adafee2018-03-07 10:12:08357 os.path.join('third_party', 'blink'),
sdefresned13d15b2016-02-17 18:06:54358 os.path.join('third_party', 'bspatch'),
sdefresned13d15b2016-02-17 18:06:54359 os.path.join('third_party', 'cld'),
sdefresned13d15b2016-02-17 18:06:54360 os.path.join('third_party', 'flot'),
361 os.path.join('third_party', 'gtk+'),
362 os.path.join('third_party', 'iaccessible2'),
363 os.path.join('third_party', 'iccjpeg'),
364 os.path.join('third_party', 'isimpledom'),
365 os.path.join('third_party', 'jsoncpp'),
366 os.path.join('third_party', 'khronos'),
367 os.path.join('third_party', 'libXNVCtrl'),
368 os.path.join('third_party', 'libevent'),
369 os.path.join('third_party', 'libjpeg'),
sdefresned13d15b2016-02-17 18:06:54370 os.path.join('third_party', 'libusb'),
sdefresned13d15b2016-02-17 18:06:54371 os.path.join('third_party', 'libxslt'),
372 os.path.join('third_party', 'lss'),
373 os.path.join('third_party', 'lzma_sdk'),
374 os.path.join('third_party', 'mesa'),
sdefresned13d15b2016-02-17 18:06:54375 os.path.join('third_party', 'motemplate'),
376 os.path.join('third_party', 'mozc'),
377 os.path.join('third_party', 'mozilla'),
378 os.path.join('third_party', 'npapi'),
379 os.path.join('third_party', 'ots'),
David Jean78ac18c2020-03-27 10:39:38380 os.path.join('third_party', 'perfetto'),
sdefresned13d15b2016-02-17 18:06:54381 os.path.join('third_party', 'ppapi'),
382 os.path.join('third_party', 'qcms'),
383 os.path.join('third_party', 're2'),
384 os.path.join('third_party', 'safe_browsing'),
sdefresned13d15b2016-02-17 18:06:54385 os.path.join('third_party', 'smhasher'),
386 os.path.join('third_party', 'sudden_motion_sensor'),
387 os.path.join('third_party', 'swiftshader'),
388 os.path.join('third_party', 'swig'),
389 os.path.join('third_party', 'talloc'),
390 os.path.join('third_party', 'tcmalloc'),
391 os.path.join('third_party', 'usb_ids'),
392 os.path.join('third_party', 'v8-i18n'),
393 os.path.join('third_party', 'wtl'),
394 os.path.join('third_party', 'yasm'),
395 os.path.join('v8', 'strongtalk'),
396])
397
[email protected]e4598592012-08-09 15:47:21398
[email protected]957082a02010-03-18 21:55:24399class LicenseError(Exception):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55400 """We raise this exception when a directory's licensing info isn't
[email protected]957082a02010-03-18 21:55:24401 fully filled out."""
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55402 pass
403
[email protected]957082a02010-03-18 21:55:24404
[email protected]a8d5a8e782012-10-05 17:38:23405def AbsolutePath(path, filename, root):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55406 """Convert a path in README.chromium to be absolute based on the source
[email protected]689d81c2012-02-03 20:03:38407 root."""
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55408 if filename.startswith('/'):
409 # Absolute-looking paths are relative to the source root
410 # (which is the directory we're run from).
411 absolute_path = os.path.join(root, filename[1:])
412 else:
413 absolute_path = os.path.join(root, path, filename)
414 if os.path.exists(absolute_path):
415 return absolute_path
416 return None
417
[email protected]957082a02010-03-18 21:55:24418
mckev95468c6e2014-10-31 02:30:10419def ParseDir(path, root, require_license_file=True, optional_keys=None):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55420 """Examine a third_party/foo component and extract its metadata."""
421 # Parse metadata fields out of README.chromium.
422 # We examine "LICENSE" for the license file by default.
423 metadata = {
424 "License File": "LICENSE", # Relative path to license text.
425 "Name": None, # Short name (for header on about:credits).
426 "URL": None, # Project home page.
427 "License": None, # Software license.
428 }
[email protected]e657bfc2010-03-22 23:56:19429
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55430 if optional_keys is None:
431 optional_keys = []
[email protected]689d81c2012-02-03 20:03:38432
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55433 if path in SPECIAL_CASES:
434 metadata.update(SPECIAL_CASES[path])
435 else:
436 # Try to find README.chromium.
437 readme_path = os.path.join(root, path, 'README.chromium')
438 if not os.path.exists(readme_path):
439 raise LicenseError("missing README.chromium or licenses.py "
440 "SPECIAL_CASES entry in %s\n" % path)
[email protected]e657bfc2010-03-22 23:56:19441
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55442 for line in open(readme_path):
443 line = line.strip()
444 if not line:
445 break
446 for key in list(metadata.keys()) + optional_keys:
447 field = key + ": "
448 if line.startswith(field):
449 metadata[key] = line[len(field):]
[email protected]957082a02010-03-18 21:55:24450
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55451 # Check that all expected metadata is present.
452 errors = []
453 for key, value in metadata.items():
454 if not value:
455 errors.append("couldn't find '" + key + "' line "
456 "in README.chromium or licences.py "
457 "SPECIAL_CASES")
[email protected]957082a02010-03-18 21:55:24458
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55459 # Special-case modules that aren't in the shipping product, so don't need
460 # their license in about:credits.
461 if metadata["License File"] != NOT_SHIPPED:
462 # Check that the license file exists.
463 for filename in (metadata["License File"], "COPYING"):
464 license_path = AbsolutePath(path, filename, root)
465 if license_path is not None:
466 break
[email protected]e64b3d82010-03-19 00:46:18467
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55468 if require_license_file and not license_path:
469 errors.append("License file not found. "
470 "Either add a file named LICENSE, "
471 "import upstream's COPYING if available, "
472 "or add a 'License File:' line to "
473 "README.chromium with the appropriate path.")
474 metadata["License File"] = license_path
[email protected]957082a02010-03-18 21:55:24475
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55476 if errors:
477 raise LicenseError("Errors in %s:\n %s\n" % (path, ";\n ".join(errors)))
478 return metadata
[email protected]957082a02010-03-18 21:55:24479
480
[email protected]a8d5a8e782012-10-05 17:38:23481def ContainsFiles(path, root):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55482 """Determines whether any files exist in a directory or in any of its
[email protected]abb1b862012-07-27 01:52:11483 subdirectories."""
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55484 for _, dirs, files in os.walk(os.path.join(root, path)):
485 if files:
486 return True
487 for vcs_metadata in VCS_METADATA_DIRS:
488 if vcs_metadata in dirs:
489 dirs.remove(vcs_metadata)
490 return False
[email protected]abb1b862012-07-27 01:52:11491
492
[email protected]7472d1e02012-11-29 23:05:37493def FilterDirsWithFiles(dirs_list, root):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55494 # If a directory contains no files, assume it's a DEPS directory for a
495 # project not used by our current configuration and skip it.
496 return [x for x in dirs_list if ContainsFiles(x, root)]
[email protected]7472d1e02012-11-29 23:05:37497
498
David Landelle71c95b2020-08-28 16:18:27499def ProcessAdditionalReadmePathsJson(root, dirname, third_party_dirs):
Justin DeWitte8d65802020-06-26 00:43:45500 """For a given directory, process the additional readme paths, and add to
501 third_party_dirs."""
David Landelle71c95b2020-08-28 16:18:27502 additional_paths_file = os.path.join(root, dirname, ADDITIONAL_PATHS_FILENAME)
Justin DeWitte8d65802020-06-26 00:43:45503 if os.path.exists(additional_paths_file):
504 with open(additional_paths_file) as paths_file:
505 extra_paths = json.load(paths_file)
506 third_party_dirs.update([os.path.join(dirname, p) for p in extra_paths])
507
508
[email protected]a8d5a8e782012-10-05 17:38:23509def FindThirdPartyDirs(prune_paths, root):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55510 """Find all third_party directories underneath the source root."""
511 third_party_dirs = set()
512 for path, dirs, files in os.walk(root):
513 path = path[len(root) + 1:] # Pretty up the path.
[email protected]957082a02010-03-18 21:55:24514
Andrew Grieve914ce0a72020-06-26 16:02:45515 # .gitignore ignores /out*/, so do the same here.
516 if path in prune_paths or path.startswith('out'):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55517 dirs[:] = []
518 continue
[email protected]e64b3d82010-03-19 00:46:18519
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55520 # Prune out directories we want to skip.
521 # (Note that we loop over PRUNE_DIRS so we're not iterating over a
522 # list that we're simultaneously mutating.)
523 for skip in PRUNE_DIRS:
524 if skip in dirs:
525 dirs.remove(skip)
[email protected]957082a02010-03-18 21:55:24526
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55527 if os.path.basename(path) == 'third_party':
528 # Add all subdirectories that are not marked for skipping.
529 for dir in dirs:
530 dirpath = os.path.join(path, dir)
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55531 if dirpath not in prune_paths:
532 third_party_dirs.add(dirpath)
Justin DeWitte8d65802020-06-26 00:43:45533
David Landelle71c95b2020-08-28 16:18:27534 ProcessAdditionalReadmePathsJson(root, dirpath, third_party_dirs)
[email protected]e64b3d82010-03-19 00:46:18535
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55536 # Don't recurse into any subdirs from here.
537 dirs[:] = []
538 continue
[email protected]957082a02010-03-18 21:55:24539
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55540 # Don't recurse into paths in ADDITIONAL_PATHS, like we do with regular
541 # third_party/foo paths.
542 if path in ADDITIONAL_PATHS:
543 dirs[:] = []
[email protected]abb1b862012-07-27 01:52:11544
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55545 for dir in ADDITIONAL_PATHS:
546 if dir not in prune_paths:
547 third_party_dirs.add(dir)
David Landelle71c95b2020-08-28 16:18:27548 ProcessAdditionalReadmePathsJson(root, dir, third_party_dirs)
[email protected]e32bfad2010-10-22 01:34:32549
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55550 return third_party_dirs
[email protected]957082a02010-03-18 21:55:24551
[email protected]cb155a82011-11-29 17:25:34552
mnaganov4b533e82015-05-28 16:08:44553def FindThirdPartyDirsWithFiles(root):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55554 third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, root)
555 return FilterDirsWithFiles(third_party_dirs, root)
mnaganov4b533e82015-05-28 16:08:44556
557
lambroslambrou7703f4b2017-03-08 23:05:56558# Many builders do not contain 'gn' in their PATH, so use the GN binary from
Xiaoqian Dai89626492018-06-28 17:07:46559# //buildtools.
lambroslambrou7703f4b2017-03-08 23:05:56560def _GnBinary():
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55561 exe = 'gn'
562 if sys.platform.startswith('linux'):
563 subdir = 'linux64'
564 elif sys.platform == 'darwin':
565 subdir = 'mac'
566 elif sys.platform == 'win32':
567 subdir, exe = 'win', 'gn.exe'
568 else:
569 raise RuntimeError("Unsupported platform '%s'." % sys.platform)
Xiaoqian Dai89626492018-06-28 17:07:46570
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55571 return os.path.join(_REPOSITORY_ROOT, 'buildtools', subdir, exe)
lambroslambrou7703f4b2017-03-08 23:05:56572
573
Misha Efimov45ca19d2019-03-21 15:53:15574def GetThirdPartyDepsFromGNDepsOutput(gn_deps, target_os):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55575 """Returns third_party/foo directories given the output of "gn desc deps".
ichikawabaea0822017-04-19 05:24:02576
577 Note that it always returns the direct sub-directory of third_party
578 where README.chromium and LICENSE files are, so that it can be passed to
579 ParseDir(). e.g.:
Hiroshi Ichikawa3c5e1dfb2018-01-19 08:40:11580 third_party/cld_3/src/src/BUILD.gn -> third_party/cld_3
581
582 It returns relative paths from _REPOSITORY_ROOT, not absolute paths.
ichikawabaea0822017-04-19 05:24:02583 """
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55584 third_party_deps = set()
585 for absolute_build_dep in gn_deps.split():
586 relative_build_dep = os.path.relpath(absolute_build_dep, _REPOSITORY_ROOT)
587 m = re.search(
588 r'^((.+[/\\])?third_party[/\\][^/\\]+[/\\])(.+[/\\])?BUILD\.gn$',
589 relative_build_dep)
590 if not m:
591 continue
592 third_party_path = m.group(1)
593 if any(third_party_path.startswith(p + os.sep) for p in PRUNE_PATHS):
594 continue
595 if (target_os == 'ios' and any(
596 third_party_path.startswith(p + os.sep)
597 for p in KNOWN_NON_IOS_LIBRARIES)):
598 # Skip over files that are known not to be used on iOS.
599 continue
600 third_party_deps.add(third_party_path[:-1])
601 return third_party_deps
ichikawabaea0822017-04-19 05:24:02602
603
Misha Efimov45ca19d2019-03-21 15:53:15604def FindThirdPartyDeps(gn_out_dir, gn_target, target_os):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55605 if not gn_out_dir:
606 raise RuntimeError("--gn-out-dir is required if --gn-target is used.")
lambroslambrou04a2ae1702017-02-28 19:07:55607
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55608 # Generate gn project in temp directory and use it to find dependencies.
609 # Current gn directory cannot be used when we run this script in a gn action
610 # rule, because gn doesn't allow recursive invocations due to potential side
611 # effects.
612 tmp_dir = None
613 try:
614 tmp_dir = tempfile.mkdtemp(dir=gn_out_dir)
615 shutil.copy(os.path.join(gn_out_dir, "args.gn"), tmp_dir)
616 subprocess.check_output([_GnBinary(), "gen", tmp_dir])
617 gn_deps = subprocess.check_output([
618 _GnBinary(), "desc", tmp_dir, gn_target, "deps", "--as=buildfile",
619 "--all"
620 ])
621 if isinstance(gn_deps, bytes):
622 gn_deps = gn_deps.decode("utf-8")
623 finally:
624 if tmp_dir and os.path.exists(tmp_dir):
625 shutil.rmtree(tmp_dir)
ichikawacc4ae12d2017-04-11 05:03:16626
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55627 return GetThirdPartyDepsFromGNDepsOutput(gn_deps, target_os)
lambroslambrou04a2ae1702017-02-28 19:07:55628
629
[email protected]a8d5a8e782012-10-05 17:38:23630def ScanThirdPartyDirs(root=None):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55631 """Scan a list of directories and report on any problems we find."""
632 if root is None:
633 root = os.getcwd()
634 third_party_dirs = FindThirdPartyDirsWithFiles(root)
[email protected]54ce7262010-04-17 00:02:55635
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55636 errors = []
637 for path in sorted(third_party_dirs):
638 try:
639 metadata = ParseDir(path, root)
640 except LicenseError as e:
641 errors.append((path, e.args[0]))
642 continue
[email protected]54ce7262010-04-17 00:02:55643
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55644 for path, error in sorted(errors):
645 print(path + ": " + error)
[email protected]54ce7262010-04-17 00:02:55646
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55647 return len(errors) == 0
[email protected]54ce7262010-04-17 00:02:55648
[email protected]cb155a82011-11-29 17:25:34649
sdefresned13d15b2016-02-17 18:06:54650def GenerateCredits(
agrievebe961802017-02-15 18:48:20651 file_template_file, entry_template_file, output_file, target_os,
lambroslambrou04a2ae1702017-02-28 19:07:55652 gn_out_dir, gn_target, depfile=None):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55653 """Generate about:credits."""
[email protected]284f26f2013-02-07 13:32:13654
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55655 def EvaluateTemplate(template, env, escape=True):
656 """Expand a template with variables like {{foo}} using a
[email protected]54ce7262010-04-17 00:02:55657 dictionary of expansions."""
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55658 for key, val in env.items():
659 if escape:
660 val = html.escape(val)
661 template = template.replace('{{%s}}' % key, val)
662 return template
[email protected]54ce7262010-04-17 00:02:55663
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55664 def MetadataToTemplateEntry(metadata, entry_template):
665 env = {
666 'name': metadata['Name'],
667 'url': metadata['URL'],
668 'license': open(metadata['License File']).read(),
669 }
670 return {
671 'name': metadata['Name'],
672 'content': EvaluateTemplate(entry_template, env),
673 'license_file': metadata['License File'],
674 }
Yipeng Wang5671d4fe2017-06-08 17:59:44675
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55676 if gn_target:
677 third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target, target_os)
lambroslambrou04a2ae1702017-02-28 19:07:55678
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55679 # Sanity-check to raise a build error if invalid gn_... settings are
680 # somehow passed to this script.
681 if not third_party_dirs:
682 raise RuntimeError("No deps found.")
683 else:
684 third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, _REPOSITORY_ROOT)
[email protected]54ce7262010-04-17 00:02:55685
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55686 if not file_template_file:
687 file_template_file = os.path.join(_REPOSITORY_ROOT, 'components',
688 'about_ui', 'resources',
689 'about_credits.tmpl')
690 if not entry_template_file:
691 entry_template_file = os.path.join(_REPOSITORY_ROOT, 'components',
692 'about_ui', 'resources',
693 'about_credits_entry.tmpl')
jamiewalch6275de52015-06-17 23:25:34694
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55695 entry_template = open(entry_template_file).read()
696 entries = []
697 # Start from Chromium's LICENSE file
698 chromium_license_metadata = {
699 'Name': 'The Chromium Project',
700 'URL': 'http://www.chromium.org',
701 'License File': os.path.join(_REPOSITORY_ROOT, 'LICENSE')
702 }
703 entries.append(
704 MetadataToTemplateEntry(chromium_license_metadata, entry_template))
Yipeng Wang5671d4fe2017-06-08 17:59:44705
Andrew Grieve9efa38112020-06-10 17:42:34706 entries_by_name = {}
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55707 for path in third_party_dirs:
708 try:
709 metadata = ParseDir(path, _REPOSITORY_ROOT)
710 except LicenseError:
711 # TODO(phajdan.jr): Convert to fatal error (http://crbug.com/39240).
712 continue
713 if metadata['License File'] == NOT_SHIPPED:
714 continue
715 if target_os == 'ios' and not gn_target:
716 # Skip over files that are known not to be used on iOS. But
717 # skipping is unnecessary if GN was used to query the actual
718 # dependencies.
719 # TODO(lambroslambrou): Remove this step once the iOS build is
720 # updated to provide --gn-target to this script.
721 if path in KNOWN_NON_IOS_LIBRARIES:
722 continue
Andrew Grieve9efa38112020-06-10 17:42:34723
724 new_entry = MetadataToTemplateEntry(metadata, entry_template)
725 # Skip entries that we've already seen (it exists in multiple directories).
726 prev_entry = entries_by_name.setdefault(new_entry['name'], new_entry)
727 if prev_entry is not new_entry and (
728 prev_entry['content'] == new_entry['content']):
729 continue
730
731 entries.append(new_entry)
Yipeng Wang5671d4fe2017-06-08 17:59:44732
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55733 entries.sort(key=lambda entry: (entry['name'].lower(), entry['content']))
734 for entry_id, entry in enumerate(entries):
735 entry['content'] = entry['content'].replace('{{id}}', str(entry_id))
[email protected]54ce7262010-04-17 00:02:55736
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55737 entries_contents = '\n'.join([entry['content'] for entry in entries])
738 file_template = open(file_template_file).read()
739 template_contents = "<!-- Generated by licenses.py; do not edit. -->"
740 template_contents += EvaluateTemplate(
741 file_template, {'entries': entries_contents}, escape=False)
[email protected]284f26f2013-02-07 13:32:13742
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55743 if output_file:
744 changed = True
745 try:
746 old_output = open(output_file, 'r').read()
747 if old_output == template_contents:
748 changed = False
749 except:
750 pass
751 if changed:
752 with open(output_file, 'w') as output:
753 output.write(template_contents)
754 else:
755 print(template_contents)
[email protected]284f26f2013-02-07 13:32:13756
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55757 if depfile:
758 assert output_file
759 # Add in build.ninja so that the target will be considered dirty whenever
760 # gn gen is run. Otherwise, it will fail to notice new files being added.
761 # This is still no perfect, as it will fail if no build files are changed,
762 # but a new README.chromium / LICENSE is added. This shouldn't happen in
763 # practice however.
764 license_file_list = (entry['license_file'] for entry in entries)
765 license_file_list = (os.path.relpath(p) for p in license_file_list)
766 license_file_list = sorted(set(license_file_list))
767 build_utils.WriteDepfile(depfile, output_file,
768 license_file_list + ['build.ninja'])
agrievebe961802017-02-15 18:48:20769
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55770 return True
[email protected]957082a02010-03-18 21:55:24771
[email protected]cb155a82011-11-29 17:25:34772
ichikawacc4ae12d2017-04-11 05:03:16773def _ReadFile(path):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55774 """Reads a file from disk.
ichikawacc4ae12d2017-04-11 05:03:16775 Args:
776 path: The path of the file to read, relative to the root of the
777 repository.
778 Returns:
779 The contents of the file as a string.
780 """
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55781 with codecs.open(os.path.join(_REPOSITORY_ROOT, path), 'r', 'utf-8') as f:
782 return f.read()
ichikawacc4ae12d2017-04-11 05:03:16783
784
Misha Efimov45ca19d2019-03-21 15:53:15785def GenerateLicenseFile(output_file, gn_out_dir, gn_target, target_os):
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55786 """Generate a plain-text LICENSE file which can be used when you ship a part
ichikawacc4ae12d2017-04-11 05:03:16787 of Chromium code (specified by gn_target) as a stand-alone library
788 (e.g., //ios/web_view).
789
790 The LICENSE file contains licenses of both Chromium and third-party
791 libraries which gn_target depends on. """
792
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55793 third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target, target_os)
ichikawacc4ae12d2017-04-11 05:03:16794
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55795 # Start with Chromium's LICENSE file.
796 content = [_ReadFile('LICENSE')]
ichikawacc4ae12d2017-04-11 05:03:16797
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55798 # Add necessary third_party.
799 for directory in sorted(third_party_dirs):
800 metadata = ParseDir(directory, _REPOSITORY_ROOT, require_license_file=True)
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55801 license_file = metadata['License File']
802 if license_file and license_file != NOT_SHIPPED:
Matt Mueller5f06c702020-06-04 21:34:04803 content.append('-' * 20)
804 content.append(directory.split(os.sep)[-1])
805 content.append('-' * 20)
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55806 content.append(_ReadFile(license_file))
ichikawacc4ae12d2017-04-11 05:03:16807
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55808 content_text = '\n'.join(content)
ichikawacc4ae12d2017-04-11 05:03:16809
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55810 if output_file:
811 with codecs.open(output_file, 'w', 'utf-8') as output:
812 output.write(content_text)
813 else:
814 print(content_text)
ichikawacc4ae12d2017-04-11 05:03:16815
ichikawacc4ae12d2017-04-11 05:03:16816
817
[email protected]cb155a82011-11-29 17:25:34818def main():
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55819 parser = argparse.ArgumentParser()
820 parser.add_argument(
821 '--file-template', help='Template HTML to use for the license page.')
822 parser.add_argument(
823 '--entry-template', help='Template HTML to use for each license.')
824 parser.add_argument('--target-os', help='OS that this build is targeting.')
825 parser.add_argument(
826 '--gn-out-dir', help='GN output directory for scanning dependencies.')
827 parser.add_argument('--gn-target', help='GN target to scan for dependencies.')
828 parser.add_argument(
829 'command', choices=['help', 'scan', 'credits', 'license_file'])
830 parser.add_argument('output_file', nargs='?')
831 build_utils.AddDepfileOption(parser)
832 args = parser.parse_args()
[email protected]54ce7262010-04-17 00:02:55833
Hiroshi Ichikawaf4fa98d2020-04-03 10:01:55834 if args.command == 'scan':
835 if not ScanThirdPartyDirs():
836 return 1
837 elif args.command == 'credits':
838 if not GenerateCredits(args.file_template, args.entry_template,
839 args.output_file, args.target_os, args.gn_out_dir,
840 args.gn_target, args.depfile):
841 return 1
842 elif args.command == 'license_file':
843 try:
844 GenerateLicenseFile(args.output_file, args.gn_out_dir, args.gn_target,
845 args.target_os)
846 except LicenseError as e:
847 print("Failed to parse README.chromium: {}".format(e))
848 return 1
849 else:
850 print(__doc__)
851 return 1
[email protected]cb155a82011-11-29 17:25:34852
853
854if __name__ == '__main__':
855 sys.exit(main())