Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / checklicenses / checklicenses.py
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.
5
6 """Makes sure that all files contain proper licensing information."""
7
8
9 import optparse
10 import os.path
11 import subprocess
12 import sys
13
14
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".
20
21   --ignore-suppressions  Ignores path-specific license whitelist. Useful when
22                          trying to remove a suppression/whitelist entry.
23
24   tocheck  Specifies the directory, relative to root, to check. This defaults
25            to "." so it checks everything.
26
27 Examples:
28   python checklicenses.py
29   python checklicenses.py --root ~/chromium/src third_party"""
30
31
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) ISC',
42     'BSD (2 clause) MIT/X11 (BSD like)',
43     'BSD (3 clause)',
44     'BSD (3 clause) GPL (v2)',
45     'BSD (3 clause) ISC',
46     'BSD (3 clause) LGPL (v2 or later)',
47     'BSD (3 clause) LGPL (v2.1 or later)',
48     'BSD (3 clause) MIT/X11 (BSD like)',
49     'BSD (4 clause)',
50     'BSD-like',
51
52     # TODO(phajdan.jr): Make licensecheck not print BSD-like twice.
53     'BSD-like MIT/X11 (BSD like)',
54
55     'BSL (v1.0)',
56     'GPL (v2) LGPL (v2.1 or later)',
57     'GPL (v2 or later) with Bison parser exception',
58     'GPL (v2 or later) with libtool exception',
59     'GPL (v3 or later) with Bison parser exception',
60     'GPL with Bison parser exception',
61     'ISC',
62     'LGPL (unversioned/unknown version)',
63     'LGPL (v2)',
64     'LGPL (v2 or later)',
65     'LGPL (v2.1)',
66     'LGPL (v2.1 or later)',
67     'LGPL (v3 or later)',
68     'MIT/X11 (BSD like)',
69     'MIT/X11 (BSD like) LGPL (v2.1 or later)',
70     'MPL (v1.0) LGPL (v2 or later)',
71     'MPL (v1.1)',
72     'MPL (v1.1) BSD (3 clause) GPL (v2) LGPL (v2.1 or later)',
73     'MPL (v1.1) BSD (3 clause) LGPL (v2.1 or later)',
74     'MPL (v1.1) BSD-like',
75     'MPL (v1.1) BSD-like GPL (unversioned/unknown version)',
76     'MPL (v1.1) BSD-like GPL (v2) LGPL (v2.1 or later)',
77     'MPL (v1.1) GPL (v2)',
78     'MPL (v1.1) GPL (v2) LGPL (v2 or later)',
79     'MPL (v1.1) GPL (v2) LGPL (v2.1 or later)',
80     'MPL (v1.1) GPL (unversioned/unknown version)',
81     'MPL (v1.1) LGPL (v2 or later)',
82     'MPL (v1.1) LGPL (v2.1 or later)',
83     'MPL (v2.0)',
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)',
94     ('University of Illinois/NCSA Open Source License (BSD like) '
95      'MIT/X11 (BSD like)'),
96 ]
97
98
99 PATH_SPECIFIC_WHITELISTED_LICENSES = {
100     'base/hash.cc': [  # http://crbug.com/98100
101         'UNKNOWN',
102     ],
103     'base/third_party/icu': [  # http://crbug.com/98087
104         'UNKNOWN',
105     ],
106
107     # http://code.google.com/p/google-breakpad/issues/detail?id=450
108     'breakpad/src': [
109         'UNKNOWN',
110     ],
111
112     'chrome/common/extensions/docs/examples': [  # http://crbug.com/98092
113         'UNKNOWN',
114     ],
115     'chrome/test/data/gpu/vt': [
116         'UNKNOWN',
117     ],
118     'courgette/third_party/bsdiff_create.cc': [  # http://crbug.com/98095
119         'UNKNOWN',
120     ],
121     'data/tab_switching': [
122         'UNKNOWN',
123     ],
124     'native_client': [  # http://crbug.com/98099
125         'UNKNOWN',
126     ],
127     'native_client/toolchain': [
128         'BSD GPL (v2 or later)',
129         'BSD (2 clause) GPL (v2 or later)',
130         'BSD (3 clause) GPL (v2 or later)',
131         'BSL (v1.0) GPL',
132         'BSL (v1.0) GPL (v3.1)',
133         'GPL',
134         'GPL (unversioned/unknown version)',
135         'GPL (v2)',
136         'GPL (v2 or later)',
137         'GPL (v3.1)',
138         'GPL (v3 or later)',
139     ],
140     'net/tools/spdyshark': [
141         'GPL (v2 or later)',
142         'UNKNOWN',
143     ],
144     'third_party/WebKit': [
145         'UNKNOWN',
146     ],
147
148     # http://code.google.com/p/angleproject/issues/detail?id=217
149     'third_party/angle': [
150         'UNKNOWN',
151     ],
152
153     # http://crbug.com/222828
154     # http://bugs.python.org/issue17514
155     'third_party/chromite/third_party/argparse.py': [
156         'UNKNOWN',
157     ],
158
159     # http://crbug.com/326117
160     # https://bitbucket.org/chrisatlee/poster/issue/21
161     'third_party/chromite/third_party/poster': [
162         'UNKNOWN',
163     ],
164
165     # http://crbug.com/333508
166     'third_party/clang_format/script': [
167         'UNKNOWN',
168     ],
169     'third_party/clang_format/scripts': [
170         'UNKNOWN',
171     ],
172
173     # Not used. http://crbug.com/156020
174     # Using third_party/cros_dbus_cplusplus/cros_dbus_cplusplus.gyp instead.
175     'third_party/cros_dbus_cplusplus/source/autogen.sh': [
176         'UNKNOWN',
177     ],
178     # Included in the source tree but not built. http://crbug.com/156020
179     'third_party/cros_dbus_cplusplus/source/examples': [
180         'UNKNOWN',
181     ],
182     'third_party/devscripts': [
183         'GPL (v2 or later)',
184     ],
185     'third_party/expat/files/lib': [  # http://crbug.com/98121
186         'UNKNOWN',
187     ],
188     'third_party/ffmpeg': [
189         'GPL',
190         'GPL (v2)',
191         'GPL (v2 or later)',
192         'UNKNOWN',  # http://crbug.com/98123
193     ],
194     'third_party/fontconfig': [
195         # https://bugs.freedesktop.org/show_bug.cgi?id=73401
196         'UNKNOWN',
197     ],
198     'third_party/freetype2': [ # http://crbug.com/177319
199         'UNKNOWN',
200     ],
201     'third_party/gles2_conform/GTF_ES': [  # http://crbug.com/98131
202         'UNKNOWN',
203     ],
204     'third_party/hunspell': [  # http://crbug.com/98134
205         'UNKNOWN',
206     ],
207     'third_party/iccjpeg': [  # http://crbug.com/98137
208         'UNKNOWN',
209     ],
210     'third_party/icu': [  # http://crbug.com/98301
211         'UNKNOWN',
212     ],
213     'third_party/jemalloc': [  # http://crbug.com/98302
214         'UNKNOWN',
215     ],
216     'third_party/JSON': [
217         'Perl',  # Build-only.
218         # License missing upstream on 3 minor files.
219         'UNKNOWN',  # https://rt.cpan.org/Public/Bug/Display.html?id=85915
220     ],
221     'third_party/lcov': [  # http://crbug.com/98304
222         'UNKNOWN',
223     ],
224     'third_party/lcov/contrib/galaxy/genflat.pl': [
225         'GPL (v2 or later)',
226     ],
227     'third_party/libc++/trunk/include/support/solaris': [
228         # http://llvm.org/bugs/show_bug.cgi?id=18291
229         'UNKNOWN',
230     ],
231     'third_party/libc++/trunk/src/support/solaris/xlocale.c': [
232         # http://llvm.org/bugs/show_bug.cgi?id=18291
233         'UNKNOWN',
234     ],
235     'third_party/libc++/trunk/test': [
236         # http://llvm.org/bugs/show_bug.cgi?id=18291
237         'UNKNOWN',
238     ],
239     'third_party/libevent': [  # http://crbug.com/98309
240         'UNKNOWN',
241     ],
242     'third_party/libjingle/source/talk': [  # http://crbug.com/98310
243         'UNKNOWN',
244     ],
245     'third_party/libjpeg': [  # http://crbug.com/98313
246         'UNKNOWN',
247     ],
248     'third_party/libjpeg_turbo': [  # http://crbug.com/98314
249         'UNKNOWN',
250     ],
251     'third_party/libpng': [  # http://crbug.com/98318
252         'UNKNOWN',
253     ],
254
255     # The following files lack license headers, but are trivial.
256     'third_party/libusb/src/libusb/os/poll_posix.h': [
257         'UNKNOWN',
258     ],
259
260     'third_party/libvpx/source': [  # http://crbug.com/98319
261         'UNKNOWN',
262     ],
263     'third_party/libvpx/source/libvpx/examples/includes': [
264         'GPL (v2 or later)',
265     ],
266     'third_party/libxml': [
267         'UNKNOWN',
268     ],
269     'third_party/libxslt': [
270         'UNKNOWN',
271     ],
272     'third_party/lzma_sdk': [
273         'UNKNOWN',
274     ],
275     'third_party/mesa/src': [
276         'GPL (v2)',
277         'GPL (v3 or later)',
278         'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception',
279         'UNKNOWN',  # http://crbug.com/98450
280     ],
281     'third_party/modp_b64': [
282         'UNKNOWN',
283     ],
284     'third_party/openmax_dl/dl' : [
285         'Khronos Group',
286     ],
287     'third_party/openssl': [  # http://crbug.com/98451
288         'UNKNOWN',
289     ],
290     'third_party/ots/tools/ttf-checksum.py': [  # http://code.google.com/p/ots/issues/detail?id=2
291         'UNKNOWN',
292     ],
293     'third_party/molokocacao': [  # http://crbug.com/98453
294         'UNKNOWN',
295     ],
296     'third_party/npapi/npspy': [
297         'UNKNOWN',
298     ],
299     'third_party/ocmock/OCMock': [  # http://crbug.com/98454
300         'UNKNOWN',
301     ],
302     'third_party/ply/__init__.py': [
303         'UNKNOWN',
304     ],
305     'third_party/protobuf': [  # http://crbug.com/98455
306         'UNKNOWN',
307     ],
308
309     # http://crbug.com/222831
310     # https://bitbucket.org/eliben/pyelftools/issue/12
311     'third_party/pyelftools': [
312         'UNKNOWN',
313     ],
314
315     'third_party/scons-2.0.1/engine/SCons': [  # http://crbug.com/98462
316         'UNKNOWN',
317     ],
318     'third_party/simplejson': [
319         'UNKNOWN',
320     ],
321     'third_party/skia': [  # http://crbug.com/98463
322         'UNKNOWN',
323     ],
324     'third_party/snappy/src': [  # http://crbug.com/98464
325         'UNKNOWN',
326     ],
327     'third_party/smhasher/src': [  # http://crbug.com/98465
328         'UNKNOWN',
329     ],
330     'third_party/speech-dispatcher/libspeechd.h': [
331         'GPL (v2 or later)',
332     ],
333     'third_party/sqlite': [
334         'UNKNOWN',
335     ],
336
337     # https://code.google.com/p/colorama/issues/detail?id=44
338     'tools/swarming_client/third_party/colorama': [
339         'UNKNOWN',
340     ],
341
342     # http://crbug.com/334668
343     # MIT license.
344     'tools/swarming_client/third_party/httplib2': [
345         'UNKNOWN',
346     ],
347
348     # http://crbug.com/334668
349     # Apache v2.0.
350     'tools/swarming_client/third_party/oauth2client': [
351         'UNKNOWN',
352     ],
353
354     # https://github.com/kennethreitz/requests/issues/1610
355     'tools/swarming_client/third_party/requests': [
356         'UNKNOWN',
357     ],
358
359     'third_party/swig/Lib/linkruntime.c': [  # http://crbug.com/98585
360         'UNKNOWN',
361     ],
362     'third_party/talloc': [
363         'GPL (v3 or later)',
364         'UNKNOWN',  # http://crbug.com/98588
365     ],
366     'third_party/tcmalloc': [
367         'UNKNOWN',  # http://crbug.com/98589
368     ],
369     'third_party/tlslite': [
370         'UNKNOWN',
371     ],
372     'third_party/webdriver': [  # http://crbug.com/98590
373         'UNKNOWN',
374     ],
375
376     # https://github.com/html5lib/html5lib-python/issues/125
377     # https://github.com/KhronosGroup/WebGL/issues/435
378     'third_party/webgl/src': [
379         'UNKNOWN',
380     ],
381
382     'third_party/webrtc': [  # http://crbug.com/98592
383         'UNKNOWN',
384     ],
385     'third_party/xdg-utils': [  # http://crbug.com/98593
386         'UNKNOWN',
387     ],
388     'third_party/yasm/source': [  # http://crbug.com/98594
389         'UNKNOWN',
390     ],
391     'third_party/zlib/contrib/minizip': [
392         'UNKNOWN',
393     ],
394     'third_party/zlib/trees.h': [
395         'UNKNOWN',
396     ],
397     'tools/emacs': [  # http://crbug.com/98595
398         'UNKNOWN',
399     ],
400     'tools/gyp/test': [
401         'UNKNOWN',
402     ],
403     'tools/histograms': [
404         'UNKNOWN',
405     ],
406     'tools/python/google/__init__.py': [
407         'UNKNOWN',
408     ],
409     'tools/stats_viewer/Properties/AssemblyInfo.cs': [
410         'UNKNOWN',
411     ],
412     'tools/symsrc/pefile.py': [
413         'UNKNOWN',
414     ],
415     'tools/telemetry/third_party/pyserial': [
416         # https://sourceforge.net/p/pyserial/feature-requests/35/
417         'UNKNOWN',
418     ],
419     'v8/test/cctest': [  # http://crbug.com/98597
420         'UNKNOWN',
421     ],
422 }
423
424
425 def check_licenses(options, args):
426   # Figure out which directory we have to check.
427   if len(args) == 0:
428     # No directory to check specified, use the repository root.
429     start_dir = options.base_directory
430   elif len(args) == 1:
431     # Directory specified. Start here. It's supposed to be relative to the
432     # base directory.
433     start_dir = os.path.abspath(os.path.join(options.base_directory, args[0]))
434   else:
435     # More than one argument, we don't handle this.
436     PrintUsage()
437     return 1
438
439   print "Using base directory:", options.base_directory
440   print "Checking:", start_dir
441   print
442
443   licensecheck_path = os.path.abspath(os.path.join(options.base_directory,
444                                                    'third_party',
445                                                    'devscripts',
446                                                    'licensecheck.pl'))
447
448   licensecheck = subprocess.Popen([licensecheck_path,
449                                    '-l', '100',
450                                    '-r', start_dir],
451                                   stdout=subprocess.PIPE,
452                                   stderr=subprocess.PIPE)
453   stdout, stderr = licensecheck.communicate()
454   if options.verbose:
455     print '----------- licensecheck stdout -----------'
456     print stdout
457     print '--------- end licensecheck stdout ---------'
458   if licensecheck.returncode != 0 or stderr:
459     print '----------- licensecheck stderr -----------'
460     print stderr
461     print '--------- end licensecheck stderr ---------'
462     print "\nFAILED\n"
463     return 1
464
465   used_suppressions = set()
466
467   success = True
468   for line in stdout.splitlines():
469     filename, license = line.split(':', 1)
470     filename = os.path.relpath(filename.strip(), options.base_directory)
471
472     # All files in the build output directory are generated one way or another.
473     # There's no need to check them.
474     if filename.startswith('out/'):
475       continue
476
477     # For now we're just interested in the license.
478     license = license.replace('*No copyright*', '').strip()
479
480     # Skip generated files.
481     if 'GENERATED FILE' in license:
482       continue
483
484     if license in WHITELISTED_LICENSES:
485       continue
486
487     if not options.ignore_suppressions:
488       matched_prefixes = [
489           prefix for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES
490           if filename.startswith(prefix) and
491           license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]]
492       if matched_prefixes:
493         used_suppressions.update(set(matched_prefixes))
494         continue
495
496     print "'%s' has non-whitelisted license '%s'" % (filename, license)
497     success = False
498
499   if success:
500     print "\nSUCCESS\n"
501
502     unused_suppressions = set(
503       PATH_SPECIFIC_WHITELISTED_LICENSES.keys()).difference(used_suppressions)
504     if unused_suppressions:
505       print "\nNOTE: unused suppressions detected:\n"
506       print '\n'.join(unused_suppressions)
507
508     return 0
509   else:
510     print "\nFAILED\n"
511     print "Please read",
512     print "http://www.chromium.org/developers/adding-3rd-party-libraries"
513     print "for more info how to handle the failure."
514     print
515     print "Please respect OWNERS of checklicenses.py. Changes violating"
516     print "this requirement may be reverted."
517
518     # Do not print unused suppressions so that above message is clearly
519     # visible and gets proper attention. Too much unrelated output
520     # would be distracting and make the important points easier to miss.
521
522     return 1
523
524
525 def main():
526   default_root = os.path.abspath(
527       os.path.join(os.path.dirname(__file__), '..', '..'))
528   option_parser = optparse.OptionParser()
529   option_parser.add_option('--root', default=default_root,
530                            dest='base_directory',
531                            help='Specifies the repository root. This defaults '
532                            'to "../.." relative to the script file, which '
533                            'will normally be the repository root.')
534   option_parser.add_option('-v', '--verbose', action='store_true',
535                            default=False, help='Print debug logging')
536   option_parser.add_option('--ignore-suppressions',
537                            action='store_true',
538                            default=False,
539                            help='Ignore path-specific license whitelist.')
540   options, args = option_parser.parse_args()
541   return check_licenses(options, args)
542
543
544 if '__main__' == __name__:
545   sys.exit(main())