• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
10import os
11import pprint
12import string
13import subprocess
14import tempfile
15
16import gn_to_bp_utils
17
18# First we start off with a template for Android.bp,
19# with holes for source lists and include directories.
20bp = string.Template('''// This file is autogenerated by gn_to_bp.py.
21
22cc_library_static {
23    name: "libskia",
24    host_supported: true,
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        },
81
82        x86_64: {
83            srcs: [
84                $x86_srcs
85            ],
86        },
87    },
88
89    target: {
90      android: {
91        srcs: [
92          $android_srcs
93          "third_party/vulkanmemoryallocator/GrVulkanMemoryAllocator.cpp",
94        ],
95        local_include_dirs: [
96          "android",
97          "third_party/vulkanmemoryallocator/",
98        ],
99        export_include_dirs: [
100          "android",
101        ],
102      },
103      linux_glibc: {
104        cflags: [
105          "-mssse3",
106        ],
107        srcs: [
108          $linux_srcs
109        ],
110        local_include_dirs: [
111          "linux",
112        ],
113        export_include_dirs: [
114          "linux",
115        ],
116      },
117      darwin: {
118        cflags: [
119          "-mssse3",
120        ],
121        srcs: [
122          $mac_srcs
123        ],
124        local_include_dirs: [
125          "mac",
126        ],
127        export_include_dirs: [
128          "mac",
129        ],
130      },
131      windows: {
132        cflags: [
133          "-mssse3",
134          "-Wno-unknown-pragmas",
135        ],
136        srcs: [
137          $win_srcs
138        ],
139        local_include_dirs: [
140          "win",
141        ],
142        export_include_dirs: [
143          "win",
144        ],
145      },
146    },
147
148    defaults: ["skia_deps",
149               "skia_pgo",
150    ],
151}
152
153// Build libskia with PGO by default.
154// Location of PGO profile data is defined in build/soong/cc/pgo.go
155// and is separate from skia.
156// To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
157// or set enable_profile_use property to false.
158cc_defaults {
159    name: "skia_pgo",
160    pgo: {
161        instrumentation: true,
162        profile_file: "hwui/hwui.profdata",
163        benchmarks: ["hwui", "skia"],
164        enable_profile_use: true,
165    },
166}
167
168// "defaults" property to disable profile use for Skia tools and benchmarks.
169cc_defaults {
170    name: "skia_pgo_no_profile_use",
171    defaults: [
172        "skia_pgo",
173    ],
174    pgo: {
175        enable_profile_use: false,
176    },
177}
178
179cc_defaults {
180    name: "skia_deps",
181    shared_libs: [
182        "libandroidicu",
183        "libdng_sdk",
184        "libexpat",
185        "libft2",
186        "libjpeg",
187        "liblog",
188        "libpiex",
189        "libpng",
190        "libz",
191    ],
192    static_libs: [
193        "libarect",
194        "libsfntly",
195        "libwebp-decode",
196        "libwebp-encode",
197    ],
198    group_static_libs: true,
199    target: {
200      android: {
201        shared_libs: [
202            "libcutils",
203            "libEGL",
204            "libGLESv2",
205            "libheif",
206            "libvulkan",
207            "libnativewindow",
208        ],
209        export_shared_lib_headers: [
210            "libvulkan",
211        ],
212      },
213      host: {
214        static_libs: [
215          "libcutils",
216        ],
217      },
218      darwin: {
219        host_ldlibs: [
220            "-framework AppKit",
221        ],
222      },
223      windows: {
224        enabled: true,
225        host_ldlibs: [
226            "-lgdi32",
227            "-loleaut32",
228            "-lole32",
229            "-lopengl32",
230            "-luuid",
231            "-lwindowscodecs",
232        ],
233      },
234    },
235}
236
237cc_defaults {
238    name: "skia_tool_deps",
239    defaults: [
240        "skia_deps",
241        "skia_pgo_no_profile_use"
242    ],
243    static_libs: [
244        "libskia",
245    ],
246    cflags: [
247        "-Wno-implicit-fallthrough",
248        "-Wno-unused-parameter",
249        "-Wno-unused-variable",
250    ],
251}
252
253cc_test {
254    name: "skia_dm",
255
256    defaults: [
257        "skia_tool_deps"
258    ],
259
260    local_include_dirs: [
261        $dm_includes
262    ],
263
264    srcs: [
265        $dm_srcs
266    ],
267
268    shared_libs: [
269        "libbinder",
270        "libutils",
271    ],
272}
273
274cc_test {
275    name: "skia_nanobench",
276
277    defaults: [
278        "skia_tool_deps"
279    ],
280
281    local_include_dirs: [
282        $nanobench_includes
283    ],
284
285    srcs: [
286        $nanobench_srcs
287    ],
288
289    data: [
290        "resources/**/*",
291    ],
292}''')
293
294# We'll run GN to get the main source lists and include directories for Skia.
295def generate_args(target_os, enable_gpu):
296  d = {
297    'is_official_build':                  'true',
298
299    # gn_to_bp_utils' GetArchSources will take care of architecture-specific
300    # files.
301    'target_cpu':                         '"none"',
302
303    # Use the custom FontMgr, as the framework will handle fonts.
304    'skia_enable_fontmgr_custom':         'false',
305    'skia_enable_fontmgr_custom_empty':   'true',
306    'skia_enable_fontmgr_android':        'false',
307    'skia_enable_fontmgr_win':            'false',
308    'skia_enable_fontmgr_win_gdi':        'false',
309    'skia_use_fonthost_mac':              'false',
310
311    # enable features used in skia_nanobench
312    'skia_enable_sksl_interpreter':       'true',
313    'skia_tools_require_resources':       'true',
314
315    'skia_use_freetype':                  'true',
316    'skia_use_fontconfig':                'false',
317    'skia_use_fixed_gamma_text':          'true',
318    'skia_include_multiframe_procs':      'false',
319    'skia_libgifcodec_path':              '"third_party/libgifcodec"',
320  }
321  d['target_os'] = target_os
322  if target_os == '"android"':
323    d['skia_enable_tools'] = 'true'
324    d['skia_use_libheif']  = 'true'
325    d['skia_include_multiframe_procs'] = 'true'
326  else:
327    d['skia_use_libheif']  = 'false'
328
329  if enable_gpu:
330    d['skia_use_vulkan']   = 'true'
331  else:
332    d['skia_use_vulkan']   = 'false'
333    d['skia_enable_gpu']   = 'false'
334
335  if target_os == '"win"':
336    # The Android Windows build system does not provide FontSub.h
337    d['skia_use_xps'] = 'false'
338
339    # BUILDCONFIG.gn expects these to be set when building for Windows, but
340    # we're just creating Android.bp, so we don't need them. Populate with
341    # some dummy values.
342    d['win_vc'] = '"dummy_version"'
343    d['win_sdk_version'] = '"dummy_version"'
344    d['win_toolchain_version'] = '"dummy_version"'
345  return d
346
347gn_args       = generate_args('"android"', True)
348gn_args_linux = generate_args('"linux"',   False)
349gn_args_mac   = generate_args('"mac"',     False)
350gn_args_win   = generate_args('"win"',     False)
351
352js = gn_to_bp_utils.GenerateJSONFromGN(gn_args)
353
354def strip_slashes(lst):
355  return {str(p.lstrip('/')) for p in lst}
356
357android_srcs    = strip_slashes(js['targets']['//:skia']['sources'])
358cflags          = strip_slashes(js['targets']['//:skia']['cflags'])
359cflags_cc       = strip_slashes(js['targets']['//:skia']['cflags_cc'])
360local_includes  = strip_slashes(js['targets']['//:skia']['include_dirs'])
361export_includes = strip_slashes(js['targets']['//:public']['include_dirs'])
362
363dm_srcs         = strip_slashes(js['targets']['//:dm']['sources'])
364dm_includes     = strip_slashes(js['targets']['//:dm']['include_dirs'])
365
366nanobench_target = js['targets']['//:nanobench']
367nanobench_srcs     = strip_slashes(nanobench_target['sources'])
368nanobench_includes = strip_slashes(nanobench_target['include_dirs'])
369
370gn_to_bp_utils.GrabDependentValues(js, '//:dm', 'sources', dm_srcs, 'skia')
371gn_to_bp_utils.GrabDependentValues(js, '//:nanobench', 'sources',
372                                   nanobench_srcs, 'skia')
373
374# skcms is a little special, kind of a second-party library.
375local_includes.add("include/third_party/skcms")
376dm_includes   .add("include/third_party/skcms")
377
378# Android's build will choke if we list headers.
379def strip_headers(sources):
380  return {s for s in sources if not s.endswith('.h')}
381
382gn_to_bp_utils.GrabDependentValues(js, '//:skia', 'sources', android_srcs, None)
383android_srcs    = strip_headers(android_srcs)
384
385js_linux        = gn_to_bp_utils.GenerateJSONFromGN(gn_args_linux)
386linux_srcs      = strip_slashes(js_linux['targets']['//:skia']['sources'])
387gn_to_bp_utils.GrabDependentValues(js_linux, '//:skia', 'sources', linux_srcs,
388                                   None)
389linux_srcs      = strip_headers(linux_srcs)
390
391js_mac          = gn_to_bp_utils.GenerateJSONFromGN(gn_args_mac)
392mac_srcs        = strip_slashes(js_mac['targets']['//:skia']['sources'])
393gn_to_bp_utils.GrabDependentValues(js_mac, '//:skia', 'sources', mac_srcs,
394                                   None)
395mac_srcs        = strip_headers(mac_srcs)
396
397js_win          = gn_to_bp_utils.GenerateJSONFromGN(gn_args_win)
398win_srcs        = strip_slashes(js_win['targets']['//:skia']['sources'])
399gn_to_bp_utils.GrabDependentValues(js_win, '//:skia', 'sources', win_srcs,
400                                   None)
401win_srcs        = strip_headers(win_srcs)
402
403srcs = android_srcs.intersection(linux_srcs).intersection(mac_srcs)
404srcs = srcs.intersection(win_srcs)
405android_srcs    = android_srcs.difference(srcs)
406linux_srcs      =   linux_srcs.difference(srcs)
407mac_srcs        =     mac_srcs.difference(srcs)
408win_srcs        =     win_srcs.difference(srcs)
409dm_srcs         = strip_headers(dm_srcs)
410nanobench_srcs  = strip_headers(nanobench_srcs)
411
412cflags = gn_to_bp_utils.CleanupCFlags(cflags)
413cflags_cc = gn_to_bp_utils.CleanupCCFlags(cflags_cc)
414
415here = os.path.dirname(__file__)
416defs = gn_to_bp_utils.GetArchSources(os.path.join(here, 'opts.gni'))
417
418def get_defines(json):
419  return {str(d) for d in json['targets']['//:skia']['defines']}
420android_defines = get_defines(js)
421linux_defines   = get_defines(js_linux)
422mac_defines     = get_defines(js_mac)
423win_defines     = get_defines(js_win)
424
425def mkdir_if_not_exists(path):
426  if not os.path.exists(path):
427    os.makedirs(path)
428mkdir_if_not_exists('android/include/config/')
429mkdir_if_not_exists('linux/include/config/')
430mkdir_if_not_exists('mac/include/config/')
431mkdir_if_not_exists('win/include/config/')
432
433platforms = { 'IOS', 'MAC', 'WIN', 'ANDROID', 'UNIX' }
434
435def disallow_platforms(config, desired):
436  with open(config, 'a') as f:
437    p = sorted(platforms.difference({ desired }))
438    s = '#if '
439    for i in range(len(p)):
440      s = s + 'defined(SK_BUILD_FOR_%s)' % p[i]
441      if i < len(p) - 1:
442        s += ' || '
443        if i % 2 == 1:
444          s += '\\\n    '
445    print >>f, s
446    print >>f, '    #error "Only SK_BUILD_FOR_%s should be defined!"' % desired
447    print >>f, '#endif'
448
449def append_to_file(config, s):
450  with open(config, 'a') as f:
451    print >>f, s
452
453android_config = 'android/include/config/SkUserConfig.h'
454gn_to_bp_utils.WriteUserConfig(android_config, android_defines)
455append_to_file(android_config, '''
456#ifndef SK_BUILD_FOR_ANDROID
457    #error "SK_BUILD_FOR_ANDROID must be defined!"
458#endif''')
459disallow_platforms(android_config, 'ANDROID')
460
461def write_config(config_path, defines, platform):
462  gn_to_bp_utils.WriteUserConfig(config_path, defines)
463  append_to_file(config_path, '''
464// Correct SK_BUILD_FOR flags that may have been set by
465// SkTypes.h/Android.bp
466#ifndef SK_BUILD_FOR_%s
467    #define SK_BUILD_FOR_%s
468#endif
469#ifdef SK_BUILD_FOR_ANDROID
470    #undef SK_BUILD_FOR_ANDROID
471#endif''' % (platform, platform))
472  disallow_platforms(config_path, platform)
473
474write_config('linux/include/config/SkUserConfig.h', linux_defines, 'UNIX')
475write_config('mac/include/config/SkUserConfig.h',   mac_defines, 'MAC')
476write_config('win/include/config/SkUserConfig.h',   win_defines, 'WIN')
477
478# Turn a list of strings into the style bpfmt outputs.
479def bpfmt(indent, lst, sort=True):
480  if sort:
481    lst = sorted(lst)
482  return ('\n' + ' '*indent).join('"%s",' % v for v in lst)
483
484# OK!  We have everything to fill in Android.bp...
485with open('Android.bp', 'w') as Android_bp:
486  print >>Android_bp, bp.substitute({
487    'export_includes': bpfmt(8, export_includes),
488    'local_includes':  bpfmt(8, local_includes),
489    'srcs':            bpfmt(8, srcs),
490    'cflags':          bpfmt(8, cflags, False),
491    'cflags_cc':       bpfmt(8, cflags_cc),
492
493    'arm_srcs':      bpfmt(16, strip_headers(defs['armv7'])),
494    'arm_neon_srcs': bpfmt(20, strip_headers(defs['neon'])),
495    'arm64_srcs':    bpfmt(16, strip_headers(defs['arm64'] +
496                                             defs['crc32'])),
497    'none_srcs':     bpfmt(16, strip_headers(defs['none'])),
498    'x86_srcs':      bpfmt(16, strip_headers(defs['sse2'] +
499                                             defs['ssse3'] +
500                                             defs['sse41'] +
501                                             defs['sse42'] +
502                                             defs['avx'  ] +
503                                             defs['hsw'  ])),
504
505    'dm_includes'       : bpfmt(8, dm_includes),
506    'dm_srcs'           : bpfmt(8, dm_srcs),
507
508    'nanobench_includes'    : bpfmt(8, nanobench_includes),
509    'nanobench_srcs'        : bpfmt(8, nanobench_srcs),
510
511    'android_srcs':  bpfmt(10, android_srcs),
512    'linux_srcs':    bpfmt(10, linux_srcs),
513    'mac_srcs':      bpfmt(10, mac_srcs),
514    'win_srcs':      bpfmt(10, win_srcs),
515  })
516