1# 2# Meson project file for FreeType 2 3# 4 5# Copyright (C) 2020 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 15project('freetype2', 'c', 16 meson_version: '>= 0.55.0', 17 default_options: ['default_library=both'], 18) 19 20# 21# Rules to compile the FreeType 2 library itself 22# 23 24 25# Apparently meson doesn't provide a read_file() function, so instead 26# running an external command is required. 27 28python = import('python') 29python_exe = python.find_installation(required: true) 30 31ft2_version = run_command(python_exe, 32 files('builds/meson/extract_freetype_version.py'), 33 files('include/freetype/freetype.h')).stdout().strip() 34 35ft2_libtool_version = run_command(python_exe, 36 files('builds/meson/extract_libtool_version.py'), 37 '--soversion', 38 files('builds/unix/configure.raw')).stdout().strip() 39 40ft2_includes = include_directories('include') 41 42 43# Generate a custom `ftmodule.h` version based on the content of 44# `modules.cfg`. 45 46ftmodule_h = custom_target('ftmodule.h', 47 output: 'ftmodule.h', 48 input: 'modules.cfg', 49 command: [python_exe, files('builds/meson/parse_modules_cfg.py'), 50 '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'], 51 install: true, 52 install_dir: 'include/freetype2/freetype/config', 53) 54ft2_sources = [ftmodule_h] 55 56 57# FreeType 2 modules. 58 59ft_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() 63 64ft2_sources += files([ 65 'src/base/ftbase.c', 66 'src/base/ftinit.c', 67]) 68 69foreach mod: ft_main_modules 70 source = mod 71 if mod == 'winfonts' 72 source = 'winfnt' 73 elif mod == 'cid' 74 source = 'type1cid' 75 endif 76 ft2_sources += 'src/@0@/@1@.c'.format(mod, source) 77endforeach 78 79# NOTE: The `gzip` and `bzip2` aux modules are handled through options. 80ft_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() 84 85foreach auxmod: ft_aux_modules 86 source = auxmod 87 # Most sources are named `src/<module>/<module>.c`, but there are a few 88 # exceptions handled here. 89 if auxmod == 'cache' 90 source = 'ftcache' 91 elif auxmod == 'lzw' 92 source = 'ftlzw' 93 elif auxmod == 'gzip' or auxmod == 'bzip2' 94 # Handled through options instead, see below. 95 continue 96 endif 97 ft2_sources += 'src/@0@/@1@.c'.format(auxmod, source) 98endforeach 99 100 101# FreeType 2 base extensions. 102# Normally configured through `modules.cfg`. 103 104base_extensions = run_command(python_exe, 105 files('builds/meson/parse_modules_cfg.py'), 106 '--format=base-extensions-list', 107 files('modules.cfg')).stdout().split() 108 109foreach ext: base_extensions 110 ft2_sources += files('src/base/' + ext) 111endforeach 112 113 114# Header files. 115 116ft2_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', 160]) 161 162ft2_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', 169]) 170 171ft2_defines = [] 172 173 174# System support file. 175 176cc = meson.get_compiler('c') 177 178# NOTE: msys2 on Windows has `unistd.h` and `fcntl.h` but not `sys/mman.h`! 179has_unistd_h = cc.has_header('unistd.h') 180has_fcntl_h = cc.has_header('fcntl.h') 181has_sys_mman_h = cc.has_header('sys/mman.h') 182 183if has_unistd_h 184 ft2_defines += ['-DHAVE_UNISTD_H=1'] 185endif 186if has_fcntl_h 187 ft2_defines += ['-DHAVE_FCNTL_H'] 188endif 189 190mmap_option = get_option('mmap') 191if mmap_option.auto() 192 use_mmap = has_unistd_h and has_fcntl_h and has_sys_mman_h 193else 194 use_mmap = mmap_option.enabled() 195endif 196if use_mmap 197 # This version of ftsystem.c uses mmap() to read input font files. 198 ft2_sources += files(['builds/unix/ftsystem.c',]) 199else 200 ft2_sources += files(['src/base/ftsystem.c',]) 201endif 202 203 204# Debug support file 205# 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. 212# 213if host_machine.system() == 'windows' 214 ft2_debug_src = 'builds/windows/ftdebug.c' 215else 216 ft2_debug_src = 'src/base/ftdebug.c' 217endif 218ft2_sources += files([ft2_debug_src]) 219 220ft2_deps = [] 221 222 223# Generate `ftoption.h` based on available dependencies. 224 225ftoption_command = [python_exe, 226 files('builds/meson/process_ftoption_h.py'), 227 '@INPUT@', '--output=@OUTPUT@'] 228 229# GZip support 230zlib_option = get_option('zlib') 231if zlib_option == 'disabled' 232 ftoption_command += ['--disable=FT_CONFIG_OPTION_USE_ZLIB'] 233else 234 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_ZLIB'] 235 if zlib_option == 'builtin' 236 ftoption_command += ['--disable=FT_CONFIG_OPTION_SYSTEM_ZLIB'] 237 else 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'] 242 endif 243 ft2_sources += files(['src/gzip/ftgzip.c',]) 244endif 245 246# BZip2 support 247# 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 251# library! 252bzip2_dep = meson.get_compiler('c').find_library('bz2', 253 static: false, 254 required: get_option('bzip2')) 255if bzip2_dep.found() 256 ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2'] 257 ft2_sources += files(['src/bzip2/ftbzip2.c',]) 258 ft2_deps += [bzip2_dep] 259endif 260 261# PNG support 262libpng_dep = dependency('libpng', required: get_option('png')) 263ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG'] 264ft2_deps += [libpng_dep] 265 266# Harfbuzz support 267harfbuzz_dep = dependency('harfbuzz', 268 version: '>= 1.8.0', 269 required: get_option('harfbuzz')) 270ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ'] 271ft2_deps += [harfbuzz_dep] 272 273# Brotli decompression support 274brotli_dep = dependency('libbrotlidec', required: get_option('brotli')) 275ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI'] 276ft2_deps += [brotli_dep] 277 278# We can now generate `ftoption.h`. 279ftoption_h = custom_target('ftoption.h', 280 input: 'include/freetype/config/ftoption.h', 281 output: 'ftoption.h', 282 command: ftoption_command, 283 install: true, 284 install_dir: 'include/freetype2/freetype/config', 285) 286ft2_sources += ftoption_h 287 288 289# QUESTION: What if the compiler doesn't support `-D` but uses `/D` instead 290# as on Windows? 291# 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 294# Studio does). 295ft2_defines += ['-DFT2_BUILD_LIBRARY=1'] 296 297 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>`. 302# 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. 306ft2_defines += ['-DFT_CONFIG_OPTIONS_H=<ftoption.h>'] 307 308ft2_c_args = ft2_defines 309if cc.has_function_attribute('visibility:hidden') 310 ft2_c_args += ['-fvisibility=hidden'] 311endif 312 313ft2_lib = library('freetype', 314 sources: ft2_sources + [ftmodule_h], 315 c_args: ft2_c_args, 316 include_directories: ft2_includes, 317 dependencies: ft2_deps, 318 install: true, 319 version: ft2_libtool_version, 320) 321 322 323# To be used by other projects including this one through subproject(). 324freetype2_dep = declare_dependency( 325 include_directories: ft2_includes, 326 link_with: ft2_lib, 327 version: ft2_libtool_version) 328 329 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. 333install_headers('include/ft2build.h', 334 install_dir: 'include/freetype2') 335install_headers(ft2_public_headers, 336 install_dir: 'include/freetype2/freetype') 337install_headers(ft2_config_headers, 338 install_dir: 'include/freetype2/freetype/config') 339 340 341# TODO(david): Declare_dependency() for using this in a Meson subproject 342# 343pkgconfig = import('pkgconfig') 344pkgconfig.generate(ft2_lib, 345 filebase: 'freetype2', 346 name: 'FreeType 2', 347 description: 'A free, high-quality, and portable font engine.', 348 url: 'https://freetype.org', 349 subdirs: 'freetype2', 350 version: ft2_libtool_version, 351) 352 353 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). 357gen_docs = custom_target('freetype2 reference documentation', 358 output: 'docs', 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@' 365 ], 366) 367 368# EOF 369