meson.build 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. project('sdl2', 'c',
  2. version : '2.0.20',
  3. license : 'zlib',
  4. meson_version : '>=0.48.0',
  5. default_options : ['c_std=none'],
  6. )
  7. # Based on https://github.com/mesonbuild/sdl2/blob/2.0.3/meson.build
  8. varr = meson.project_version().split('.')
  9. version_major = varr[0]
  10. version_minor = varr[1]
  11. version_micro = varr[2]
  12. cc = meson.get_compiler('c')
  13. c_args = cc.get_supported_arguments(
  14. '-Wall',
  15. '-Wdeclaration-after-statement',
  16. '-Wshadow',
  17. '-fno-strict-aliasing',
  18. '-mpreferred-stack-boundary=2',
  19. )
  20. add_project_arguments(c_args, language : 'c')
  21. # BEGIN platform detection logic
  22. # FIXME: detect this properly
  23. platform_is_linux_desktop = (host_machine.system() == 'linux')
  24. platform_is_android = (host_machine.system() == 'android')
  25. platform_is_linux = platform_is_android or platform_is_linux_desktop
  26. platform_is_darwin = (host_machine.system() == 'darwin')
  27. # FIXME: detect this properly
  28. platform_is_macos = platform_is_darwin
  29. platform_is_ios = false
  30. platform_is_windows = (host_machine.system() == 'windows')
  31. # FIXME: detect this properly
  32. platform_is_win32 = platform_is_windows
  33. platform_is_winrt = false
  34. platform_is_vita = (host_machine.system() == 'vita')
  35. platform_is_os2 = (host_machine.system() == 'os2')
  36. platform_is_dragonflybsd = (host_machine.system() == 'dragonfly')
  37. platform_is_freebsd = (host_machine.system() == 'freebsd')
  38. platform_is_netbsd = (host_machine.system() == 'netbsd')
  39. platform_is_openbsd = (host_machine.system() == 'openbsd')
  40. platform_is_bsd = (
  41. platform_is_dragonflybsd or
  42. platform_is_freebsd or
  43. platform_is_netbsd or
  44. platform_is_openbsd or
  45. false)
  46. platform_is_haiku = (host_machine.system() == 'haiku')
  47. platform_is_emscripten = (host_machine.system() == 'emscripten')
  48. platform_is_psp = (host_machine.system() == 'psp')
  49. # FIXME: verify this
  50. platform_is_nacl = (host_machine.system() == 'nacl')
  51. platform_is_unixlike = (
  52. platform_is_bsd or
  53. platform_is_darwin or
  54. platform_is_emscripten or
  55. platform_is_haiku or # FIXME: verify this
  56. platform_is_linux or
  57. false)
  58. # END platform detection logic
  59. opt_atomic = get_option('use_atomic')
  60. opt_audio = get_option('use_audio')
  61. opt_cpuinfo = get_option('use_cpuinfo')
  62. opt_events = get_option('use_events')
  63. opt_file = get_option('use_file')
  64. opt_filesystem = get_option('use_filesystem')
  65. opt_haptic = get_option('use_haptic')
  66. opt_hidapi = get_option('use_hidapi')
  67. opt_joystick = get_option('use_joystick')
  68. opt_loadso = get_option('use_loadso')
  69. opt_locale= get_option('use_locale')
  70. opt_power = get_option('use_power')
  71. opt_render = get_option('use_render')
  72. opt_sensor = get_option('use_sensor')
  73. opt_threads = get_option('use_threads')
  74. opt_timers = get_option('use_timers')
  75. opt_video = get_option('use_video')
  76. opt_video_x11 = get_option('use_video_x11')
  77. opt_video_wayland = get_option('use_video_wayland')
  78. opt_video_wayland_libdecor = get_option('use_video_wayland_libdecor')
  79. opt_video_opengl = get_option('use_video_opengl')
  80. opt_video_openglesv2 = get_option('use_video_openglesv2')
  81. opt_video_vulkan = get_option('use_video_vulkan')
  82. opt_video_offscreen = get_option('use_video_offscreen')
  83. if opt_video.disabled()
  84. opt_video_x11 = opt_video
  85. opt_video_wayland = opt_video
  86. opt_video_opengl = opt_video
  87. opt_video_openglesv2 = opt_video
  88. opt_video_vulkan = opt_video
  89. opt_video_offscreen = opt_video
  90. opt_render = opt_video
  91. endif
  92. if opt_video_wayland.disabled()
  93. opt_video_wayland_libdecor = opt_video_wayland
  94. endif
  95. opt_audio_alsa = get_option('use_audio_alsa')
  96. opt_audio_pulseaudio = get_option('use_audio_pulseaudio')
  97. opt_audio_jack = get_option('use_audio_jack')
  98. opt_audio_pipewire = get_option('use_audio_pipewire')
  99. if opt_audio.disabled()
  100. opt_audio_alsa = opt_audio
  101. opt_audio_pulseaudio = opt_audio
  102. opt_audio_jack = opt_audio
  103. opt_audio_pipewire = opt_audio
  104. endif
  105. if platform_is_android
  106. opt_haptic = opt_joystick
  107. endif
  108. fake_dep = dependency('non-existent fake dependency', required : false)
  109. assert(not fake_dep.found())
  110. # BEGIN awful shitfucked GL hacks
  111. khronos_dep = declare_dependency(
  112. include_directories : include_directories(join_paths('src', 'video', 'khronos'))
  113. )
  114. gl_req_hack = opt_video_opengl.enabled() ? false : opt_video_opengl
  115. gles2_req_hack = opt_video_openglesv2.enabled() ? false : opt_video_openglesv2
  116. gl_dep = dependency('gl', required : opt_video_opengl)
  117. glesv2_dep = dependency('glesv2', required : gles2_req_hack)
  118. if not glesv2_dep.found() and not opt_video_openglesv2.disabled()
  119. # we have the headers, we'll load the lib dynamically (which might be something like ANGLE)
  120. glesv2_dep = khronos_dep
  121. message('Using embedded GLESv2 headers')
  122. endif
  123. egl_dep = dependency('egl', required : opt_video_openglesv2)
  124. if not egl_dep.found()
  125. egl_dep = dependency('egl', required : opt_video_wayland)
  126. endif
  127. if not egl_dep.found() and not opt_video_openglesv2.disabled()
  128. # we have the headers, we'll load the lib dynamically (which might be something like ANGLE)
  129. egl_dep = khronos_dep
  130. message('Using embedded EGL headers')
  131. endif
  132. # we don't want to link against these!
  133. gl_dep = gl_dep.partial_dependency(compile_args : true, includes : true, sources : true)
  134. glesv2_dep = glesv2_dep.partial_dependency(compile_args : true, includes : true, sources : true)
  135. egl_dep = egl_dep.partial_dependency(compile_args : true, includes : true, sources : true)
  136. gl_deps = [
  137. egl_dep,
  138. gl_dep,
  139. glesv2_dep,
  140. ]
  141. # END awful shitfucked GL hacks
  142. cdata = configuration_data()
  143. alsa_dep = dependency('alsa', required : opt_audio_alsa)
  144. libpulse_simple_dep = dependency('libpulse-simple', required : opt_audio_pulseaudio)
  145. jack_dep = dependency('jack', required : opt_audio_jack)
  146. libpipewire_dep = dependency('libpipewire-0.3', required : opt_audio_jack)
  147. vulkan_dep = dependency('vulkan', required : opt_video_vulkan)
  148. x11_dep = dependency('x11', required : opt_video_x11)
  149. xext_dep = dependency('xext', required : opt_video_x11)
  150. xi_dep = dependency('xi', required : opt_video_x11)
  151. xinerama_dep = dependency('xinerama', required : opt_video_x11)
  152. xkbcommon_dep = dependency('xkbcommon', required : opt_video_wayland)
  153. xrandr_dep = dependency('xrandr', required : opt_video_x11)
  154. xfixes_dep = dependency('xfixes', required : opt_video_x11)
  155. xcursor_dep = dependency('xcursor', required : opt_video_x11)
  156. threads_dep = dependency('threads', required : opt_threads)
  157. libusb_dep = dependency('libusb-1.0', required : opt_hidapi)
  158. # FIXME: I think DBus may be usable on other platforms (*BSD?), but SDL puts the code interfacing
  159. # with it in src/core/linux for some reason.
  160. if platform_is_linux_desktop
  161. dbus_dep = dependency('dbus-1', required : false).partial_dependency(
  162. compile_args : true, includes : true, sources : true
  163. )
  164. else
  165. dbus_dep = fake_dep
  166. endif
  167. if dbus_dep.found()
  168. ibus_dep = dependency('ibus-1.0', required : false).partial_dependency(
  169. compile_args : true, includes : true, sources : true
  170. )
  171. else
  172. ibus_dep = fake_dep
  173. endif
  174. wayland_found = true
  175. wayland_client_dep = dependency('wayland-client', required : opt_video_wayland)
  176. wayland_cursor_dep = dependency('wayland-cursor', required : opt_video_wayland)
  177. wayland_egl_dep = dependency('wayland-egl', required : opt_video_wayland)
  178. wayland_protocols_dep = dependency('wayland-protocols', required : opt_video_wayland)
  179. wayland_scanner_dep = dependency('wayland-scanner', required : opt_video_wayland)
  180. wayland_libdecor_dep = dependency('libdecor-0', required : opt_video_wayland_libdecor)
  181. if wayland_scanner_dep.found()
  182. wayland_scanner = find_program(
  183. wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'),
  184. required : opt_video_wayland
  185. )
  186. if not wayland_scanner.found()
  187. wayland_scanner = find_program('wayland-scanner', required : opt_video_wayland)
  188. endif
  189. else
  190. wayland_scanner = find_program('wayland-scanner', required : opt_video_wayland)
  191. endif
  192. dlopen_table = [
  193. { 'dep_var' : 'alsa_dep', 'lib' : 'asound', 'conf_var' : 'SDL_AUDIO_DRIVER_ALSA_DYNAMIC' },
  194. { 'dep_var' : 'jack_dep', 'lib' : 'jack', 'conf_var' : 'SDL_AUDIO_DRIVER_JACK_DYNAMIC' },
  195. { 'dep_var' : 'libpipewire_dep', 'lib' : 'pipewire-0.3', 'conf_var' : 'SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC' },
  196. { 'dep_var' : 'libpulse_simple_dep', 'lib' : 'pulse-simple', 'conf_var' : 'SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC' },
  197. { 'dep_var' : 'libusb_dep', 'lib' : 'usb-1.0', 'conf_var' : 'SDL_LIBUSB_DYNAMIC ' },
  198. { 'dep_var' : 'wayland_client_dep', 'lib' : 'wayland-client', 'conf_var' : 'SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC' },
  199. { 'dep_var' : 'wayland_cursor_dep', 'lib' : 'wayland-cursor', 'conf_var' : 'SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR' },
  200. { 'dep_var' : 'wayland_egl_dep', 'lib' : 'wayland-egl', 'conf_var' : 'SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL' },
  201. { 'dep_var' : 'wayland_libdecor_dep', 'lib' : 'decor-0', 'conf_var' : 'SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR' },
  202. { 'dep_var' : 'x11_dep', 'lib' : 'X11', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC' },
  203. { 'dep_var' : 'xcursor_dep', 'lib' : 'Xcursor', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR' },
  204. { 'dep_var' : 'xext_dep', 'lib' : 'Xext', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT' },
  205. { 'dep_var' : 'xfixes_dep', 'lib' : 'Xfixes', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES' },
  206. { 'dep_var' : 'xi_dep', 'lib' : 'Xi', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2' },
  207. { 'dep_var' : 'xinerama_dep', 'lib' : 'Xinerama', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA' },
  208. { 'dep_var' : 'xkbcommon_dep', 'lib' : 'xkbcommon', 'conf_var' : 'SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON' },
  209. { 'dep_var' : 'xrandr_dep', 'lib' : 'Xrandr', 'conf_var' : 'SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR' },
  210. ]
  211. if get_option('prefer_dlopen')
  212. find_dylib_name = find_program('./find-dylib-name.py', required : true)
  213. foreach dep_entry : dlopen_table
  214. dep = get_variable(dep_entry['dep_var'])
  215. if dep.found()
  216. r = run_command(find_dylib_name, dep_entry['lib'], cc.cmd_array())
  217. if r.returncode() == 0
  218. lib = r.stdout().strip()
  219. cdata.set_quoted(dep_entry['conf_var'], lib)
  220. set_variable(dep_entry['dep_var'], dep.partial_dependency(
  221. compile_args : true, includes : true, sources : true
  222. ))
  223. message('Configured @0@ for dynamic loading'.format(lib))
  224. endif
  225. endif
  226. endforeach
  227. endif
  228. cdata.set('DYNAPI_NEEDS_DLOPEN', platform_is_unixlike)
  229. x11_deps = [
  230. x11_dep,
  231. xcursor_dep,
  232. xext_dep,
  233. xi_dep,
  234. xinerama_dep,
  235. xrandr_dep,
  236. xfixes_dep,
  237. ]
  238. if wayland_scanner.found()
  239. wayland_deps = [
  240. wayland_client_dep,
  241. wayland_cursor_dep,
  242. wayland_egl_dep,
  243. wayland_protocols_dep,
  244. egl_dep,
  245. xkbcommon_dep,
  246. ]
  247. foreach wdep : wayland_deps
  248. if not wdep.found()
  249. wayland_found = false
  250. endif
  251. endforeach
  252. if not wayland_found
  253. wayland_deps = []
  254. endif
  255. else
  256. wayland_deps = []
  257. wayland_found = false
  258. endif
  259. if wayland_found and wayland_libdecor_dep.found()
  260. wayland_deps += wayland_libdecor_dep
  261. cdata.set('HAVE_LIBDECOR_H', 1)
  262. endif
  263. if dbus_dep.found()
  264. cdata.set('HAVE_FCITX', 1)
  265. cdata.set('HAVE_DBUS_DBUS_H', 1)
  266. endif
  267. if ibus_dep.found()
  268. cdata.set('HAVE_IBUS_IBUS_H', 1)
  269. endif
  270. core_deps = [
  271. cc.find_library('m', required : false),
  272. cc.find_library('dl', required : false),
  273. cc.find_library('iconv', required : false),
  274. dbus_dep,
  275. ibus_dep,
  276. ]
  277. extra_deps = []
  278. if meson.get_cross_property('threads_dep_is_broken', false)
  279. if opt_threads.disabled()
  280. threads_dep = fake_dep
  281. else
  282. threads_dep = declare_dependency()
  283. endif
  284. endif
  285. core_subsystems = {
  286. 'atomic' : { 'opt' : opt_atomic, 'deps' : [], 'opt_deps' : [] },
  287. 'audio' : { 'opt' : opt_audio, 'deps' : [], 'opt_deps' : [alsa_dep, libpulse_simple_dep, jack_dep, libpipewire_dep] },
  288. 'cpuinfo' : { 'opt' : opt_cpuinfo, 'deps' : [], 'opt_deps' : [] },
  289. 'events' : { 'opt' : opt_events, 'deps' : [], 'opt_deps' : x11_deps + wayland_deps },
  290. 'file' : { 'opt' : opt_file, 'deps' : [], 'opt_deps' : [] },
  291. 'filesystem' : { 'opt' : opt_filesystem, 'deps' : [], 'opt_deps' : [] },
  292. 'haptic' : { 'opt' : opt_haptic, 'deps' : [], 'opt_deps' : [] },
  293. 'hidapi' : { 'opt' : opt_hidapi, 'deps' : [], 'opt_deps' : [libusb_dep] },
  294. 'joystick' : { 'opt' : opt_joystick, 'deps' : [], 'opt_deps' : [] },
  295. 'loadso' : { 'opt' : opt_loadso, 'deps' : [], 'opt_deps' : [] },
  296. 'locale' : { 'opt' : opt_locale, 'deps' : [], 'opt_deps' : [] },
  297. 'power' : { 'opt' : opt_power, 'deps' : [], 'opt_deps' : [] },
  298. 'render' : { 'opt' : opt_render, 'deps' : [], 'opt_deps' : [vulkan_dep] + x11_deps + wayland_deps + gl_deps },
  299. 'sensor' : { 'opt' : opt_sensor, 'deps' : [], 'opt_deps' : [] },
  300. 'threads' : { 'opt' : opt_threads, 'deps' : [threads_dep], 'opt_deps' : [] },
  301. 'timers' : { 'opt' : opt_timers, 'deps' : [], 'opt_deps' : [] },
  302. 'video' : { 'opt' : opt_video, 'deps' : [], 'opt_deps' : [vulkan_dep] + x11_deps + wayland_deps + gl_deps },
  303. }
  304. enabled_subsystems = []
  305. foreach ss_name, subsystem : core_subsystems
  306. ss_enabled = true
  307. if not subsystem['opt'].disabled()
  308. foreach dep : subsystem['deps']
  309. if not dep.found()
  310. warning('Subsystem "@0@" disabled due to missing dependency "@1@"'.format(ss_name, dep.name()))
  311. if subsystem['opt'].enabled()
  312. error('Subsystem @0@ couldn\'t be enabled'.format(ss_name))
  313. endif
  314. ss_enabled = false
  315. endif
  316. endforeach
  317. else
  318. ss_enabled = false
  319. endif
  320. if ss_enabled
  321. foreach dep : subsystem['deps']
  322. if dep.found() and not extra_deps.contains(dep)
  323. core_deps += dep
  324. endif
  325. endforeach
  326. foreach dep : subsystem['opt_deps']
  327. if dep.found() and not extra_deps.contains(dep)
  328. extra_deps += dep
  329. endif
  330. endforeach
  331. message('Subsystem "@0@" is ENABLED'.format(ss_name))
  332. enabled_subsystems += ss_name
  333. else
  334. cdata.set('SDL_@0@_DISABLED'.format(ss_name.to_upper()), 1)
  335. message('Subsystem "@0@" is DISABLED'.format(ss_name))
  336. endif
  337. endforeach
  338. # sigh...
  339. # https://github.com/mesonbuild/meson/issues/1889
  340. # Let's try to cure the superproject std
  341. unfuck_std = '''
  342. #define _DEFAULT_SOURCE
  343. #define _GNU_SOURCE
  344. #define _ISOC11_SOURCE
  345. #define _ISOC99_SOURCE
  346. #define _POSIX_C_SOURCE 200809L
  347. #define _XOPEN_SOURCE 700
  348. #undef __STRICT_ANSI__
  349. '''
  350. cdata.set('SIZEOF_VOIDP', cc.sizeof('void*'))
  351. check_headers = [
  352. 'alloca.h',
  353. 'altivec.h',
  354. 'audioclient.h',
  355. 'ctype.h',
  356. # 'dbus/dbus.h', # NOTE: handled by dependency()
  357. 'ddraw.h',
  358. 'dinput.h',
  359. 'dsound.h',
  360. 'dxgi.h',
  361. 'endpointvolume.h',
  362. 'fcitx/frontend.h',
  363. 'float.h',
  364. 'iconv.h',
  365. 'immintrin.h',
  366. 'inttypes.h',
  367. 'libsamplerate.h',
  368. 'libudev.h',
  369. 'libunwind.h',
  370. 'limits.h',
  371. 'malloc.h',
  372. 'math.h',
  373. 'memory.h',
  374. 'mmdeviceapi.h',
  375. 'pthread.h',
  376. 'pthread_np.h',
  377. 'semaphore.h',
  378. 'sensorsapi.h',
  379. 'signal.h',
  380. 'stdarg.h',
  381. 'stdint.h',
  382. 'stdio.h',
  383. 'stdlib.h',
  384. 'string.h',
  385. 'strings.h',
  386. 'sys/inotify.h',
  387. 'sys/types.h',
  388. 'wchar.h',
  389. 'windows.gaming.input.h',
  390. 'xinput.h',
  391. ]
  392. foreach h : check_headers
  393. if cc.check_header(h, dependencies : core_deps)
  394. cdata.set('HAVE_@0@'.format(h.to_upper().underscorify()), 1)
  395. endif
  396. endforeach
  397. if platform_is_emscripten
  398. # TODO: properly support building with emscripten's SSE emulation
  399. cdata.set('SDL_DISABLE_IMMINTRIN_H', 1)
  400. endif
  401. check_symbols = [
  402. ['O_CLOEXEC', 'fcntl.h'],
  403. ['M_PI', 'math.h'],
  404. ]
  405. foreach entry : check_symbols
  406. symbol = entry[0]
  407. header = entry[1]
  408. if cc.has_header_symbol(header, symbol, prefix : unfuck_std, dependencies : core_deps)
  409. cdata.set('HAVE_@0@'.format(symbol.underscorify().to_upper()), 1)
  410. endif
  411. endforeach
  412. if cc.has_header_symbol('pthread.h', 'PTHREAD_MUTEX_RECURSIVE', prefix : unfuck_std)
  413. cdata.set('SDL_THREAD_PTHREAD_RECURSIVE_MUTEX', 1)
  414. endif
  415. if cc.has_header_symbol('pthread.h', 'PTHREAD_MUTEX_RECURSIVE_NP', prefix : unfuck_std)
  416. cdata.set('SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP', 1)
  417. endif
  418. check_functions = [
  419. ['_Exit', 'stdlib.h'],
  420. ['_i64toa', 'stdlib.h'],
  421. ['_ltoa', 'stlib.h'],
  422. ['_stricmp', 'string.h'],
  423. ['_strlwr', 'string.h'],
  424. ['_strnicmp', 'string.h'],
  425. ['_strrev', 'string.h'],
  426. ['_strupr', 'string.h'],
  427. ['_uit64toa', 'stdlib.h'],
  428. ['_uitoa', 'stdlib.h'],
  429. ['_ultoa', 'stdlib.h'],
  430. ['_wcsdup', 'wchar.h'],
  431. ['_wcsicmp', 'wchar.h'],
  432. ['_wcsnicmp', 'wchar.h'],
  433. ['abs', 'stdlib.h'],
  434. ['acos', 'math.h'],
  435. ['acosf', 'math.h'],
  436. ['alloca', 'stdlib.h'],
  437. ['asin', 'math.h'],
  438. ['asinf', 'math.h'],
  439. ['atan', 'math.h'],
  440. ['atan2', 'math.h'],
  441. ['atan2f', 'math.h'],
  442. ['atanf', 'math.h'],
  443. ['atof', 'stdlib.h'],
  444. ['atoi', 'stdlib.h'],
  445. ['bcopy', 'strings.h'],
  446. ['calloc', 'stdlib.h'],
  447. ['ceil', 'math.h'],
  448. ['ceilf', 'math.h'],
  449. ['clock_gettime', 'time.h'],
  450. ['copysign', 'math.h'],
  451. ['copysignf', 'math.h'],
  452. ['cos', 'math.h'],
  453. ['cosf', 'math.h'],
  454. ['dlopen', 'dlfcn.h'],
  455. ['elf_aux_info', 'sys/auxv.h'],
  456. ['exp', 'math.h'],
  457. ['expf', 'math.h'],
  458. ['fabs', 'math.h'],
  459. ['fabsf', 'math.h'],
  460. ['floor', 'math.h'],
  461. ['floorf', 'math.h'],
  462. ['fmod', 'math.h'],
  463. ['fmodf', 'math.h'],
  464. ['fopen64', 'stdio.h'],
  465. ['free', 'stdlib.h'],
  466. ['fseeko', 'stdio.h'],
  467. ['fseeko64', 'stdio.h'],
  468. ['getauxval', 'sys/auxv.h'],
  469. ['getenv', 'stdlib.h'],
  470. ['getpagesize', 'unistd.h'],
  471. ['iconv', 'iconv.h'],
  472. ['index', 'strings.h'],
  473. ['inotify_init', 'sys/inotify.h'],
  474. ['inotify_init1', 'sys/inotify.h'],
  475. ['itoa', 'stdlib.h'],
  476. ['log', 'math.h'],
  477. ['log10', 'math.h'],
  478. ['log10f', 'math.h'],
  479. ['logf', 'math.h'],
  480. ['lround', 'math.h'],
  481. ['lroundf', 'math.h'],
  482. ['malloc', 'stdlib.h'],
  483. ['memcmp', 'string.h'],
  484. ['memcpy', 'string.h'],
  485. ['memmove', 'string.h'],
  486. ['memset', 'string.h'],
  487. ['mprotect', 'sys/mman.h'],
  488. ['nanosleep', 'time.h'],
  489. ['poll', 'poll.h'],
  490. ['pow', 'math.h'],
  491. ['powf', 'math.h'],
  492. ['pthread_set_name_np', 'pthread.h'],
  493. ['pthread_setname_np', 'pthread.h'],
  494. ['putenv', 'stdlib.h'],
  495. ['qsort', 'stdlib.h'],
  496. ['realloc', 'stdlib.h'],
  497. ['rindex', 'strings.h'],
  498. ['round', 'math.h'],
  499. ['roundf', 'math.h'],
  500. ['scalbn', 'math.h'],
  501. ['scalbnf', 'math.h'],
  502. ['sem_timedwait', 'semaphore.h'],
  503. ['setenv', 'stdlib.h'],
  504. ['setjmp', 'setjmp.h'],
  505. ['sigaction', 'signal.h'],
  506. ['sin', 'math.h'],
  507. ['sinf', 'math.h'],
  508. ['snprintf', 'stdio.h'],
  509. ['sqrt', 'math.h'],
  510. ['sqrtf', 'math.h'],
  511. ['sscanf', 'stdio.h'],
  512. ['strcasecmp', 'strings.h'],
  513. ['strchr', 'string.h'],
  514. ['strcmp', 'string.h'],
  515. ['strdup', 'string.h'],
  516. ['strlcat', 'string.h'],
  517. ['strlcpy', 'string.h'],
  518. ['strlen', 'string.h'],
  519. ['strncasecmp', 'strings.h'],
  520. ['strncmp', 'string.h'],
  521. ['strrchr', 'string.h'],
  522. ['strstr', 'string.h'],
  523. ['strtod', 'stdlib.h'],
  524. ['strtok_r', 'string.h'],
  525. ['strtol', 'stdlib.h'],
  526. ['strtoll', 'stdlib.h'],
  527. ['strtoul', 'stdlib.h'],
  528. ['strtoull', 'stdlib.h'],
  529. ['sysconf', 'unistd.h'],
  530. ['sysctlbyname', 'sys/sysctl.h'],
  531. ['tan', 'math.h'],
  532. ['tanf', 'math.h'],
  533. ['trunc', 'math.h'],
  534. ['truncf', 'math.h'],
  535. ['unsetenv', 'stdlib.h'],
  536. ['vsnprintf', 'stdio.h'],
  537. ['vsscanf', 'stdio.h'],
  538. ['wcscmp', 'wchar.h'],
  539. ['wcsdup', 'wchar.h'],
  540. ['wcslen', 'wchar.h'],
  541. ['wcsncmp', 'wchar.h'],
  542. ['wcsstr', 'wchar.h'],
  543. ]
  544. foreach entry : check_functions
  545. func = entry[0]
  546. header = entry[1]
  547. prefix = unfuck_std + '#include <@0@>'.format(header)
  548. if cc.has_function(func, prefix : prefix, dependencies : core_deps)
  549. cdata.set('HAVE_@0@'.format(func.underscorify().to_upper()), 1)
  550. endif
  551. endforeach
  552. check_types = [
  553. ['XINPUT_GAMEPAD_EX', 'windows.h'],
  554. ['XINPUT_STATE_EX', 'windows.h'],
  555. ]
  556. foreach entry : check_types
  557. type = entry[0]
  558. header = entry[1]
  559. prefix = unfuck_std + '#include <@0@>'.format(header)
  560. if cc.has_type(type, prefix : prefix, dependencies : core_deps)
  561. cdata.set('HAVE_@0@'.format(type.underscorify().to_upper()), 1)
  562. endif
  563. endforeach
  564. if cc.has_member('struct sigaction', 'sa_sigaction', prefix : '@0@#include <signal.h>'.format(unfuck_std))
  565. cdata.set('HAVE_SA_SIGACTION', 1)
  566. endif
  567. if cdata.get('HAVE_INOTIFY_INIT', 0) == 1
  568. cdata.set('HAVE_INOTIFY', 1)
  569. endif
  570. cdata.set('HAVE_LIBC', 1)
  571. if platform_is_emscripten
  572. # USE_SDL is 1 by default for some reason. This interferes with our build.
  573. # https://github.com/emscripten-core/emscripten/issues/18072
  574. emcc_args = ['-sUSE_SDL=0']
  575. else
  576. emcc_args = []
  577. endif
  578. core_args = ['-DUSING_GENERATED_CONFIG_H'] + emcc_args
  579. core_ldflags = [] + emcc_args
  580. cdata.set10('HAVE_GCC_ATOMICS',
  581. cc.links('int main() { int x; return __atomic_load_n(&x, __ATOMIC_SEQ_CST); }',
  582. name : '__atomic_load_n test'
  583. )
  584. )
  585. cdata.set10('HAVE_GCC_SYNC_LOCK_TEST_AND_SET',
  586. cc.links('int main() { int x; return __sync_lock_test_and_set(&x, 1); }',
  587. name : '__sync_lock_test_and_set test'
  588. )
  589. )
  590. if cdata.get('HAVE_FCITX', 0) == 1 or cdata.get('HAVE_IBUS_IBUS_H', 0) == 1
  591. cdata.set('SDL_USE_IME', 1)
  592. endif
  593. sys_default_audio_driver = ['dummy']
  594. sys_default_filesystem = ['dummy']
  595. sys_default_haptic = ['dummy']
  596. sys_default_input = []
  597. sys_default_joystick = ['dummy']
  598. sys_default_loadso = ['dummy']
  599. sys_default_power = []
  600. sys_default_sensor = ['dummy']
  601. sys_default_thread = []
  602. sys_default_timer = ['dummy']
  603. sys_default_video = []
  604. sys_default_video_driver = ['dummy']
  605. sys_default_video_render = []
  606. sys_audio_driver = sys_default_audio_driver
  607. sys_filesystem = sys_default_filesystem
  608. sys_haptic = sys_default_haptic
  609. sys_input = sys_default_input
  610. sys_joystick = sys_default_joystick
  611. sys_loadso = sys_default_loadso
  612. sys_power = sys_default_power
  613. sys_sensor = sys_default_sensor
  614. sys_thread = sys_default_thread
  615. sys_timer = sys_default_timer
  616. sys_video = sys_default_video
  617. sys_video_driver = sys_default_video_driver
  618. sys_video_render = sys_default_video_render
  619. sys_gl_wsi = []
  620. modular_subsystems = [
  621. 'filesystem',
  622. 'haptic',
  623. 'joystick',
  624. 'loadso',
  625. 'power',
  626. 'sensor',
  627. 'video',
  628. ]
  629. fake_subsystems = []
  630. fake_subsystems_map = {
  631. 'events' : ['input'],
  632. 'audio' : ['audio_driver'],
  633. 'video' : ['video_driver'],
  634. 'render' : ['video_render'],
  635. 'threads' : ['thread'],
  636. 'timers' : ['timer'],
  637. }
  638. all_modular_subsystems = modular_subsystems
  639. foreach real_ss, fake_ss : fake_subsystems_map
  640. if enabled_subsystems.contains(real_ss)
  641. fake_subsystems += fake_ss
  642. endif
  643. all_modular_subsystems += fake_ss
  644. endforeach
  645. sys_dynamic_api = true
  646. sys_thread_generic_cond_suffix = false
  647. if platform_is_unixlike
  648. # Some sane defaults
  649. sys_filesystem = ['unix']
  650. sys_loadso = ['dlopen']
  651. sys_timer = ['unix']
  652. sys_thread = ['pthread']
  653. endif
  654. if platform_is_android
  655. sys_filesystem = ['android']
  656. sys_haptic = ['android']
  657. sys_input = ['android']
  658. sys_joystick = ['android']
  659. sys_power = ['android']
  660. sys_sensor = ['android']
  661. sys_audio_driver = ['opensles', 'android']
  662. sys_video_driver = ['android']
  663. sys_video_render = ['ogl_es2']
  664. extra_deps += [
  665. cc.find_library('android'),
  666. cc.find_library('log'),
  667. ]
  668. if not opt_video_openglesv2.disabled()
  669. extra_deps += cc.find_library('GLESv2', required : opt_video_openglesv2.enabled())
  670. endif
  671. elif platform_is_linux
  672. sys_haptic = ['linux']
  673. sys_input = ['linuxev', 'linuxkd']
  674. sys_joystick = ['linux']
  675. sys_power = ['linux']
  676. elif platform_is_windows
  677. sys_audio_driver = ['wasapi'] # XXX: winmm needed?
  678. sys_filesystem = ['windows']
  679. sys_haptic = []
  680. sys_joystick = [] # XXX: winmm needed?
  681. sys_loadso = ['windows']
  682. sys_power = ['windows']
  683. sys_thread = ['windows']
  684. sys_thread_generic_cond_suffix = true
  685. sys_timer = ['windows']
  686. sys_video_driver = ['windows']
  687. sys_video_render = ['d3d', 'd3d11']
  688. sys_gl_wsi = ['wgl']
  689. extra_deps += [
  690. # TODO: maybe filter this out conditionally...
  691. cc.find_library('dxerr8'),
  692. cc.find_library('dxguid'),
  693. cc.find_library('gdi32'),
  694. cc.find_library('imm32'),
  695. cc.find_library('ole32'),
  696. cc.find_library('oleaut32'),
  697. cc.find_library('setupapi'),
  698. cc.find_library('user32'),
  699. cc.find_library('version'),
  700. cc.find_library('winmm'),
  701. ]
  702. # XInput is loaded dynamically
  703. if not get_option('use_joystick_xinput').disabled()
  704. sys_joystick += 'xinput'
  705. sys_haptic += 'xinput'
  706. endif
  707. dinput = cc.find_library('dinput8', required : get_option('use_joystick_dinput'))
  708. if dinput.found()
  709. extra_deps += dinput
  710. sys_joystick += 'dinput'
  711. sys_haptic += 'dinput'
  712. endif
  713. if sys_joystick.contains('xinput') or sys_joystick.contains('dinput')
  714. sys_joystick += 'rawinput'
  715. endif
  716. if sys_joystick.contains('xinput') and cdata.get('HAVE_WINDOWS_GAMING_INPUT_H', 0) == 1
  717. if not get_option('use_joystick_wgi').disabled()
  718. sys_joystick += 'wgi'
  719. endif
  720. endif
  721. elif platform_is_macos
  722. sys_audio_driver = ['coreaudio']
  723. sys_filesystem = ['cocoa']
  724. sys_gl_wsi = ['cgl']
  725. sys_haptic = ['iokit']
  726. sys_joystick = ['iokit']
  727. sys_power = ['macosx']
  728. sys_video_driver = ['cocoa']
  729. extra_deps += dependency('appleframeworks', modules : [
  730. # TODO: maybe filter this out conditionally...
  731. 'AudioToolbox',
  732. 'AudioUnit',
  733. 'Carbon',
  734. 'Cocoa',
  735. 'CoreAudio',
  736. 'CoreFoundation',
  737. 'CoreGraphics',
  738. 'CoreServices',
  739. 'ForceFeedback',
  740. 'Foundation',
  741. 'IOKit',
  742. 'QuartzCore',
  743. ])
  744. elif platform_is_emscripten
  745. sys_audio_driver = ['emscripten']
  746. sys_filesystem = ['emscripten']
  747. sys_joystick = ['emscripten']
  748. sys_power = ['emscripten']
  749. sys_video_driver = ['emscripten']
  750. sys_dynamic_api = false
  751. else
  752. error('Unknown platform @0@, please add.'.format(host_machine.system()))
  753. endif
  754. if sys_dynamic_api
  755. cdata.set('SDL_DYNAMIC_API', 1)
  756. endif
  757. cdata.set10('SDL_THREAD_GENERIC_COND_SUFFIX', sys_thread_generic_cond_suffix)
  758. if extra_deps.contains(gl_dep)
  759. sys_video += 'opengl'
  760. sys_video_render += 'ogl'
  761. endif
  762. if extra_deps.contains(glesv2_dep)
  763. sys_video += 'opengl_es2'
  764. sys_video_render += 'ogl_es2'
  765. endif
  766. if extra_deps.contains(egl_dep)
  767. sys_video += 'opengl_egl'
  768. endif
  769. if extra_deps.contains(vulkan_dep)
  770. sys_video += 'vulkan'
  771. endif
  772. if extra_deps.contains(x11_dep)
  773. sys_video_driver += 'x11'
  774. sys_gl_wsi += 'glx'
  775. # FIXME: test for this?
  776. sys_video_driver += 'x11_supports_generic_events'
  777. if extra_deps.contains(xi_dep)
  778. sys_video_driver += 'x11_xinput2'
  779. # FIXME: test for this?
  780. sys_video_driver += 'x11_xinput2_supports_multitouch'
  781. endif
  782. if extra_deps.contains(xrandr_dep)
  783. sys_video_driver += 'x11_xrandr'
  784. endif
  785. if extra_deps.contains(xfixes_dep)
  786. sys_video_driver += 'x11_xfixes'
  787. endif
  788. if extra_deps.contains(xinerama_dep)
  789. sys_video_driver += 'x11_xinerama'
  790. endif
  791. if extra_deps.contains(xcursor_dep)
  792. sys_video_driver += 'x11_xcursor'
  793. endif
  794. if cc.has_header_symbol('X11/XKBlib.h', 'XkbKeycodeToKeysym', dependencies : x11_dep)
  795. sys_video_driver += 'x11_has_xkbkeycodetokeysym'
  796. endif
  797. endif
  798. if wayland_found and extra_deps.contains(wayland_client_dep)
  799. sys_video_driver += 'wayland'
  800. endif
  801. if not opt_video_offscreen.disabled()
  802. sys_video_driver += 'offscreen'
  803. endif
  804. if extra_deps.contains(gl_dep) or extra_deps.contains(glesv2_dep)
  805. foreach wsi : sys_gl_wsi
  806. sys_video += ['opengl_@0@'.format(wsi)]
  807. endforeach
  808. endif
  809. if extra_deps.contains(alsa_dep)
  810. cdata.set('SDL_AUDIO_DRIVER_ALSA', 1)
  811. sys_audio_driver += 'alsa'
  812. endif
  813. if extra_deps.contains(libpulse_simple_dep)
  814. sys_audio_driver += 'pulseaudio'
  815. endif
  816. if extra_deps.contains(jack_dep)
  817. sys_audio_driver += 'jack'
  818. endif
  819. if extra_deps.contains(libpipewire_dep)
  820. sys_audio_driver += 'pipewire'
  821. endif
  822. if not get_option('use_joystick_virtual').disabled()
  823. sys_joystick += 'virtual'
  824. endif
  825. if enabled_subsystems.contains('hidapi')
  826. sys_joystick += 'hidapi'
  827. endif
  828. if get_option('use_dummies')
  829. sys_audio_driver += 'dummy'
  830. sys_video_driver += 'dummy'
  831. sys_joystick += 'dummy'
  832. sys_sensor += 'dummy'
  833. endif
  834. foreach ss : all_modular_subsystems
  835. var_want = 'sys_@0@'.format(ss)
  836. var_default = 'sys_default_@0@'.format(ss)
  837. if not (enabled_subsystems + fake_subsystems).contains(ss)
  838. set_variable(var_want, get_variable(var_default))
  839. endif
  840. dedup_list = []
  841. foreach backend : get_variable(var_want)
  842. if not dedup_list.contains(backend)
  843. dedup_list += backend
  844. endif
  845. endforeach
  846. message('@1@: @0@'.format(', '.join(dedup_list), ss))
  847. foreach backend : dedup_list
  848. cfg_var = 'SDL_@0@_@1@'.format(ss.to_upper(), backend.to_upper())
  849. cdata.set(cfg_var, 1)
  850. # message('Setting @0@ to 1'.format(cfg_var))
  851. endforeach
  852. endforeach
  853. core_inc = [include_directories('include')]
  854. c_sources = []
  855. cxx_sources = []
  856. objc_sources = []
  857. main_sources = []
  858. subdir('include')
  859. subdir('src')
  860. subdir('wayland-protocols')
  861. all_sources = [c_sources]
  862. if platform_is_darwin
  863. add_languages('objc')
  864. all_sources += [objc_sources]
  865. endif
  866. if platform_is_winrt or platform_is_haiku
  867. add_languages('cpp')
  868. all_sources += [cxx_sources]
  869. endif
  870. sdl2 = library('sdl2',
  871. all_sources,
  872. include_directories : core_inc,
  873. implicit_include_directories : false,
  874. c_args : core_args,
  875. link_args : core_ldflags,
  876. dependencies : [core_deps, extra_deps],
  877. override_options : ['c_std=none'],
  878. install : false,
  879. build_by_default : not meson.is_subproject(),
  880. )
  881. use_sdl2main = not sdl2main_is_dummy
  882. if use_sdl2main
  883. main_c_args = ['-Dmain=SDL_main']
  884. sdl2main = static_library('sdl2main',
  885. main_sources,
  886. include_directories : core_inc,
  887. implicit_include_directories : false,
  888. c_args : [core_args, main_c_args],
  889. install : false,
  890. build_by_default : not meson.is_subproject(),
  891. )
  892. sdl2_dep = declare_dependency(
  893. link_with : sdl2,
  894. link_whole : sdl2main,
  895. include_directories : core_inc,
  896. compile_args : main_c_args + emcc_args,
  897. link_args : emcc_args,
  898. )
  899. sdl2main_dep = declare_dependency(
  900. link_whole : sdl2main,
  901. include_directories : core_inc,
  902. compile_args : main_c_args + emcc_args,
  903. link_args : emcc_args,
  904. )
  905. else
  906. sdl2_dep = declare_dependency(
  907. link_with : sdl2,
  908. include_directories : core_inc,
  909. compile_args : emcc_args,
  910. link_args : emcc_args,
  911. )
  912. endif
  913. if meson.version().version_compare('>=0.54')
  914. meson.override_dependency('sdl2', sdl2_dep)
  915. endif