5401e5df6e9637ed5da8d38f298ecc2ab54790d2
[platform/upstream/harfbuzz.git] / src / meson.build
1 fs = import('fs')
2
3 hb_version_h = configure_file(
4                command: [find_program('gen-hb-version.py'), meson.project_version(), '@OUTPUT@', '@INPUT@'],
5                input: 'hb-version.h.in',
6                output: 'hb-version.h',
7                install: true,
8                install_dir: get_option('includedir') / meson.project_name())
9
10 # Base and default-included sources and headers
11 hb_base_sources = files(
12   'hb-aat-layout-ankr-table.hh',
13   'hb-aat-layout-bsln-table.hh',
14   'hb-aat-layout-common.hh',
15   'hb-aat-layout-feat-table.hh',
16   'hb-aat-layout-just-table.hh',
17   'hb-aat-layout-kerx-table.hh',
18   'hb-aat-layout-morx-table.hh',
19   'hb-aat-layout-opbd-table.hh',
20   'hb-aat-layout-trak-table.hh',
21   'hb-aat-layout.cc',
22   'hb-aat-layout.hh',
23   'hb-aat-ltag-table.hh',
24   'hb-aat-map.cc',
25   'hb-aat-map.hh',
26   'hb-algs.hh',
27   'hb-array.hh',
28   'hb-atomic.hh',
29   'hb-bimap.hh',
30   'hb-bit-page.hh',
31   'hb-blob.cc',
32   'hb-blob.hh',
33   'hb-buffer-serialize.cc',
34   'hb-buffer-verify.cc',
35   'hb-buffer.cc',
36   'hb-buffer.hh',
37   'hb-cache.hh',
38   'hb-cff-interp-common.hh',
39   'hb-cff-interp-cs-common.hh',
40   'hb-cff-interp-dict-common.hh',
41   'hb-cff1-interp-cs.hh',
42   'hb-cff2-interp-cs.hh',
43   'hb-common.cc',
44   'hb-config.hh',
45   'hb-debug.hh',
46   'hb-dispatch.hh',
47   'hb-draw.cc',
48   'hb-draw.hh',
49   'hb-paint.cc',
50   'hb-paint.hh',
51   'hb-paint-extents.cc',
52   'hb-paint-extents.hh',
53   'hb-face.cc',
54   'hb-face.hh',
55   'hb-face-builder.cc',
56   'hb-fallback-shape.cc',
57   'hb-font.cc',
58   'hb-font.hh',
59   'hb-iter.hh',
60   'hb-kern.hh',
61   'hb-limits.hh',
62   'hb-machinery.hh',
63   'hb-map.cc',
64   'hb-map.hh',
65   'hb-meta.hh',
66   'hb-ms-feature-ranges.hh',
67   'hb-multimap.hh',
68   'hb-mutex.hh',
69   'hb-null.hh',
70   'hb-number.cc',
71   'hb-number.hh',
72   'hb-object.hh',
73   'hb-open-file.hh',
74   'hb-open-type.hh',
75   'hb-ot-cff-common.hh',
76   'hb-ot-cff1-std-str.hh',
77   'hb-ot-cff1-table.cc',
78   'hb-ot-cff1-table.hh',
79   'hb-ot-cff2-table.cc',
80   'hb-ot-cff2-table.hh',
81   'hb-ot-cmap-table.hh',
82   'hb-ot-color.cc',
83   'hb-ot-face-table-list.hh',
84   'hb-ot-face.cc',
85   'hb-ot-face.hh',
86   'hb-ot-font.cc',
87   'hb-ot-gasp-table.hh',
88   'hb-ot-glyf-table.hh',
89   'hb-ot-hdmx-table.hh',
90   'hb-ot-head-table.hh',
91   'hb-ot-hhea-table.hh',
92   'hb-ot-hmtx-table.hh',
93   'hb-ot-kern-table.hh',
94   'hb-ot-layout-base-table.hh',
95   'hb-ot-layout-common.hh',
96   'hb-ot-layout-gdef-table.hh',
97   'hb-ot-layout-gpos-table.hh',
98   'hb-ot-layout-gsub-table.hh',
99   'hb-outline.hh',
100   'hb-outline.cc',
101   'OT/Color/CBDT/CBDT.hh',
102   'OT/Color/COLR/COLR.hh',
103   'OT/Color/CPAL/CPAL.hh',
104   'OT/Color/sbix/sbix.hh',
105   'OT/Color/svg/svg.hh',
106   'OT/glyf/glyf.hh',
107   'OT/glyf/glyf-helpers.hh',
108   'OT/glyf/loca.hh',
109   'OT/glyf/path-builder.hh',
110   'OT/glyf/Glyph.hh',
111   'OT/glyf/GlyphHeader.hh',
112   'OT/glyf/SimpleGlyph.hh',
113   'OT/glyf/CompositeGlyph.hh',
114   'OT/glyf/SubsetGlyph.hh',
115   'OT/Layout/types.hh',
116   'OT/Layout/Common/Coverage.hh',
117   'OT/Layout/Common/CoverageFormat1.hh',
118   'OT/Layout/Common/CoverageFormat2.hh',
119   'OT/Layout/Common/RangeRecord.hh',
120   'OT/Layout/GDEF/GDEF.hh',
121   'OT/Layout/GPOS/AnchorFormat1.hh',
122   'OT/Layout/GPOS/AnchorFormat2.hh',
123   'OT/Layout/GPOS/AnchorFormat3.hh',
124   'OT/Layout/GPOS/Anchor.hh',
125   'OT/Layout/GPOS/AnchorMatrix.hh',
126   'OT/Layout/GPOS/ChainContextPos.hh',
127   'OT/Layout/GPOS/Common.hh',
128   'OT/Layout/GPOS/ContextPos.hh',
129   'OT/Layout/GPOS/CursivePosFormat1.hh',
130   'OT/Layout/GPOS/CursivePos.hh',
131   'OT/Layout/GPOS/ExtensionPos.hh',
132   'OT/Layout/GPOS/GPOS.hh',
133   'OT/Layout/GPOS/LigatureArray.hh',
134   'OT/Layout/GPOS/MarkArray.hh',
135   'OT/Layout/GPOS/MarkBasePosFormat1.hh',
136   'OT/Layout/GPOS/MarkBasePos.hh',
137   'OT/Layout/GPOS/MarkLigPosFormat1.hh',
138   'OT/Layout/GPOS/MarkLigPos.hh',
139   'OT/Layout/GPOS/MarkMarkPosFormat1.hh',
140   'OT/Layout/GPOS/MarkMarkPos.hh',
141   'OT/Layout/GPOS/MarkRecord.hh',
142   'OT/Layout/GPOS/PairPosFormat1.hh',
143   'OT/Layout/GPOS/PairPosFormat2.hh',
144   'OT/Layout/GPOS/PairPos.hh',
145   'OT/Layout/GPOS/PairSet.hh',
146   'OT/Layout/GPOS/PairValueRecord.hh',
147   'OT/Layout/GPOS/PosLookup.hh',
148   'OT/Layout/GPOS/PosLookupSubTable.hh',
149   'OT/Layout/GPOS/SinglePosFormat1.hh',
150   'OT/Layout/GPOS/SinglePosFormat2.hh',
151   'OT/Layout/GPOS/SinglePos.hh',
152   'OT/Layout/GPOS/ValueFormat.hh',
153   'OT/Layout/GSUB/AlternateSet.hh',
154   'OT/Layout/GSUB/AlternateSubstFormat1.hh',
155   'OT/Layout/GSUB/AlternateSubst.hh',
156   'OT/Layout/GSUB/ChainContextSubst.hh',
157   'OT/Layout/GSUB/Common.hh',
158   'OT/Layout/GSUB/ContextSubst.hh',
159   'OT/Layout/GSUB/ExtensionSubst.hh',
160   'OT/Layout/GSUB/GSUB.hh',
161   'OT/Layout/GSUB/Ligature.hh',
162   'OT/Layout/GSUB/LigatureSet.hh',
163   'OT/Layout/GSUB/LigatureSubstFormat1.hh',
164   'OT/Layout/GSUB/LigatureSubst.hh',
165   'OT/Layout/GSUB/MultipleSubstFormat1.hh',
166   'OT/Layout/GSUB/MultipleSubst.hh',
167   'OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh',
168   'OT/Layout/GSUB/ReverseChainSingleSubst.hh',
169   'OT/Layout/GSUB/Sequence.hh',
170   'OT/Layout/GSUB/SingleSubstFormat1.hh',
171   'OT/Layout/GSUB/SingleSubstFormat2.hh',
172   'OT/Layout/GSUB/SingleSubst.hh',
173   'OT/Layout/GSUB/SubstLookup.hh',
174   'OT/Layout/GSUB/SubstLookupSubTable.hh',
175   'OT/name/name.hh',
176   'hb-ot-layout-gsubgpos.hh',
177   'hb-ot-layout-jstf-table.hh',
178   'hb-ot-layout.cc',
179   'hb-ot-layout.hh',
180   'hb-ot-map.cc',
181   'hb-ot-map.hh',
182   'hb-ot-math-table.hh',
183   'hb-ot-math.cc',
184   'hb-ot-maxp-table.hh',
185   'hb-ot-meta-table.hh',
186   'hb-ot-meta.cc',
187   'hb-ot-metrics.cc',
188   'hb-ot-metrics.hh',
189   'hb-ot-name-language-static.hh',
190   'hb-ot-name-language.hh',
191   'hb-ot-name-table.hh',
192   'hb-ot-name.cc',
193   'hb-ot-os2-table.hh',
194   'hb-ot-os2-unicode-ranges.hh',
195   'hb-ot-post-macroman.hh',
196   'hb-ot-post-table.hh',
197   'hb-ot-shaper-arabic-fallback.hh',
198   'hb-ot-shaper-arabic-joining-list.hh',
199   'hb-ot-shaper-arabic-pua.hh',
200   'hb-ot-shaper-arabic-table.hh',
201   'hb-ot-shaper-arabic-win1256.hh',
202   'hb-ot-shaper-arabic.cc',
203   'hb-ot-shaper-arabic.hh',
204   'hb-ot-shaper-default.cc',
205   'hb-ot-shaper-hangul.cc',
206   'hb-ot-shaper-hebrew.cc',
207   'hb-ot-shaper-indic-table.cc',
208   'hb-ot-shaper-indic.cc',
209   'hb-ot-shaper-indic.hh',
210   'hb-ot-shaper-khmer.cc',
211   'hb-ot-shaper-myanmar.cc',
212   'hb-ot-shaper-syllabic.cc',
213   'hb-ot-shaper-syllabic.hh',
214   'hb-ot-shaper-thai.cc',
215   'hb-ot-shaper-use-table.hh',
216   'hb-ot-shaper-use.cc',
217   'hb-ot-shaper-vowel-constraints.cc',
218   'hb-ot-shaper-vowel-constraints.hh',
219   'hb-ot-shaper.hh',
220   'hb-ot-shape-fallback.cc',
221   'hb-ot-shape-fallback.hh',
222   'hb-ot-shape-normalize.cc',
223   'hb-ot-shape-normalize.hh',
224   'hb-ot-shape.cc',
225   'hb-ot-shape.hh',
226   'hb-ot-stat-table.hh',
227   'hb-ot-tag-table.hh',
228   'hb-ot-tag.cc',
229   'hb-ot-var-avar-table.hh',
230   'hb-ot-var-common.hh',
231   'hb-ot-var-cvar-table.hh',
232   'hb-ot-var-fvar-table.hh',
233   'hb-ot-var-gvar-table.hh',
234   'hb-ot-var-hvar-table.hh',
235   'hb-ot-var-mvar-table.hh',
236   'hb-ot-var.cc',
237   'hb-ot-vorg-table.hh',
238   'hb-pool.hh',
239   'hb-sanitize.hh',
240   'hb-serialize.hh',
241   'hb-set-digest.hh',
242   'hb-set.cc',
243   'hb-set.hh',
244   'hb-shape-plan.cc',
245   'hb-shape-plan.hh',
246   'hb-shape.cc',
247   'hb-shaper-impl.hh',
248   'hb-shaper-list.hh',
249   'hb-shaper.cc',
250   'hb-shaper.hh',
251   'hb-static.cc',
252   'hb-string-array.hh',
253   'hb-style.cc',
254   'hb-ucd-table.hh',
255   'hb-ucd.cc',
256   'hb-unicode-emoji-table.hh',
257   'hb-unicode.cc',
258   'hb-unicode.hh',
259   'hb-utf.hh',
260   'hb-vector.hh',
261   'hb.hh',
262 )
263
264 hb_base_ragel_generated_sources = files(
265   'hb-buffer-deserialize-json.hh',
266   'hb-buffer-deserialize-text-glyphs.hh',
267   'hb-buffer-deserialize-text-unicode.hh',
268   'hb-number-parser.hh',
269   'hb-ot-shaper-indic-machine.hh',
270   'hb-ot-shaper-khmer-machine.hh',
271   'hb-ot-shaper-myanmar-machine.hh',
272   'hb-ot-shaper-use-machine.hh',
273 )
274 hb_base_ragel_sources = [
275   'hb-buffer-deserialize-json.rl',
276   'hb-buffer-deserialize-text-glyphs.rl',
277   'hb-buffer-deserialize-text-unicode.rl',
278   'hb-number-parser.rl',
279   'hb-ot-shaper-indic-machine.rl',
280   'hb-ot-shaper-khmer-machine.rl',
281   'hb-ot-shaper-myanmar-machine.rl',
282   'hb-ot-shaper-use-machine.rl',
283 ]
284
285 hb_base_headers = files(
286   'hb-aat-layout.h',
287   'hb-aat.h',
288   'hb-blob.h',
289   'hb-buffer.h',
290   'hb-common.h',
291   'hb-cplusplus.hh',
292   'hb-deprecated.h',
293   'hb-draw.h',
294   'hb-paint.h',
295   'hb-face.h',
296   'hb-font.h',
297   'hb-map.h',
298   'hb-ot-color.h',
299   'hb-ot-deprecated.h',
300   'hb-ot-font.h',
301   'hb-ot-layout.h',
302   'hb-ot-math.h',
303   'hb-ot-meta.h',
304   'hb-ot-metrics.h',
305   'hb-ot-name.h',
306   'hb-ot-shape.h',
307   'hb-ot-var.h',
308   'hb-ot.h',
309   'hb-set.h',
310   'hb-shape-plan.h',
311   'hb-shape.h',
312   'hb-style.h',
313   'hb-unicode.h',
314   'hb.h',
315 )
316 hb_base_headers += hb_version_h
317
318 # Optional Sources and Headers with external deps
319
320 hb_ft_sources = files('hb-ft.cc', 'hb-ft-colr.hh')
321 hb_ft_headers = files('hb-ft.h')
322
323 hb_glib_sources = files('hb-glib.cc')
324 hb_glib_headers = files('hb-glib.h')
325
326 hb_graphite2_sources = files('hb-graphite2.cc')
327 hb_graphite2_headers = files('hb-graphite2.h')
328
329 hb_wasm_sources = files(
330   'hb-wasm-api.cc',
331   'hb-wasm-api.hh',
332   'hb-wasm-api-blob.hh',
333   'hb-wasm-api-buffer.hh',
334   'hb-wasm-api-common.hh',
335   'hb-wasm-api-face.hh',
336   'hb-wasm-api-font.hh',
337   'hb-wasm-api-shape.hh',
338   'hb-wasm-shape.cc',
339 )
340 hb_wasm_headers = files()
341
342 # System-dependent sources and headers
343
344 hb_coretext_sources = files('hb-coretext.cc')
345 hb_coretext_headers = files('hb-coretext.h')
346
347 hb_directwrite_sources = files('hb-directwrite.cc')
348 hb_directwrite_headers = files('hb-directwrite.h')
349
350 hb_gdi_sources = files('hb-gdi.cc')
351 hb_gdi_headers = files('hb-gdi.h')
352
353 hb_uniscribe_sources = files('hb-uniscribe.cc')
354 hb_uniscribe_headers = files('hb-uniscribe.h')
355
356 # Sources for libharfbuzz-gobject and libharfbuzz-icu
357 hb_icu_sources = files('hb-icu.cc')
358 hb_icu_headers = files('hb-icu.h')
359
360 # Sources for libharfbuzz-subset
361 hb_subset_sources = files(
362   'hb-number.cc',
363   'hb-number.hh',
364   'hb-ot-cff1-table.cc',
365   'hb-ot-cff2-table.cc',
366   'hb-static.cc',
367   'hb-subset-accelerator.hh',
368   'hb-subset-cff-common.cc',
369   'hb-subset-cff-common.hh',
370   'hb-subset-cff1.cc',
371   'hb-subset-cff2.cc',
372   'hb-subset-input.cc',
373   'hb-subset-input.hh',
374   'hb-subset-instancer-solver.hh',
375   'hb-subset-instancer-solver.cc',
376   'hb-subset-plan.cc',
377   'hb-subset-plan.hh',
378   'hb-subset-plan-member-list.hh',
379   'hb-subset-repacker.cc',
380   'graph/gsubgpos-context.cc',
381   'graph/gsubgpos-context.hh',
382   'graph/gsubgpos-graph.hh',
383   'graph/pairpos-graph.hh',
384   'graph/markbasepos-graph.hh',
385   'graph/coverage-graph.hh',
386   'graph/classdef-graph.hh',
387   'graph/split-helpers.hh',
388   'hb-subset.cc',
389   'hb-subset.hh',
390 )
391
392 hb_subset_headers = files(
393   'hb-subset.h',
394   'hb-subset-repacker.h'
395 )
396
397 hb_gobject_sources = files(
398   'hb-gobject-structs.cc'
399 )
400
401 hb_gobject_headers = files(
402   'hb-gobject.h',
403   'hb-gobject-structs.h',
404 )
405
406 ragel = find_program('ragel', version: '6.10', required: false)
407 has_ragel = ragel.found()
408 if not has_ragel and get_option('ragel_subproject')
409     ragel = subproject('ragel').get_variable('ragel')
410     has_ragel = true
411 endif
412 if not has_ragel
413   if not meson.is_subproject()
414     warning('You have to install ragel if you are going to develop HarfBuzz itself')
415   endif
416 else
417   ragel_helper = find_program('gen-ragel-artifacts.py')
418   foreach rl : hb_base_ragel_sources
419     hh = rl.split('.')[0] + '.hh'
420     custom_target('@0@'.format(hh),
421       build_by_default: true,
422       input: rl,
423       output: hh,
424       command: [ragel_helper, ragel, '@OUTPUT@', meson.current_source_dir(), '@INPUT@'],
425     )
426   endforeach
427 endif
428
429 custom_target('harfbuzz.cc',
430   build_by_default: true,
431   output: 'harfbuzz.cc',
432   input: hb_base_sources + hb_glib_sources + hb_ft_sources +
433          hb_graphite2_sources + hb_uniscribe_sources + hb_gdi_sources +
434          hb_directwrite_sources + hb_coretext_sources + hb_wasm_sources,
435   command: [find_program('gen-harfbuzzcc.py'),
436             '@OUTPUT@', meson.current_source_dir(), '@INPUT@'],
437 )
438
439 incsrc = include_directories('.')
440
441 hb_sources = hb_base_sources + hb_base_ragel_generated_sources
442 hb_headers = hb_base_headers
443
444 harfbuzz_deps = [thread_dep, m_dep] + harfbuzz_extra_deps
445
446 libharfbuzz_link_language = 'c'
447
448 if conf.get('HAVE_FREETYPE', 0) == 1
449   hb_sources += hb_ft_sources
450   hb_headers += hb_ft_headers
451   harfbuzz_deps += [freetype_dep]
452 endif
453
454 if conf.get('HAVE_GLIB', 0) == 1
455   hb_sources += hb_glib_sources
456   hb_headers += hb_glib_headers
457   harfbuzz_deps += [glib_dep]
458 endif
459
460 # We set those here to not include the sources below that are of no use to
461 # GObject Introspection
462 gir_sources = hb_sources + hb_gobject_sources
463 gir_headers = hb_headers + hb_gobject_headers
464
465 if conf.get('HAVE_GDI', 0) == 1
466   hb_sources += hb_gdi_sources
467   hb_headers += hb_gdi_headers
468   harfbuzz_deps += gdi_uniscribe_deps
469 endif
470
471 if conf.get('HAVE_GRAPHITE2', 0) == 1
472   hb_sources += hb_graphite2_sources
473   hb_headers += hb_graphite2_headers
474   harfbuzz_deps += [graphite2_dep, graphite_dep]
475 endif
476
477 if conf.get('HAVE_WASM', 0) == 1
478   hb_sources += hb_wasm_sources
479   hb_headers += hb_wasm_headers
480   harfbuzz_deps += wasm_dep
481   #harfbuzz_deps += llvm_dep
482 endif
483
484 if conf.get('HAVE_UNISCRIBE', 0) == 1
485   hb_sources += hb_uniscribe_sources
486   hb_headers += hb_uniscribe_headers
487 endif
488
489 if conf.get('HAVE_DIRECTWRITE', 0) == 1
490   hb_sources += hb_directwrite_sources
491   hb_headers += hb_directwrite_headers
492   # hb-directwrite needs a C++ linker
493   libharfbuzz_link_language = 'cpp'
494 endif
495
496 if conf.get('HAVE_CORETEXT', 0) == 1
497   hb_sources += hb_coretext_sources
498   hb_headers += hb_coretext_headers
499   harfbuzz_deps += coretext_deps
500 endif
501
502 have_icu = conf.get('HAVE_ICU', 0) == 1
503 have_icu_builtin = conf.get('HAVE_ICU_BUILTIN', 0) == 1
504 if have_icu and have_icu_builtin
505   hb_sources += hb_icu_sources
506   hb_headers += hb_icu_headers
507   harfbuzz_deps += [icu_dep]
508 endif
509
510 features = [
511   'CAIRO',
512   'CORETEXT',
513   'DIRECTWRITE',
514   'FREETYPE',
515   'GDI',
516   'GLIB',
517   'GOBJECT',
518   'GRAPHITE',
519   'ICU',
520   'UNISCRIBE',
521   'WASM',
522 ]
523
524 hb_enabled_features = configuration_data()
525 hb_supported_features = configuration_data()
526 foreach feature : features
527   key = 'HB_HAS_@0@'.format(feature)
528   hb_enabled_features.set(key, conf.get('HAVE_@0@'.format(feature), false))
529   hb_supported_features.set(key, 1)
530 endforeach
531
532 # The enabled features. This file is installed.
533 hb_features_h = configure_file(input: 'hb-features.h.in',
534                                output: 'hb-features.h',
535                                configuration: hb_enabled_features,
536                                install: true,
537                                install_dir: get_option('includedir') / meson.project_name())
538
539 # This file is generated to convince gtk-doc to generate documentation for all
540 # HB_HAS_* macros, whether they are enabled for the current build or not.
541 # This file should not be installed.
542 hb_supported_features_h = configure_file(input: 'hb-features.h.in',
543                                output: 'hb-supported-features.h',
544                                configuration: hb_supported_features,
545                                install: false)
546
547 # Base and default-included sources and headers
548
549 gen_def = find_program('gen-def.py')
550 gen_def_cmd = [gen_def, '@OUTPUT@', '@INPUT@']
551 if get_option('experimental_api')
552   gen_def_cmd += '--experimental-api'
553 endif
554
555 # harfbuzz
556 harfbuzz_def = custom_target('harfbuzz.def',
557     command: gen_def_cmd,
558     input: hb_headers,
559     output: 'harfbuzz.def')
560 defs_list = [harfbuzz_def]
561
562 version = '0.@0@.0'.format(hb_version_int)
563
564 extra_hb_cpp_args = []
565 if cpp.get_define('_MSC_FULL_VER') != ''
566   if get_option('default_library') != 'static'
567     extra_hb_cpp_args += '-DHB_DLL_EXPORT'
568   endif
569   hb_so_version = ''
570 else
571   hb_so_version = '0'
572 endif
573
574 if get_option('fuzzer_ldflags') != ''
575   extra_hb_cpp_args += ['-DHB_CUSTOM_MALLOC']
576   hb_sources += 'failing-alloc.c'
577   hb_subset_sources += 'failing-alloc.c'
578   hb_icu_sources += 'failing-alloc.c'
579   hb_gobject_sources += 'failing-alloc.c'
580 endif
581
582 darwin_versions = [hb_version_int, '@0@.0.0'.format(hb_version_int)]
583
584 libharfbuzz = library('harfbuzz', hb_sources,
585   include_directories: incconfig,
586   dependencies: harfbuzz_deps,
587   cpp_args: cpp_args + extra_hb_cpp_args,
588   soversion: hb_so_version,
589   version: version,
590   install: true,
591   darwin_versions: darwin_versions,
592   link_language: libharfbuzz_link_language,
593 )
594
595 libharfbuzz_dep = declare_dependency(
596   link_with: libharfbuzz,
597   include_directories: incsrc,
598   dependencies: harfbuzz_deps)
599 meson.override_dependency('harfbuzz', libharfbuzz_dep)
600
601 # harfbuzz-subset
602 harfbuzz_subset_def = custom_target('harfbuzz-subset.def',
603     command: gen_def_cmd,
604     input: hb_subset_headers,
605     output: 'harfbuzz-subset.def')
606 defs_list += [harfbuzz_subset_def]
607
608 libharfbuzz_subset = library('harfbuzz-subset', hb_subset_sources,
609   include_directories: incconfig,
610   dependencies: [m_dep],
611   link_with: [libharfbuzz],
612   cpp_args: cpp_args + extra_hb_cpp_args,
613   soversion: hb_so_version,
614   version: version,
615   install: true,
616   darwin_versions: darwin_versions,
617   link_language: 'c',
618 )
619
620 custom_target('harfbuzz-subset.cc',
621   build_by_default: true,
622   output: 'harfbuzz-subset.cc',
623   input: hb_base_sources + hb_subset_sources,
624   command: [find_program('gen-harfbuzzcc.py'),
625             '@OUTPUT@', meson.current_source_dir(), '@INPUT@'],
626 )
627
628 libharfbuzz_subset_dep = declare_dependency(
629   link_with: libharfbuzz_subset,
630   include_directories: incsrc,
631   dependencies: [m_dep])
632 meson.override_dependency('harfbuzz-subset', libharfbuzz_subset_dep)
633
634 libharfbuzz_cairo_dep = null_dep
635 if conf.get('HAVE_CAIRO', 0) == 1
636   hb_cairo_sources = [
637     'hb-cairo.cc',
638     'hb-cairo-utils.cc',
639     'hb-static.cc'
640   ]
641
642   hb_cairo_headers = [
643     'hb-cairo.h',
644   ]
645
646   cairo_dep = dependency('cairo')
647
648   libharfbuzz_cairo = library('harfbuzz-cairo', hb_cairo_sources,
649     include_directories: incconfig,
650     dependencies: [m_dep, cairo_dep],
651     link_with: [libharfbuzz],
652      cpp_args: cpp_args + extra_hb_cpp_args,
653     soversion: hb_so_version,
654     version: version,
655     install: true,
656     darwin_versions: darwin_versions,
657     link_language: 'c',
658   )
659
660   install_headers(hb_cairo_headers, subdir: meson.project_name())
661
662   libharfbuzz_cairo_dep = declare_dependency(
663     link_with: libharfbuzz_cairo,
664     include_directories: incsrc,
665     dependencies: [m_dep, cairo_dep])
666   meson.override_dependency('harfbuzz-cairo', libharfbuzz_cairo_dep)
667
668   harfbuzz_cairo_def = custom_target('harfbuzz-cairo.def',
669     command: gen_def_cmd,
670     input: hb_cairo_headers,
671     output: 'harfbuzz-cairo.def')
672   defs_list += [harfbuzz_cairo_def]
673
674   pkgmod.generate(libharfbuzz_cairo,
675     description: 'HarfBuzz cairo support',
676     requires: ['harfbuzz = @0@'.format(meson.project_version())],
677     subdirs: [meson.project_name()],
678     version: meson.project_version(),
679   )
680 endif
681
682 if get_option('tests').enabled()
683   # TODO: MSVC gives the following,
684   # error LNK2019: unresolved external symbol "unsigned __int64 const * const _hb_NullPool"
685   if cpp.get_define('_MSC_FULL_VER') == ''
686     noinst_programs = {
687       'main': 'main.cc',
688       'test-algs': ['test-algs.cc', 'hb-static.cc'],
689       'test-basics': 'test.cc',
690       'test-bimap': ['test-bimap.cc', 'hb-static.cc'],
691       'test-buffer-serialize': 'test-buffer-serialize.cc',
692       'test-classdef-graph': ['graph/test-classdef-graph.cc', 'hb-static.cc', 'graph/gsubgpos-context.cc'],
693       'test-instancer-solver': ['test-subset-instancer-solver.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'],
694       'test-iter': ['test-iter.cc', 'hb-static.cc'],
695       'test-map': ['test-map.cc', 'hb-static.cc'],
696       'test-multimap': ['test-multimap.cc', 'hb-static.cc'],
697       'test-ot-meta': 'test-ot-meta.cc',
698       'test-ot-name': 'test-ot-name.cc',
699       'test-ot-glyphname': 'test-ot-glyphname.cc',
700       'test-ot-gpos-size-params': 'test-gpos-size-params.cc',
701       'test-ot-gsub-get-alternates': 'test-gsub-get-alternates.cc',
702       'test-ot-gsub-would-substitute': 'test-gsub-would-substitute.cc',
703       'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
704       'test-repacker': ['test-repacker.cc', 'hb-static.cc', 'graph/gsubgpos-context.cc'],
705       'test-serialize': ['test-serialize.cc', 'hb-static.cc'],
706       'test-set': ['test-set.cc', 'hb-static.cc'],
707       'test-tuple-varstore': ['test-tuple-varstore.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'],
708       'test-item-varstore': ['test-item-varstore.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'],
709       'test-use-table': 'test-use-table.cc',
710       'test-vector': ['test-vector.cc', 'hb-static.cc'],
711     }
712     foreach name, source : noinst_programs
713       executable(name, source,
714         include_directories: incconfig,
715         cpp_args: cpp_args + ['-UNDEBUG'],
716         dependencies: libharfbuzz_dep,
717         install: false,
718       )
719     endforeach
720   endif
721
722   compiled_tests = {
723     'test-array': ['test-array.cc'],
724     'test-machinery': ['test-machinery.cc', 'hb-static.cc'],
725     'test-number': ['test-number.cc', 'hb-number.cc'],
726     'test-ot-tag': ['hb-ot-tag.cc'],
727     'test-unicode-ranges': ['test-unicode-ranges.cc'],
728   }
729   foreach name, source : compiled_tests
730     if cpp.get_argument_syntax() == 'msvc' and source.contains('hb-static.cc')
731       # TODO: MSVC doesn't like tests having hb-static.cc, fix them
732       continue
733     endif
734     test(name, executable(name, source,
735       include_directories: incconfig,
736       cpp_args: cpp_args + ['-DMAIN', '-UNDEBUG'],
737       dependencies: libharfbuzz_dep,
738       install: false,
739     ), suite: ['src'])
740   endforeach
741 endif
742
743 pkgmod.generate(libharfbuzz,
744   description: 'HarfBuzz text shaping library',
745   subdirs: [meson.project_name()],
746   version: meson.project_version(),
747 )
748
749 pkgmod.generate(libharfbuzz_subset,
750   description: 'HarfBuzz font subsetter',
751   requires: ['harfbuzz = @0@'.format(meson.project_version())],
752   subdirs: [meson.project_name()],
753   version: meson.project_version(),
754 )
755
756 libharfbuzz_icu_dep = null_dep
757 if have_icu and not have_icu_builtin
758   harfbuzz_icu_def = custom_target('harfbuzz-icu.def',
759     command: gen_def_cmd,
760     input: [hb_icu_headers],
761     output: 'harfbuzz-icu.def')
762   defs_list += [harfbuzz_icu_def]
763
764   libharfbuzz_icu = library('harfbuzz-icu', [hb_icu_sources, hb_icu_headers],
765     include_directories: incconfig,
766     dependencies: icu_dep,
767     link_with: [libharfbuzz],
768     cpp_args: cpp_args + extra_hb_cpp_args,
769     soversion: hb_so_version,
770     version: version,
771     install: true,
772     darwin_versions: darwin_versions,
773     # ICU links to stdc++ anyway so the default linker is good
774     # link_language: 'c',
775   )
776
777   libharfbuzz_icu_dep = declare_dependency(
778     link_with: libharfbuzz_icu,
779     include_directories: incsrc,
780     dependencies: icu_dep)
781   meson.override_dependency('harfbuzz-icu', libharfbuzz_icu_dep)
782
783   pkgmod.generate(libharfbuzz_icu,
784     description: 'HarfBuzz text shaping library ICU integration',
785     requires: ['harfbuzz = @0@'.format(meson.project_version())],
786     subdirs: [meson.project_name()],
787     version: meson.project_version(),
788   )
789
790   install_headers(hb_icu_headers, subdir: meson.project_name())
791 endif
792
793 have_gobject = conf.get('HAVE_GOBJECT', 0) == 1
794
795 # This code (especially PACKAGE_INIT) kept similar to what CMake's own
796 # configure_package_config_file() generates, see
797 # https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html#command:configure_package_config_file
798
799 cmake_config = configuration_data()
800 cmake_config_dir = cmake_package_install_dir / 'harfbuzz'
801
802 have_fs_relative_to = meson.version().version_compare('>=1.3.0')
803
804 if not have_fs_relative_to
805   relative_to = find_program('relative_to.py')
806 endif
807
808 if have_fs_relative_to
809   cmake_package_prefix_dir = fs.relative_to(get_option('prefix'), get_option('prefix') / cmake_config_dir)
810 else
811   cmake_package_prefix_dir = run_command(relative_to, get_option('prefix'), get_option('prefix') / cmake_config_dir, check: true).stdout().strip()
812 endif
813
814 cmake_package_prefix_dir = '${CMAKE_CURRENT_LIST_DIR}/@0@'.format(cmake_package_prefix_dir)
815
816 # Make all the relevant paths relative to our prefix, so we can later append
817 # them onto ${PACKAGE_PREFIX_DIR} to get the correct paths.
818
819 cmake_install_includedir = get_option('includedir')
820
821 if fs.is_absolute(cmake_install_includedir)
822   if have_fs_relative_to
823     cmake_install_includedir = fs.relative_to(cmake_install_includedir, get_option('prefix'))
824   else
825     cmake_install_includedir = run_command(relative_to, cmake_install_includedir, get_option('prefix'), check: true).stdout().strip()
826   endif
827 endif
828
829 cmake_install_libdir = get_option('libdir')
830
831 if fs.is_absolute(cmake_install_libdir)
832   if have_fs_relative_to
833     cmake_install_libdir = fs.relative_to(cmake_install_libdir, get_option('prefix'))
834   else
835     cmake_install_libdir = run_command(relative_to, cmake_install_libdir, get_option('prefix'), check: true).stdout().strip()
836   endif
837 endif
838
839 cmake_config.set('PACKAGE_INIT', '''
840 get_filename_component(PACKAGE_PREFIX_DIR "@0@" ABSOLUTE)
841
842 macro(set_and_check _var _file)
843   set(${_var} "${_file}")
844   if(NOT EXISTS "${_file}")
845     message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
846   endif()
847 endmacro()
848
849 macro(check_required_components _NAME)
850   foreach(comp ${${_NAME}_FIND_COMPONENTS})
851     if(NOT ${_NAME}_${comp}_FOUND)
852       if(${_NAME}_FIND_REQUIRED_${comp})
853         set(${_NAME}_FOUND FALSE)
854       endif()
855     endif()
856   endforeach()
857 endmacro()
858 '''.format(cmake_package_prefix_dir))
859
860 cmake_config.set('PACKAGE_CMAKE_INSTALL_INCLUDEDIR', '${PACKAGE_PREFIX_DIR}/@0@'.format(cmake_install_includedir))
861 cmake_config.set('PACKAGE_CMAKE_INSTALL_LIBDIR', '${PACKAGE_PREFIX_DIR}/@0@'.format(cmake_install_libdir))
862 cmake_config.set('PACKAGE_INCLUDE_INSTALL_DIR', '${PACKAGE_PREFIX_DIR}/@0@/@1@'.format(cmake_install_includedir, meson.project_name()))
863 cmake_config.set('HB_HAVE_GOBJECT', have_gobject ? 'YES' : 'NO')
864 cmake_config.set('HB_LIBRARY_TYPE', get_option('default_library') == 'static' ? 'STATIC' : 'SHARED')
865
866 if get_option('default_library') == 'static'
867   cmake_config.set('HB_LIB_PREFIX', '${CMAKE_STATIC_LIBRARY_PREFIX}')
868   cmake_config.set('HB_LIB_SUFFIX', '${CMAKE_STATIC_LIBRARY_SUFFIX}')
869 elif host_machine.system() == 'darwin'
870   cmake_config.set('HB_LIB_PREFIX', '${CMAKE_SHARED_LIBRARY_PREFIX}')
871   cmake_config.set('HB_LIB_SUFFIX', '.@0@.${CMAKE_SHARED_LIBRARY_SUFFIX}'.format(hb_so_version))
872 elif host_machine.system() == 'windows'
873   cmake_config.set('HB_LIB_PREFIX', '${CMAKE_IMPORT_LIBRARY_PREFIX}')
874   cmake_config.set('HB_LIB_SUFFIX', '${CMAKE_IMPORT_LIBRARY_SUFFIX}')
875 else
876   cmake_config.set('HB_LIB_PREFIX', '${CMAKE_SHARED_LIBRARY_PREFIX}')
877   cmake_config.set('HB_LIB_SUFFIX', '${CMAKE_SHARED_LIBRARY_SUFFIX}.@0@'.format(version))
878 endif
879
880 configure_file(input: 'harfbuzz-config.cmake.in',
881   output: 'harfbuzz-config.cmake',
882   configuration: cmake_config,
883   install_dir: cmake_config_dir,
884 )
885
886 gobject_enums_c = []
887 gobject_enums_h = []
888 libharfbuzz_gobject_dep = null_dep
889 if have_gobject
890   gnome = import('gnome')
891
892   h_templ = configure_file(
893     input: 'hb-gobject-enums.h.tmpl',
894     output: 'hb-gobject-enums-tmp.h.tmpl',
895     copy: true)
896
897   cc_templ = configure_file(
898     input: 'hb-gobject-enums.cc.tmpl',
899     output: 'hb-gobject-enums-tmp.cc.tmpl',
900     copy: true)
901
902   enums = gnome.mkenums('hb-gobject',
903     sources: hb_headers,
904     h_template: h_templ,
905     c_template: cc_templ,
906     identifier_prefix: 'hb_',
907     symbol_prefix: 'hb_gobject',
908   )
909
910   gobject_enums_c = custom_target('hb-gobject-enums.cc',
911     input: enums[0],
912     output: 'hb-gobject-enums.cc',
913     command: [find_program('fix_get_types.py'), '@INPUT@', '@OUTPUT@']
914   )
915
916   gobject_enums_h = custom_target('hb-gobject-enums.h',
917     input: enums[1],
918     output: 'hb-gobject-enums.h',
919     command: [find_program('fix_get_types.py'), '@INPUT@', '@OUTPUT@'],
920     install: true,
921     install_dir: get_option('prefix') / get_option('includedir') / meson.project_name(),
922   )
923
924   hb_gobject_sources += [gobject_enums_c]
925
926   harfbuzz_gobject_def = custom_target('harfbuzz-gobject.def',
927     command: gen_def_cmd,
928     input: [hb_gobject_headers, gobject_enums_h],
929     output: 'harfbuzz-gobject.def')
930   defs_list += [harfbuzz_gobject_def]
931
932   libharfbuzz_gobject = library('harfbuzz-gobject', [hb_gobject_sources, gobject_enums_c, gobject_enums_h],
933     include_directories: incconfig,
934     dependencies: [glib_dep, gobject_dep],
935     link_with: [libharfbuzz],
936     cpp_args: cpp_args + extra_hb_cpp_args,
937     soversion: hb_so_version,
938     version: version,
939     install: true,
940     darwin_versions: darwin_versions,
941     link_language: 'c',
942   )
943
944   gir = find_program('g-ir-scanner', required: get_option('introspection'))
945   build_gir = gir.found() and (not meson.is_cross_build() or get_option('introspection').enabled())
946
947   build_gir = build_gir and get_option('default_library') != 'static'
948   if not build_gir and get_option('introspection').enabled()
949     error('Introspection support is requested but the default library option should be shared or both')
950   endif
951
952   if build_gir
953     conf.set('HAVE_INTROSPECTION', 1)
954     hb_gen_files_gir = gnome.generate_gir([libharfbuzz_gobject, libharfbuzz],
955       sources: [gir_headers, gir_sources, gobject_enums_h],
956       dependencies: libharfbuzz_dep,
957       namespace: 'HarfBuzz',
958       nsversion: '0.0',
959       identifier_prefix: 'hb_',
960       symbol_prefix: ['hb', 'hb_gobject'],
961       includes: ['GObject-2.0', 'freetype2-2.0'],
962       export_packages: ['harfbuzz-gobject', 'harfbuzz'],
963       header: 'hb-gobject.h',
964       install: true,
965       extra_args:  ['--cflags-begin',
966                     '-DHB_NO_SINGLE_HEADER_ERROR',
967                     '-DHAVE_GOBJECT',
968                     '-DHB_EXTERN=',
969                     '--cflags-end'])
970   endif
971
972   libharfbuzz_gobject_dep = declare_dependency(
973     link_with: libharfbuzz_gobject,
974     include_directories: incsrc,
975     sources: build_gir ? hb_gen_files_gir : hb_gobject_sources,
976     dependencies: [glib_dep, gobject_dep])
977   meson.override_dependency('harfbuzz-gobject', libharfbuzz_gobject_dep)
978
979   pkgmod.generate(libharfbuzz_gobject,
980     description: 'HarfBuzz text shaping library GObject integration',
981     requires: ['harfbuzz = @0@'.format(meson.project_version()), 'glib-2.0', 'gobject-2.0'],
982     subdirs: [meson.project_name()],
983     version: meson.project_version(),
984   )
985
986   install_headers(hb_gobject_headers, subdir: meson.project_name())
987 else
988   if get_option('introspection').enabled()
989     error('introspection requires gobject to be enabled')
990   endif
991 endif
992
993 if get_option('tests').enabled()
994   dist_check_script = [
995     'check-c-linkage-decls',
996     'check-externs',
997     'check-header-guards',
998     'check-includes',
999   ]
1000
1001   env = environment()
1002   env.set('srcdir', meson.current_source_dir())
1003   env.set('base_srcdir', meson.source_root())
1004   env.set('builddir', meson.current_build_dir())
1005   env.set('libs', meson.current_build_dir()) # TODO: Merge this with builddir after autotools removal
1006   HBSOURCES = []
1007   foreach f : hb_sources
1008     HBSOURCES += '@0@'.format(f)
1009   endforeach
1010   env.set('HBSOURCES', ' '.join(HBSOURCES))
1011   HBHEADERS = []
1012   foreach f : hb_headers
1013     HBHEADERS += '@0@'.format(f)
1014   endforeach
1015   env.set('HBHEADERS', ' '.join(HBHEADERS))
1016
1017   if cpp.get_argument_syntax() != 'msvc' and not meson.is_cross_build() # ensure the local tools are usable
1018     dist_check_script += ['check-static-inits', 'check-symbols']
1019     if get_option('wasm').disabled()
1020       dist_check_script += ['check-libstdc++']
1021     endif
1022   endif
1023
1024   foreach name : dist_check_script
1025     test(name, find_program(name + '.py'),
1026       env: env,
1027       depends: name == 'check-symbols' ? defs_list : [],
1028       suite: ['src'],
1029     )
1030   endforeach
1031 endif
1032
1033 install_headers(hb_headers + hb_subset_headers, subdir: meson.project_name())