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."""
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.
28 python checklicenses.py
29 python checklicenses.py --root ~/chromium/src third_party"""
32 WHITELISTED_LICENSES
= [
34 'Apache (v2.0) BSD (2 clause)',
35 'Apache (v2.0) GPL (v2)',
36 'Apple MIT', # https://fedoraproject.org/wiki/Licensing/Apple_MIT_License
38 'APSL (v2) BSD (4 clause)',
41 'BSD (2 clause) MIT/X11 (BSD like)',
43 'BSD (3 clause) GPL (v2)',
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)',
51 # TODO(phajdan.jr): Make licensecheck not print BSD-like twice.
52 'BSD-like MIT/X11 (BSD like)',
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',
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)',
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)',
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)',
87 'Public domain BSD (3 clause)',
88 'Public domain BSD-like',
89 'Public domain LGPL (v2.1 or later)',
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
101 'base/third_party/icu': [ # http://crbug.com/98087
105 # http://code.google.com/p/google-breakpad/issues/detail?id=450
110 'chrome/common/extensions/docs/examples': [ # http://crbug.com/98092
113 'chrome/test/data/gpu/vt': [
116 'chrome/test/data/layout_tests/LayoutTests': [
119 'courgette/third_party/bsdiff_create.cc': [ # http://crbug.com/98095
122 'data/mozilla_js_tests': [
125 'data/page_cycler': [
129 'data/tab_switching': [
132 'googleurl': [ # http://code.google.com/p/google-url/issues/detail?id=15
136 'native_client': [ # http://crbug.com/98099
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)',
144 'BSL (v1.0) GPL (v3.1)',
146 'GPL (unversioned/unknown version)',
152 'net/tools/spdyshark': [
156 'third_party/WebKit': [
159 'third_party/WebKit/Websites/webkit.org/blog/wp-content/plugins/'
160 'akismet/akismet.php': [
163 'third_party/WebKit/Source/JavaScriptCore/tests/mozilla': [
166 'GPL (unversioned/unknown version)',
168 'third_party/active_doc': [ # http://crbug.com/98113
172 # http://code.google.com/p/angleproject/issues/detail?id=217
173 'third_party/angle': [
177 'third_party/bsdiff/mbsdiff.cc': [
180 'third_party/bzip2': [
184 # http://crbug.com/222828
185 # http://bugs.python.org/issue17514
186 'third_party/chromite/third_party/argparse.py': [
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': [
195 # Included in the source tree but not built. http://crbug.com/156020
196 'third_party/cros_dbus_cplusplus/source/examples': [
199 'third_party/devscripts': [
202 'third_party/expat/files/lib': [ # http://crbug.com/98121
205 'third_party/ffmpeg': [
209 'UNKNOWN', # http://crbug.com/98123
211 'third_party/findbugs/doc': [ # http://crbug.com/157206
214 'third_party/freetype2': [ # http://crbug.com/177319
217 'third_party/gles2_book': [ # http://crbug.com/98130
220 'third_party/gles2_conform/GTF_ES': [ # http://crbug.com/98131
223 'third_party/harfbuzz': [ # http://crbug.com/98133
226 'third_party/hunspell': [ # http://crbug.com/98134
229 'third_party/hyphen/hyphen.tex': [ # http://crbug.com/157375
232 'third_party/iccjpeg': [ # http://crbug.com/98137
235 'third_party/icu': [ # http://crbug.com/98301
238 'third_party/jemalloc': [ # http://crbug.com/98302
241 'third_party/lcov': [ # http://crbug.com/98304
244 'third_party/lcov/contrib/galaxy/genflat.pl': [
247 'third_party/lcov-1.9/contrib/galaxy/genflat.pl': [
250 'third_party/libevent': [ # http://crbug.com/98309
253 'third_party/libjingle/source/talk': [ # http://crbug.com/98310
256 'third_party/libjingle/source_internal/talk': [ # http://crbug.com/98310
259 'third_party/libjpeg': [ # http://crbug.com/98313
262 'third_party/libjpeg_turbo': [ # http://crbug.com/98314
265 'third_party/libpng': [ # http://crbug.com/98318
269 # The following files lack license headers, but are trivial.
270 'third_party/libusb/src/libusb/os/poll_posix.h': [
273 'third_party/libusb/src/libusb/version.h': [
276 'third_party/libusb/src/autogen.sh': [
279 'third_party/libusb/src/config.h': [
282 'third_party/libusb/src/msvc/config.h': [
286 'third_party/libvpx/source': [ # http://crbug.com/98319
289 'third_party/libvpx/source/libvpx/examples/includes': [
292 'third_party/libwebp': [ # http://crbug.com/98448
295 'third_party/libxml': [
298 'third_party/libxslt': [
301 'third_party/lzma_sdk': [
304 'third_party/mesa/MesaLib': [
307 'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception',
308 'UNKNOWN', # http://crbug.com/98450
310 'third_party/modp_b64': [
313 'third_party/npapi/npspy/extern/java': [
314 'GPL (unversioned/unknown version)',
316 'third_party/openmax_dl/dl' : [
319 'third_party/openssl': [ # http://crbug.com/98451
322 'third_party/ots/tools/ttf-checksum.py': [ # http://code.google.com/p/ots/issues/detail?id=2
325 'third_party/molokocacao': [ # http://crbug.com/98453
328 'third_party/npapi/npspy': [
331 'third_party/ocmock/OCMock': [ # http://crbug.com/98454
334 'third_party/ply/__init__.py': [
337 'third_party/protobuf': [ # http://crbug.com/98455
341 # http://crbug.com/222831
342 # https://bitbucket.org/eliben/pyelftools/issue/12
343 'third_party/pyelftools': [
347 'third_party/pylib': [
350 'third_party/scons-2.0.1/engine/SCons': [ # http://crbug.com/98462
353 'third_party/simplejson': [
356 'third_party/skia': [ # http://crbug.com/98463
359 'third_party/snappy/src': [ # http://crbug.com/98464
362 'third_party/smhasher/src': [ # http://crbug.com/98465
365 'third_party/speech-dispatcher/libspeechd.h': [
368 'third_party/sqlite': [
371 'third_party/swig/Lib/linkruntime.c': [ # http://crbug.com/98585
374 'third_party/talloc': [
376 'UNKNOWN', # http://crbug.com/98588
378 'third_party/tcmalloc': [
379 'UNKNOWN', # http://crbug.com/98589
381 'third_party/tlslite': [
384 'third_party/webdriver': [ # http://crbug.com/98590
387 'third_party/webrtc': [ # http://crbug.com/98592
390 'third_party/xdg-utils': [ # http://crbug.com/98593
393 'third_party/yasm/source': [ # http://crbug.com/98594
396 'third_party/zlib/contrib/minizip': [
399 'third_party/zlib/trees.h': [
402 'tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py': [
405 'tools/emacs': [ # http://crbug.com/98595
408 'tools/grit/grit/node/custom/__init__.py': [
414 'tools/histograms': [
417 'tools/memory_watcher': [
420 'tools/playback_benchmark': [
423 'tools/python/google/__init__.py': [
426 'tools/site_compare': [
429 'tools/stats_viewer/Properties/AssemblyInfo.cs': [
432 'tools/symsrc/pefile.py': [
435 'v8/test/cctest': [ # http://crbug.com/98597
438 'webkit/data/ico_decoder': [
444 def check_licenses(options
, args
):
445 # Figure out which directory we have to check.
447 # No directory to check specified, use the repository root.
448 start_dir
= options
.base_directory
450 # Directory specified. Start here. It's supposed to be relative to the
452 start_dir
= os
.path
.abspath(os
.path
.join(options
.base_directory
, args
[0]))
454 # More than one argument, we don't handle this.
458 print "Using base directory:", options
.base_directory
459 print "Checking:", start_dir
462 licensecheck_path
= os
.path
.abspath(os
.path
.join(options
.base_directory
,
467 licensecheck
= subprocess
.Popen([licensecheck_path
,
470 stdout
=subprocess
.PIPE
,
471 stderr
=subprocess
.PIPE
)
472 stdout
, stderr
= licensecheck
.communicate()
474 print '----------- licensecheck stdout -----------'
476 print '--------- end licensecheck stdout ---------'
477 if licensecheck
.returncode
!= 0 or stderr
:
478 print '----------- licensecheck stderr -----------'
480 print '--------- end licensecheck stderr ---------'
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/'):
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
:
501 if license
in WHITELISTED_LICENSES
:
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
511 if found_path_specific
:
514 print "'%s' has non-whitelisted license '%s'" % (filename
, license
)
523 print "http://www.chromium.org/developers/adding-3rd-party-libraries"
524 print "for more info how to handle the failure."
526 print "Please respect OWNERS of checklicenses.py. Changes violating"
527 print "this requirement may be reverted."
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',
545 help='Ignore path-specific license whitelist.')
546 options
, args
= option_parser
.parse_args()
547 return check_licenses(options
, args
)
550 if '__main__' == __name__
: