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