xref: /aosp_15_r20/external/freetype/meson.build (revision 63949dbd25bcc50c4e1178497ff9e9574d44fc5a)
1#
2# Meson project file for FreeType 2
3#
4
5# Copyright (C) 2020-2023 by
6# David Turner, Robert Wilhelm, and Werner Lemberg.
7#
8# This file is part of the FreeType project, and may only be used, modified,
9# and distributed under the terms of the FreeType project license,
10# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
11# indicate that you have read the license and understand and accept it
12# fully.
13
14#
15# Say
16#
17#   meson configure
18#
19# to see all configuration options and their default values.  For example,
20# to build only a shared version of FreeType, override the default value
21# with
22#
23#   meson setup -Ddefault_library=shared
24#
25
26project('freetype2', 'c',
27  meson_version: '>= 0.55.0',
28  version: run_command('builds/meson/extract_freetype_version.py',
29                       'include/freetype/freetype.h',
30                       check: true).stdout().strip(),
31)
32
33
34# Only meson >= 0.57 can read a file and assign its contents to a
35# variable; we thus use an external command to have this functionality
36# with older versions, too.
37
38python_exe = find_program('python3')
39
40ft2_so_version = run_command(python_exe,
41  files('builds/meson/extract_libtool_version.py'),
42  '--soversion',
43  files('builds/unix/configure.raw'),
44  check: true).stdout().strip()
45
46ft2_pkgconfig_version = run_command(python_exe,
47  files('builds/meson/extract_libtool_version.py'),
48  files('builds/unix/configure.raw'),
49  check: true).stdout().strip()
50
51ft2_includes = include_directories('include')
52
53freetype_includedir = join_paths(get_option('includedir'), 'freetype2')
54
55ft2_defines = []
56
57# Generate a custom `ftmodule.h` version based on the content of
58# `modules.cfg`.
59
60ftmodule_h = custom_target('ftmodule.h',
61  output: 'ftmodule.h',
62  input: 'modules.cfg',
63  command: [python_exe, files('builds/meson/parse_modules_cfg.py'),
64            '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'],
65  install: true,
66  install_dir: join_paths(freetype_includedir, 'freetype/config'),
67)
68ft2_sources = [ftmodule_h]
69ft2_defines += ['-DFT_CONFIG_MODULES_H=<ftmodule.h>']
70
71
72# FreeType 2 modules.
73
74ft_main_modules = run_command(python_exe,
75  files('builds/meson/parse_modules_cfg.py'),
76  '--format=main-modules',
77  files('modules.cfg'),
78  check: true).stdout().strip().split()
79
80ft2_sources += files([
81  'src/base/ftbase.c',
82  'src/base/ftinit.c',
83])
84
85foreach mod: ft_main_modules
86  source = mod
87  if mod == 'winfonts'
88    source = 'winfnt'
89  elif mod == 'cid'
90    source = 'type1cid'
91  endif
92  ft2_sources += 'src/@0@/@[email protected]'.format(mod, source)
93endforeach
94
95# NOTE: The `bzip2` aux module is handled through options.
96ft_aux_modules = run_command(python_exe,
97  files('builds/meson/parse_modules_cfg.py'),
98  '--format=aux-modules',
99  files('modules.cfg'),
100  check: true).stdout().strip().split()
101
102foreach auxmod: ft_aux_modules
103  source = auxmod
104  # Most sources are named `src/<module>/<module>.c`, but there are a few
105  # exceptions handled here.
106  if auxmod == 'cache'
107    source = 'ftcache'
108  elif auxmod == 'lzw'
109    source = 'ftlzw'
110  elif auxmod == 'gzip'
111    source = 'ftgzip'
112  elif auxmod == 'bzip2'
113    # Handled through options instead, see below.
114    continue
115  endif
116  ft2_sources += 'src/@0@/@[email protected]'.format(auxmod, source)
117endforeach
118
119
120# FreeType 2 base extensions.
121# To be configured in `modules.cfg`.
122
123base_extensions = run_command(python_exe,
124  files('builds/meson/parse_modules_cfg.py'),
125  '--format=base-extensions-list',
126  files('modules.cfg'),
127  check: true).stdout().split()
128
129foreach ext: base_extensions
130  ft2_sources += files('src/base/' + ext)
131endforeach
132
133
134# Header files.
135
136ft2_public_headers = files([
137  'include/freetype/freetype.h',
138  'include/freetype/ftadvanc.h',
139  'include/freetype/ftbbox.h',
140  'include/freetype/ftbdf.h',
141  'include/freetype/ftbitmap.h',
142  'include/freetype/ftbzip2.h',
143  'include/freetype/ftcache.h',
144  'include/freetype/ftchapters.h',
145  'include/freetype/ftcid.h',
146  'include/freetype/ftcolor.h',
147  'include/freetype/ftdriver.h',
148  'include/freetype/fterrdef.h',
149  'include/freetype/fterrors.h',
150  'include/freetype/ftfntfmt.h',
151  'include/freetype/ftgasp.h',
152  'include/freetype/ftglyph.h',
153  'include/freetype/ftgxval.h',
154  'include/freetype/ftgzip.h',
155  'include/freetype/ftimage.h',
156  'include/freetype/ftincrem.h',
157  'include/freetype/ftlcdfil.h',
158  'include/freetype/ftlist.h',
159  'include/freetype/ftlzw.h',
160  'include/freetype/ftmac.h',
161  'include/freetype/ftmm.h',
162  'include/freetype/ftmodapi.h',
163  'include/freetype/ftmoderr.h',
164  'include/freetype/ftotval.h',
165  'include/freetype/ftoutln.h',
166  'include/freetype/ftparams.h',
167  'include/freetype/ftpfr.h',
168  'include/freetype/ftrender.h',
169  'include/freetype/ftsizes.h',
170  'include/freetype/ftsnames.h',
171  'include/freetype/ftstroke.h',
172  'include/freetype/ftsynth.h',
173  'include/freetype/ftsystem.h',
174  'include/freetype/fttrigon.h',
175  'include/freetype/fttypes.h',
176  'include/freetype/ftwinfnt.h',
177  'include/freetype/otsvg.h',
178  'include/freetype/t1tables.h',
179  'include/freetype/ttnameid.h',
180  'include/freetype/tttables.h',
181  'include/freetype/tttags.h',
182])
183
184ft2_config_headers = files([
185  'include/freetype/config/ftconfig.h',
186  'include/freetype/config/ftheader.h',
187  'include/freetype/config/ftstdlib.h',
188  'include/freetype/config/integer-types.h',
189  'include/freetype/config/mac-support.h',
190  'include/freetype/config/public-macros.h',
191])
192
193ft2_defines += ['-DFT2_BUILD_LIBRARY=1']
194
195
196# System support file.
197
198cc = meson.get_compiler('c')
199
200# NOTE: msys2 on Windows has `unistd.h` and `fcntl.h` but not `sys/mman.h`!
201has_unistd_h = cc.has_header('unistd.h')
202has_fcntl_h = cc.has_header('fcntl.h')
203has_sys_mman_h = cc.has_header('sys/mman.h')
204
205mmap_option = get_option('mmap')
206
207use_unix_ftsystem_c = false
208if mmap_option.disabled()
209  ft2_sources += files(['src/base/ftsystem.c',])
210elif host_machine.system() == 'windows'
211  ft2_sources += files(['builds/windows/ftsystem.c',])
212else
213  if has_unistd_h and has_fcntl_h and has_sys_mman_h
214    # This version of `ftsystem.c` uses `mmap` to read input font files.
215    ft2_sources += files(['builds/unix/ftsystem.c',])
216    use_unix_ftsystem_c = true
217  elif mmap_option.enabled()
218    error('mmap was enabled via options but is not available,'
219          + ' required headers were not found!')
220  else
221    ft2_sources += files(['src/base/ftsystem.c',])
222  endif
223endif
224
225
226# Debug support file
227#
228# NOTE: Some specialized versions exist for other platforms not supported by
229# Meson.  Most implementation differences are extremely minor, i.e., in the
230# implementation of `FT_Message` and `FT_Panic`, and getting the `FT2_DEBUG`
231# value from the environment, when this is supported.  A smaller refactor
232# might make these platform-specific files much smaller, and could be moved
233# into `ftsystem.c` as well.
234#
235if host_machine.system() == 'windows'
236  winmod = import('windows')
237  ft2_sources += [
238    'builds/windows/ftdebug.c',
239    winmod.compile_resources('src/base/ftver.rc'),
240  ]
241else
242  ft2_sources += 'src/base/ftdebug.c'
243endif
244
245
246ft2_deps = []
247common_ldflags = []
248
249
250# Correct compatibility version for OS x.
251#
252# OSX sets the compatibility_version (aka libtools version) differently from
253# the library name.
254#
255if host_machine.system() == 'darwin'
256  # maintain compatibility with autotools on macOS
257  common_ldflags = [
258    '-compatibility_version', ft2_pkgconfig_version.split('.')[0],
259    '-current_version', ft2_pkgconfig_version
260  ]
261endif
262
263
264# Generate `ftoption.h` based on available dependencies.
265
266process_header_command = [python_exe,
267  files('builds/meson/process_ftoption_h.py'),
268  '@INPUT@', '--output=@OUTPUT@']
269ftoption_command = process_header_command
270
271
272# external GZip support
273zlib_option = get_option('zlib')
274
275# Backwards-compatible aliases.
276if zlib_option == 'disabled'
277  zlib_option = 'none'
278elif zlib_option == 'enabled'
279  zlib_option = 'auto'
280endif
281
282if zlib_option == 'auto'
283  # First try to find a system installation, otherwise fall back to
284  # the subproject.
285  zlib_dep = dependency('zlib',
286    required: false)
287  if zlib_dep.found()
288    zlib_option = 'system'
289  else
290    zlib_option = 'external'
291  endif
292endif
293
294if zlib_option == 'none'
295  ftoption_command += [ '--disable=FT_CONFIG_OPTION_USE_ZLIB' ]
296elif zlib_option == 'internal'
297  ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB' ]
298elif zlib_option == 'external'
299  ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB' ]
300  zlib_project = subproject('zlib',
301    required: true,
302    default_options: 'default_library=static')
303  zlib_dep = zlib_project.get_variable('zlib_dep')
304  ft2_deps += [zlib_dep]
305elif zlib_option == 'system'
306  zlib_dep = dependency('zlib',
307    required: true)
308  assert(zlib_dep.found(), 'Could not find system zlib installation!')
309  ftoption_command += [
310    '--enable=FT_CONFIG_OPTION_USE_ZLIB',
311    '--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB',
312  ]
313  ft2_deps += [zlib_dep]
314else
315  assert(false, 'Invalid zlib option ' + zlib_option)
316endif
317
318# BZip2 support
319bzip2_dep = cc.find_library('bz2',
320  required: get_option('bzip2'))
321
322if bzip2_dep.found()
323  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2']
324  ft2_sources += files(['src/bzip2/ftbzip2.c',])
325  ft2_deps += [bzip2_dep]
326endif
327
328# PNG support
329libpng_dep = dependency('libpng',
330  required: get_option('png'),
331  fallback: 'libpng')
332
333if libpng_dep.found()
334  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG']
335  ft2_deps += [libpng_dep]
336endif
337
338# Harfbuzz support
339harfbuzz_dep = dependency('harfbuzz',
340  version: '>= 2.0.0',
341  required: get_option('harfbuzz'),
342  default_options: ['freetype=disabled'])
343
344if harfbuzz_dep.found()
345  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ']
346  ft2_deps += [harfbuzz_dep]
347endif
348
349# Brotli decompression support
350brotli_dep = dependency('libbrotlidec',
351  required: get_option('brotli'))
352
353if brotli_dep.found()
354  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI']
355  ft2_deps += [brotli_dep]
356endif
357
358# We can now generate `ftoption.h`.
359ftoption_h = custom_target('ftoption.h',
360  input: 'include/freetype/config/ftoption.h',
361  output: 'ftoption.h',
362  command: ftoption_command,
363  install: true,
364  install_dir: join_paths(freetype_includedir, 'freetype/config'),
365)
366ft2_sources += ftoption_h
367ft2_defines += ['-DFT_CONFIG_OPTIONS_H=<ftoption.h>']
368
369if host_machine.system() == 'windows'
370  ft2_defines += ['-DDLL_EXPORT=1']
371endif
372
373
374# Generate `ftconfig.h`.
375
376ftconfig_command = process_header_command
377if has_unistd_h
378  ftconfig_command += '--enable=HAVE_UNISTD_H'
379endif
380if has_fcntl_h
381  ftconfig_command += '--enable=HAVE_FCNTL_H'
382endif
383
384if use_unix_ftsystem_c
385  ftconfig_h_in = files('builds/unix/ftconfig.h.in')
386  ftconfig_h = custom_target('ftconfig.h',
387    input: ftconfig_h_in,
388    output: 'ftconfig.h',
389    command: ftconfig_command,
390    install: true,
391    install_dir: join_paths(freetype_includedir, 'freetype/config'),
392  )
393  ft2_sources += ftconfig_h
394  ft2_defines += ['-DFT_CONFIG_CONFIG_H=<ftconfig.h>']
395endif
396
397
398ft2_lib = library('freetype',
399  sources: ft2_sources + [ftmodule_h],
400  c_args: ft2_defines,
401  gnu_symbol_visibility: 'hidden',
402  include_directories: ft2_includes,
403  dependencies: ft2_deps,
404  install: true,
405  version: ft2_so_version,
406  link_args: common_ldflags,
407)
408
409
410# To be used by other projects including this one through `subproject`.
411freetype_dep = declare_dependency(
412  include_directories: ft2_includes,
413  link_with: ft2_lib,
414  version: ft2_pkgconfig_version)
415
416meson.override_dependency('freetype2', freetype_dep)
417
418
419# NOTE: Using both `install_dir` and `subdir` doesn't seem to work below,
420# i.e., the subdir value seems to be ignored, contrary to examples in the
421# Meson documentation.
422install_headers('include/ft2build.h',
423  install_dir: freetype_includedir)
424install_headers(ft2_public_headers,
425  install_dir: join_paths(freetype_includedir, 'freetype'))
426install_headers(ft2_config_headers,
427  install_dir: join_paths(freetype_includedir, 'freetype/config'))
428
429
430pkgconfig = import('pkgconfig')
431
432pkgconfig.generate(ft2_lib,
433  filebase: 'freetype2',
434  name: 'FreeType 2',
435  description: 'A free, high-quality, and portable font engine.',
436  url: 'https://freetype.org',
437  subdirs: 'freetype2',
438  version: ft2_pkgconfig_version,
439)
440
441if get_option('tests').enabled()
442  subdir('tests')
443endif
444
445# NOTE: Unlike the old `make refdoc` command, this generates the
446# documentation under `$BUILD/docs/` since Meson doesn't support modifying
447# the source root directory (which is a good thing).
448gen_docs = custom_target('freetype2 reference documentation',
449  output: 'docs',
450  input: ft2_public_headers + ft2_config_headers,
451  command: [python_exe,
452    files('builds/meson/generate_reference_docs.py'),
453    '--version=' + meson.project_version(),
454    '--input-dir=' + meson.current_source_dir(),
455    '--output-dir=@OUTPUT@'
456  ],
457)
458
459
460summary({'OS': host_machine.system(),
461        }, section: 'Operating System')
462
463summary({'Zlib': zlib_option,
464         'Bzip2': bzip2_dep.found() ? 'yes' : 'no',
465         'Png': libpng_dep.found() ? 'yes' : 'no',
466         'Harfbuzz': harfbuzz_dep.found() ? 'yes' : 'no',
467         'Brotli': brotli_dep.found() ? 'yes' : 'no',
468        }, section: 'Used Libraries')
469
470# EOF
471