2
0

meson.build 13 KB

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