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