freetype/meson.build
Eli Schwartz d6a5c57727 * meson.build: Optimize lookup for python3 program.
The python module's `find_installation` method is intended to provide
routines for compiling and installing python modules into the
`site-packages` directory.  It does a couple of slow things, including run
an introspection command to scrape sysconfig info from the detected
interpreter, which are not needed for the sole use case of invoking the
found installation as an executable.

Furthermore, when invoked without the name or path of a python binary, it is
hardcoded to always look for `python3` corresponding to the interpreter
meson itself uses to run.  So using `find_installation` did not even allow
detecting `python2` as a fallback.

Instead, switch to a simple `find_program` lookup that finishes as soon as
the program is found.
2021-12-17 10:47:13 +01:00

433 lines
12 KiB
Meson

#
# Meson project file for FreeType 2
#
# Copyright (C) 2020-2021 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',
default_options: ['default_library=both'],
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')
# 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]
# 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/<module>/<module>.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/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_dep = dependency('zlib',
required: get_option('zlib'),
fallback: 'zlib')
if zlib_dep.found()
ftoption_command += ['--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
ft2_deps += [zlib_dep]
else
ftoption_command += ['--disable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
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'))
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=<ftoption.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=<ftconfig.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_dep.found() ? 'external' : 'internal',
'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