# # Meson project file for FreeType 2 # # Copyright (C) 2020-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, # and distributed under the terms of the FreeType project license, # LICENSE.TXT. By continuing to use, modify, or distribute this file you # indicate that you have read the license and understand and accept it # fully. # # Say # # meson configure # # to see all configuration options and their default values. For example, # to build only a shared version of FreeType, override the default value # with # # meson setup -Ddefault_library=shared # project('freetype2', 'c', meson_version: '>= 0.55.0', version: run_command('builds/meson/extract_freetype_version.py', 'include/freetype/freetype.h', check: true).stdout().strip(), ) # Only meson >= 0.57 can read a file and assign its contents to a # variable; we thus use an external command to have this functionality # with older versions, too. python_exe = find_program('python3') ft2_so_version = run_command(python_exe, files('builds/meson/extract_libtool_version.py'), '--soversion', files('builds/unix/configure.raw'), check: true).stdout().strip() ft2_pkgconfig_version = run_command(python_exe, files('builds/meson/extract_libtool_version.py'), files('builds/unix/configure.raw'), check: true).stdout().strip() ft2_includes = include_directories('include') freetype_includedir = join_paths(get_option('includedir'), 'freetype2') ft2_defines = [] # Generate a custom `ftmodule.h` version based on the content of # `modules.cfg`. ftmodule_h = custom_target('ftmodule.h', output: 'ftmodule.h', input: 'modules.cfg', command: [python_exe, files('builds/meson/parse_modules_cfg.py'), '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'], install: true, install_dir: join_paths(freetype_includedir, 'freetype/config'), ) ft2_sources = [ftmodule_h] ft2_defines += ['-DFT_CONFIG_MODULES_H='] # FreeType 2 modules. ft_main_modules = run_command(python_exe, files('builds/meson/parse_modules_cfg.py'), '--format=main-modules', files('modules.cfg'), check: true).stdout().strip().split() ft2_sources += files([ 'src/base/ftbase.c', 'src/base/ftinit.c', ]) foreach mod: ft_main_modules source = mod if mod == 'winfonts' source = 'winfnt' elif mod == 'cid' source = 'type1cid' endif ft2_sources += 'src/@0@/@1@.c'.format(mod, source) endforeach # NOTE: The `bzip2` aux module is handled through options. ft_aux_modules = run_command(python_exe, files('builds/meson/parse_modules_cfg.py'), '--format=aux-modules', files('modules.cfg'), check: true).stdout().strip().split() foreach auxmod: ft_aux_modules source = auxmod # Most sources are named `src//.c`, but there are a few # exceptions handled here. if auxmod == 'cache' source = 'ftcache' elif auxmod == 'lzw' source = 'ftlzw' elif auxmod == 'gzip' source = 'ftgzip' elif auxmod == 'bzip2' # Handled through options instead, see below. continue endif ft2_sources += 'src/@0@/@1@.c'.format(auxmod, source) endforeach # FreeType 2 base extensions. # To be configured in `modules.cfg`. base_extensions = run_command(python_exe, files('builds/meson/parse_modules_cfg.py'), '--format=base-extensions-list', files('modules.cfg'), check: true).stdout().split() foreach ext: base_extensions ft2_sources += files('src/base/' + ext) endforeach # Header files. ft2_public_headers = files([ 'include/freetype/freetype.h', 'include/freetype/ftadvanc.h', 'include/freetype/ftbbox.h', 'include/freetype/ftbdf.h', 'include/freetype/ftbitmap.h', 'include/freetype/ftbzip2.h', 'include/freetype/ftcache.h', 'include/freetype/ftchapters.h', 'include/freetype/ftcid.h', 'include/freetype/ftcolor.h', 'include/freetype/ftdriver.h', 'include/freetype/fterrdef.h', 'include/freetype/fterrors.h', 'include/freetype/ftfntfmt.h', 'include/freetype/ftgasp.h', 'include/freetype/ftglyph.h', 'include/freetype/ftgxval.h', 'include/freetype/ftgzip.h', 'include/freetype/ftimage.h', 'include/freetype/ftincrem.h', 'include/freetype/ftlcdfil.h', 'include/freetype/ftlist.h', 'include/freetype/ftlzw.h', 'include/freetype/ftmac.h', 'include/freetype/ftmm.h', 'include/freetype/ftmodapi.h', 'include/freetype/ftmoderr.h', 'include/freetype/ftotval.h', 'include/freetype/ftoutln.h', 'include/freetype/ftparams.h', 'include/freetype/ftpfr.h', 'include/freetype/ftrender.h', 'include/freetype/ftsizes.h', 'include/freetype/ftsnames.h', 'include/freetype/ftstroke.h', 'include/freetype/ftsynth.h', 'include/freetype/ftsystem.h', 'include/freetype/fttrigon.h', 'include/freetype/fttypes.h', 'include/freetype/ftwinfnt.h', 'include/freetype/otsvg.h', 'include/freetype/t1tables.h', 'include/freetype/ttnameid.h', 'include/freetype/tttables.h', 'include/freetype/tttags.h', ]) ft2_config_headers = files([ 'include/freetype/config/ftconfig.h', 'include/freetype/config/ftheader.h', 'include/freetype/config/ftstdlib.h', 'include/freetype/config/integer-types.h', 'include/freetype/config/mac-support.h', 'include/freetype/config/public-macros.h', ]) ft2_defines += ['-DFT2_BUILD_LIBRARY=1'] # System support file. cc = meson.get_compiler('c') # NOTE: msys2 on Windows has `unistd.h` and `fcntl.h` but not `sys/mman.h`! has_unistd_h = cc.has_header('unistd.h') has_fcntl_h = cc.has_header('fcntl.h') has_sys_mman_h = cc.has_header('sys/mman.h') mmap_option = get_option('mmap') use_unix_ftsystem_c = false if mmap_option.disabled() ft2_sources += files(['src/base/ftsystem.c',]) elif host_machine.system() == 'windows' ft2_sources += files(['builds/windows/ftsystem.c',]) else if has_unistd_h and has_fcntl_h and has_sys_mman_h # This version of `ftsystem.c` uses `mmap` to read input font files. ft2_sources += files(['builds/unix/ftsystem.c',]) use_unix_ftsystem_c = true elif mmap_option.enabled() error('mmap was enabled via options but is not available,' + ' required headers were not found!') else ft2_sources += files(['src/base/ftsystem.c',]) endif endif # Debug support file # # NOTE: Some specialized versions exist for other platforms not supported by # Meson. Most implementation differences are extremely minor, i.e., in the # implementation of `FT_Message` and `FT_Panic`, and getting the `FT2_DEBUG` # value from the environment, when this is supported. A smaller refactor # might make these platform-specific files much smaller, and could be moved # into `ftsystem.c` as well. # if host_machine.system() == 'windows' winmod = import('windows') ft2_sources += [ 'builds/windows/ftdebug.c', winmod.compile_resources('src/base/ftver.rc'), ] else ft2_sources += 'src/base/ftdebug.c' endif ft2_deps = [] common_ldflags = [] # Correct compatibility version for OS x. # # OSX sets the compatibility_version (aka libtools version) differently from # the library name. # if host_machine.system() == 'darwin' # maintain compatibility with autotools on macOS common_ldflags = [ '-compatibility_version', ft2_pkgconfig_version.split('.')[0], '-current_version', ft2_pkgconfig_version ] endif # Generate `ftoption.h` based on available dependencies. process_header_command = [python_exe, files('builds/meson/process_ftoption_h.py'), '@INPUT@', '--output=@OUTPUT@'] ftoption_command = process_header_command # external GZip support zlib_option = get_option('zlib') # Backwards-compatible aliases. if zlib_option == 'disabled' zlib_option = 'none' elif zlib_option == 'enabled' zlib_option = 'auto' endif if zlib_option == 'auto' # First try to find a system installation, otherwise fall back to # the subproject. zlib_dep = dependency('zlib', required: false) if zlib_dep.found() zlib_option = 'system' else zlib_option = 'external' endif endif if zlib_option == 'none' ftoption_command += [ '--disable=FT_CONFIG_OPTION_USE_ZLIB' ] elif zlib_option == 'internal' ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB' ] elif zlib_option == 'external' ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB' ] zlib_project = subproject('zlib', required: true, default_options: 'default_library=static') zlib_dep = zlib_project.get_variable('zlib_dep') ft2_deps += [zlib_dep] elif zlib_option == 'system' zlib_dep = dependency('zlib', required: true) assert(zlib_dep.found(), 'Could not find system zlib installation!') ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB', '--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB', ] ft2_deps += [zlib_dep] else assert(false, 'Invalid zlib option ' + zlib_option) endif # BZip2 support bzip2_dep = cc.find_library('bz2', required: get_option('bzip2')) if bzip2_dep.found() ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2'] ft2_sources += files(['src/bzip2/ftbzip2.c',]) ft2_deps += [bzip2_dep] endif # PNG support libpng_dep = dependency('libpng', required: get_option('png'), fallback: 'libpng') if libpng_dep.found() ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG'] ft2_deps += [libpng_dep] endif # Harfbuzz support harfbuzz_dep = dependency('harfbuzz', version: '>= 2.0.0', required: get_option('harfbuzz'), default_options: ['freetype=disabled']) if harfbuzz_dep.found() ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ'] ft2_deps += [harfbuzz_dep] endif # Brotli decompression support brotli_dep = dependency('libbrotlidec', required: get_option('brotli')) if brotli_dep.found() ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI'] ft2_deps += [brotli_dep] endif # We can now generate `ftoption.h`. ftoption_h = custom_target('ftoption.h', input: 'include/freetype/config/ftoption.h', output: 'ftoption.h', command: ftoption_command, install: true, install_dir: join_paths(freetype_includedir, 'freetype/config'), ) ft2_sources += ftoption_h ft2_defines += ['-DFT_CONFIG_OPTIONS_H='] if host_machine.system() == 'windows' ft2_defines += ['-DDLL_EXPORT=1'] endif # Generate `ftconfig.h`. ftconfig_command = process_header_command if has_unistd_h ftconfig_command += '--enable=HAVE_UNISTD_H' endif if has_fcntl_h ftconfig_command += '--enable=HAVE_FCNTL_H' endif if use_unix_ftsystem_c ftconfig_h_in = files('builds/unix/ftconfig.h.in') ftconfig_h = custom_target('ftconfig.h', input: ftconfig_h_in, output: 'ftconfig.h', command: ftconfig_command, install: true, install_dir: join_paths(freetype_includedir, 'freetype/config'), ) ft2_sources += ftconfig_h ft2_defines += ['-DFT_CONFIG_CONFIG_H='] endif ft2_lib = library('freetype', sources: ft2_sources + [ftmodule_h], c_args: ft2_defines, gnu_symbol_visibility: 'hidden', include_directories: ft2_includes, dependencies: ft2_deps, install: true, version: ft2_so_version, link_args: common_ldflags, ) # To be used by other projects including this one through `subproject`. freetype_dep = declare_dependency( include_directories: ft2_includes, link_with: ft2_lib, version: ft2_pkgconfig_version) meson.override_dependency('freetype2', freetype_dep) # NOTE: Using both `install_dir` and `subdir` doesn't seem to work below, # i.e., the subdir value seems to be ignored, contrary to examples in the # Meson documentation. install_headers('include/ft2build.h', install_dir: freetype_includedir) install_headers(ft2_public_headers, install_dir: join_paths(freetype_includedir, 'freetype')) install_headers(ft2_config_headers, install_dir: join_paths(freetype_includedir, 'freetype/config')) pkgconfig = import('pkgconfig') pkgconfig.generate(ft2_lib, filebase: 'freetype2', name: 'FreeType 2', description: 'A free, high-quality, and portable font engine.', url: 'https://freetype.org', subdirs: 'freetype2', version: ft2_pkgconfig_version, ) if get_option('tests').enabled() subdir('tests') endif # NOTE: Unlike the old `make refdoc` command, this generates the # documentation under `$BUILD/docs/` since Meson doesn't support modifying # the source root directory (which is a good thing). gen_docs = custom_target('freetype2 reference documentation', output: 'docs', input: ft2_public_headers + ft2_config_headers, command: [python_exe, files('builds/meson/generate_reference_docs.py'), '--version=' + meson.project_version(), '--input-dir=' + meson.current_source_dir(), '--output-dir=@OUTPUT@' ], ) summary({'OS': host_machine.system(), }, section: 'Operating System') summary({'Zlib': zlib_option, 'Bzip2': bzip2_dep.found() ? 'yes' : 'no', 'Png': libpng_dep.found() ? 'yes' : 'no', 'Harfbuzz': harfbuzz_dep.found() ? 'yes' : 'no', 'Brotli': brotli_dep.found() ? 'yes' : 'no', }, section: 'Used Libraries') # EOF