1#!/usr/bin/env python
2
3from __future__ import print_function
4import locale
5import subprocess
6from collections import defaultdict
7locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
8
9header = """
10#
11#   #####   #######           #     #     #     #     #     #
12# ##     #  #     #          # #    #  #  #    # #     #   #
13# ##        #     #         #   #   #  #  #   #   #     # #
14# ##  ####  #     #        #     #  #  #  #  #     #     #
15# ##     #  #     #        #######  #  #  #  #######     #      ###
16# ##     #  #     #        #     #  #  #  #  #     #     #      ###
17# # #####   #######        #     #   ## ##   #     #     #      ###
18#
19# Seriously. You shouldn't even be looking at this file unless you're
20# debugging generate_mozbuild.py.
21#
22# DO NOT MODIFY THIS FILE IT IS AUTOGENERATED.
23#
24
25skia_opt_flags = []
26
27if CONFIG['MOZ_OPTIMIZE']:
28    if CONFIG['CC_TYPE'] == 'clang-cl':
29        skia_opt_flags += ['-O2']
30    elif CONFIG['CC_TYPE'] in ('clang', 'gcc'):
31        skia_opt_flags += ['-O3']
32
33"""
34
35footer = """
36
37# We allow warnings for third-party code that can be updated from upstream.
38AllowCompilerWarnings()
39
40FINAL_LIBRARY = 'gkmedias'
41LOCAL_INCLUDES += [
42    'skia',
43    'skia/include/third_party/skcms',
44]
45
46if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
47    DEFINES['UNICODE'] = True
48    DEFINES['_UNICODE'] = True
49    UNIFIED_SOURCES += [
50        'skia/src/fonts/SkFontMgr_indirect.cpp',
51        'skia/src/fonts/SkRemotableFontMgr.cpp',
52    ]
53
54# We should autogenerate these SSE related flags.
55
56if CONFIG['INTEL_ARCHITECTURE']:
57    SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
58    SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
59    SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-msse4.2']
60    SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
61    SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-mavx2', '-mf16c', '-mfma']
62elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
63    CXXFLAGS += CONFIG['NEON_FLAGS']
64elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
65    SOURCES['skia/src/opts/SkOpts_crc32.cpp'].flags += ['-march=armv8-a+crc']
66
67DEFINES['SKIA_IMPLEMENTATION'] = 1
68
69DEFINES['SK_PDF_USE_HARFBUZZ_SUBSETTING'] = 1
70
71if CONFIG['MOZ_TREE_FREETYPE']:
72    DEFINES['SK_CAN_USE_DLOPEN'] = 0
73
74# Reduce strength of synthetic-emboldening used in the freetype backend
75# (see bug 1600470).
76DEFINES['SK_OUTLINE_EMBOLDEN_DIVISOR'] = 48
77
78# Suppress warnings in third-party code.
79CXXFLAGS += [
80    '-Wno-deprecated-declarations',
81    '-Wno-overloaded-virtual',
82    '-Wno-shadow',
83    '-Wno-sign-compare',
84    '-Wno-unreachable-code',
85    '-Wno-unused-function',
86]
87if CONFIG['CC_TYPE'] == 'gcc':
88    CXXFLAGS += [
89        '-Wno-logical-op',
90        '-Wno-maybe-uninitialized',
91    ]
92if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'):
93    CXXFLAGS += [
94        '-Wno-implicit-fallthrough',
95        '-Wno-inconsistent-missing-override',
96        '-Wno-macro-redefined',
97        '-Wno-unused-private-field',
98    ]
99
100if CONFIG['MOZ_SYSTEM_HARFBUZZ']:
101    CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS']
102
103if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'android'):
104    CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
105    CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
106
107if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
108    CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
109"""
110
111import json
112
113platforms = ['linux', 'mac', 'android', 'win']
114
115def parse_sources(output):
116  return set(v.replace('//', 'skia/') for v in output.split() if v.endswith('.cpp') or v.endswith('.S'))
117
118def generate_opt_sources():
119  cpus = [('intel', 'x86', [':sse2', ':ssse3', ':sse41', ':sse42', ':avx', ':hsw']),
120          ('arm', 'arm', [':armv7']),
121          ('arm64', 'arm64', [':arm64', ':crc32']),
122          ('none', 'none', [':none'])]
123
124  opt_sources = {}
125  for key, cpu, deps in cpus:
126    subprocess.check_output('cd skia && bin/gn gen out/{0} --args=\'target_cpu="{1}"\''.format(key, cpu), shell=True)
127    opt_sources[key] = set()
128    for dep in deps:
129        try:
130            output = subprocess.check_output('cd skia && bin/gn desc out/{0} {1} sources'.format(key, dep), shell=True)
131            if output:
132                opt_sources[key].update(parse_sources(output))
133        except subprocess.CalledProcessError as e:
134            if e.output.find('source_set') < 0:
135                raise
136
137  return opt_sources
138
139def generate_platform_sources():
140  sources = {}
141  platform_args = {
142    'win' : 'win_vc="C:/" win_sdk_version="00.0.00000.0" win_toolchain_version="00.00.00000"'
143  }
144  for plat in platforms:
145    args = platform_args.get(plat, '')
146    output = subprocess.check_output('cd skia && bin/gn gen out/{0} --args=\'target_os="{0}" {1}\' > /dev/null && bin/gn desc out/{0} :skia sources'.format(plat, args), shell=True)
147    if output:
148      sources[plat] = parse_sources(output)
149
150  plat_deps = {':fontmgr_win' : 'win', ':fontmgr_win_gdi' : 'win'}
151  for dep, key in plat_deps.items():
152    output = subprocess.check_output('cd skia && bin/gn desc out/{1} {0} sources'.format(dep, key), shell=True)
153    if output:
154      sources[key].update(parse_sources(output))
155
156  deps = {':pdf' : 'pdf'}
157  for dep, key in deps.items():
158    output = subprocess.check_output('cd skia && bin/gn desc out/linux {} sources'.format(dep), shell=True)
159    if output:
160      sources[key] = parse_sources(output)
161
162  return dict(sources.items() + generate_opt_sources().items())
163
164
165def generate_separated_sources(platform_sources):
166  blacklist = [
167    'skia/src/android/',
168    'skia/src/atlastext/',
169    'skia/src/c/',
170    'skia/src/effects/',
171    'skia/src/fonts/',
172    'skia/src/ports/SkImageEncoder',
173    'skia/src/ports/SkImageGenerator',
174    'SkBitmapRegion',
175    'SkLite',
176    'SkLight',
177    'SkNormal',
178    'codec',
179    'SkWGL',
180    'SkMemory_malloc',
181    'third_party',
182    'Sk3D',
183    'SkAnimCodecPlayer',
184    'SkCamera',
185    'SkCanvasStack',
186    'SkCanvasStateUtils',
187    'SkFrontBufferedStream',
188    'SkInterpolator',
189    'JSON',
190    'SkMultiPictureDocument',
191    'SkNullCanvas',
192    'SkNWayCanvas',
193    'SkOverdrawCanvas',
194    'SkPaintFilterCanvas',
195    'SkParseColor',
196    'SkWhitelistTypefaces',
197    'SkXPS',
198    'SkCreateCGImageRef',
199    'skia/src/ports/SkGlobalInitialization',
200  ]
201
202  def isblacklisted(value):
203    for item in blacklist:
204      if value.find(item) >= 0:
205        return True
206
207    return False
208
209  separated = defaultdict(set, {
210    'common': {
211      'skia/src/codec/SkMasks.cpp',
212      'skia/src/effects/imagefilters/SkBlurImageFilter.cpp',
213      'skia/src/effects/imagefilters/SkComposeImageFilter.cpp',
214      'skia/src/effects/SkDashPathEffect.cpp',
215      'skia/src/ports/SkDiscardableMemory_none.cpp',
216      'skia/src/ports/SkGlobalInitialization_default.cpp',
217      'skia/src/ports/SkMemory_mozalloc.cpp',
218      'skia/src/ports/SkImageGenerator_none.cpp',
219      'skia/third_party/skcms/skcms.cc',
220    },
221    'android': {
222      # 'skia/src/ports/SkDebug_android.cpp',
223      'skia/src/ports/SkFontHost_cairo.cpp',
224      # 'skia/src/ports/SkFontHost_FreeType.cpp',
225      'skia/src/ports/SkFontHost_FreeType_common.cpp',
226      # 'skia/src/ports/SkTime_Unix.cpp',
227      # 'skia/src/utils/SkThreadUtils_pthread.cpp',
228    },
229    'linux': {
230      'skia/src/ports/SkFontHost_cairo.cpp',
231      'skia/src/ports/SkFontHost_FreeType_common.cpp',
232    },
233    'intel': set(),
234    'arm': set(),
235    'arm64': set(),
236    'none': set(),
237    'pdf': set()
238  })
239
240  for plat in platform_sources.keys():
241    for value in platform_sources[plat]:
242      if isblacklisted(value):
243        continue
244
245      if value in separated['common']:
246        continue
247
248      key = plat
249
250      if all(value in platform_sources.get(p, {})
251             for p in platforms if p != plat):
252        key = 'common'
253
254      separated[key].add(value)
255
256  return separated
257
258def uniq(seq):
259  seen = set()
260  seen_add = seen.add
261  return [ x for x in seq if x not in seen and not seen_add(x)]
262
263def write_cflags(f, values, subsearch, cflag, indent):
264  def write_indent(indent):
265    for _ in range(indent):
266        f.write(' ')
267
268  if isinstance(subsearch, str):
269    subsearch = [ subsearch ]
270
271  def iswhitelisted(value):
272    for item in subsearch:
273      if value.find(item) >= 0:
274        return True
275
276    return False
277
278  val_list = uniq(sorted(values, key=lambda x: x.lower()))
279
280  if len(val_list) == 0:
281    return
282
283  for val in val_list:
284    if iswhitelisted(val):
285      write_indent(indent)
286      f.write("SOURCES[\'" + val + "\'].flags += " + cflag + "\n")
287
288opt_whitelist = [
289  'SkOpts',
290  'SkBitmapProcState',
291  'SkBitmapScaler',
292  'SkBlitRow',
293  'SkBlitter',
294  'SkSpriteBlitter',
295  'SkMatrix.cpp',
296  'skcms',
297]
298
299# Unfortunately for now the gpu and pathops directories are
300# non-unifiable. Keep track of this and fix it.
301unified_blacklist = [
302  'FontHost',
303  'SkBitmapProcState_matrixProcs.cpp',
304  'SkBlitter_A8.cpp',
305  'SkBlitter_ARGB32.cpp',
306  'SkBlitter_RGB16.cpp',
307  'SkBlitter_Sprite.cpp',
308  'SkScan_Antihair.cpp',
309  'SkScan_AntiPath.cpp',
310  'SkScan_DAAPath.cpp',
311  'SkParse.cpp',
312  'SkPDFFont.cpp',
313  'SkPDFDevice.cpp',
314  'SkPDFType1Font.cpp',
315  'SkPictureData.cpp',
316  'SkColorSpace',
317  'SkPathOpsDebug.cpp',
318  'SkParsePath.cpp',
319  'SkRecorder.cpp',
320  'SkMiniRecorder.cpp',
321  'SkXfermode',
322  'SkMatrix44.cpp',
323  'SkRTree.cpp',
324  'SkVertices.cpp',
325  'SkSLHCodeGenerator.cpp',
326  'SkSLLexer.cpp',
327] + opt_whitelist
328
329def write_sources(f, values, indent):
330  def isblacklisted(value):
331    for item in unified_blacklist:
332      if value.find(item) >= 0:
333        return True
334
335    return False
336
337  sources = {}
338  sources['nonunified'] = set()
339  sources['unified'] = set()
340
341  for item in values:
342    if isblacklisted(item):
343      sources['nonunified'].add(item)
344    else:
345      sources['unified'].add(item)
346
347  write_list(f, "UNIFIED_SOURCES", sources['unified'], indent)
348  write_list(f, "SOURCES", sources['nonunified'], indent)
349
350def write_list(f, name, values, indent):
351  def write_indent(indent):
352    for _ in range(indent):
353        f.write(' ')
354
355  val_list = uniq(sorted(values, key=lambda x: x.lower()))
356
357  if len(val_list) == 0:
358    return
359
360  write_indent(indent)
361  f.write(name + ' += [\n')
362  for val in val_list:
363    write_indent(indent + 4)
364    f.write('\'' + val + '\',\n')
365
366  write_indent(indent)
367  f.write(']\n')
368
369def write_mozbuild(sources):
370  filename = 'moz.build'
371  f = open(filename, 'w')
372
373  f.write(header)
374
375  write_sources(f, sources['common'], 0)
376  write_cflags(f, sources['common'], opt_whitelist, 'skia_opt_flags', 0)
377
378  f.write("if CONFIG['MOZ_ENABLE_SKIA_PDF']:\n")
379  write_sources(f, sources['pdf'], 4)
380
381  f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':\n")
382  write_sources(f, sources['android'], 4)
383
384  f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):\n")
385  write_sources(f, sources['mac'], 4)
386
387  f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':\n")
388  write_sources(f, sources['linux'], 4)
389
390  f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':\n")
391  write_list(f, "SOURCES", sources['win'], 4)
392
393  f.write("if CONFIG['INTEL_ARCHITECTURE']:\n")
394  write_sources(f, sources['intel'], 4)
395  write_cflags(f, sources['intel'], opt_whitelist, 'skia_opt_flags', 4)
396
397  if sources['arm']:
398    f.write("elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):\n")
399    write_sources(f, sources['arm'], 4)
400    write_cflags(f, sources['arm'], opt_whitelist, 'skia_opt_flags', 4)
401
402  if sources['arm64']:
403    f.write("elif CONFIG['CPU_ARCH'] == 'aarch64':\n")
404    write_sources(f, sources['arm64'], 4)
405    write_cflags(f, sources['arm64'], opt_whitelist, 'skia_opt_flags', 4)
406
407  if sources['none']:
408    f.write("else:\n")
409    write_sources(f, sources['none'], 4)
410
411  f.write(footer)
412
413  f.close()
414
415  print('Wrote ' + filename)
416
417def main():
418  platform_sources = generate_platform_sources()
419  separated_sources = generate_separated_sources(platform_sources)
420  write_mozbuild(separated_sources)
421
422
423if __name__ == '__main__':
424  main()
425