1project('pugl', ['c'], 2 version: '0.3.0', 3 license: 'ISC', 4 meson_version: '>= 0.49.2', 5 default_options: [ 6 'c_std=c99', 7 'cpp_std=c++11', 8 'default_library=shared' 9 ]) 10 11pugl_src_root = meson.current_source_dir() 12major_version = meson.project_version().split('.')[0] 13version_suffix = '-@0@'.format(major_version) 14versioned_name = 'pugl' + version_suffix 15 16# Load build tools 17pkg = import('pkgconfig') 18cc = meson.get_compiler('c') 19 20# Enable C++ support if we're building the examples 21if get_option('examples') 22 add_languages(['cpp']) 23 cpp = meson.get_compiler('cpp') 24endif 25 26# Enable Objective C support if we're building for MacOS 27if host_machine.system() == 'darwin' 28 add_languages(['objc']) 29 objcc = meson.get_compiler('objc') 30endif 31 32# Set ultra strict warnings for developers, if requested 33if get_option('strict') 34 subdir('meson') 35 36 # C warnings 37 c_warnings = all_c_warnings 38 if cc.get_id() == 'clang' 39 c_warnings += [ 40 '-Wno-bad-function-cast', 41 '-Wno-documentation', # Cairo 42 '-Wno-documentation-unknown-command', # Cairo 43 '-Wno-float-equal', 44 '-Wno-implicit-fallthrough', 45 '-Wno-padded', 46 '-Wno-reserved-id-macro', 47 '-Wno-switch-default', 48 '-Wno-switch-enum', 49 '-Wno-unused-macros', # Mac 50 ] 51 elif cc.get_id() == 'gcc' 52 c_warnings += [ 53 '-Wno-bad-function-cast', 54 '-Wno-float-equal', 55 '-Wno-inline', 56 '-Wno-padded', 57 '-Wno-pedantic', 58 '-Wno-suggest-attribute=const', 59 '-Wno-suggest-attribute=malloc', 60 '-Wno-suggest-attribute=pure', 61 '-Wno-switch-default', 62 '-Wno-switch-enum', 63 '-Wno-unsuffixed-float-constants', 64 ] 65 elif cc.get_id() == 'msvc' 66 c_warnings += [ 67 '/wd4028', # formal parameter different from declaration 68 '/wd4061', # enumerator in switch is not explicitly handled 69 '/wd4191', # unsafe conversion from type to type 70 '/wd4514', # unreferenced inline function has been removed 71 '/wd4706', # assignment within conditional expression 72 '/wd4710', # function not inlined 73 '/wd4711', # function selected for automatic inline expansion 74 '/wd4800', # implicit conversion from int to bool 75 '/wd4820', # padding added after construct 76 '/wd4996', # function or variable may be unsafe 77 '/wd5045', # will insert Spectre mitigation for memory load 78 ] 79 endif 80 81 add_project_arguments(cc.get_supported_arguments(c_warnings), 82 language: ['c', 'objc']) 83 84 # C++ warnings 85 cpp_warnings = all_cpp_warnings 86 if is_variable('cpp') 87 if cpp.get_id() == 'clang' 88 cpp_warnings += [ 89 '-Wno-documentation-unknown-command', # Cairo 90 '-Wno-old-style-cast', 91 '-Wno-padded', 92 '-Wno-reserved-id-macro', 93 '-Wno-switch-enum', 94 '-Wno-unused-macros', # Mac 95 ] 96 elif cpp.get_id() == 'gcc' 97 cpp_warnings += [ 98 '-Wno-effc++', 99 '-Wno-inline', 100 '-Wno-old-style-cast', 101 '-Wno-padded', 102 '-Wno-suggest-attribute=const', 103 '-Wno-suggest-attribute=malloc', 104 '-Wno-suggest-attribute=pure', 105 '-Wno-suggest-final-methods', 106 '-Wno-switch-default', 107 '-Wno-switch-enum', 108 '-Wno-unused-const-variable', 109 '-Wno-useless-cast', 110 ] 111 elif cpp.get_id() == 'msvc' 112 cpp_warnings += [ 113 '/wd4061', # enumerator in switch is not explicitly handled 114 '/wd4191', # unsafe conversion from type to type 115 '/wd4355', # 'this' used in base member initializer list 116 '/wd4514', # unreferenced inline function has been removed 117 '/wd4571', # structured exceptions (SEH) are no longer caught 118 '/wd4625', # copy constructor implicitly deleted 119 '/wd4626', # assignment operator implicitly deleted 120 '/wd4706', # assignment within conditional expression 121 '/wd4710', # function not inlined 122 '/wd4711', # function selected for automatic inline expansion 123 '/wd4800', # implicit conversion from int to bool 124 '/wd4820', # padding added after construct 125 '/wd4868', # compiler may not enforce left-to-right evaluation order 126 '/wd4996', # function or variable may be unsafe 127 '/wd5026', # move constructor implicitly deleted 128 '/wd5027', # move assignment operator implicitly deleted 129 '/wd5039', # potentially throwing function passed to C 130 '/wd5045', # will insert Spectre mitigation for memory load 131 ] 132 endif 133 134 add_project_arguments(cpp.get_supported_arguments(cpp_warnings), 135 language: ['cpp']) 136 endif 137 138 # Objective C warnings 139 if is_variable('objcc') 140 add_project_arguments(objcc.get_supported_arguments(all_objc_warnings), 141 language: ['objc']) 142 endif 143endif 144 145# Disable deprecated API which is not used by tests or examples 146add_project_arguments(['-DPUGL_DISABLE_DEPRECATED'], 147 language: ['c', 'cpp', 'objc']) 148 149c_headers = [ 150 'include/pugl/pugl.h', 151 152 'include/pugl/cairo.h', 153 'include/pugl/gl.h', 154 'include/pugl/stub.h', 155 'include/pugl/vulkan.h', 156] 157 158c_header_files = files(c_headers) 159 160cpp_headers = [ 161 'bindings/cxx/include/pugl/pugl.hpp', 162 163 'bindings/cxx/include/pugl/cairo.hpp', 164 'bindings/cxx/include/pugl/gl.hpp', 165 'bindings/cxx/include/pugl/stub.hpp', 166 'bindings/cxx/include/pugl/vulkan.hpp', 167] 168 169cpp_header_files = files(cpp_headers) 170 171core_sources = [ 172 'src/implementation.c' 173] 174 175# System libraries 176m_dep = cc.find_library('m', required: false) 177dl_dep = cc.find_library('dl', required: false) 178thread_dep = dependency('threads') 179 180# Cairo (optional backend) 181cairo_dep = dependency('cairo', 182 required: get_option('cairo')) 183 184# OpenGL (optional backend) 185opengl_dep = dependency('GL', 186 required: get_option('opengl')) 187 188# Vulkan (optional backend) 189vulkan_dep = dependency('vulkan', 190 required: get_option('vulkan')) 191 192core_args = [] 193 194# MacOS 195if host_machine.system() == 'darwin' 196 cocoa_dep = dependency('Cocoa', required: false, modules: 'foundation') 197 corevideo_dep = dependency('CoreVideo', required: false) 198 199 platform = 'mac' 200 platform_sources = ['src/mac.m', 'src/mac_stub.m'] 201 core_deps = [cocoa_dep, corevideo_dep] 202 extension = '.m' 203 204 add_project_arguments(['-Wno-deprecated-declarations'], language: ['objc']) 205 add_project_arguments(['-Wno-direct-ivar-access'], language: ['objc']) 206 207 add_project_arguments(['-DGL_SILENCE_DEPRECATION'], 208 language: ['c', 'objc']) 209 210 add_project_link_arguments(['-Wl,-framework,Cocoa'], 211 language: ['c', 'objc']) 212 213# Windows 214elif host_machine.system() == 'windows' 215 if cpp.get_id() == 'msvc' 216 msvc_args = [ 217 '/TP', 218 '/experimental:external', 219 '/external:W0', 220 '/external:anglebrackets', 221 ] 222 223 add_project_arguments(msvc_args, language: ['c', 'cpp']) 224 endif 225 226 win_args = [ 227 '-DWIN32_LEAN_AND_MEAN', 228 '-D_CRT_SECURE_NO_WARNINGS', 229 ] 230 231 add_project_arguments(win_args, language: ['c', 'cpp']) 232 233 platform = 'win' 234 platform_sources = ['src/win.c'] 235 core_deps = [] 236 extension = '.c' 237 238else # X11 239 x11_dep = cc.find_library('X11') 240 241 xcursor_dep = cc.find_library('Xcursor', required: false) 242 if xcursor_dep.found() 243 core_args += ['-DHAVE_XCURSOR'] 244 endif 245 246 xrandr_dep = cc.find_library('Xrandr', required: false) 247 if xrandr_dep.found() 248 core_args += ['-DHAVE_XRANDR'] 249 endif 250 251 xext_dep = cc.find_library('Xext', required: false) 252 if xext_dep.found() 253 xsync_fragment = '''#include <X11/Xlib.h> 254 #include <X11/extensions/sync.h> 255 int main(void) { XSyncQueryExtension(0, 0, 0); return 0; }''' 256 if cc.compiles(xsync_fragment, name: 'Xsync') 257 core_args += ['-DHAVE_XSYNC'] 258 endif 259 endif 260 261 platform = 'x11' 262 platform_sources = ['src/x11.c'] 263 core_deps = [x11_dep, xcursor_dep, xrandr_dep, xext_dep] 264 extension = '.c' 265endif 266 267# Build core library 268 269core_deps += [m_dep] 270core_sources += platform_sources 271core_name = 'pugl_@0@@1@'.format(platform, version_suffix) 272 273library_args = ['-DPUGL_INTERNAL'] 274if get_option('default_library') == 'both' 275 if host_machine.system() == 'windows' 276 error('default_library=both is not supported on Windows') 277 endif 278 279 library_type = 'both_libraries' 280elif get_option('default_library') == 'shared' 281 library_type = 'shared_library' 282else 283 library_type = 'static_library' 284 add_project_arguments(['-DPUGL_STATIC'], language: ['c', 'cpp', 'objc']) 285endif 286 287libpugl = build_target( 288 core_name, core_sources, 289 version: meson.project_version(), 290 include_directories: include_directories(['include']), 291 c_args: library_args + core_args, 292 dependencies: core_deps, 293 gnu_symbol_visibility: 'hidden', 294 install: true, 295 target_type: library_type) 296 297pugl_dep = declare_dependency(link_with: libpugl, dependencies: core_deps) 298 299pkg.generate(libpugl, 300 name: 'Pugl', 301 filebase: versioned_name, 302 subdirs: [versioned_name], 303 version: meson.project_version(), 304 description: 'Pugl GUI library core') 305 306# Build stub backend 307 308name = 'pugl_' + platform + '_stub' + version_suffix 309sources = 'src/' + platform + '_stub' + extension 310 311stub_backend = build_target( 312 name, sources, 313 version: meson.project_version(), 314 include_directories: include_directories(['include']), 315 c_args: library_args, 316 dependencies: [pugl_dep], 317 gnu_symbol_visibility: 'hidden', 318 install: true, 319 target_type: library_type) 320 321stub_backend_dep = declare_dependency(link_with: stub_backend) 322 323pkg.generate(stub_backend, 324 name: 'Pugl Stub', 325 filebase: 'pugl-stub-@0@'.format(major_version), 326 subdirs: [name], 327 version: meson.project_version(), 328 description: 'Native window pugl graphics backend') 329 330# Build GL backend 331if opengl_dep.found() 332 name = 'pugl_' + platform + '_gl' + version_suffix 333 sources = 'src/' + platform + '_gl' + extension 334 335 gl_backend = build_target( 336 name, sources, 337 version: meson.project_version(), 338 include_directories: include_directories(['include']), 339 c_args: library_args, 340 dependencies: [pugl_dep, opengl_dep], 341 gnu_symbol_visibility: 'hidden', 342 install: true, 343 target_type: library_type) 344 345 gl_backend_dep = declare_dependency(link_with: gl_backend, 346 dependencies: [pugl_dep, opengl_dep]) 347 348 pkg.generate(gl_backend, 349 name: 'Pugl OpenGL', 350 filebase: 'pugl-gl-@0@'.format(major_version), 351 subdirs: [name], 352 version: meson.project_version(), 353 description: 'Pugl GUI library with OpenGL backend') 354endif 355 356# Build Cairo backend 357if cairo_dep.found() 358 name = 'pugl_' + platform + '_cairo' + version_suffix 359 sources = ['src/' + platform + '_cairo' + extension, 360 'src/' + platform + '_stub' + extension] 361 362 cairo_backend = build_target( 363 name, sources, 364 version: meson.project_version(), 365 include_directories: include_directories(['include']), 366 c_args: library_args, 367 dependencies: [pugl_dep, cairo_dep, stub_backend_dep], 368 gnu_symbol_visibility: 'hidden', 369 install: true, 370 target_type: library_type) 371 372 cairo_backend_dep = declare_dependency( 373 link_with: cairo_backend, 374 dependencies: [pugl_dep, cairo_dep, stub_backend_dep]) 375 376 pkg.generate(cairo_backend, 377 name: 'Pugl Cairo', 378 filebase: 'pugl-cairo-@0@'.format(major_version), 379 subdirs: [name], 380 version: meson.project_version(), 381 description: 'Pugl GUI library with Cairo backend') 382endif 383 384# Build Vulkan backend 385if vulkan_dep.found() 386 name = 'pugl_' + platform + '_vulkan' + version_suffix 387 sources = ['src/' + platform + '_vulkan' + extension, 388 'src/' + platform + '_stub' + extension] 389 390 vulkan_deps = [pugl_dep, vulkan_dep, dl_dep] 391 vulkan_c_args = library_args 392 vulkan_link_args = [] 393 if platform == 'mac' 394 metal_dep = dependency('Metal', modules: 'foundation') 395 quartzcore_dep = dependency('QuartzCore', modules: 'foundation') 396 397 vulkan_deps += [metal_dep, quartzcore_dep] 398 endif 399 400 vulkan_backend = build_target( 401 name, sources, 402 version: meson.project_version(), 403 include_directories: include_directories(['include']), 404 c_args: library_args, 405 dependencies: vulkan_deps, 406 gnu_symbol_visibility: 'hidden', 407 install: true, 408 target_type: library_type) 409 410 vulkan_backend_dep = declare_dependency( 411 link_with: vulkan_backend, 412 dependencies: [pugl_dep, vulkan_dep, thread_dep]) 413 414 pkg.generate(vulkan_backend, 415 name: 'Pugl Vulkan', 416 filebase: 'pugl-vulkan-@0@'.format(major_version), 417 subdirs: [name], 418 version: meson.project_version(), 419 description: 'Pugl GUI library with Vulkan backend') 420endif 421 422install_headers(c_headers, subdir: versioned_name / 'pugl') 423install_headers(cpp_headers, subdir: 'puglxx' + version_suffix) 424 425if not get_option('docs').disabled() 426 subdir('doc') 427else 428 build_docs = false 429endif 430 431if get_option('examples') 432 subdir('examples') 433endif 434 435if get_option('tests') 436 subdir('test') 437endif 438 439if meson.version().version_compare('>=0.53.0') 440 summary('Platform', platform) 441 summary('Cairo backend', cairo_dep.found(), bool_yn: true) 442 summary('OpenGL backend', opengl_dep.found(), bool_yn: true) 443 summary('Vulkan backend', vulkan_dep.found(), bool_yn: true) 444 summary('Tests', get_option('tests'), bool_yn: true) 445 summary('Examples', get_option('examples'), bool_yn: true) 446 summary('Documentation', build_docs, bool_yn: true) 447 448 summary('Install prefix', get_option('prefix')) 449 summary('Headers', get_option('prefix') / get_option('includedir')) 450 summary('Libraries', get_option('prefix') / get_option('libdir')) 451 452 if get_option('examples') 453 summary('Executables', get_option('prefix') / get_option('bindir')) 454 endif 455endif 456