Fix build break
[chromium-blink-merge.git] / tools / checklicenses / checklicenses.py
blobbd1e045c96bb8312bdefa8e8df5834e530a5e72b
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) ISC',
44 'BSD (3 clause) LGPL (v2 or later)',
45 'BSD (3 clause) LGPL (v2.1 or later)',
46 'BSD (3 clause) MIT/X11 (BSD like)',
47 'BSD (4 clause)',
48 'BSD-like',
50 # TODO(phajdan.jr): Make licensecheck not print BSD-like twice.
51 'BSD-like MIT/X11 (BSD like)',
53 'BSL (v1.0)',
54 'GPL (v2 or later) with Bison parser exception',
55 'GPL (v2 or later) with libtool exception',
56 'GPL (v3 or later) with Bison parser exception',
57 'GPL with Bison parser exception',
58 'ISC',
59 'LGPL',
60 'LGPL (v2)',
61 'LGPL (v2 or later)',
62 'LGPL (v2.1)',
63 'LGPL (v3 or later)',
65 # TODO(phajdan.jr): Make licensecheck convert that comma to a dot.
66 'LGPL (v2,1 or later)',
68 'LGPL (v2.1 or later)',
69 'MPL (v1.0) LGPL (v2 or later)',
70 'MPL (v1.1)',
71 'MPL (v1.1) BSD-like',
72 'MPL (v1.1) BSD-like GPL (unversioned/unknown version)',
73 'MPL (v1.1,) BSD (3 clause) GPL (unversioned/unknown version) '
74 'LGPL (v2.1 or later)',
75 'MPL (v1.1) GPL (unversioned/unknown version)',
76 'MPL (v2.0)',
78 # TODO(phajdan.jr): Make licensecheck not print the comma after 1.1.
79 'MPL (v1.1,) GPL (unversioned/unknown version) LGPL (v2 or later)',
80 'MPL (v1.1,) GPL (unversioned/unknown version) LGPL (v2.1 or later)',
82 'MIT/X11 (BSD like)',
83 'Ms-PL',
84 'Public domain',
85 'Public domain BSD',
86 'Public domain BSD (3 clause)',
87 'Public domain BSD-like',
88 'Public domain LGPL (v2.1 or later)',
89 'libpng',
90 'zlib/libpng',
91 'SGI Free Software License B',
92 'University of Illinois/NCSA Open Source License (BSD like)',
96 PATH_SPECIFIC_WHITELISTED_LICENSES = {
97 'base/hash.cc': [ # http://crbug.com/98100
98 'UNKNOWN',
100 'base/third_party/icu': [ # http://crbug.com/98087
101 'UNKNOWN',
104 # http://code.google.com/p/google-breakpad/issues/detail?id=450
105 'breakpad/src': [
106 'UNKNOWN',
109 'chrome/common/extensions/docs/examples': [ # http://crbug.com/98092
110 'UNKNOWN',
112 'chrome/test/data/gpu/vt': [
113 'UNKNOWN',
115 'chrome/test/data/layout_tests/LayoutTests': [
116 'UNKNOWN',
118 'courgette/third_party/bsdiff_create.cc': [ # http://crbug.com/98095
119 'UNKNOWN',
121 'data/mozilla_js_tests': [
122 'UNKNOWN',
124 'data/page_cycler': [
125 'UNKNOWN',
126 'GPL (v2 or later)',
128 'data/tab_switching': [
129 'UNKNOWN',
131 'googleurl': [ # http://code.google.com/p/google-url/issues/detail?id=15
132 'UNKNOWN',
135 'native_client': [ # http://crbug.com/98099
136 'UNKNOWN',
138 'native_client/toolchain': [
139 'BSD GPL (v2 or later)',
140 'BSD (2 clause) GPL (v2 or later)',
141 'BSD (3 clause) GPL (v2 or later)',
142 'BSL (v1.0) GPL',
143 'BSL (v1.0) GPL (v3.1)',
144 'GPL',
145 'GPL (unversioned/unknown version)',
146 'GPL (v2)',
147 'GPL (v2 or later)',
148 'GPL (v3.1)',
149 'GPL (v3 or later)',
151 'net/tools/spdyshark': [
152 'GPL (v2 or later)',
153 'UNKNOWN',
155 'third_party/WebKit': [
156 'UNKNOWN',
158 'third_party/WebKit/Websites/webkit.org/blog/wp-content/plugins/'
159 'akismet/akismet.php': [
160 'GPL (v2 or later)'
162 'third_party/WebKit/Source/JavaScriptCore/tests/mozilla': [
163 'GPL',
164 'GPL (v2 or later)',
165 'GPL (unversioned/unknown version)',
167 'third_party/active_doc': [ # http://crbug.com/98113
168 'UNKNOWN',
171 # http://code.google.com/p/angleproject/issues/detail?id=217
172 'third_party/angle': [
173 'UNKNOWN',
176 'third_party/bsdiff/mbsdiff.cc': [
177 'UNKNOWN',
179 'third_party/bzip2': [
180 'UNKNOWN',
183 # http://crbug.com/222828
184 # http://bugs.python.org/issue17514
185 'third_party/chromite/third_party/argparse.py': [
186 'UNKNOWN',
189 # Not used. http://crbug.com/156020
190 # Using third_party/cros_dbus_cplusplus/cros_dbus_cplusplus.gyp instead.
191 'third_party/cros_dbus_cplusplus/source/autogen.sh': [
192 'UNKNOWN',
194 # Included in the source tree but not built. http://crbug.com/156020
195 'third_party/cros_dbus_cplusplus/source/examples': [
196 'UNKNOWN',
198 'third_party/devscripts': [
199 'GPL (v2 or later)',
201 'third_party/expat/files/lib': [ # http://crbug.com/98121
202 'UNKNOWN',
204 'third_party/ffmpeg': [
205 'GPL',
206 'GPL (v2)',
207 'GPL (v2 or later)',
208 'UNKNOWN', # http://crbug.com/98123
210 'third_party/findbugs/doc': [ # http://crbug.com/157206
211 'UNKNOWN',
213 'third_party/freetype2': [ # http://crbug.com/177319
214 'UNKNOWN',
216 'third_party/gles2_book': [ # http://crbug.com/98130
217 'UNKNOWN',
219 'third_party/gles2_conform/GTF_ES': [ # http://crbug.com/98131
220 'UNKNOWN',
222 'third_party/harfbuzz': [ # http://crbug.com/98133
223 'UNKNOWN',
225 'third_party/hunspell': [ # http://crbug.com/98134
226 'UNKNOWN',
228 'third_party/hyphen/hyphen.tex': [ # http://crbug.com/157375
229 'UNKNOWN',
231 'third_party/iccjpeg': [ # http://crbug.com/98137
232 'UNKNOWN',
234 'third_party/icu': [ # http://crbug.com/98301
235 'UNKNOWN',
237 'third_party/jemalloc': [ # http://crbug.com/98302
238 'UNKNOWN',
240 'third_party/lcov': [ # http://crbug.com/98304
241 'UNKNOWN',
243 'third_party/lcov/contrib/galaxy/genflat.pl': [
244 'GPL (v2 or later)',
246 'third_party/lcov-1.9/contrib/galaxy/genflat.pl': [
247 'GPL (v2 or later)',
249 'third_party/libevent': [ # http://crbug.com/98309
250 'UNKNOWN',
252 'third_party/libjingle/source/talk': [ # http://crbug.com/98310
253 'UNKNOWN',
255 'third_party/libjingle/source_internal/talk': [ # http://crbug.com/98310
256 'UNKNOWN',
258 'third_party/libjpeg': [ # http://crbug.com/98313
259 'UNKNOWN',
261 'third_party/libjpeg_turbo': [ # http://crbug.com/98314
262 'UNKNOWN',
264 'third_party/libpng': [ # http://crbug.com/98318
265 'UNKNOWN',
268 # The following files lack license headers, but are trivial.
269 'third_party/libusb/src/libusb/os/poll_posix.h': [
270 'UNKNOWN',
272 'third_party/libusb/src/libusb/version.h': [
273 'UNKNOWN',
275 'third_party/libusb/src/autogen.sh': [
276 'UNKNOWN',
278 'third_party/libusb/src/config.h': [
279 'UNKNOWN',
281 'third_party/libusb/src/msvc/config.h': [
282 'UNKNOWN',
285 'third_party/libvpx/source': [ # http://crbug.com/98319
286 'UNKNOWN',
288 'third_party/libvpx/source/libvpx/examples/includes': [
289 'GPL (v2 or later)',
291 'third_party/libwebp': [ # http://crbug.com/98448
292 'UNKNOWN',
294 'third_party/libxml': [
295 'UNKNOWN',
297 'third_party/libxslt': [
298 'UNKNOWN',
300 'third_party/lzma_sdk': [
301 'UNKNOWN',
303 'third_party/mesa/MesaLib': [
304 'GPL (v2)',
305 'GPL (v3 or later)',
306 'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception',
307 'UNKNOWN', # http://crbug.com/98450
309 'third_party/modp_b64': [
310 'UNKNOWN',
312 'third_party/npapi/npspy/extern/java': [
313 'GPL (unversioned/unknown version)',
315 'third_party/openmax_dl/dl' : [
316 'Khronos Group',
318 'third_party/openssl': [ # http://crbug.com/98451
319 'UNKNOWN',
321 'third_party/ots/tools/ttf-checksum.py': [ # http://code.google.com/p/ots/issues/detail?id=2
322 'UNKNOWN',
324 'third_party/molokocacao': [ # http://crbug.com/98453
325 'UNKNOWN',
327 'third_party/npapi/npspy': [
328 'UNKNOWN',
330 'third_party/ocmock/OCMock': [ # http://crbug.com/98454
331 'UNKNOWN',
333 'third_party/ply/__init__.py': [
334 'UNKNOWN',
336 'third_party/protobuf': [ # http://crbug.com/98455
337 'UNKNOWN',
340 # http://crbug.com/222831
341 # https://bitbucket.org/eliben/pyelftools/issue/12
342 'third_party/pyelftools': [
343 'UNKNOWN',
346 'third_party/pylib': [
347 'UNKNOWN',
349 'third_party/scons-2.0.1/engine/SCons': [ # http://crbug.com/98462
350 'UNKNOWN',
352 'third_party/simplejson': [
353 'UNKNOWN',
355 'third_party/skia': [ # http://crbug.com/98463
356 'UNKNOWN',
358 'third_party/snappy/src': [ # http://crbug.com/98464
359 'UNKNOWN',
361 'third_party/smhasher/src': [ # http://crbug.com/98465
362 'UNKNOWN',
364 'third_party/sqlite': [
365 'UNKNOWN',
367 'third_party/swig/Lib/linkruntime.c': [ # http://crbug.com/98585
368 'UNKNOWN',
370 'third_party/talloc': [
371 'GPL (v3 or later)',
372 'UNKNOWN', # http://crbug.com/98588
374 'third_party/tcmalloc': [
375 'UNKNOWN', # http://crbug.com/98589
377 'third_party/tlslite': [
378 'UNKNOWN',
380 'third_party/webdriver': [ # http://crbug.com/98590
381 'UNKNOWN',
383 'third_party/webrtc': [ # http://crbug.com/98592
384 'UNKNOWN',
386 'third_party/xdg-utils': [ # http://crbug.com/98593
387 'UNKNOWN',
389 'third_party/yasm/source': [ # http://crbug.com/98594
390 'UNKNOWN',
392 'third_party/zlib/contrib/minizip': [
393 'UNKNOWN',
395 'third_party/zlib/trees.h': [
396 'UNKNOWN',
398 'tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py': [
399 'UNKNOWN',
401 'tools/emacs': [ # http://crbug.com/98595
402 'UNKNOWN',
404 'tools/grit/grit/node/custom/__init__.py': [
405 'UNKNOWN',
407 'tools/gyp/test': [
408 'UNKNOWN',
410 'tools/histograms': [
411 'UNKNOWN',
413 'tools/memory_watcher': [
414 'UNKNOWN',
416 'tools/playback_benchmark': [
417 'UNKNOWN',
419 'tools/python/google/__init__.py': [
420 'UNKNOWN',
422 'tools/site_compare': [
423 'UNKNOWN',
425 'tools/stats_viewer/Properties/AssemblyInfo.cs': [
426 'UNKNOWN',
428 'tools/symsrc/pefile.py': [
429 'UNKNOWN',
431 'v8/test/cctest': [ # http://crbug.com/98597
432 'UNKNOWN',
434 'webkit/data/ico_decoder': [
435 'UNKNOWN',
440 def check_licenses(options, args):
441 # Figure out which directory we have to check.
442 if len(args) == 0:
443 # No directory to check specified, use the repository root.
444 start_dir = options.base_directory
445 elif len(args) == 1:
446 # Directory specified. Start here. It's supposed to be relative to the
447 # base directory.
448 start_dir = os.path.abspath(os.path.join(options.base_directory, args[0]))
449 else:
450 # More than one argument, we don't handle this.
451 PrintUsage()
452 return 1
454 print "Using base directory:", options.base_directory
455 print "Checking:", start_dir
456 print
458 licensecheck_path = os.path.abspath(os.path.join(options.base_directory,
459 'third_party',
460 'devscripts',
461 'licensecheck.pl'))
463 licensecheck = subprocess.Popen([licensecheck_path,
464 '-l', '100',
465 '-r', start_dir],
466 stdout=subprocess.PIPE,
467 stderr=subprocess.PIPE)
468 stdout, stderr = licensecheck.communicate()
469 if options.verbose:
470 print '----------- licensecheck stdout -----------'
471 print stdout
472 print '--------- end licensecheck stdout ---------'
473 if licensecheck.returncode != 0 or stderr:
474 print '----------- licensecheck stderr -----------'
475 print stderr
476 print '--------- end licensecheck stderr ---------'
477 print "\nFAILED\n"
478 return 1
480 success = True
481 for line in stdout.splitlines():
482 filename, license = line.split(':', 1)
483 filename = os.path.relpath(filename.strip(), options.base_directory)
485 # All files in the build output directory are generated one way or another.
486 # There's no need to check them.
487 if filename.startswith('out/') or filename.startswith('sconsbuild/'):
488 continue
490 # For now we're just interested in the license.
491 license = license.replace('*No copyright*', '').strip()
493 # Skip generated files.
494 if 'GENERATED FILE' in license:
495 continue
497 if license in WHITELISTED_LICENSES:
498 continue
500 if not options.ignore_suppressions:
501 found_path_specific = False
502 for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES:
503 if (filename.startswith(prefix) and
504 license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]):
505 found_path_specific = True
506 break
507 if found_path_specific:
508 continue
510 print "'%s' has non-whitelisted license '%s'" % (filename, license)
511 success = False
513 if success:
514 print "\nSUCCESS\n"
515 return 0
516 else:
517 print "\nFAILED\n"
518 print "Please read",
519 print "http://www.chromium.org/developers/adding-3rd-party-libraries"
520 print "for more info how to handle the failure."
521 print
522 print "Please respect OWNERS of checklicenses.py. Changes violating"
523 print "this requirement may be reverted."
524 return 1
527 def main():
528 default_root = os.path.abspath(
529 os.path.join(os.path.dirname(__file__), '..', '..'))
530 option_parser = optparse.OptionParser()
531 option_parser.add_option('--root', default=default_root,
532 dest='base_directory',
533 help='Specifies the repository root. This defaults '
534 'to "../.." relative to the script file, which '
535 'will normally be the repository root.')
536 option_parser.add_option('-v', '--verbose', action='store_true',
537 default=False, help='Print debug logging')
538 option_parser.add_option('--ignore-suppressions',
539 action='store_true',
540 default=False,
541 help='Ignore path-specific license whitelist.')
542 options, args = option_parser.parse_args()
543 return check_licenses(options, args)
546 if '__main__' == __name__:
547 sys.exit(main())