version up to 2.13.2
[platform/upstream/freetype2.git] / meson.build
1 #
2 # Meson project file for FreeType 2
3 #
4
5 # Copyright (C) 2020-2023 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
26 project('freetype2', 'c',
27   meson_version: '>= 0.55.0',
28   version: run_command('builds/meson/extract_freetype_version.py',
29                        'include/freetype/freetype.h',
30                        check: true).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
38 python_exe = find_program('python3')
39
40 ft2_so_version = run_command(python_exe,
41   files('builds/meson/extract_libtool_version.py'),
42   '--soversion',
43   files('builds/unix/configure.raw'),
44   check: true).stdout().strip()
45
46 ft2_pkgconfig_version = run_command(python_exe,
47   files('builds/meson/extract_libtool_version.py'),
48   files('builds/unix/configure.raw'),
49   check: true).stdout().strip()
50
51 ft2_includes = include_directories('include')
52
53 freetype_includedir = join_paths(get_option('includedir'), 'freetype2')
54
55 ft2_defines = []
56
57 # Generate a custom `ftmodule.h` version based on the content of
58 # `modules.cfg`.
59
60 ftmodule_h = custom_target('ftmodule.h',
61   output: 'ftmodule.h',
62   input: 'modules.cfg',
63   command: [python_exe, files('builds/meson/parse_modules_cfg.py'),
64             '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'],
65   install: true,
66   install_dir: join_paths(freetype_includedir, 'freetype/config'),
67 )
68 ft2_sources = [ftmodule_h]
69 ft2_defines += ['-DFT_CONFIG_MODULES_H=<ftmodule.h>']
70
71
72 # FreeType 2 modules.
73
74 ft_main_modules = run_command(python_exe,
75   files('builds/meson/parse_modules_cfg.py'),
76   '--format=main-modules',
77   files('modules.cfg'),
78   check: true).stdout().strip().split()
79
80 ft2_sources += files([
81   'src/base/ftbase.c',
82   'src/base/ftinit.c',
83 ])
84
85 foreach mod: ft_main_modules
86   source = mod
87   if mod == 'winfonts'
88     source = 'winfnt'
89   elif mod == 'cid'
90     source = 'type1cid'
91   endif
92   ft2_sources += 'src/@0@/@1@.c'.format(mod, source)
93 endforeach
94
95 # NOTE: The `bzip2` aux module is handled through options.
96 ft_aux_modules = run_command(python_exe,
97   files('builds/meson/parse_modules_cfg.py'),
98   '--format=aux-modules',
99   files('modules.cfg'),
100   check: true).stdout().strip().split()
101
102 foreach auxmod: ft_aux_modules
103   source = auxmod
104   # Most sources are named `src/<module>/<module>.c`, but there are a few
105   # exceptions handled here.
106   if auxmod == 'cache'
107     source = 'ftcache'
108   elif auxmod == 'lzw'
109     source = 'ftlzw'
110   elif auxmod == 'gzip'
111     source = 'ftgzip'
112   elif auxmod == 'bzip2'
113     # Handled through options instead, see below.
114     continue
115   endif
116   ft2_sources += 'src/@0@/@1@.c'.format(auxmod, source)
117 endforeach
118
119
120 # FreeType 2 base extensions.
121 # To be configured in `modules.cfg`.
122
123 base_extensions = run_command(python_exe,
124   files('builds/meson/parse_modules_cfg.py'),
125   '--format=base-extensions-list',
126   files('modules.cfg'),
127   check: true).stdout().split()
128
129 foreach ext: base_extensions
130   ft2_sources += files('src/base/' + ext)
131 endforeach
132
133
134 # Header files.
135
136 ft2_public_headers = files([
137   'include/freetype/freetype.h',
138   'include/freetype/ftadvanc.h',
139   'include/freetype/ftbbox.h',
140   'include/freetype/ftbdf.h',
141   'include/freetype/ftbitmap.h',
142   'include/freetype/ftbzip2.h',
143   'include/freetype/ftcache.h',
144   'include/freetype/ftchapters.h',
145   'include/freetype/ftcid.h',
146   'include/freetype/ftcolor.h',
147   'include/freetype/ftdriver.h',
148   'include/freetype/fterrdef.h',
149   'include/freetype/fterrors.h',
150   'include/freetype/ftfntfmt.h',
151   'include/freetype/ftgasp.h',
152   'include/freetype/ftglyph.h',
153   'include/freetype/ftgxval.h',
154   'include/freetype/ftgzip.h',
155   'include/freetype/ftimage.h',
156   'include/freetype/ftincrem.h',
157   'include/freetype/ftlcdfil.h',
158   'include/freetype/ftlist.h',
159   'include/freetype/ftlzw.h',
160   'include/freetype/ftmac.h',
161   'include/freetype/ftmm.h',
162   'include/freetype/ftmodapi.h',
163   'include/freetype/ftmoderr.h',
164   'include/freetype/ftotval.h',
165   'include/freetype/ftoutln.h',
166   'include/freetype/ftparams.h',
167   'include/freetype/ftpfr.h',
168   'include/freetype/ftrender.h',
169   'include/freetype/ftsizes.h',
170   'include/freetype/ftsnames.h',
171   'include/freetype/ftstroke.h',
172   'include/freetype/ftsynth.h',
173   'include/freetype/ftsystem.h',
174   'include/freetype/fttrigon.h',
175   'include/freetype/fttypes.h',
176   'include/freetype/ftwinfnt.h',
177   'include/freetype/otsvg.h',
178   'include/freetype/t1tables.h',
179   'include/freetype/ttnameid.h',
180   'include/freetype/tttables.h',
181   'include/freetype/tttags.h',
182 ])
183
184 ft2_config_headers = files([
185   'include/freetype/config/ftconfig.h',
186   'include/freetype/config/ftheader.h',
187   'include/freetype/config/ftstdlib.h',
188   'include/freetype/config/integer-types.h',
189   'include/freetype/config/mac-support.h',
190   'include/freetype/config/public-macros.h',
191 ])
192
193 ft2_defines += ['-DFT2_BUILD_LIBRARY=1']
194
195
196 # System support file.
197
198 cc = meson.get_compiler('c')
199
200 # NOTE: msys2 on Windows has `unistd.h` and `fcntl.h` but not `sys/mman.h`!
201 has_unistd_h = cc.has_header('unistd.h')
202 has_fcntl_h = cc.has_header('fcntl.h')
203 has_sys_mman_h = cc.has_header('sys/mman.h')
204
205 mmap_option = get_option('mmap')
206
207 use_unix_ftsystem_c = false
208 if mmap_option.disabled()
209   ft2_sources += files(['src/base/ftsystem.c',])
210 elif host_machine.system() == 'windows'
211   ft2_sources += files(['builds/windows/ftsystem.c',])
212 else
213   if has_unistd_h and has_fcntl_h and has_sys_mman_h
214     # This version of `ftsystem.c` uses `mmap` to read input font files.
215     ft2_sources += files(['builds/unix/ftsystem.c',])
216     use_unix_ftsystem_c = true
217   elif mmap_option.enabled()
218     error('mmap was enabled via options but is not available,'
219           + ' required headers were not found!')
220   else
221     ft2_sources += files(['src/base/ftsystem.c',])
222   endif
223 endif
224
225
226 # Debug support file
227 #
228 # NOTE: Some specialized versions exist for other platforms not supported by
229 # Meson.  Most implementation differences are extremely minor, i.e., in the
230 # implementation of `FT_Message` and `FT_Panic`, and getting the `FT2_DEBUG`
231 # value from the environment, when this is supported.  A smaller refactor
232 # might make these platform-specific files much smaller, and could be moved
233 # into `ftsystem.c` as well.
234 #
235 if host_machine.system() == 'windows'
236   winmod = import('windows')
237   ft2_sources += [
238     'builds/windows/ftdebug.c',
239     winmod.compile_resources('src/base/ftver.rc'),
240   ]
241 else
242   ft2_sources += 'src/base/ftdebug.c'
243 endif
244
245
246 ft2_deps = []
247 common_ldflags = []
248
249
250 # Correct compatibility version for OS x.
251 #
252 # OSX sets the compatibility_version (aka libtools version) differently from
253 # the library name.
254 #
255 if host_machine.system() == 'darwin'
256   # maintain compatibility with autotools on macOS
257   common_ldflags = [
258     '-compatibility_version', ft2_pkgconfig_version.split('.')[0],
259     '-current_version', ft2_pkgconfig_version
260   ]
261 endif
262
263
264 # Generate `ftoption.h` based on available dependencies.
265
266 process_header_command = [python_exe,
267   files('builds/meson/process_ftoption_h.py'),
268   '@INPUT@', '--output=@OUTPUT@']
269 ftoption_command = process_header_command
270
271
272 # external GZip support
273 zlib_option = get_option('zlib')
274
275 # Backwards-compatible aliases.
276 if zlib_option == 'disabled'
277   zlib_option = 'none'
278 elif zlib_option == 'enabled'
279   zlib_option = 'auto'
280 endif
281
282 if zlib_option == 'auto'
283   # First try to find a system installation, otherwise fall back to
284   # the subproject.
285   zlib_dep = dependency('zlib',
286     required: false)
287   if zlib_dep.found()
288     zlib_option = 'system'
289   else
290     zlib_option = 'external'
291   endif
292 endif
293
294 if zlib_option == 'none'
295   ftoption_command += [ '--disable=FT_CONFIG_OPTION_USE_ZLIB' ]
296 elif zlib_option == 'internal'
297   ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB' ]
298 elif zlib_option == 'external'
299   ftoption_command += [ '--enable=FT_CONFIG_OPTION_USE_ZLIB' ]
300   zlib_project = subproject('zlib',
301     required: true,
302     default_options: 'default_library=static')
303   zlib_dep = zlib_project.get_variable('zlib_dep')
304   ft2_deps += [zlib_dep]
305 elif zlib_option == 'system'
306   zlib_dep = dependency('zlib',
307     required: true)
308   assert(zlib_dep.found(), 'Could not find system zlib installation!')
309   ftoption_command += [
310     '--enable=FT_CONFIG_OPTION_USE_ZLIB',
311     '--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB',
312   ]
313   ft2_deps += [zlib_dep]
314 else
315   assert(false, 'Invalid zlib option ' + zlib_option)
316 endif
317
318 # BZip2 support
319 bzip2_dep = cc.find_library('bz2',
320   required: get_option('bzip2'))
321
322 if bzip2_dep.found()
323   ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2']
324   ft2_sources += files(['src/bzip2/ftbzip2.c',])
325   ft2_deps += [bzip2_dep]
326 endif
327
328 # PNG support
329 libpng_dep = dependency('libpng',
330   required: get_option('png'),
331   fallback: 'libpng')
332
333 if libpng_dep.found()
334   ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG']
335   ft2_deps += [libpng_dep]
336 endif
337
338 # Harfbuzz support
339 harfbuzz_dep = dependency('harfbuzz',
340   version: '>= 2.0.0',
341   required: get_option('harfbuzz'),
342   default_options: ['freetype=disabled'])
343
344 if harfbuzz_dep.found()
345   ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ']
346   ft2_deps += [harfbuzz_dep]
347 endif
348
349 # Brotli decompression support
350 brotli_dep = dependency('libbrotlidec',
351   required: get_option('brotli'))
352
353 if brotli_dep.found()
354   ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI']
355   ft2_deps += [brotli_dep]
356 endif
357
358 # We can now generate `ftoption.h`.
359 ftoption_h = custom_target('ftoption.h',
360   input: 'include/freetype/config/ftoption.h',
361   output: 'ftoption.h',
362   command: ftoption_command,
363   install: true,
364   install_dir: join_paths(freetype_includedir, 'freetype/config'),
365 )
366 ft2_sources += ftoption_h
367 ft2_defines += ['-DFT_CONFIG_OPTIONS_H=<ftoption.h>']
368
369 if host_machine.system() == 'windows'
370   ft2_defines += ['-DDLL_EXPORT=1']
371 endif
372
373
374 # Generate `ftconfig.h`.
375
376 ftconfig_command = process_header_command
377 if has_unistd_h
378   ftconfig_command += '--enable=HAVE_UNISTD_H'
379 endif
380 if has_fcntl_h
381   ftconfig_command += '--enable=HAVE_FCNTL_H'
382 endif
383
384 if use_unix_ftsystem_c
385   ftconfig_h_in = files('builds/unix/ftconfig.h.in')
386   ftconfig_h = custom_target('ftconfig.h',
387     input: ftconfig_h_in,
388     output: 'ftconfig.h',
389     command: ftconfig_command,
390     install: true,
391     install_dir: join_paths(freetype_includedir, 'freetype/config'),
392   )
393   ft2_sources += ftconfig_h
394   ft2_defines += ['-DFT_CONFIG_CONFIG_H=<ftconfig.h>']
395 endif
396
397
398 ft2_lib = library('freetype',
399   sources: ft2_sources + [ftmodule_h],
400   c_args: ft2_defines,
401   gnu_symbol_visibility: 'hidden',
402   include_directories: ft2_includes,
403   dependencies: ft2_deps,
404   install: true,
405   version: ft2_so_version,
406   link_args: common_ldflags,
407 )
408
409
410 # To be used by other projects including this one through `subproject`.
411 freetype_dep = declare_dependency(
412   include_directories: ft2_includes,
413   link_with: ft2_lib,
414   version: ft2_pkgconfig_version)
415
416 meson.override_dependency('freetype2', freetype_dep)
417
418
419 # NOTE: Using both `install_dir` and `subdir` doesn't seem to work below,
420 # i.e., the subdir value seems to be ignored, contrary to examples in the
421 # Meson documentation.
422 install_headers('include/ft2build.h',
423   install_dir: freetype_includedir)
424 install_headers(ft2_public_headers,
425   install_dir: join_paths(freetype_includedir, 'freetype'))
426 install_headers(ft2_config_headers,
427   install_dir: join_paths(freetype_includedir, 'freetype/config'))
428
429
430 pkgconfig = import('pkgconfig')
431
432 pkgconfig.generate(ft2_lib,
433   filebase: 'freetype2',
434   name: 'FreeType 2',
435   description: 'A free, high-quality, and portable font engine.',
436   url: 'https://freetype.org',
437   subdirs: 'freetype2',
438   version: ft2_pkgconfig_version,
439 )
440
441 if get_option('tests').enabled()
442   subdir('tests')
443 endif
444
445 # NOTE: Unlike the old `make refdoc` command, this generates the
446 # documentation under `$BUILD/docs/` since Meson doesn't support modifying
447 # the source root directory (which is a good thing).
448 gen_docs = custom_target('freetype2 reference documentation',
449   output: 'docs',
450   input: ft2_public_headers + ft2_config_headers,
451   command: [python_exe,
452     files('builds/meson/generate_reference_docs.py'),
453     '--version=' + meson.project_version(),
454     '--input-dir=' + meson.current_source_dir(),
455     '--output-dir=@OUTPUT@'
456   ],
457 )
458
459
460 summary({'OS': host_machine.system(),
461         }, section: 'Operating System')
462
463 summary({'Zlib': zlib_option,
464          'Bzip2': bzip2_dep.found() ? 'yes' : 'no',
465          'Png': libpng_dep.found() ? 'yes' : 'no',
466          'Harfbuzz': harfbuzz_dep.found() ? 'yes' : 'no',
467          'Brotli': brotli_dep.found() ? 'yes' : 'no',
468         }, section: 'Used Libraries')
469
470 # EOF