meson.build 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. project(
  2. 'libxkbcommon',
  3. 'c',
  4. version: '1.14.0-beta1',
  5. default_options: [
  6. 'c_std=c11',
  7. 'build.c_std=c11',
  8. 'warning_level=3',
  9. ],
  10. meson_version: '>= 1.4.0', # Released on March 2024
  11. )
  12. xkbcommon_project_version_parts = meson.project_version().split('-')
  13. xkbcommon_project_version = xkbcommon_project_version_parts[0].split('.')
  14. if xkbcommon_project_version[0] != '1'
  15. # The versioning used for the shared libraries assumes that the major
  16. # version of xkbcommon as a whole will increase to 2 if and only if there
  17. # is an ABI break, at which point we should probably bump the SONAME of
  18. # all libraries to .so.2.
  19. error('We probably need to bump the SONAME of libxkbcommon')
  20. else
  21. # To avoid an unnecessary SONAME bump, xkbcommon 1.x.y produces
  22. # libxkbcommon.so.0.x.y, libxkbcommon-x11.so.0.x.y, libxkbregistry.so.0.x.y.
  23. soname_version = '.'.join(
  24. ['0', xkbcommon_project_version[1], xkbcommon_project_version[2]],
  25. )
  26. endif
  27. pkgconfig = import('pkgconfig')
  28. cc = meson.get_compiler('c')
  29. dir_libexec = get_option('prefix') / get_option('libexecdir') / 'xkbcommon'
  30. # Compiler flags.
  31. cflags = [
  32. '-fno-strict-aliasing',
  33. '-Wno-unused-parameter',
  34. '-Wno-missing-field-initializers',
  35. '-Wpointer-arith',
  36. '-Wmissing-declarations',
  37. '-Wformat=2',
  38. '-Wstrict-prototypes',
  39. '-Wmissing-prototypes',
  40. '-Wnested-externs',
  41. '-Wbad-function-cast',
  42. '-Wshadow',
  43. '-Wlogical-op',
  44. '-Wdate-time',
  45. '-Wwrite-strings',
  46. '-Wno-documentation-deprecated-sync',
  47. '-Wno-pedantic',
  48. '/utf-8',
  49. '/wd4100', # Disable MSVC C4100: unreferenced formal parameter
  50. '/wd4127', # Disable MSVC C4127: conditional expression is constant
  51. ]
  52. add_project_arguments(cc.get_supported_arguments(cflags), language: 'c')
  53. # The legacy X11 config root. Only xkeyboard-config 2.* provides it.
  54. # This is intended when using old xkeyboard-config and as a last resort for
  55. # misconfigured setups.
  56. # Try both un- and versioned pkg-config (xkeyboard-config < 2.45).
  57. XKB_LEGACY_ROOT = ''
  58. foreach v : ['-2', '']
  59. xkeyboard_config_dep = dependency(f'xkeyboard-config@v@', required: false)
  60. if xkeyboard_config_dep.found()
  61. XKB_LEGACY_ROOT = xkeyboard_config_dep.get_variable(
  62. pkgconfig: 'xkb_base',
  63. default_value: '',
  64. )
  65. break
  66. endif
  67. endforeach
  68. if XKB_LEGACY_ROOT == ''
  69. # Fallback to the legacy X11 directory
  70. XKB_LEGACY_ROOT = get_option('prefix') / get_option('datadir') / 'X11' / 'xkb'
  71. endif
  72. # The xkeyboard-config root
  73. # Try to set it from the xkeyboard-config package, from the most recent to the
  74. # oldest major version. The hard-coded major versions list should cover a few
  75. # decades, given the expected pace of xkeyboard-config format changes.
  76. XKEYBOARD_CONFIG_ROOT = ''
  77. XKEYBOARD_CONFIG_VERSION_MAJOR = ''
  78. XKEYBOARD_CONFIG_VERSIONED_EXTENSIONS_PATH = ''
  79. XKEYBOARD_CONFIG_UNVERSIONED_EXTENSIONS_PATH = ''
  80. foreach v : [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
  81. xkeyboard_config_dep = dependency(f'xkeyboard-config-@v@', required: false)
  82. if xkeyboard_config_dep.found()
  83. XKEYBOARD_CONFIG_ROOT = xkeyboard_config_dep.get_variable(
  84. pkgconfig: 'xkb_root',
  85. )
  86. XKEYBOARD_CONFIG_VERSION_MAJOR = xkeyboard_config_dep.version().split(
  87. '.',
  88. )[0]
  89. # The following variables may not be defined
  90. XKEYBOARD_CONFIG_VERSIONED_EXTENSIONS_PATH = xkeyboard_config_dep.get_variable(
  91. pkgconfig: 'xkb_versioned_extensions_path',
  92. default_value: '',
  93. )
  94. XKEYBOARD_CONFIG_UNVERSIONED_EXTENSIONS_PATH = xkeyboard_config_dep.get_variable(
  95. pkgconfig: 'xkb_unversioned_extensions_path',
  96. default_value: '',
  97. )
  98. break
  99. endif
  100. endforeach
  101. if XKEYBOARD_CONFIG_ROOT == ''
  102. # Try old unversioned pkg-config (xkeyboard-config < 2.45)
  103. xkeyboard_config_dep = dependency('xkeyboard-config', required: false)
  104. if xkeyboard_config_dep.found()
  105. XKEYBOARD_CONFIG_ROOT = xkeyboard_config_dep.get_variable(
  106. pkgconfig: 'xkb_base',
  107. )
  108. XKEYBOARD_CONFIG_VERSION_MAJOR = xkeyboard_config_dep.version().split(
  109. '.',
  110. )[0]
  111. # No extension path defined
  112. endif
  113. endif
  114. # The XKB config root for libxkbcommon
  115. XKB_CONFIG_ROOT = get_option('xkb-config-root')
  116. if XKB_CONFIG_ROOT == ''
  117. if XKEYBOARD_CONFIG_ROOT != ''
  118. XKB_CONFIG_ROOT = XKEYBOARD_CONFIG_ROOT
  119. else
  120. # No xkeyboard-config or too old: use legacy X11 path fallback
  121. XKB_CONFIG_ROOT = XKB_LEGACY_ROOT
  122. endif
  123. endif
  124. # The XKB extensions directories
  125. XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH = get_option(
  126. 'xkb-config-unversioned-extensions-path',
  127. )
  128. if XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH == '' and XKEYBOARD_CONFIG_ROOT != ''
  129. if XKEYBOARD_CONFIG_UNVERSIONED_EXTENSIONS_PATH != ''
  130. XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH = XKEYBOARD_CONFIG_UNVERSIONED_EXTENSIONS_PATH
  131. elif XKEYBOARD_CONFIG_ROOT.endswith(f'-@XKEYBOARD_CONFIG_VERSION_MAJOR@')
  132. # The xkeyboard-config root is versioned: remove the version suffix
  133. # Meson does not have a length() function… Compute the length manually
  134. s = XKEYBOARD_CONFIG_VERSION_MAJOR
  135. foreach len : range(3)
  136. if s == ''
  137. break
  138. endif
  139. s = s.substring(1)
  140. endforeach
  141. XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH = XKEYBOARD_CONFIG_ROOT.substring(
  142. 0,
  143. -len - 1,
  144. ) + '.d'
  145. else
  146. XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH = get_option('prefix') / get_option(
  147. 'datadir',
  148. ) / 'xkeyboard-config.d'
  149. endif
  150. endif
  151. XKB_CONFIG_VERSIONED_EXTENSIONS_PATH = get_option(
  152. 'xkb-config-versioned-extensions-path',
  153. )
  154. if XKB_CONFIG_VERSIONED_EXTENSIONS_PATH == '' and XKEYBOARD_CONFIG_ROOT != ''
  155. if XKEYBOARD_CONFIG_VERSIONED_EXTENSIONS_PATH != ''
  156. XKB_CONFIG_VERSIONED_EXTENSIONS_PATH = XKEYBOARD_CONFIG_VERSIONED_EXTENSIONS_PATH
  157. else
  158. XKB_CONFIG_VERSIONED_EXTENSIONS_PATH = f'@XKEYBOARD_CONFIG_ROOT@.d'
  159. endif
  160. endif
  161. XKB_CONFIG_EXTRA_PATH = get_option('xkb-config-extra-path')
  162. if XKB_CONFIG_EXTRA_PATH == ''
  163. XKB_CONFIG_EXTRA_PATH = get_option('prefix') / get_option('sysconfdir') / 'xkb'
  164. endif
  165. # The X locale directory for compose.
  166. XLOCALEDIR = get_option('x-locale-root')
  167. if XLOCALEDIR == ''
  168. XLOCALEDIR = get_option('prefix') / get_option('datadir') / 'X11' / 'locale'
  169. endif
  170. # config.h.
  171. configh_data = configuration_data()
  172. configh_data.set('EXIT_INVALID_USAGE', '2')
  173. configh_data.set_quoted('LIBXKBCOMMON_VERSION', meson.project_version())
  174. configh_data.set_quoted('LIBXKBCOMMON_TOOL_PATH', dir_libexec)
  175. # Like AC_USE_SYSTEM_EXTENSIONS, what #define to use to get extensions
  176. # beyond the base POSIX function set.
  177. if host_machine.system() == 'sunos'
  178. system_extensions = '__EXTENSIONS__'
  179. else
  180. system_extensions = '_GNU_SOURCE'
  181. endif
  182. configh_data.set(system_extensions, 1)
  183. system_ext_define = '#define ' + system_extensions
  184. configh_data.set_quoted('DFLT_XKB_LEGACY_ROOT', XKB_LEGACY_ROOT)
  185. configh_data.set_quoted('DFLT_XKB_CONFIG_ROOT', XKB_CONFIG_ROOT)
  186. if XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH != ''
  187. configh_data.set_quoted(
  188. 'DFLT_XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH',
  189. XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH,
  190. )
  191. endif
  192. if XKB_CONFIG_VERSIONED_EXTENSIONS_PATH != ''
  193. configh_data.set_quoted(
  194. 'DFLT_XKB_CONFIG_VERSIONED_EXTENSIONS_PATH',
  195. XKB_CONFIG_VERSIONED_EXTENSIONS_PATH,
  196. )
  197. endif
  198. configh_data.set_quoted('DFLT_XKB_CONFIG_EXTRA_PATH', XKB_CONFIG_EXTRA_PATH)
  199. configh_data.set_quoted('XLOCALEDIR', XLOCALEDIR)
  200. configh_data.set_quoted('DEFAULT_XKB_RULES', get_option('default-rules'))
  201. configh_data.set_quoted('DEFAULT_XKB_MODEL', get_option('default-model'))
  202. configh_data.set_quoted('DEFAULT_XKB_LAYOUT', get_option('default-layout'))
  203. if get_option('default-variant') != ''
  204. configh_data.set_quoted('DEFAULT_XKB_VARIANT', get_option('default-variant'))
  205. else
  206. configh_data.set('DEFAULT_XKB_VARIANT', 'NULL')
  207. endif
  208. if get_option('default-options') != ''
  209. configh_data.set_quoted('DEFAULT_XKB_OPTIONS', get_option('default-options'))
  210. else
  211. configh_data.set('DEFAULT_XKB_OPTIONS', 'NULL')
  212. endif
  213. have_unistd_h = cc.has_header('unistd.h')
  214. configh_data.set10('HAVE_UNISTD_H', have_unistd_h)
  215. have_dirent_h = cc.has_header('dirent.h')
  216. configh_data.set10('HAVE_DIRENT_H', have_dirent_h)
  217. has_extensions_directories = have_unistd_h and have_dirent_h
  218. configh_data.set10('HAVE_XKB_EXTENSIONS_DIRECTORIES', has_extensions_directories)
  219. if cc.links(
  220. 'int main(void){if(__builtin_expect(1<0,0)){}}',
  221. name: '__builtin_expect',
  222. )
  223. configh_data.set10('HAVE___BUILTIN_EXPECT', true)
  224. endif
  225. # Test if counted_by attribute is available, and supported on pointer fields
  226. # (not just flexible array fields).
  227. if cc.compiles(
  228. '''
  229. struct test {
  230. int count;
  231. int *items __attribute__((counted_by(count)));
  232. };
  233. int main(void) {
  234. struct test t = {0};
  235. return 0;
  236. }
  237. ''',
  238. args: cc.get_supported_arguments('-Werror=attributes'),
  239. name: 'counted_by attribute for pointers',
  240. )
  241. configh_data.set10('HAVE_ATTR_COUNTED_BY', true)
  242. endif
  243. if cc.has_header_symbol('unistd.h', 'eaccess', prefix: system_ext_define)
  244. configh_data.set10('HAVE_EACCESS', true)
  245. endif
  246. if cc.has_header_symbol('unistd.h', 'euidaccess', prefix: system_ext_define)
  247. configh_data.set10('HAVE_EUIDACCESS', true)
  248. endif
  249. if cc.has_header_symbol('sys/mman.h', 'mmap')
  250. configh_data.set10('HAVE_MMAP', true)
  251. endif
  252. if cc.has_header_symbol('stdlib.h', 'mkostemp', prefix: system_ext_define)
  253. configh_data.set10('HAVE_MKOSTEMP', true)
  254. endif
  255. if cc.has_header_symbol('fcntl.h', 'posix_fallocate', prefix: system_ext_define)
  256. configh_data.set10('HAVE_POSIX_FALLOCATE', true)
  257. endif
  258. if cc.has_header_symbol('string.h', 'strndup', prefix: system_ext_define)
  259. configh_data.set10('HAVE_STRNDUP', true)
  260. endif
  261. if cc.has_header_symbol('stdio.h', 'asprintf', prefix: system_ext_define)
  262. configh_data.set10('HAVE_ASPRINTF', true)
  263. elif cc.has_header_symbol('stdio.h', 'vasprintf', prefix: system_ext_define)
  264. configh_data.set10('HAVE_VASPRINTF', true)
  265. endif
  266. if cc.has_header_symbol('stdio.h', 'open_memstream', prefix: system_ext_define)
  267. configh_data.set10('HAVE_OPEN_MEMSTREAM', true)
  268. endif
  269. if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: system_ext_define)
  270. configh_data.set10('HAVE_SECURE_GETENV', true)
  271. elif cc.has_header_symbol(
  272. 'stdlib.h',
  273. '__secure_getenv',
  274. prefix: system_ext_define,
  275. )
  276. configh_data.set10('HAVE___SECURE_GETENV', true)
  277. else
  278. message('C library does not support secure_getenv, using getenv instead')
  279. endif
  280. if cc.has_header_symbol('stdlib.h', 'random', prefix: system_ext_define)
  281. configh_data.set10('HAVE_RANDOM', true)
  282. endif
  283. if cc.has_header_symbol('stdlib.h', 'realpath', prefix: system_ext_define)
  284. configh_data.set10('HAVE_REAL_PATH', true)
  285. endif
  286. if not cc.has_header_symbol('limits.h', 'PATH_MAX', prefix: system_ext_define)
  287. if host_machine.system() == 'windows'
  288. # see https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
  289. configh_data.set('PATH_MAX', 260)
  290. else
  291. configh_data.set('PATH_MAX', 4096)
  292. endif
  293. endif
  294. if cc.has_header_symbol(
  295. 'time.h',
  296. 'CLOCK_PROCESS_CPUTIME_ID',
  297. prefix: system_ext_define,
  298. )
  299. configh_data.set10('HAVE_CLOCK_PROCESS_CPUTIME_ID', true)
  300. endif
  301. if cc.has_header_symbol('time.h', 'CLOCK_MONOTONIC', prefix: system_ext_define)
  302. configh_data.set10('HAVE_CLOCK_MONOTONIC', true)
  303. endif
  304. if cc.has_header_symbol('termios.h', 'tcsetattr', prefix: system_ext_define)
  305. configh_data.set10('HAVE_TERMIOS', true)
  306. endif
  307. has_glibc = cc.has_function(
  308. 'gnu_get_libc_version',
  309. prefix: '#include <gnu/libc-version.h>',
  310. )
  311. has_compose_locale_fallback = false
  312. if cc.has_header_symbol('locale.h', 'newlocale', prefix: system_ext_define)
  313. # Use newlocale only if it fails on missing locales
  314. if meson.can_run_host_binaries()
  315. # Check newlocale implementation
  316. r = cc.run(
  317. '''
  318. #define _GNU_SOURCE
  319. #include <locale.h>
  320. int main(void){
  321. locale_t loc = newlocale(LC_ALL_MASK, "¡NONSENSE!", (locale_t) 0);
  322. return (loc != (locale_t) 0);
  323. }''',
  324. name: 'newlocale fails on invalid locales',
  325. )
  326. if r.compiled() and r.returncode() == 0
  327. has_compose_locale_fallback = true
  328. endif
  329. elif has_glibc
  330. # Cannot check implementation, so enable only for implementations
  331. # known to failed on missing locales.
  332. has_compose_locale_fallback = true
  333. endif
  334. if has_compose_locale_fallback
  335. configh_data.set10('HAVE_NEWLOCALE', true)
  336. endif
  337. endif
  338. # Silence some security & deprecation warnings on MSVC
  339. # for some unix/C functions we use.
  340. # https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=vs-2019
  341. configh_data.set10('_CRT_SECURE_NO_WARNINGS', true)
  342. configh_data.set10('_CRT_NONSTDC_NO_WARNINGS', true)
  343. configh_data.set10('_CRT_NONSTDC_NO_DEPRECATE', true)
  344. # Reduce unnecessary includes on MSVC.
  345. configh_data.set10('WIN32_LEAN_AND_MEAN', true)
  346. xkbcommon_map = meson.current_source_dir() / 'xkbcommon.map'
  347. # Supports -Wl,--version-script?
  348. meson_test_map = meson.current_source_dir() / 'test' / 'meson_test.map'
  349. have_version_script = cc.links(
  350. 'int main(void) { return 0; }',
  351. args: f'-Wl,--version-script=@meson_test_map@',
  352. name: '-Wl,--version-script',
  353. )
  354. map_to_def = find_program('scripts/map-to-def')
  355. # Parser utils
  356. enable_parser_auto_generation = get_option('enable-parser-auto-generation')
  357. bison = find_program(
  358. 'bison',
  359. 'win_bison',
  360. required: enable_parser_auto_generation,
  361. version: '>= 3.6',
  362. )
  363. yacc = bison
  364. subdir('src/xkbcomp')
  365. # libxkbcommon.
  366. libxkbcommon_sources = [
  367. 'src/compose/parser.c',
  368. 'src/compose/paths.c',
  369. 'src/compose/state.c',
  370. 'src/compose/table.c',
  371. 'src/xkbcomp/action.c',
  372. 'src/xkbcomp/ast-build.c',
  373. 'src/xkbcomp/compat.c',
  374. 'src/xkbcomp/expr.c',
  375. 'src/xkbcomp/include.c',
  376. 'src/xkbcomp/keycodes.c',
  377. 'src/xkbcomp/keymap.c',
  378. 'src/xkbcomp/keymap-dump.c',
  379. 'src/xkbcomp/keywords.c',
  380. # - If enable-parser-regeneration=false, then use the pre-generated parser files.
  381. # These files may be regenerated manually using the target: src/xkbcomp/update-parser.
  382. # - Otherwise regenerate the parser files automatically in the *build* directory.
  383. parser_files,
  384. 'src/xkbcomp/rules.c',
  385. 'src/xkbcomp/scanner.c',
  386. 'src/xkbcomp/symbols.c',
  387. 'src/xkbcomp/types.c',
  388. 'src/xkbcomp/vmod.c',
  389. 'src/xkbcomp/xkbcomp.c',
  390. 'src/abi-check.c',
  391. 'src/atom.c',
  392. 'src/context.c',
  393. 'src/context-priv.c',
  394. 'src/features.c',
  395. 'src/keysym.c',
  396. 'src/keysym-case-mappings.c',
  397. 'src/keysym-utf.c',
  398. 'src/keymap.c',
  399. 'src/keymap-compare.c',
  400. 'src/keymap-priv.c',
  401. 'src/rmlvo.c',
  402. 'src/scanner-utils.c',
  403. 'src/state.c',
  404. 'src/text.c',
  405. 'src/utf8.c',
  406. 'src/utf8-decoding.c',
  407. 'src/utils.c',
  408. 'src/utils-paths.c',
  409. ]
  410. libxkbcommon_link_args = []
  411. libxkbcommon_link_deps = []
  412. if have_version_script
  413. libxkbcommon_link_args += f'-Wl,--version-script=@xkbcommon_map@'
  414. libxkbcommon_link_deps += 'xkbcommon.map'
  415. elif cc.get_argument_syntax() == 'msvc'
  416. libxkbcommon_def = custom_target(
  417. 'xkbcommon.def',
  418. command: [map_to_def, '@INPUT@', soname_version, '@OUTPUT@'],
  419. input: 'xkbcommon.map',
  420. output: 'xkbcommon.def',
  421. )
  422. libxkbcommon_link_deps += libxkbcommon_def
  423. libxkbcommon_link_args += '/DEF:' + libxkbcommon_def.full_path()
  424. endif
  425. libxkbcommon = library(
  426. 'xkbcommon',
  427. libxkbcommon_sources,
  428. link_args: libxkbcommon_link_args,
  429. link_depends: libxkbcommon_link_deps,
  430. gnu_symbol_visibility: 'hidden',
  431. version: soname_version,
  432. install: true,
  433. include_directories: include_directories('src', 'include'),
  434. )
  435. # Some tests need to use unexported symbols, so we link them against
  436. # an internal copy of libxkbcommon with all symbols exposed.
  437. libxkbcommon_test_internal = library(
  438. 'xkbcommon-test-internal',
  439. libxkbcommon_sources,
  440. 'src/xkbcomp/keymap-file-iterator.c',
  441. c_args: ['-DENABLE_PRIVATE_APIS'],
  442. gnu_symbol_visibility: 'hidden',
  443. install: false,
  444. include_directories: include_directories('src', 'include'),
  445. )
  446. install_headers(
  447. 'include/xkbcommon/xkbcommon.h',
  448. 'include/xkbcommon/xkbcommon-compat.h',
  449. 'include/xkbcommon/xkbcommon-compose.h',
  450. 'include/xkbcommon/xkbcommon-errors.h',
  451. 'include/xkbcommon/xkbcommon-features.h',
  452. 'include/xkbcommon/xkbcommon-keysyms.h',
  453. 'include/xkbcommon/xkbcommon-names.h',
  454. subdir: 'xkbcommon',
  455. )
  456. dep_libxkbcommon = declare_dependency(
  457. link_with: libxkbcommon,
  458. include_directories: include_directories('include'),
  459. )
  460. meson.override_dependency('xkbcommon', dep_libxkbcommon)
  461. pkgconfig_variables = [
  462. f'xkb_root=@XKB_CONFIG_ROOT@',
  463. f'xkb_extra_path=@XKB_CONFIG_EXTRA_PATH@',
  464. ]
  465. if has_extensions_directories
  466. pkgconfig_variables += [
  467. f'xkb_unversioned_extensions_path=@XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH@',
  468. f'xkb_versioned_extensions_path=@XKB_CONFIG_VERSIONED_EXTENSIONS_PATH@',
  469. ]
  470. endif
  471. pkgconfig.generate(
  472. libxkbcommon,
  473. name: 'xkbcommon',
  474. filebase: 'xkbcommon',
  475. version: meson.project_version(),
  476. description: 'XKB API common to servers and clients',
  477. variables: pkgconfig_variables,
  478. )
  479. # libxkbcommon-x11.
  480. if get_option('enable-x11')
  481. xcb_dep = dependency('xcb', version: '>=1.10', required: false)
  482. xcb_xkb_dep = dependency('xcb-xkb', version: '>=1.10', required: false)
  483. if not xcb_dep.found() or not xcb_xkb_dep.found()
  484. error(
  485. '''X11 support requires xcb-xkb >= 1.10 which was not found.
  486. You can disable X11 support with -Denable-x11=false.''',
  487. )
  488. endif
  489. libxkbcommon_x11_sources = files(
  490. 'src/atom.c',
  491. 'src/context-priv.c',
  492. 'src/context.c',
  493. 'src/keymap-priv.c',
  494. 'src/utils.c',
  495. 'src/x11/keymap.c',
  496. 'src/x11/state.c',
  497. 'src/x11/util.c',
  498. )
  499. libxkbcommon_x11_link_args = []
  500. libxkbcommon_x11_link_deps = []
  501. if have_version_script
  502. libxkbcommon_x11_link_args += '-Wl,--version-script=' + meson.current_source_dir() / 'xkbcommon-x11.map'
  503. libxkbcommon_x11_link_deps += 'xkbcommon-x11.map'
  504. elif cc.get_argument_syntax() == 'msvc'
  505. libxkbcommon_x11_def = custom_target(
  506. 'xkbcommon-x11.def',
  507. command: [map_to_def, '@INPUT@', soname_version, '@OUTPUT@'],
  508. input: 'xkbcommon-x11.map',
  509. output: 'xkbcommon-x11.def',
  510. )
  511. libxkbcommon_x11_link_deps += libxkbcommon_x11_def
  512. libxkbcommon_x11_link_args += '/DEF:' + libxkbcommon_x11_def.full_path()
  513. endif
  514. libxkbcommon_x11 = library(
  515. 'xkbcommon-x11',
  516. libxkbcommon_x11_sources,
  517. link_args: libxkbcommon_x11_link_args,
  518. link_depends: libxkbcommon_x11_link_deps,
  519. gnu_symbol_visibility: 'hidden',
  520. version: soname_version,
  521. install: true,
  522. include_directories: include_directories('src', 'include'),
  523. link_with: libxkbcommon,
  524. dependencies: [
  525. xcb_dep,
  526. xcb_xkb_dep,
  527. ],
  528. )
  529. # Some tests need to use unexported symbols, so we link them against
  530. # an internal copy of libxkbcommon-x11 with all symbols exposed.
  531. libxkbcommon_x11_test_internal = library(
  532. 'xkbcommon-x11-internal',
  533. libxkbcommon_x11_sources,
  534. c_args: ['-DENABLE_PRIVATE_APIS'],
  535. gnu_symbol_visibility: 'hidden',
  536. install: false,
  537. include_directories: include_directories('src', 'include'),
  538. link_with: libxkbcommon_test_internal,
  539. dependencies: [
  540. xcb_dep,
  541. xcb_xkb_dep,
  542. ],
  543. )
  544. install_headers(
  545. 'include/xkbcommon/xkbcommon-x11.h',
  546. subdir: 'xkbcommon',
  547. )
  548. dep_libxkbcommon_x11 = declare_dependency(
  549. link_with: libxkbcommon_x11,
  550. include_directories: include_directories('include'),
  551. )
  552. meson.override_dependency('xkbcommon-x11', dep_libxkbcommon_x11)
  553. pkgconfig.generate(
  554. libxkbcommon_x11,
  555. name: 'xkbcommon-x11',
  556. filebase: 'xkbcommon-x11',
  557. version: meson.project_version(),
  558. description: 'XKB API common to servers and clients - X11 support',
  559. requires: ['xkbcommon'],
  560. requires_private: ['xcb>=1.10', 'xcb-xkb>=1.10'],
  561. )
  562. endif
  563. # libxkbregistry
  564. if get_option('enable-xkbregistry')
  565. dep_libxml = dependency('libxml-2.0')
  566. # Since libxml-2.13
  567. if cc.has_header_symbol(
  568. 'libxml/parser.h',
  569. 'xmlCtxtSetErrorHandler',
  570. prefix: system_ext_define,
  571. dependencies: dep_libxml,
  572. )
  573. configh_data.set10('HAVE_XML_CTXT_SET_ERRORHANDLER', true)
  574. endif
  575. # Since libxml-2.14
  576. if cc.has_header_symbol(
  577. 'libxml/parser.h',
  578. 'xmlCtxtParseDtd',
  579. prefix: system_ext_define,
  580. dependencies: dep_libxml,
  581. )
  582. configh_data.set10('HAVE_XML_CTXT_PARSE_DTD', true)
  583. endif
  584. deps_libxkbregistry = [dep_libxml]
  585. libxkbregistry_sources = [
  586. 'src/registry.c',
  587. 'src/utils.c',
  588. 'src/util-list.c',
  589. ]
  590. libxkbregistry_link_args = []
  591. libxkbregistry_link_deps = []
  592. if have_version_script
  593. libxkbregistry_link_args += '-Wl,--version-script=' + meson.current_source_dir() / 'xkbregistry.map'
  594. libxkbregistry_link_deps += 'xkbregistry.map'
  595. elif cc.get_argument_syntax() == 'msvc'
  596. libxkbregistry_def = custom_target(
  597. 'xkbregistry.def',
  598. command: [map_to_def, '@INPUT@', soname_version, '@OUTPUT@'],
  599. input: 'xkbregistry.map',
  600. output: 'xkbregistry.def',
  601. )
  602. libxkbregistry_link_deps += libxkbregistry_def
  603. libxkbregistry_link_args += '/DEF:' + libxkbregistry_def.full_path()
  604. endif
  605. libxkbregistry = library(
  606. 'xkbregistry',
  607. libxkbregistry_sources,
  608. link_args: libxkbregistry_link_args,
  609. link_depends: libxkbregistry_link_deps,
  610. gnu_symbol_visibility: 'hidden',
  611. dependencies: deps_libxkbregistry,
  612. version: soname_version,
  613. install: true,
  614. include_directories: include_directories('src', 'include'),
  615. )
  616. install_headers(
  617. 'include/xkbcommon/xkbregistry.h',
  618. subdir: 'xkbcommon',
  619. )
  620. pkgconfig.generate(
  621. libxkbregistry,
  622. name: 'xkbregistry',
  623. filebase: 'xkbregistry',
  624. version: meson.project_version(),
  625. description: 'XKB API to query available rules, models, layouts, variants and options',
  626. )
  627. dep_libxkbregistry = declare_dependency(
  628. link_with: libxkbregistry,
  629. include_directories: include_directories('include'),
  630. )
  631. meson.override_dependency('xkbregistry', dep_libxkbregistry)
  632. endif
  633. # Tools
  634. icu_dep = dependency('icu-uc', required: false)
  635. tools_shared_lib = static_library(
  636. 'tools-shared',
  637. sources: [
  638. 'tools/tools-common.c',
  639. 'src/keymap-formats.c',
  640. 'src/utf8-decoding.c',
  641. ],
  642. include_directories: include_directories('include', 'src', 'tools'),
  643. )
  644. build_tools = get_option('enable-tools') and cc.has_header_symbol(
  645. 'getopt.h',
  646. 'getopt_long',
  647. prefix: '#define _GNU_SOURCE',
  648. )
  649. if build_tools
  650. subdir('tools')
  651. else
  652. tools_dep = declare_dependency()
  653. endif
  654. # Tests
  655. subdir('test')
  656. # Fuzzing target programs.
  657. subdir('fuzz')
  658. # Benchmarks.
  659. subdir('bench')
  660. # Documentation.
  661. if get_option('enable-docs')
  662. subdir('doc')
  663. endif
  664. configure_file(output: 'config.h', configuration: configh_data)
  665. # Stable variables for projects using xkbcommon as a subproject.
  666. # These variables should not be renamed.
  667. libxkbcommon_dep = dep_libxkbcommon
  668. if get_option('enable-x11')
  669. libxkbcommon_x11_dep = dep_libxkbcommon_x11
  670. endif
  671. if get_option('enable-xkbregistry')
  672. libxkbregistry_dep = dep_libxkbregistry
  673. endif
  674. summary(
  675. {
  676. 'backend': meson.backend(),
  677. 'buildtype': get_option('buildtype'),
  678. 'id': cc.get_id(),
  679. 'c_args': get_option('c_args'),
  680. 'c_link_args': get_option('c_link_args'),
  681. 'yacc': yacc.found() ? yacc.full_path() + ' ' + yacc.version() : '(not found)',
  682. 'glibc': has_glibc,
  683. },
  684. section: 'Compiler',
  685. )
  686. summary(
  687. {
  688. 'prefix': get_option('prefix'),
  689. 'bindir': get_option('bindir'),
  690. 'libdir': get_option('libdir'),
  691. 'datadir': get_option('datadir'),
  692. 'xkb-config-root': XKB_CONFIG_ROOT,
  693. 'xkb-legacy-root': XKB_LEGACY_ROOT,
  694. 'xkb-config-unversioned-extensions-path': XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH,
  695. 'xkb-config-versioned-extensions-path': XKB_CONFIG_VERSIONED_EXTENSIONS_PATH,
  696. 'xkb-config-extra-path': XKB_CONFIG_EXTRA_PATH,
  697. 'xlocaledir': XLOCALEDIR,
  698. },
  699. section: 'Directories',
  700. )
  701. summary(
  702. {
  703. 'docs': get_option('enable-docs'),
  704. 'tools': get_option('enable-tools'),
  705. 'wayland': get_option('enable-wayland'),
  706. 'x11': get_option('enable-x11'),
  707. 'compose locale fallback': has_compose_locale_fallback,
  708. 'XKB extensions directories': has_extensions_directories,
  709. },
  710. section: 'Features',
  711. )
  712. summary(
  713. {
  714. 'layout': get_option('default-layout'),
  715. 'model': get_option('default-model'),
  716. 'options': get_option('default-options'),
  717. 'rules': get_option('default-rules'),
  718. 'variant': get_option('default-variant'),
  719. },
  720. section: 'Defaults',
  721. )
  722. summary(
  723. {
  724. 'merge-modes': has_merge_modes_tests,
  725. },
  726. section: 'Tests',
  727. )