Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 
      3 # Copyright 2017 Google Inc.
      4 #
      5 # Use of this source code is governed by a BSD-style license that can be
      6 # found in the LICENSE file.
      7 
      8 import fnmatch
      9 import multiprocessing
     10 import os
     11 import subprocess
     12 import sys
     13 
     14 
     15 public_header_args = [
     16     '-Iinclude/core',
     17     '-Iinclude/config',
     18     '-Iinclude/android',
     19     '-Iinclude/codec',
     20     '-Iinclude/effects',
     21     '-Iinclude/gpu',
     22     '-Iinclude/gpu/gl',
     23     '-Iinclude/pathops',
     24     '-Iinclude/ports',
     25     '-Iinclude/private',
     26     '-Iinclude/svg',
     27     '-Iinclude/utils',
     28     '-Iinclude/utils/mac',
     29     '-Iinclude/views',
     30 ]
     31 
     32 all_header_args = [
     33     '-Iinclude/core',
     34     '-Iinclude/config',
     35     '-Iinclude/android',
     36     '-Iinclude/c',
     37     '-Iinclude/codec',
     38     '-Iinclude/effects',
     39     '-Iinclude/gpu',
     40     '-Iinclude/gpu/gl',
     41     '-Iinclude/pathops',
     42     '-Iinclude/ports',
     43     '-Iinclude/private',
     44     '-Iinclude/svg',
     45     '-Iinclude/utils',
     46     '-Iinclude/utils/mac',
     47     '-Iinclude/views',
     48     '-Isrc/codec',
     49     '-Isrc/core',
     50     '-Isrc/effects',
     51     '-Isrc/effects/gradients',
     52     '-Isrc/fonts',
     53     '-Isrc/gpu',
     54     '-Isrc/image',
     55     '-Isrc/images',
     56     '-Isrc/lazy',
     57     '-Isrc/opts',
     58     '-Isrc/pathops',
     59     '-Isrc/ports',
     60     '-Isrc/sfnt',
     61     '-Isrc/sksl',
     62     '-Isrc/utils',
     63     '-Isrc/utils/win',
     64     '-Isrc/xml',
     65     '-Igm',
     66     '-Itests',
     67     '-Itools',
     68     '-Itools/debugger',
     69     '-Itools/flags',
     70     '-Itools/gpu',
     71     '-Itools/timer',
     72     '-Ithird_party/etc1',
     73     '-Ithird_party/externals/jsoncpp/include',
     74     '-Ithird_party/externals/libjpeg-turbo',
     75     '-Ithird_party/externals/sfntly/cpp/src',
     76     '-Ithird_party/externals/zlib',
     77     '-Ithird_party/gif',
     78 ]
     79 
     80 ignore = [
     81     '*/lex.*.h',
     82     '*/osmesa_wrapper.h',
     83     'debugger/QT/*',
     84     'example/*',
     85     'experimental/*',
     86     'include/config/*',
     87     'include/core/SkPostConfig.h',
     88     'include/gpu/vk/*',
     89     'include/ports/SkFontMgr_android.h',
     90     'include/ports/SkFontMgr_fontconfig.h',
     91     'include/ports/SkTypeface_win.h',
     92     'include/private/*_impl.h',
     93     'include/utils/mac/SkCGUtils.h',
     94     'include/views/SkOSWindow_*.h',
     95     'src/c/sk_c_from_to.h',
     96     'src/core/*Template.h',
     97     'src/core/SkBitmapProcState_*.h',
     98     'src/core/SkFDot6Constants.h',
     99     'src/core/SkLinearBitmapPipeline.h',
    100     'src/core/SkLinearBitmapPipeline_*.h',
    101     'src/core/SkUnPreMultiplyPriv.h',
    102     'src/gpu/vk/*.h',
    103     'src/opts/*_SSE2.h',
    104     'src/opts/*_SSSE3.h',
    105     'src/opts/*_neon.h',
    106     'src/opts/*_sse.h',
    107     'src/opts/Sk4px_*.h',
    108     'src/ports/*',
    109     'src/utils/*_win.h',
    110     'src/utils/win/*',
    111     'src/views/*',
    112     'third_party/*',
    113     'tools/fiddle/*',
    114     'tools/viewer/*',
    115 ]
    116 
    117 # test header for self-sufficiency and idempotency.
    118 # Returns a string containing errors, or None iff there are no errors.
    119 def compile_header(header):
    120     args = ([]                 if fnmatch.fnmatch(header, 'include/c/*') else
    121             public_header_args if fnmatch.fnmatch(header, 'include/*')   else
    122             all_header_args)
    123     cmd = ['c++', '--std=c++11'] + args + [ '-o', '/dev/null', '-c', '-x', 'c++', '-']
    124     proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
    125                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    126     proc.stdin.write('#include "%s"\n#include "%s"\n' % (header, header))
    127     proc.stdin.close()
    128     errors = proc.stdout.read().strip()
    129     if proc.wait() != 0 or len(errors) > 0:
    130         return '\n\033[7m ERROR: %s \033[0m\n%s\n\n' % (header, errors)
    131     return None
    132 
    133 def main():
    134     class N: good = True
    135     # N.good is a global scoped to main() to make a print_and_exit_if() a closure
    136     pool = multiprocessing.Pool()
    137     def print_and_exit_if(r):
    138         if r is not None:
    139             sys.stdout.write(r)
    140             N.good = False
    141             pool.terminate()
    142 
    143     os.chdir(os.path.join(os.path.dirname(__file__), os.pardir))
    144     for path in subprocess.check_output(['git', 'ls-files']).splitlines():
    145         if path.endswith('.h') and not any(fnmatch.fnmatch(path, pattern) for pattern in ignore):
    146             pool.apply_async(compile_header, args=(path, ), callback=print_and_exit_if)
    147     pool.close()
    148     pool.join()
    149     if N.good:
    150         sys.stdout.write('all good :)\n')
    151     else:
    152         exit(1)
    153 
    154 if __name__ == '__main__':
    155     main()
    156 
    157