2 # Meson project file for FreeType 2
5 # Copyright (C) 2020 by
6 # David Turner, Robert Wilhelm, and Werner Lemberg.
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
15 project('freetype2', 'c',
16 meson_version: '>= 0.55.0',
17 default_options: ['default_library=both'],
21 # Rules to compile the FreeType 2 library itself
25 # Apparently meson doesn't provide a read_file() function, so instead
26 # running an external command is required.
28 python = import('python')
29 python_exe = python.find_installation(required: true)
31 ft2_version = run_command(python_exe,
32 files('builds/meson/extract_freetype_version.py'),
33 files('include/freetype/freetype.h')).stdout().strip()
35 ft2_libtool_version = run_command(python_exe,
36 files('builds/meson/extract_libtool_version.py'),
38 files('builds/unix/configure.raw')).stdout().strip()
40 ft2_includes = include_directories('include')
43 # Generate a custom `ftmodule.h` version based on the content of
46 ftmodule_h = custom_target('ftmodule.h',
49 command: [python_exe, files('builds/meson/parse_modules_cfg.py'),
50 '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'],
52 install_dir: 'include/freetype2/freetype/config',
54 ft2_sources = [ftmodule_h]
59 ft_main_modules = run_command(python_exe,
60 files('builds/meson/parse_modules_cfg.py'),
61 '--format=main-modules',
62 files('modules.cfg')).stdout().strip().split()
64 ft2_sources += files([
69 foreach mod: ft_main_modules
76 ft2_sources += 'src/@0@/@1@.c'.format(mod, source)
79 # NOTE: The `gzip` and `bzip2` aux modules are handled through options.
80 ft_aux_modules = run_command(python_exe,
81 files('builds/meson/parse_modules_cfg.py'),
82 '--format=aux-modules',
83 files('modules.cfg')).stdout().strip().split()
85 foreach auxmod: ft_aux_modules
87 # Most sources are named `src/<module>/<module>.c`, but there are a few
88 # exceptions handled here.
93 elif auxmod == 'gzip' or auxmod == 'bzip2'
94 # Handled through options instead, see below.
97 ft2_sources += 'src/@0@/@1@.c'.format(auxmod, source)
101 # FreeType 2 base extensions.
102 # Normally configured through `modules.cfg`.
104 base_extensions = run_command(python_exe,
105 files('builds/meson/parse_modules_cfg.py'),
106 '--format=base-extensions-list',
107 files('modules.cfg')).stdout().split()
109 foreach ext: base_extensions
110 ft2_sources += files('src/base/' + ext)
116 ft2_public_headers = files([
117 'include/freetype/freetype.h',
118 'include/freetype/ftadvanc.h',
119 'include/freetype/ftbbox.h',
120 'include/freetype/ftbdf.h',
121 'include/freetype/ftbitmap.h',
122 'include/freetype/ftbzip2.h',
123 'include/freetype/ftcache.h',
124 'include/freetype/ftchapters.h',
125 'include/freetype/ftcolor.h',
126 'include/freetype/ftdriver.h',
127 'include/freetype/fterrdef.h',
128 'include/freetype/fterrors.h',
129 'include/freetype/ftfntfmt.h',
130 'include/freetype/ftgasp.h',
131 'include/freetype/ftglyph.h',
132 'include/freetype/ftgxval.h',
133 'include/freetype/ftgzip.h',
134 'include/freetype/ftimage.h',
135 'include/freetype/ftincrem.h',
136 'include/freetype/ftlcdfil.h',
137 'include/freetype/ftlist.h',
138 'include/freetype/ftlzw.h',
139 'include/freetype/ftmac.h',
140 'include/freetype/ftmm.h',
141 'include/freetype/ftmodapi.h',
142 'include/freetype/ftmoderr.h',
143 'include/freetype/ftotval.h',
144 'include/freetype/ftoutln.h',
145 'include/freetype/ftparams.h',
146 'include/freetype/ftpfr.h',
147 'include/freetype/ftrender.h',
148 'include/freetype/ftsizes.h',
149 'include/freetype/ftsnames.h',
150 'include/freetype/ftstroke.h',
151 'include/freetype/ftsynth.h',
152 'include/freetype/ftsystem.h',
153 'include/freetype/fttrigon.h',
154 'include/freetype/fttypes.h',
155 'include/freetype/ftwinfnt.h',
156 'include/freetype/t1tables.h',
157 'include/freetype/ttnameid.h',
158 'include/freetype/tttables.h',
159 'include/freetype/tttags.h',
162 ft2_config_headers = files([
163 'include/freetype/config/ftconfig.h',
164 'include/freetype/config/ftheader.h',
165 'include/freetype/config/ftstdlib.h',
166 'include/freetype/config/integer-types.h',
167 'include/freetype/config/mac-support.h',
168 'include/freetype/config/public-macros.h',
174 # System support file.
176 cc = meson.get_compiler('c')
178 # NOTE: msys2 on Windows has `unistd.h` and `fcntl.h` but not `sys/mman.h`!
179 has_unistd_h = cc.has_header('unistd.h')
180 has_fcntl_h = cc.has_header('fcntl.h')
181 has_sys_mman_h = cc.has_header('sys/mman.h')
184 ft2_defines += ['-DHAVE_UNISTD_H=1']
187 ft2_defines += ['-DHAVE_FCNTL_H']
190 mmap_option = get_option('mmap')
191 if mmap_option.auto()
192 use_mmap = has_unistd_h and has_fcntl_h and has_sys_mman_h
194 use_mmap = mmap_option.enabled()
197 # This version of ftsystem.c uses mmap() to read input font files.
198 ft2_sources += files(['builds/unix/ftsystem.c',])
200 ft2_sources += files(['src/base/ftsystem.c',])
206 # NOTE: Some specialized versions exist for other platforms not supported by
207 # Meson. Most implementation differences are extremely minor, i.e., in the
208 # implementation of FT_Message() and FT_Panic(), and getting the `FT2_DEBUG`
209 # value from the environment, when this is supported. A smaller refactor
210 # might make these platform-specific files much smaller, and could be moved
211 # into `ftsystem.c` as well.
213 if host_machine.system() == 'windows'
214 ft2_debug_src = 'builds/windows/ftdebug.c'
216 ft2_debug_src = 'src/base/ftdebug.c'
218 ft2_sources += files([ft2_debug_src])
223 # Generate `ftoption.h` based on available dependencies.
225 ftoption_command = [python_exe,
226 files('builds/meson/process_ftoption_h.py'),
227 '@INPUT@', '--output=@OUTPUT@']
230 zlib_option = get_option('zlib')
231 if zlib_option == 'disabled'
232 ftoption_command += ['--disable=FT_CONFIG_OPTION_USE_ZLIB']
234 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_ZLIB']
235 if zlib_option == 'builtin'
236 ftoption_command += ['--disable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
238 # Probe for the system version.
239 zlib_system = dependency('zlib', required: zlib_option == 'system')
240 ft2_deps += [zlib_system]
241 ftoption_command += ['--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
243 ft2_sources += files(['src/gzip/ftgzip.c',])
248 # IMPORTANT NOTE: Without `static: false` here, Meson will find both the
249 # static library version and the shared library version when they are
250 # installed on the system, and will try to link them *both* to the final
252 bzip2_dep = meson.get_compiler('c').find_library('bz2',
254 required: get_option('bzip2'))
256 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2']
257 ft2_sources += files(['src/bzip2/ftbzip2.c',])
258 ft2_deps += [bzip2_dep]
262 libpng_dep = dependency('libpng', required: get_option('png'))
263 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG']
264 ft2_deps += [libpng_dep]
267 harfbuzz_dep = dependency('harfbuzz',
269 required: get_option('harfbuzz'))
270 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ']
271 ft2_deps += [harfbuzz_dep]
273 # Brotli decompression support
274 brotli_dep = dependency('libbrotlidec', required: get_option('brotli'))
275 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI']
276 ft2_deps += [brotli_dep]
278 # We can now generate `ftoption.h`.
279 ftoption_h = custom_target('ftoption.h',
280 input: 'include/freetype/config/ftoption.h',
281 output: 'ftoption.h',
282 command: ftoption_command,
284 install_dir: 'include/freetype2/freetype/config',
286 ft2_sources += ftoption_h
289 # QUESTION: What if the compiler doesn't support `-D` but uses `/D` instead
292 # Other build systems have something like c_defines to list defines in a
293 # more portable way. For now assume the compiler supports `-D` (hint: Visual
295 ft2_defines += ['-DFT2_BUILD_LIBRARY=1']
298 # Ensure that the `ftoption.h` file generated above will be used to build
299 # FreeType. Unfortunately, and very surprisingly, configure_file() does not
300 # support putting the output file in a sub-directory, so we have to override
301 # the default which is `<freetype/config/ftoption.h>`.
303 # It would be cleaner to generate the file directly into
304 # `${MESON_BUILD_DIR}/freetype/config/ftoption.h`. See
305 # 'https://github.com/mesonbuild/meson/issues/2320' for details.
306 ft2_defines += ['-DFT_CONFIG_OPTIONS_H=<ftoption.h>']
308 ft2_c_args = ft2_defines
309 if cc.has_function_attribute('visibility:hidden')
310 ft2_c_args += ['-fvisibility=hidden']
313 ft2_lib = library('freetype',
314 sources: ft2_sources + [ftmodule_h],
316 include_directories: ft2_includes,
317 dependencies: ft2_deps,
319 version: ft2_libtool_version,
323 # To be used by other projects including this one through subproject().
324 freetype2_dep = declare_dependency(
325 include_directories: ft2_includes,
327 version: ft2_libtool_version)
330 # NOTE: Using both `install_dir` and `subdir` doesn't seem to work below,
331 # i.e., the subdir value seems to be ignored, contrary to examples in the
332 # Meson documentation.
333 install_headers('include/ft2build.h',
334 install_dir: 'include/freetype2')
335 install_headers(ft2_public_headers,
336 install_dir: 'include/freetype2/freetype')
337 install_headers(ft2_config_headers,
338 install_dir: 'include/freetype2/freetype/config')
341 # TODO(david): Declare_dependency() for using this in a Meson subproject
343 pkgconfig = import('pkgconfig')
344 pkgconfig.generate(ft2_lib,
345 filebase: 'freetype2',
347 description: 'A free, high-quality, and portable font engine.',
348 url: 'https://freetype.org',
349 subdirs: 'freetype2',
350 version: ft2_libtool_version,
354 # NOTE: Unlike the old `make refdoc` command, this generates the
355 # documentation under `$BUILD/docs/` since Meson doesn't support modifying
356 # the source root directory (which is a good thing).
357 gen_docs = custom_target('freetype2 reference documentation',
359 input: ft2_public_headers + ft2_config_headers,
360 command: [python_exe,
361 files('builds/meson/generate_reference_docs.py'),
362 '--version=' + ft2_version,
363 '--input-dir=' + meson.source_root(),
364 '--output-dir=@OUTPUT@'