• 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
10from __future__ import print_function
11
12import os
13import pprint
14import string
15import subprocess
16import tempfile
17
18import gn_to_bp_utils
19
20# First we start off with a template for Android.bp,
21# with holes for source lists and include directories.
22bp = string.Template('''// This file is autogenerated by gn_to_bp.py.
23// To make changes to this file, follow the instructions on skia.org for
24// downloading Skia and submitting changes. Modify gn_to_bp.py (or the build
25// files it uses) and submit. The autoroller will then create the updated
26// Android.bp. Or ask a Skia engineer for help.
27
28package {
29    default_applicable_licenses: ["external_skia_license"],
30}
31
32// Added automatically by a large-scale-change that took the approach of
33// 'apply every license found to every target'. While this makes sure we respect
34// every license restriction, it may not be entirely correct.
35//
36// e.g. GPL in an MIT project might only apply to the contrib/ directory.
37//
38// Please consider splitting the single license below into multiple licenses,
39// taking care not to lose any license_kind information, and overriding the
40// default license using the 'licenses: [...]' property on targets as needed.
41//
42// For unused files, consider creating a 'fileGroup' with "//visibility:private"
43// to attach the license to, and including a comment whether the files may be
44// used in the current project.
45//
46// large-scale-change included anything that looked like it might be a license
47// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
48//
49// Please consider removing redundant or irrelevant files from 'license_text:'.
50//
51// large-scale-change filtered out the below license kinds as false-positives:
52//   SPDX-license-identifier-CC-BY-NC
53//   SPDX-license-identifier-GPL-2.0
54//   SPDX-license-identifier-LGPL-2.1
55//   SPDX-license-identifier-OFL:by_exception_only
56// See: http://go/android-license-faq
57license {
58    name: "external_skia_license",
59    visibility: [":__subpackages__"],
60    license_kinds: [
61        "SPDX-license-identifier-Apache-2.0",
62        "SPDX-license-identifier-BSD",
63        "SPDX-license-identifier-CC0-1.0",
64        "SPDX-license-identifier-FTL",
65        "SPDX-license-identifier-MIT",
66        "SPDX-license-identifier-MPL",
67        "legacy_unencumbered",
68    ],
69    license_text: [
70        "LICENSE",
71        "NOTICE",
72    ],
73}
74
75cc_defaults {
76    name: "skia_defaults",
77    cflags: [
78        $cflags
79    ],
80
81    cppflags:[
82        $cflags_cc
83    ],
84
85    export_include_dirs: [
86        $export_includes
87    ],
88
89    local_include_dirs: [
90        $local_includes
91    ],
92
93    arch: {
94        arm: {
95            srcs: [
96                $arm_srcs
97            ],
98
99            neon: {
100                srcs: [
101                    $arm_neon_srcs
102                ],
103            },
104        },
105
106        arm64: {
107            srcs: [
108                $arm64_srcs
109            ],
110        },
111
112        x86: {
113            srcs: [
114                $x86_srcs
115            ],
116        },
117
118        x86_64: {
119            srcs: [
120                $x86_srcs
121            ],
122        },
123    },
124
125    target: {
126      android: {
127        srcs: [
128          "third_party/vulkanmemoryallocator/GrVulkanMemoryAllocator.cpp",
129        ],
130        local_include_dirs: [
131          "third_party/vulkanmemoryallocator/",
132        ],
133      },
134    },
135}
136
137cc_library_static {
138    // Smaller version of Skia, without e.g. codecs, intended for use by RenderEngine.
139    name: "libskia_renderengine",
140    defaults: ["skia_defaults",
141               "skia_renderengine_deps"],
142    srcs: [
143        $renderengine_srcs
144    ],
145    local_include_dirs: [
146        "renderengine",
147    ],
148    export_include_dirs: [
149        "renderengine",
150    ],
151}
152
153cc_library_static {
154    name: "libskia",
155    host_supported: true,
156    cppflags:[
157        // Exceptions are necessary for SkRawCodec.
158        // FIXME: Should we split SkRawCodec into a separate target so the rest
159        // of Skia need not be compiled with exceptions?
160        "-fexceptions",
161    ],
162
163    srcs: [
164        $srcs
165    ],
166
167    target: {
168      android: {
169        srcs: [
170          $android_srcs
171        ],
172        local_include_dirs: [
173          "android",
174        ],
175        export_include_dirs: [
176          "android",
177        ],
178      },
179      linux_glibc: {
180        srcs: [
181          $linux_srcs
182        ],
183        local_include_dirs: [
184          "linux",
185        ],
186        export_include_dirs: [
187          "linux",
188        ],
189      },
190      darwin: {
191        srcs: [
192          $mac_srcs
193        ],
194        local_include_dirs: [
195          "mac",
196        ],
197        export_include_dirs: [
198          "mac",
199        ],
200      },
201      windows: {
202        enabled: true,
203        cflags: [
204          "-Wno-unknown-pragmas",
205        ],
206        srcs: [
207          $win_srcs
208        ],
209        local_include_dirs: [
210          "win",
211        ],
212        export_include_dirs: [
213          "win",
214        ],
215      },
216    },
217
218    defaults: ["skia_deps",
219               "skia_pgo",
220               "skia_defaults",
221    ],
222}
223
224// Build libskia with PGO by default.
225// Location of PGO profile data is defined in build/soong/cc/pgo.go
226// and is separate from skia.
227// To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
228// or set enable_profile_use property to false.
229cc_defaults {
230    name: "skia_pgo",
231    pgo: {
232        instrumentation: true,
233        profile_file: "hwui/hwui.profdata",
234        benchmarks: ["hwui", "skia"],
235        enable_profile_use: true,
236    },
237}
238
239// "defaults" property to disable profile use for Skia tools and benchmarks.
240cc_defaults {
241    name: "skia_pgo_no_profile_use",
242    defaults: [
243        "skia_pgo",
244    ],
245    pgo: {
246        enable_profile_use: false,
247    },
248}
249
250cc_defaults {
251    // Subset of the larger "skia_deps", which includes only the dependencies
252    // needed for libskia_renderengine. Note that it includes libpng and libz
253    // for the purposes of MSKP captures, but we could instead leave it up to
254    // RenderEngine to provide its own SkSerializerProcs if another client
255    // wants an even smaller version of libskia.
256    name: "skia_renderengine_deps",
257    shared_libs: [
258        "libcutils",
259        "liblog",
260        "libpng",
261        "libz",
262    ],
263    static_libs: [
264        "libarect",
265    ],
266    group_static_libs: true,
267    target: {
268      android: {
269        shared_libs: [
270            "libEGL",
271            "libGLESv2",
272            "libvulkan",
273            "libnativewindow",
274        ],
275        export_shared_lib_headers: [
276            "libvulkan",
277        ],
278      },
279    },
280}
281
282cc_defaults {
283    name: "skia_deps",
284    defaults: ["skia_renderengine_deps"],
285    shared_libs: [
286        "libdng_sdk",
287        "libjpeg",
288        "libpiex",
289        "libexpat",
290        "libft2",
291    ],
292    static_libs: [
293        "libwebp-decode",
294        "libwebp-encode",
295        "libsfntly",
296    ],
297    target: {
298      android: {
299        shared_libs: [
300            "libheif",
301        ],
302      },
303      darwin: {
304        host_ldlibs: [
305            "-framework AppKit",
306        ],
307      },
308      windows: {
309        host_ldlibs: [
310            "-lgdi32",
311            "-loleaut32",
312            "-lole32",
313            "-lopengl32",
314            "-luuid",
315            "-lwindowscodecs",
316        ],
317      },
318    },
319}
320
321cc_defaults {
322    name: "skia_tool_deps",
323    defaults: [
324        "skia_deps",
325        "skia_pgo_no_profile_use"
326    ],
327    shared_libs: [
328        "libicu",
329        "libharfbuzz_ng",
330    ],
331    static_libs: [
332        "libskia",
333    ],
334    cflags: [
335        "-DSK_SHAPER_HARFBUZZ_AVAILABLE",
336        "-DSK_UNICODE_AVAILABLE",
337        "-Wno-implicit-fallthrough",
338        "-Wno-unused-parameter",
339        "-Wno-unused-variable",
340    ],
341    target: {
342      windows: {
343        enabled: true,
344      },
345    },
346}
347
348cc_test {
349    name: "skia_dm",
350
351    defaults: [
352        "skia_tool_deps"
353    ],
354
355    local_include_dirs: [
356        $dm_includes
357    ],
358
359    srcs: [
360        $dm_srcs
361    ],
362
363    shared_libs: [
364        "libbinder",
365        "libutils",
366    ],
367}
368
369cc_test {
370    name: "skia_nanobench",
371
372    defaults: [
373        "skia_tool_deps"
374    ],
375
376    local_include_dirs: [
377        $nanobench_includes
378    ],
379
380    srcs: [
381        $nanobench_srcs
382    ],
383
384    data: [
385        "resources/**/*",
386    ],
387}''')
388
389# We'll run GN to get the main source lists and include directories for Skia.
390def generate_args(target_os, enable_gpu, renderengine = False):
391  d = {
392    'is_official_build':                    'true',
393
394    # gn_to_bp_utils' GetArchSources will take care of architecture-specific
395    # files.
396    'target_cpu':                           '"none"',
397
398    # Use the custom FontMgr, as the framework will handle fonts.
399    'skia_enable_fontmgr_custom_directory': 'false',
400    'skia_enable_fontmgr_custom_embedded':  'false',
401    'skia_enable_fontmgr_android':          'false',
402    'skia_enable_fontmgr_win':              'false',
403    'skia_enable_fontmgr_win_gdi':          'false',
404    'skia_use_fonthost_mac':                'false',
405
406    # enable features used in skia_nanobench
407    'skia_tools_require_resources':         'true',
408
409    'skia_use_fontconfig':                  'false',
410    'skia_include_multiframe_procs':        'false',
411    'skia_libgifcodec_path':                '"third_party/libgifcodec"',
412  }
413  d['target_os'] = target_os
414  if target_os == '"android"':
415    d['skia_enable_tools'] = 'true'
416    d['skia_include_multiframe_procs'] = 'true'
417
418  if enable_gpu:
419    d['skia_use_vulkan']   = 'true'
420  else:
421    d['skia_use_vulkan']   = 'false'
422    d['skia_enable_gpu']   = 'false'
423
424  if target_os == '"win"':
425    # The Android Windows build system does not provide FontSub.h
426    d['skia_use_xps'] = 'false'
427
428    # BUILDCONFIG.gn expects these to be set when building for Windows, but
429    # we're just creating Android.bp, so we don't need them. Populate with
430    # some placeholder values.
431    d['win_vc'] = '"placeholder_version"'
432    d['win_sdk_version'] = '"placeholder_version"'
433    d['win_toolchain_version'] = '"placeholder_version"'
434
435  if target_os == '"android"' and not renderengine:
436    d['skia_use_libheif']  = 'true'
437  else:
438    d['skia_use_libheif']  = 'false'
439
440  if renderengine:
441    d['skia_use_libpng_decode'] = 'false'
442    d['skia_use_libjpeg_turbo_decode'] = 'false'
443    d['skia_use_libjpeg_turbo_encode'] = 'false'
444    d['skia_use_libwebp_decode'] = 'false'
445    d['skia_use_libwebp_encode'] = 'false'
446    d['skia_use_libgifcodec'] = 'false'
447    d['skia_enable_pdf'] = 'false'
448    d['skia_use_freetype'] = 'false'
449    d['skia_use_fixed_gamma_text'] = 'false'
450    d['skia_use_expat'] = 'false'
451    d['skia_enable_fontmgr_custom_empty'] = 'false'
452  else:
453    d['skia_enable_android_utils'] = 'true'
454    d['skia_use_freetype'] = 'true'
455    d['skia_use_fixed_gamma_text'] = 'true'
456    d['skia_enable_fontmgr_custom_empty'] = 'true'
457
458  return d
459
460gn_args       = generate_args('"android"', True)
461gn_args_linux = generate_args('"linux"',   False)
462gn_args_mac   = generate_args('"mac"',     False)
463gn_args_win   = generate_args('"win"',     False)
464gn_args_renderengine  = generate_args('"android"', True, True)
465
466js = gn_to_bp_utils.GenerateJSONFromGN(gn_args)
467
468def strip_slashes(lst):
469  return {str(p.lstrip('/')) for p in lst}
470
471android_srcs    = strip_slashes(js['targets']['//:skia']['sources'])
472cflags          = strip_slashes(js['targets']['//:skia']['cflags'])
473cflags_cc       = strip_slashes(js['targets']['//:skia']['cflags_cc'])
474local_includes  = strip_slashes(js['targets']['//:skia']['include_dirs'])
475export_includes = strip_slashes(js['targets']['//:public']['include_dirs'])
476
477dm_srcs         = strip_slashes(js['targets']['//:dm']['sources'])
478dm_includes     = strip_slashes(js['targets']['//:dm']['include_dirs'])
479
480nanobench_target = js['targets']['//:nanobench']
481nanobench_srcs     = strip_slashes(nanobench_target['sources'])
482nanobench_includes = strip_slashes(nanobench_target['include_dirs'])
483
484gn_to_bp_utils.GrabDependentValues(js, '//:dm', 'sources', dm_srcs, 'skia')
485gn_to_bp_utils.GrabDependentValues(js, '//:nanobench', 'sources',
486                                   nanobench_srcs, 'skia')
487
488# skcms is a little special, kind of a second-party library.
489local_includes.add("include/third_party/skcms")
490dm_includes   .add("include/third_party/skcms")
491
492# Android's build will choke if we list headers.
493def strip_headers(sources):
494  return {s for s in sources if not s.endswith('.h')}
495
496gn_to_bp_utils.GrabDependentValues(js, '//:skia', 'sources', android_srcs, None)
497android_srcs    = strip_headers(android_srcs)
498
499js_linux        = gn_to_bp_utils.GenerateJSONFromGN(gn_args_linux)
500linux_srcs      = strip_slashes(js_linux['targets']['//:skia']['sources'])
501gn_to_bp_utils.GrabDependentValues(js_linux, '//:skia', 'sources', linux_srcs,
502                                   None)
503linux_srcs      = strip_headers(linux_srcs)
504
505js_mac          = gn_to_bp_utils.GenerateJSONFromGN(gn_args_mac)
506mac_srcs        = strip_slashes(js_mac['targets']['//:skia']['sources'])
507gn_to_bp_utils.GrabDependentValues(js_mac, '//:skia', 'sources', mac_srcs,
508                                   None)
509mac_srcs        = strip_headers(mac_srcs)
510
511js_win          = gn_to_bp_utils.GenerateJSONFromGN(gn_args_win)
512win_srcs        = strip_slashes(js_win['targets']['//:skia']['sources'])
513gn_to_bp_utils.GrabDependentValues(js_win, '//:skia', 'sources', win_srcs,
514                                   None)
515win_srcs        = strip_headers(win_srcs)
516
517srcs = android_srcs.intersection(linux_srcs).intersection(mac_srcs)
518srcs = srcs.intersection(win_srcs)
519android_srcs    = android_srcs.difference(srcs)
520linux_srcs      =   linux_srcs.difference(srcs)
521mac_srcs        =     mac_srcs.difference(srcs)
522win_srcs        =     win_srcs.difference(srcs)
523
524js_renderengine   = gn_to_bp_utils.GenerateJSONFromGN(gn_args_renderengine)
525renderengine_srcs = strip_slashes(
526    js_renderengine['targets']['//:skia']['sources'])
527gn_to_bp_utils.GrabDependentValues(js_renderengine, '//:skia', 'sources',
528                                   renderengine_srcs, None)
529renderengine_srcs = strip_headers(renderengine_srcs)
530
531dm_srcs         = strip_headers(dm_srcs)
532nanobench_srcs  = strip_headers(nanobench_srcs)
533
534cflags = gn_to_bp_utils.CleanupCFlags(cflags)
535cflags_cc = gn_to_bp_utils.CleanupCCFlags(cflags_cc)
536
537here = os.path.dirname(__file__)
538defs = gn_to_bp_utils.GetArchSources(os.path.join(here, 'opts.gni'))
539
540def get_defines(json):
541  return {str(d) for d in json['targets']['//:skia']['defines']}
542android_defines      = get_defines(js)
543linux_defines        = get_defines(js_linux)
544mac_defines          = get_defines(js_mac)
545win_defines          = get_defines(js_win)
546renderengine_defines = get_defines(js_renderengine)
547
548def mkdir_if_not_exists(path):
549  if not os.path.exists(path):
550    os.makedirs(path)
551mkdir_if_not_exists('android/include/config/')
552mkdir_if_not_exists('linux/include/config/')
553mkdir_if_not_exists('mac/include/config/')
554mkdir_if_not_exists('win/include/config/')
555mkdir_if_not_exists('renderengine/include/config/')
556
557platforms = { 'IOS', 'MAC', 'WIN', 'ANDROID', 'UNIX' }
558
559def disallow_platforms(config, desired):
560  with open(config, 'a') as f:
561    p = sorted(platforms.difference({ desired }))
562    s = '#if '
563    for i in range(len(p)):
564      s = s + 'defined(SK_BUILD_FOR_%s)' % p[i]
565      if i < len(p) - 1:
566        s += ' || '
567        if i % 2 == 1:
568          s += '\\\n    '
569    print(s, file=f)
570    print('    #error "Only SK_BUILD_FOR_%s should be defined!"' % desired, file=f)
571    print('#endif', file=f)
572
573def append_to_file(config, s):
574  with open(config, 'a') as f:
575    print(s, file=f)
576
577def write_android_config(config_path, defines):
578  gn_to_bp_utils.WriteUserConfig(config_path, defines)
579  append_to_file(config_path, '''
580#ifndef SK_BUILD_FOR_ANDROID
581    #error "SK_BUILD_FOR_ANDROID must be defined!"
582#endif''')
583  disallow_platforms(config_path, 'ANDROID')
584
585write_android_config('android/include/config/SkUserConfig.h', android_defines)
586write_android_config('renderengine/include/config/SkUserConfig.h', renderengine_defines)
587
588def write_config(config_path, defines, platform):
589  gn_to_bp_utils.WriteUserConfig(config_path, defines)
590  append_to_file(config_path, '''
591// Correct SK_BUILD_FOR flags that may have been set by
592// SkTypes.h/Android.bp
593#ifndef SK_BUILD_FOR_%s
594    #define SK_BUILD_FOR_%s
595#endif
596#ifdef SK_BUILD_FOR_ANDROID
597    #undef SK_BUILD_FOR_ANDROID
598#endif''' % (platform, platform))
599  disallow_platforms(config_path, platform)
600
601write_config('linux/include/config/SkUserConfig.h', linux_defines, 'UNIX')
602write_config('mac/include/config/SkUserConfig.h',   mac_defines, 'MAC')
603write_config('win/include/config/SkUserConfig.h',   win_defines, 'WIN')
604
605# Turn a list of strings into the style bpfmt outputs.
606def bpfmt(indent, lst, sort=True):
607  if sort:
608    lst = sorted(lst)
609  return ('\n' + ' '*indent).join('"%s",' % v for v in lst)
610
611# OK!  We have everything to fill in Android.bp...
612with open('Android.bp', 'w') as Android_bp:
613  print(bp.substitute({
614    'export_includes': bpfmt(8, export_includes),
615    'local_includes':  bpfmt(8, local_includes),
616    'srcs':            bpfmt(8, srcs),
617    'cflags':          bpfmt(8, cflags, False),
618    'cflags_cc':       bpfmt(8, cflags_cc),
619
620    'arm_srcs':      bpfmt(16, strip_headers(defs['armv7'])),
621    'arm_neon_srcs': bpfmt(20, strip_headers(defs['neon'])),
622    'arm64_srcs':    bpfmt(16, strip_headers(defs['arm64'] +
623                                             defs['crc32'])),
624    'x86_srcs':      bpfmt(16, strip_headers(defs['sse2'] +
625                                             defs['ssse3'] +
626                                             defs['sse41'] +
627                                             defs['sse42'] +
628                                             defs['avx'  ] +
629                                             defs['hsw'  ] +
630                                             defs['skx'  ])),
631
632    'dm_includes'       : bpfmt(8, dm_includes),
633    'dm_srcs'           : bpfmt(8, dm_srcs),
634
635    'nanobench_includes'    : bpfmt(8, nanobench_includes),
636    'nanobench_srcs'        : bpfmt(8, nanobench_srcs),
637
638    'android_srcs':  bpfmt(10, android_srcs),
639    'linux_srcs':    bpfmt(10, linux_srcs),
640    'mac_srcs':      bpfmt(10, mac_srcs),
641    'win_srcs':      bpfmt(10, win_srcs),
642
643    'renderengine_srcs': bpfmt(8, renderengine_srcs),
644  }), file=Android_bp)
645