Fix a type mismatch on Windows caused by r201738.
[chromium-blink-merge.git] / tools / checklicenses / checklicenses.py
blobbc1a2af2a147c41007bd552006bd98c59a8954e6
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/modp_b64': [
311 'UNKNOWN',
313 'third_party/npapi/npspy/extern/java': [
314 'GPL (unversioned/unknown version)',
316 'third_party/openmax_dl/dl' : [
317 'Khronos Group',
319 'third_party/openssl': [ # http://crbug.com/98451
320 'UNKNOWN',
322 'third_party/ots/tools/ttf-checksum.py': [ # http://code.google.com/p/ots/issues/detail?id=2
323 'UNKNOWN',
325 'third_party/molokocacao': [ # http://crbug.com/98453
326 'UNKNOWN',
328 'third_party/npapi/npspy': [
329 'UNKNOWN',
331 'third_party/ocmock/OCMock': [ # http://crbug.com/98454
332 'UNKNOWN',
334 'third_party/ply/__init__.py': [
335 'UNKNOWN',
337 'third_party/protobuf': [ # http://crbug.com/98455
338 'UNKNOWN',
341 # http://crbug.com/222831
342 # https://bitbucket.org/eliben/pyelftools/issue/12
343 'third_party/pyelftools': [
344 'UNKNOWN',
347 'third_party/pylib': [
348 'UNKNOWN',
350 'third_party/scons-2.0.1/engine/SCons': [ # http://crbug.com/98462
351 'UNKNOWN',
353 'third_party/simplejson': [
354 'UNKNOWN',
356 'third_party/skia': [ # http://crbug.com/98463
357 'UNKNOWN',
359 'third_party/snappy/src': [ # http://crbug.com/98464
360 'UNKNOWN',
362 'third_party/smhasher/src': [ # http://crbug.com/98465
363 'UNKNOWN',
365 'third_party/speech-dispatcher/libspeechd.h': [
366 'GPL (v2 or later)',
368 'third_party/sqlite': [
369 'UNKNOWN',
371 'third_party/swig/Lib/linkruntime.c': [ # http://crbug.com/98585
372 'UNKNOWN',
374 'third_party/talloc': [
375 'GPL (v3 or later)',
376 'UNKNOWN', # http://crbug.com/98588
378 'third_party/tcmalloc': [
379 'UNKNOWN', # http://crbug.com/98589
381 'third_party/tlslite': [
382 'UNKNOWN',
384 'third_party/webdriver': [ # http://crbug.com/98590
385 'UNKNOWN',
387 'third_party/webrtc': [ # http://crbug.com/98592
388 'UNKNOWN',
390 'third_party/xdg-utils': [ # http://crbug.com/98593
391 'UNKNOWN',
393 'third_party/yasm/source': [ # http://crbug.com/98594
394 'UNKNOWN',
396 'third_party/zlib/contrib/minizip': [
397 'UNKNOWN',
399 'third_party/zlib/trees.h': [
400 'UNKNOWN',
402 'tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py': [
403 'UNKNOWN',
405 'tools/emacs': [ # http://crbug.com/98595
406 'UNKNOWN',
408 'tools/grit/grit/node/custom/__init__.py': [
409 'UNKNOWN',
411 'tools/gyp/test': [
412 'UNKNOWN',
414 'tools/histograms': [
415 'UNKNOWN',
417 'tools/memory_watcher': [
418 'UNKNOWN',
420 'tools/playback_benchmark': [
421 'UNKNOWN',
423 'tools/python/google/__init__.py': [
424 'UNKNOWN',
426 'tools/site_compare': [
427 'UNKNOWN',
429 'tools/stats_viewer/Properties/AssemblyInfo.cs': [
430 'UNKNOWN',
432 'tools/symsrc/pefile.py': [
433 'UNKNOWN',
435 'v8/test/cctest': [ # http://crbug.com/98597
436 'UNKNOWN',
438 'webkit/data/ico_decoder': [
439 'UNKNOWN',
444 def check_licenses(options, args):
445 # Figure out which directory we have to check.
446 if len(args) == 0:
447 # No directory to check specified, use the repository root.
448 start_dir = options.base_directory
449 elif len(args) == 1:
450 # Directory specified. Start here. It's supposed to be relative to the
451 # base directory.
452 start_dir = os.path.abspath(os.path.join(options.base_directory, args[0]))
453 else:
454 # More than one argument, we don't handle this.
455 PrintUsage()
456 return 1
458 print "Using base directory:", options.base_directory
459 print "Checking:", start_dir
460 print
462 licensecheck_path = os.path.abspath(os.path.join(options.base_directory,
463 'third_party',
464 'devscripts',
465 'licensecheck.pl'))
467 licensecheck = subprocess.Popen([licensecheck_path,
468 '-l', '100',
469 '-r', start_dir],
470 stdout=subprocess.PIPE,
471 stderr=subprocess.PIPE)
472 stdout, stderr = licensecheck.communicate()
473 if options.verbose:
474 print '----------- licensecheck stdout -----------'
475 print stdout
476 print '--------- end licensecheck stdout ---------'
477 if licensecheck.returncode != 0 or stderr:
478 print '----------- licensecheck stderr -----------'
479 print stderr
480 print '--------- end licensecheck stderr ---------'
481 print "\nFAILED\n"
482 return 1
484 success = True
485 for line in stdout.splitlines():
486 filename, license = line.split(':', 1)
487 filename = os.path.relpath(filename.strip(), options.base_directory)
489 # All files in the build output directory are generated one way or another.
490 # There's no need to check them.
491 if filename.startswith('out/') or filename.startswith('sconsbuild/'):
492 continue
494 # For now we're just interested in the license.
495 license = license.replace('*No copyright*', '').strip()
497 # Skip generated files.
498 if 'GENERATED FILE' in license:
499 continue
501 if license in WHITELISTED_LICENSES:
502 continue
504 if not options.ignore_suppressions:
505 found_path_specific = False
506 for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES:
507 if (filename.startswith(prefix) and
508 license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]):
509 found_path_specific = True
510 break
511 if found_path_specific:
512 continue
514 print "'%s' has non-whitelisted license '%s'" % (filename, license)
515 success = False
517 if success:
518 print "\nSUCCESS\n"
519 return 0
520 else:
521 print "\nFAILED\n"
522 print "Please read",
523 print "http://www.chromium.org/developers/adding-3rd-party-libraries"
524 print "for more info how to handle the failure."
525 print
526 print "Please respect OWNERS of checklicenses.py. Changes violating"
527 print "this requirement may be reverted."
528 return 1
531 def main():
532 default_root = os.path.abspath(
533 os.path.join(os.path.dirname(__file__), '..', '..'))
534 option_parser = optparse.OptionParser()
535 option_parser.add_option('--root', default=default_root,
536 dest='base_directory',
537 help='Specifies the repository root. This defaults '
538 'to "../.." relative to the script file, which '
539 'will normally be the repository root.')
540 option_parser.add_option('-v', '--verbose', action='store_true',
541 default=False, help='Print debug logging')
542 option_parser.add_option('--ignore-suppressions',
543 action='store_true',
544 default=False,
545 help='Ignore path-specific license whitelist.')
546 options, args = option_parser.parse_args()
547 return check_licenses(options, args)
550 if '__main__' == __name__:
551 sys.exit(main())