Revert 205057 "Add JSON.pm to third_party"
[chromium-blink-merge.git] / tools / checklicenses / checklicenses.py
blobd78708514b2698e39344123d3e47a54560d1e90d
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Makes sure that all files contain proper licensing information."""
9 import optparse
10 import os.path
11 import subprocess
12 import sys
15 def PrintUsage():
16 print """Usage: python checklicenses.py [--root <root>] [tocheck]
17 --root Specifies the repository root. This defaults to "../.." relative
18 to the script file. This will be correct given the normal location
19 of the script in "<root>/tools/checklicenses".
21 --ignore-suppressions Ignores path-specific license whitelist. Useful when
22 trying to remove a suppression/whitelist entry.
24 tocheck Specifies the directory, relative to root, to check. This defaults
25 to "." so it checks everything.
27 Examples:
28 python checklicenses.py
29 python checklicenses.py --root ~/chromium/src third_party"""
32 WHITELISTED_LICENSES = [
33 'Apache (v2.0)',
34 'Apache (v2.0) BSD (2 clause)',
35 'Apache (v2.0) GPL (v2)',
36 'Apple MIT', # https://fedoraproject.org/wiki/Licensing/Apple_MIT_License
37 'APSL (v2)',
38 'APSL (v2) BSD (4 clause)',
39 'BSD',
40 'BSD (2 clause)',
41 'BSD (2 clause) MIT/X11 (BSD like)',
42 'BSD (3 clause)',
43 'BSD (3 clause) GPL (v2)',
44 'BSD (3 clause) ISC',
45 'BSD (3 clause) LGPL (v2 or later)',
46 'BSD (3 clause) LGPL (v2.1 or later)',
47 'BSD (3 clause) MIT/X11 (BSD like)',
48 'BSD (4 clause)',
49 'BSD-like',
51 # TODO(phajdan.jr): Make licensecheck not print BSD-like twice.
52 'BSD-like MIT/X11 (BSD like)',
54 'BSL (v1.0)',
55 'GPL (v2 or later) with Bison parser exception',
56 'GPL (v2 or later) with libtool exception',
57 'GPL (v3 or later) with Bison parser exception',
58 'GPL with Bison parser exception',
59 'ISC',
60 'LGPL',
61 'LGPL (v2)',
62 'LGPL (v2 or later)',
63 'LGPL (v2.1)',
64 'LGPL (v3 or later)',
66 # TODO(phajdan.jr): Make licensecheck convert that comma to a dot.
67 'LGPL (v2,1 or later)',
69 'LGPL (v2.1 or later)',
70 'MPL (v1.0) LGPL (v2 or later)',
71 'MPL (v1.1)',
72 'MPL (v1.1) BSD-like',
73 'MPL (v1.1) BSD-like GPL (unversioned/unknown version)',
74 'MPL (v1.1,) BSD (3 clause) GPL (unversioned/unknown version) '
75 'LGPL (v2.1 or later)',
76 'MPL (v1.1) GPL (unversioned/unknown version)',
77 'MPL (v2.0)',
79 # TODO(phajdan.jr): Make licensecheck not print the comma after 1.1.
80 'MPL (v1.1,) GPL (unversioned/unknown version) LGPL (v2 or later)',
81 'MPL (v1.1,) GPL (unversioned/unknown version) LGPL (v2.1 or later)',
83 'MIT/X11 (BSD like)',
84 'Ms-PL',
85 'Public domain',
86 'Public domain BSD',
87 'Public domain BSD (3 clause)',
88 'Public domain BSD-like',
89 'Public domain LGPL (v2.1 or later)',
90 'libpng',
91 'zlib/libpng',
92 'SGI Free Software License B',
93 'University of Illinois/NCSA Open Source License (BSD like)',
97 PATH_SPECIFIC_WHITELISTED_LICENSES = {
98 'base/hash.cc': [ # http://crbug.com/98100
99 'UNKNOWN',
101 'base/third_party/icu': [ # http://crbug.com/98087
102 'UNKNOWN',
105 # http://code.google.com/p/google-breakpad/issues/detail?id=450
106 'breakpad/src': [
107 'UNKNOWN',
110 'chrome/common/extensions/docs/examples': [ # http://crbug.com/98092
111 'UNKNOWN',
113 'chrome/test/data/gpu/vt': [
114 'UNKNOWN',
116 'chrome/test/data/layout_tests/LayoutTests': [
117 'UNKNOWN',
119 'courgette/third_party/bsdiff_create.cc': [ # http://crbug.com/98095
120 'UNKNOWN',
122 'data/mozilla_js_tests': [
123 'UNKNOWN',
125 'data/page_cycler': [
126 'UNKNOWN',
127 'GPL (v2 or later)',
129 'data/tab_switching': [
130 'UNKNOWN',
132 'googleurl': [ # http://code.google.com/p/google-url/issues/detail?id=15
133 'UNKNOWN',
136 'native_client': [ # http://crbug.com/98099
137 'UNKNOWN',
139 'native_client/toolchain': [
140 'BSD GPL (v2 or later)',
141 'BSD (2 clause) GPL (v2 or later)',
142 'BSD (3 clause) GPL (v2 or later)',
143 'BSL (v1.0) GPL',
144 'BSL (v1.0) GPL (v3.1)',
145 'GPL',
146 'GPL (unversioned/unknown version)',
147 'GPL (v2)',
148 'GPL (v2 or later)',
149 'GPL (v3.1)',
150 'GPL (v3 or later)',
152 'net/tools/spdyshark': [
153 'GPL (v2 or later)',
154 'UNKNOWN',
156 'third_party/WebKit': [
157 'UNKNOWN',
159 'third_party/WebKit/Websites/webkit.org/blog/wp-content/plugins/'
160 'akismet/akismet.php': [
161 'GPL (v2 or later)'
163 'third_party/WebKit/Source/JavaScriptCore/tests/mozilla': [
164 'GPL',
165 'GPL (v2 or later)',
166 'GPL (unversioned/unknown version)',
168 'third_party/active_doc': [ # http://crbug.com/98113
169 'UNKNOWN',
172 # http://code.google.com/p/angleproject/issues/detail?id=217
173 'third_party/angle': [
174 'UNKNOWN',
177 'third_party/bsdiff/mbsdiff.cc': [
178 'UNKNOWN',
180 'third_party/bzip2': [
181 'UNKNOWN',
184 # http://crbug.com/222828
185 # http://bugs.python.org/issue17514
186 'third_party/chromite/third_party/argparse.py': [
187 'UNKNOWN',
190 # Not used. http://crbug.com/156020
191 # Using third_party/cros_dbus_cplusplus/cros_dbus_cplusplus.gyp instead.
192 'third_party/cros_dbus_cplusplus/source/autogen.sh': [
193 'UNKNOWN',
195 # Included in the source tree but not built. http://crbug.com/156020
196 'third_party/cros_dbus_cplusplus/source/examples': [
197 'UNKNOWN',
199 'third_party/devscripts': [
200 'GPL (v2 or later)',
202 'third_party/expat/files/lib': [ # http://crbug.com/98121
203 'UNKNOWN',
205 'third_party/ffmpeg': [
206 'GPL',
207 'GPL (v2)',
208 'GPL (v2 or later)',
209 'UNKNOWN', # http://crbug.com/98123
211 'third_party/findbugs/doc': [ # http://crbug.com/157206
212 'UNKNOWN',
214 'third_party/freetype2': [ # http://crbug.com/177319
215 'UNKNOWN',
217 'third_party/gles2_book': [ # http://crbug.com/98130
218 'UNKNOWN',
220 'third_party/gles2_conform/GTF_ES': [ # http://crbug.com/98131
221 'UNKNOWN',
223 'third_party/harfbuzz': [ # http://crbug.com/98133
224 'UNKNOWN',
226 'third_party/hunspell': [ # http://crbug.com/98134
227 'UNKNOWN',
229 'third_party/hyphen/hyphen.tex': [ # http://crbug.com/157375
230 'UNKNOWN',
232 'third_party/iccjpeg': [ # http://crbug.com/98137
233 'UNKNOWN',
235 'third_party/icu': [ # http://crbug.com/98301
236 'UNKNOWN',
238 'third_party/jemalloc': [ # http://crbug.com/98302
239 'UNKNOWN',
241 'third_party/lcov': [ # http://crbug.com/98304
242 'UNKNOWN',
244 'third_party/lcov/contrib/galaxy/genflat.pl': [
245 'GPL (v2 or later)',
247 'third_party/lcov-1.9/contrib/galaxy/genflat.pl': [
248 'GPL (v2 or later)',
250 'third_party/libevent': [ # http://crbug.com/98309
251 'UNKNOWN',
253 'third_party/libjingle/source/talk': [ # http://crbug.com/98310
254 'UNKNOWN',
256 'third_party/libjingle/source_internal/talk': [ # http://crbug.com/98310
257 'UNKNOWN',
259 'third_party/libjpeg': [ # http://crbug.com/98313
260 'UNKNOWN',
262 'third_party/libjpeg_turbo': [ # http://crbug.com/98314
263 'UNKNOWN',
265 'third_party/libpng': [ # http://crbug.com/98318
266 'UNKNOWN',
269 # The following files lack license headers, but are trivial.
270 'third_party/libusb/src/libusb/os/poll_posix.h': [
271 'UNKNOWN',
273 'third_party/libusb/src/libusb/version.h': [
274 'UNKNOWN',
276 'third_party/libusb/src/autogen.sh': [
277 'UNKNOWN',
279 'third_party/libusb/src/config.h': [
280 'UNKNOWN',
282 'third_party/libusb/src/msvc/config.h': [
283 'UNKNOWN',
286 'third_party/libvpx/source': [ # http://crbug.com/98319
287 'UNKNOWN',
289 'third_party/libvpx/source/libvpx/examples/includes': [
290 'GPL (v2 or later)',
292 'third_party/libwebp': [ # http://crbug.com/98448
293 'UNKNOWN',
295 'third_party/libxml': [
296 'UNKNOWN',
298 'third_party/libxslt': [
299 'UNKNOWN',
301 'third_party/lzma_sdk': [
302 'UNKNOWN',
304 'third_party/mesa/MesaLib': [
305 'GPL (v2)',
306 'GPL (v3 or later)',
307 'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception',
308 'UNKNOWN', # http://crbug.com/98450
310 'third_party/mesa/src': [
311 'GPL (v2)',
312 'GPL (v3 or later)',
313 'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception',
314 'UNKNOWN', # http://crbug.com/98450
316 'third_party/modp_b64': [
317 'UNKNOWN',
319 'third_party/npapi/npspy/extern/java': [
320 'GPL (unversioned/unknown version)',
322 'third_party/openmax_dl/dl' : [
323 'Khronos Group',
325 'third_party/openssl': [ # http://crbug.com/98451
326 'UNKNOWN',
328 'third_party/ots/tools/ttf-checksum.py': [ # http://code.google.com/p/ots/issues/detail?id=2
329 'UNKNOWN',
331 'third_party/molokocacao': [ # http://crbug.com/98453
332 'UNKNOWN',
334 'third_party/npapi/npspy': [
335 'UNKNOWN',
337 'third_party/ocmock/OCMock': [ # http://crbug.com/98454
338 'UNKNOWN',
340 'third_party/ply/__init__.py': [
341 'UNKNOWN',
343 'third_party/protobuf': [ # http://crbug.com/98455
344 'UNKNOWN',
347 # http://crbug.com/222831
348 # https://bitbucket.org/eliben/pyelftools/issue/12
349 'third_party/pyelftools': [
350 'UNKNOWN',
353 'third_party/pylib': [
354 'UNKNOWN',
356 'third_party/scons-2.0.1/engine/SCons': [ # http://crbug.com/98462
357 'UNKNOWN',
359 'third_party/simplejson': [
360 'UNKNOWN',
362 'third_party/skia': [ # http://crbug.com/98463
363 'UNKNOWN',
365 'third_party/snappy/src': [ # http://crbug.com/98464
366 'UNKNOWN',
368 'third_party/smhasher/src': [ # http://crbug.com/98465
369 'UNKNOWN',
371 'third_party/speech-dispatcher/libspeechd.h': [
372 'GPL (v2 or later)',
374 'third_party/sqlite': [
375 'UNKNOWN',
377 'third_party/swig/Lib/linkruntime.c': [ # http://crbug.com/98585
378 'UNKNOWN',
380 'third_party/talloc': [
381 'GPL (v3 or later)',
382 'UNKNOWN', # http://crbug.com/98588
384 'third_party/tcmalloc': [
385 'UNKNOWN', # http://crbug.com/98589
387 'third_party/tlslite': [
388 'UNKNOWN',
390 'third_party/webdriver': [ # http://crbug.com/98590
391 'UNKNOWN',
393 'third_party/webrtc': [ # http://crbug.com/98592
394 'UNKNOWN',
396 'third_party/xdg-utils': [ # http://crbug.com/98593
397 'UNKNOWN',
399 'third_party/yasm/source': [ # http://crbug.com/98594
400 'UNKNOWN',
402 'third_party/zlib/contrib/minizip': [
403 'UNKNOWN',
405 'third_party/zlib/trees.h': [
406 'UNKNOWN',
408 'tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py': [
409 'UNKNOWN',
411 'tools/emacs': [ # http://crbug.com/98595
412 'UNKNOWN',
414 'tools/grit/grit/node/custom/__init__.py': [
415 'UNKNOWN',
417 'tools/gyp/test': [
418 'UNKNOWN',
420 'tools/histograms': [
421 'UNKNOWN',
423 'tools/memory_watcher': [
424 'UNKNOWN',
426 'tools/playback_benchmark': [
427 'UNKNOWN',
429 'tools/python/google/__init__.py': [
430 'UNKNOWN',
432 'tools/site_compare': [
433 'UNKNOWN',
435 'tools/stats_viewer/Properties/AssemblyInfo.cs': [
436 'UNKNOWN',
438 'tools/symsrc/pefile.py': [
439 'UNKNOWN',
441 'v8/test/cctest': [ # http://crbug.com/98597
442 'UNKNOWN',
444 'webkit/data/ico_decoder': [
445 'UNKNOWN',
450 def check_licenses(options, args):
451 # Figure out which directory we have to check.
452 if len(args) == 0:
453 # No directory to check specified, use the repository root.
454 start_dir = options.base_directory
455 elif len(args) == 1:
456 # Directory specified. Start here. It's supposed to be relative to the
457 # base directory.
458 start_dir = os.path.abspath(os.path.join(options.base_directory, args[0]))
459 else:
460 # More than one argument, we don't handle this.
461 PrintUsage()
462 return 1
464 print "Using base directory:", options.base_directory
465 print "Checking:", start_dir
466 print
468 licensecheck_path = os.path.abspath(os.path.join(options.base_directory,
469 'third_party',
470 'devscripts',
471 'licensecheck.pl'))
473 licensecheck = subprocess.Popen([licensecheck_path,
474 '-l', '100',
475 '-r', start_dir],
476 stdout=subprocess.PIPE,
477 stderr=subprocess.PIPE)
478 stdout, stderr = licensecheck.communicate()
479 if options.verbose:
480 print '----------- licensecheck stdout -----------'
481 print stdout
482 print '--------- end licensecheck stdout ---------'
483 if licensecheck.returncode != 0 or stderr:
484 print '----------- licensecheck stderr -----------'
485 print stderr
486 print '--------- end licensecheck stderr ---------'
487 print "\nFAILED\n"
488 return 1
490 success = True
491 for line in stdout.splitlines():
492 filename, license = line.split(':', 1)
493 filename = os.path.relpath(filename.strip(), options.base_directory)
495 # All files in the build output directory are generated one way or another.
496 # There's no need to check them.
497 if filename.startswith('out/') or filename.startswith('sconsbuild/'):
498 continue
500 # For now we're just interested in the license.
501 license = license.replace('*No copyright*', '').strip()
503 # Skip generated files.
504 if 'GENERATED FILE' in license:
505 continue
507 if license in WHITELISTED_LICENSES:
508 continue
510 if not options.ignore_suppressions:
511 found_path_specific = False
512 for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES:
513 if (filename.startswith(prefix) and
514 license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]):
515 found_path_specific = True
516 break
517 if found_path_specific:
518 continue
520 print "'%s' has non-whitelisted license '%s'" % (filename, license)
521 success = False
523 if success:
524 print "\nSUCCESS\n"
525 return 0
526 else:
527 print "\nFAILED\n"
528 print "Please read",
529 print "http://www.chromium.org/developers/adding-3rd-party-libraries"
530 print "for more info how to handle the failure."
531 print
532 print "Please respect OWNERS of checklicenses.py. Changes violating"
533 print "this requirement may be reverted."
534 return 1
537 def main():
538 default_root = os.path.abspath(
539 os.path.join(os.path.dirname(__file__), '..', '..'))
540 option_parser = optparse.OptionParser()
541 option_parser.add_option('--root', default=default_root,
542 dest='base_directory',
543 help='Specifies the repository root. This defaults '
544 'to "../.." relative to the script file, which '
545 'will normally be the repository root.')
546 option_parser.add_option('-v', '--verbose', action='store_true',
547 default=False, help='Print debug logging')
548 option_parser.add_option('--ignore-suppressions',
549 action='store_true',
550 default=False,
551 help='Ignore path-specific license whitelist.')
552 options, args = option_parser.parse_args()
553 return check_licenses(options, args)
556 if '__main__' == __name__:
557 sys.exit(main())