check-headers-self-sufficient 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/env python
  2. # Copyright 2017 Google Inc.
  3. #
  4. # Use of this source code is governed by a BSD-style license that can be
  5. # found in the LICENSE file.
  6. import multiprocessing
  7. import os
  8. import re
  9. import subprocess
  10. import sys
  11. '''
  12. If called with arguments, this script will verify that those headers are
  13. self-sufficient and idempotent.
  14. Otherwise, test all checked-in headers except for those in the ignore list.
  15. '''
  16. ignore = re.compile('|'.join([
  17. r'debugger/QT/.*',
  18. r'example/.*',
  19. r'experimental/.*',
  20. r'include/config/.*',
  21. r'include/core/SkPostConfig\.h',
  22. r'include/gpu/mtl/.*',
  23. r'include/gpu/vk/.*',
  24. r'include/ports/SkFontMgr_android\.h',
  25. r'include/ports/SkFontMgr_fontconfig\.h',
  26. r'include/ports/SkFontMgr_fuchsia\.h',
  27. r'include/ports/SkTypeface_win\.h',
  28. r'include/private/.*_impl\.h',
  29. r'include/private/.*_neon\.h',
  30. r'include/private/.*_sse\.h',
  31. r'include/third_party/vulkan/.*',
  32. r'include/utils/mac/SkCGUtils\.h',
  33. r'include/views/SkOSWindow_.*\.h',
  34. r'modules/.*',
  35. r'platform_tools/.*',
  36. r'src/c/sk_c_from_to\.h',
  37. r'src/core/.*Template\.h',
  38. r'src/core/SkBitmapProcState_.*\.h',
  39. r'src/core/SkLinearBitmapPipeline\.h',
  40. r'src/core/SkLinearBitmapPipeline_.*\.h',
  41. r'src/gpu/mtl/.*',
  42. r'src/gpu/vk/.*',
  43. r'src/opts/.*_SSE2\.h',
  44. r'src/opts/.*_SSSE3\.h',
  45. r'src/opts/.*_neon\.h',
  46. r'src/opts/.*_sse\.h',
  47. r'src/opts/Sk4px_.*\.h',
  48. r'src/ports/.*',
  49. r'src/utils/.*_win\.h',
  50. r'src/utils/win/.*',
  51. r'src/views/.*',
  52. r'third_party/.*',
  53. r'tools/fiddle/.*',
  54. r'tools/gpu/vk/.*',
  55. r'tools/mdbviz/.*',
  56. r'tools/sk_app/.*',
  57. r'tools/viewer/.*',
  58. ]))
  59. # test header for self-sufficiency and idempotency.
  60. # Returns a string containing errors, or None iff there are no errors.
  61. def compile_header(header):
  62. cmd = ['c++', '--std=c++14', '-I.', '-o', '/dev/null', '-c', '-x', 'c++', '-']
  63. proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
  64. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  65. proc.stdin.write('#include "%s"\n#include "%s"\n' % (header, header))
  66. proc.stdin.close()
  67. errors = proc.stdout.read().strip()
  68. if proc.wait() != 0 or len(errors) > 0:
  69. return '\n\033[7m ERROR: %s \033[0m\n%s\n\n' % (header, errors)
  70. return None
  71. # for h in headers:
  72. # compile_header(h)
  73. # ...Except use a multiprocessing pool.
  74. # Exit at first error.
  75. def compile_headers(headers):
  76. class N: good = True
  77. # N.good is a global scoped to this function to make a print_and_exit_if() a closure
  78. pool = multiprocessing.Pool()
  79. def print_and_exit_if(r):
  80. if r is not None:
  81. sys.stdout.write(r)
  82. N.good = False
  83. pool.terminate()
  84. for path in headers:
  85. assert os.path.exists(path)
  86. pool.apply_async(compile_header, args=(path, ), callback=print_and_exit_if)
  87. pool.close()
  88. pool.join()
  89. if N.good:
  90. sys.stdout.write('all good :)\n')
  91. else:
  92. exit(1)
  93. def main(argv):
  94. skia_dir = os.path.join(os.path.dirname(__file__), os.pardir)
  95. if len(argv) > 1:
  96. paths = [os.path.relpath(os.path.abspath(arg), skia_dir) for arg in argv[1:]]
  97. os.chdir(skia_dir)
  98. else:
  99. os.chdir(skia_dir)
  100. paths = [path for path in subprocess.check_output(['git', 'ls-files']).splitlines()
  101. if path.endswith('.h') and not ignore.match(path)]
  102. compile_headers(paths)
  103. if __name__ == '__main__':
  104. main(sys.argv)