gn_to_bp_utils.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2018 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. # Generate Android.bp for Skia from GN configuration.
  8. import argparse
  9. import json
  10. import os
  11. import pprint
  12. import string
  13. import subprocess
  14. import tempfile
  15. parser = argparse.ArgumentParser(description='Process some cmdline flags.')
  16. parser.add_argument('--gn', dest='gn_cmd', default='gn')
  17. args = parser.parse_args()
  18. def GenerateJSONFromGN(gn_args):
  19. gn_args = ' '.join(sorted('%s=%s' % (k,v) for (k,v) in gn_args.iteritems()))
  20. tmp = tempfile.mkdtemp()
  21. subprocess.check_call([args.gn_cmd, 'gen', tmp, '--args=%s' % gn_args,
  22. '--ide=json'])
  23. return json.load(open(os.path.join(tmp, 'project.json')))
  24. def _strip_slash(lst):
  25. return {str(p.lstrip('/')) for p in lst}
  26. def GrabDependentValues(js, name, value_type, list_to_extend, exclude):
  27. # Grab the values from other targets that $name depends on (e.g. optional
  28. # Skia components, gms, tests, etc).
  29. for dep in js['targets'][name]['deps']:
  30. if 'modules' in dep:
  31. continue # Modules require special handling -- skip for now.
  32. if 'third_party' in dep:
  33. continue # We've handled all third-party DEPS as static or shared_libs.
  34. if 'none' in dep:
  35. continue # We'll handle all cpu-specific sources manually later.
  36. if exclude and exclude in dep:
  37. continue
  38. list_to_extend.update(_strip_slash(js['targets'][dep].get(value_type, [])))
  39. GrabDependentValues(js, dep, value_type, list_to_extend, exclude)
  40. def CleanupCFlags(cflags):
  41. # Only use the generated flags related to warnings.
  42. cflags = {s for s in cflags if s.startswith('-W')}
  43. # Add additional warning suppressions so we can build
  44. # third_party/vulkanmemoryallocator
  45. cflags = cflags.union([
  46. "-Wno-implicit-fallthrough",
  47. "-Wno-missing-field-initializers",
  48. "-Wno-thread-safety-analysis",
  49. "-Wno-unused-variable",
  50. ])
  51. # Add the rest of the flags we want.
  52. cflags = cflags.union([
  53. "-fvisibility=hidden",
  54. "-D_FORTIFY_SOURCE=1",
  55. "-DSKIA_DLL",
  56. "-DSKIA_IMPLEMENTATION=1",
  57. "-DATRACE_TAG=ATRACE_TAG_VIEW",
  58. "-DSK_PRINT_CODEC_MESSAGES",
  59. ])
  60. # We need to undefine FORTIFY_SOURCE before we define it. Insert it at the
  61. # beginning after sorting.
  62. cflags = sorted(cflags)
  63. cflags.insert(0, "-U_FORTIFY_SOURCE")
  64. return cflags
  65. def CleanupCCFlags(cflags_cc):
  66. # Only use the generated flags related to warnings.
  67. cflags_cc = {s for s in cflags_cc if s.startswith('-W')}
  68. # Add the rest of the flags we want.
  69. cflags_cc.add("-fexceptions")
  70. return cflags_cc
  71. def _get_path_info(path, kind):
  72. assert path == "../src"
  73. assert kind == "abspath"
  74. # While we want absolute paths in GN, relative paths work best here.
  75. return "src"
  76. def GetArchSources(opts_file):
  77. # For architecture specific files, it's easier to just read the same source
  78. # that GN does (opts.gni) rather than re-run GN once for each architecture.
  79. # This .gni file we want to read is close enough to Python syntax
  80. # that we can use execfile() if we supply definitions for GN builtins.
  81. builtins = { 'get_path_info': _get_path_info }
  82. defs = {}
  83. execfile(opts_file, builtins, defs)
  84. # Perform any string substitutions.
  85. for arch in defs:
  86. defs[arch] = [ p.replace('$_src', 'src') for p in defs[arch]]
  87. return defs
  88. def WriteUserConfig(userConfigPath, defines):
  89. # Most defines go into SkUserConfig.h
  90. defines.remove('NDEBUG') # Controlled by the Android build
  91. defines.remove('SKIA_IMPLEMENTATION=1') # don't export this define.
  92. if 'WIN32_LEAN_AND_MEAN' in defines: # Controlled by the Android build
  93. defines.remove('WIN32_LEAN_AND_MEAN')
  94. if '_HAS_EXCEPTIONS=0' in defines: # Controlled by the Android build
  95. defines.remove('_HAS_EXCEPTIONS=0')
  96. #... and all the #defines we want to put in SkUserConfig.h.
  97. with open(userConfigPath, 'w') as f:
  98. print >>f, '// DO NOT MODIFY! This file is autogenerated by gn_to_bp.py.'
  99. print >>f, '// If need to change a define, modify SkUserConfigManual.h'
  100. print >>f, '#pragma once'
  101. print >>f, '#include "SkUserConfigManual.h"'
  102. for define in sorted(defines):
  103. print >>f, '#define', define.replace('=', ' ')