Home | History | Annotate | Download | only in gn
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2016 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 # Generate Android.bp for Skia from GN configuration.
      9 
     10 import json
     11 import os
     12 import pprint
     13 import string
     14 import subprocess
     15 import tempfile
     16 
     17 import gn_to_bp_utils
     18 
     19 # First we start off with a template for Android.bp,
     20 # with holes for source lists and include directories.
     21 bp = string.Template('''// This file is autogenerated by gn_to_bp.py.
     22 
     23 cc_library_static {
     24     name: "libskia",
     25     cflags: [
     26         $cflags
     27     ],
     28 
     29     cppflags:[
     30         $cflags_cc
     31     ],
     32 
     33     export_include_dirs: [
     34         $export_includes
     35     ],
     36 
     37     local_include_dirs: [
     38         $local_includes
     39     ],
     40 
     41     srcs: [
     42         $srcs
     43     ],
     44 
     45     arch: {
     46         arm: {
     47             srcs: [
     48                 $arm_srcs
     49             ],
     50 
     51             neon: {
     52                 srcs: [
     53                     $arm_neon_srcs
     54                 ],
     55             },
     56         },
     57 
     58         arm64: {
     59             srcs: [
     60                 $arm64_srcs
     61             ],
     62         },
     63 
     64         mips: {
     65             srcs: [
     66                 $none_srcs
     67             ],
     68         },
     69 
     70         mips64: {
     71             srcs: [
     72                 $none_srcs
     73             ],
     74         },
     75 
     76         x86: {
     77             srcs: [
     78                 $x86_srcs
     79             ],
     80             cflags: [
     81                 // Clang seems to think new/malloc will only be 4-byte aligned
     82                 // on x86 Android. We're pretty sure it's actually 8-byte
     83                 // alignment. tests/OverAlignedTest.cpp has more information,
     84                 // and should fail if we're wrong.
     85                 "-Wno-over-aligned"
     86             ],
     87         },
     88 
     89         x86_64: {
     90             srcs: [
     91                 $x86_srcs
     92             ],
     93         },
     94     },
     95 
     96     defaults: ["skia_deps",
     97                "skia_pgo",
     98     ],
     99 }
    100 
    101 // Build libskia with PGO by default.
    102 // Location of PGO profile data is defined in build/soong/cc/pgo.go
    103 // and is separate from skia.
    104 // To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
    105 // or set enable_profile_use property to false.
    106 cc_defaults {
    107     name: "skia_pgo",
    108     pgo: {
    109         instrumentation: true,
    110         profile_file: "hwui/hwui.profdata",
    111         benchmarks: ["hwui", "skia"],
    112         enable_profile_use: true,
    113     },
    114 }
    115 
    116 // "defaults" property to disable profile use for Skia tools and benchmarks.
    117 cc_defaults {
    118     name: "skia_pgo_no_profile_use",
    119     defaults: [
    120         "skia_pgo",
    121     ],
    122     pgo: {
    123         enable_profile_use: false,
    124     },
    125 }
    126 
    127 cc_defaults {
    128     name: "skia_deps",
    129     shared_libs: [
    130         "libEGL",
    131         "libGLESv2",
    132         "libdng_sdk",
    133         "libexpat",
    134         "libft2",
    135         "libheif",
    136         "libicui18n",
    137         "libicuuc",
    138         "libjpeg",
    139         "liblog",
    140         "libpiex",
    141         "libpng",
    142         "libvulkan",
    143         "libz",
    144         "libcutils",
    145         "libnativewindow",
    146     ],
    147     static_libs: [
    148         "libarect",
    149         "libsfntly",
    150         "libwebp-decode",
    151         "libwebp-encode",
    152     ],
    153     group_static_libs: true,
    154 }
    155 
    156 cc_defaults {
    157     name: "skia_tool_deps",
    158     defaults: [
    159         "skia_deps",
    160         "skia_pgo_no_profile_use"
    161     ],
    162     static_libs: [
    163         "libjsoncpp",
    164         "libskia",
    165     ],
    166     cflags: [
    167         "-Wno-unused-parameter",
    168         "-Wno-unused-variable",
    169     ],
    170 }
    171 
    172 cc_test {
    173     name: "skia_dm",
    174 
    175     defaults: [
    176         "skia_tool_deps"
    177     ],
    178 
    179     local_include_dirs: [
    180         $dm_includes
    181     ],
    182 
    183     srcs: [
    184         $dm_srcs
    185     ],
    186 
    187     shared_libs: [
    188         "libbinder",
    189         "libutils",
    190     ],
    191 }
    192 
    193 cc_test {
    194     name: "skia_nanobench",
    195 
    196     defaults: [
    197         "skia_tool_deps"
    198     ],
    199 
    200     local_include_dirs: [
    201         $nanobench_includes
    202     ],
    203 
    204     srcs: [
    205         $nanobench_srcs
    206     ],
    207 
    208     data: [
    209         "resources/*",
    210     ],
    211 }''')
    212 
    213 # We'll run GN to get the main source lists and include directories for Skia.
    214 gn_args = {
    215   'is_official_build':  'true',
    216   'skia_enable_tools':  'true',
    217   'skia_use_libheif':   'true',
    218   'skia_use_vulkan':    'true',
    219   'target_cpu':         '"none"',
    220   'target_os':          '"android"',
    221   'skia_vulkan_header': '"Skia_Vulkan_Android.h"',
    222 }
    223 
    224 js = gn_to_bp_utils.GenerateJSONFromGN(gn_args)
    225 
    226 def strip_slashes(lst):
    227   return {str(p.lstrip('/')) for p in lst}
    228 
    229 srcs            = strip_slashes(js['targets']['//:skia']['sources'])
    230 cflags          = strip_slashes(js['targets']['//:skia']['cflags'])
    231 cflags_cc       = strip_slashes(js['targets']['//:skia']['cflags_cc'])
    232 local_includes  = strip_slashes(js['targets']['//:skia']['include_dirs'])
    233 export_includes = strip_slashes(js['targets']['//:public']['include_dirs'])
    234 defines      = [str(d) for d in js['targets']['//:skia']['defines']]
    235 
    236 dm_srcs         = strip_slashes(js['targets']['//:dm']['sources'])
    237 dm_includes     = strip_slashes(js['targets']['//:dm']['include_dirs'])
    238 
    239 nanobench_target = js['targets']['//:nanobench']
    240 nanobench_srcs     = strip_slashes(nanobench_target['sources'])
    241 nanobench_includes = strip_slashes(nanobench_target['include_dirs'])
    242 
    243 gn_to_bp_utils.GrabDependentValues(js, '//:skia', 'sources', srcs, None)
    244 gn_to_bp_utils.GrabDependentValues(js, '//:dm', 'sources', dm_srcs, 'skia')
    245 gn_to_bp_utils.GrabDependentValues(js, '//:nanobench', 'sources',
    246                                    nanobench_srcs, 'skia')
    247 
    248 # No need to list headers.
    249 srcs            = {s for s in srcs           if not s.endswith('.h')}
    250 dm_srcs         = {s for s in dm_srcs        if not s.endswith('.h')}
    251 nanobench_srcs  = {s for s in nanobench_srcs if not s.endswith('.h')}
    252 
    253 cflags = gn_to_bp_utils.CleanupCFlags(cflags)
    254 cflags_cc = gn_to_bp_utils.CleanupCCFlags(cflags_cc)
    255 
    256 # We need to add the include path to the vulkan defines and header file set in
    257 # then skia_vulkan_header gn arg that is used for framework builds.
    258 local_includes.add("platform_tools/android/vulkan")
    259 export_includes.add("platform_tools/android/vulkan")
    260 
    261 here = os.path.dirname(__file__)
    262 defs = gn_to_bp_utils.GetArchSources(os.path.join(here, 'opts.gni'))
    263 
    264 gn_to_bp_utils.WriteUserConfig('include/config/SkUserConfig.h', defines)
    265 
    266 # Turn a list of strings into the style bpfmt outputs.
    267 def bpfmt(indent, lst, sort=True):
    268   if sort:
    269     lst = sorted(lst)
    270   return ('\n' + ' '*indent).join('"%s",' % v for v in lst)
    271 
    272 # OK!  We have everything to fill in Android.bp...
    273 with open('Android.bp', 'w') as f:
    274   print >>f, bp.substitute({
    275     'export_includes': bpfmt(8, export_includes),
    276     'local_includes':  bpfmt(8, local_includes),
    277     'srcs':            bpfmt(8, srcs),
    278     'cflags':          bpfmt(8, cflags, False),
    279     'cflags_cc':       bpfmt(8, cflags_cc),
    280 
    281     'arm_srcs':      bpfmt(16, defs['armv7']),
    282     'arm_neon_srcs': bpfmt(20, defs['neon']),
    283     'arm64_srcs':    bpfmt(16, defs['arm64'] +
    284                                defs['crc32']),
    285     'none_srcs':     bpfmt(16, defs['none']),
    286     'x86_srcs':      bpfmt(16, defs['sse2'] +
    287                                defs['ssse3'] +
    288                                defs['sse41'] +
    289                                defs['sse42'] +
    290                                defs['avx'  ]),
    291 
    292     'dm_includes'       : bpfmt(8, dm_includes),
    293     'dm_srcs'           : bpfmt(8, dm_srcs),
    294 
    295     'nanobench_includes'    : bpfmt(8, nanobench_includes),
    296     'nanobench_srcs'        : bpfmt(8, nanobench_srcs),
    297   })
    298