meson.build 13 KB

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