### Common dependencies unwind = dependency('libunwind', required: get_option('unwind')) libexecinfo = cc.find_library('execinfo', required: false) has_execinfo = cc.has_function('backtrace_symbols', dependencies: libexecinfo, prefix: '#include ') dbghelp = cc.check_header('dbghelp.h', prefix: '#include ') conf_internal.set('PL_HAVE_DBGHELP', dbghelp) conf_internal.set('PL_HAVE_UNWIND', unwind.found()) conf_internal.set('PL_HAVE_EXECINFO', has_execinfo) if dbghelp build_deps += cc.find_library('shlwapi', required: true) elif unwind.found() build_deps += [unwind, cc.find_library('dl', required : false)] elif has_execinfo build_deps += libexecinfo endif link_args = [] link_depends = [] # Looks like meson in certain configuration returns ' ' instead of empty string mingw32 = cc.get_define('__MINGW32__').strip() if host_machine.system() == 'windows' and mingw32 != '' and host_machine.cpu() in ['aarch64', 'arm', 'x86_64'] # MinGW-w64 math functions are significantly slower than the UCRT ones. # In particular powf is over 7 times slower than UCRT counterpart. # MinGW-w64 explicitly excludes some math functions from their ucrtbase def # file and replaces with own versions. To workaround the issue, generate the # import library and link it with UCRT versions of math functions. dlltool = find_program('llvm-dlltool', 'dlltool') ucrt_math = custom_target('ucrt_math.lib', output : ['ucrt_math.lib'], input : 'ucrt_math.def', command : [dlltool, '-d', '@INPUT@', '-l', '@OUTPUT@']) link_args += ucrt_math.full_path() link_depends += ucrt_math # MinGW-w64 inlines functions like powf, rewriting them to pow. We want to use # the powf specialization from UCRT, so disable inlining. add_project_arguments(['-D__CRT__NO_INLINE'], language: ['c', 'cpp']) endif # Work around missing atomics on some (obscure) platforms atomic_test = ''' #include #include int main(void) { _Atomic uint32_t x32; atomic_init(&x32, 0); }''' if not cc.links(atomic_test) build_deps += cc.find_library('atomic') endif ### Common source files headers = [ 'cache.h', 'colorspace.h', 'common.h', 'd3d11.h', 'dispatch.h', 'dither.h', 'dummy.h', 'filters.h', 'gamut_mapping.h', 'gpu.h', 'log.h', 'opengl.h', 'options.h', 'renderer.h', 'shaders/colorspace.h', 'shaders/custom.h', 'shaders/deinterlacing.h', 'shaders/dithering.h', 'shaders/film_grain.h', 'shaders/icc.h', 'shaders/lut.h', 'shaders/sampling.h', 'shaders.h', 'swapchain.h', 'tone_mapping.h', 'utils/dav1d.h', 'utils/dav1d_internal.h', 'utils/dolbyvision.h', 'utils/frame_queue.h', 'utils/libav.h', 'utils/libav_internal.h', 'utils/upload.h', 'vulkan.h', ] sources = [ 'cache.c', 'colorspace.c', 'common.c', 'convert.cc', 'dither.c', 'dispatch.c', 'dummy.c', 'filters.c', 'format.c', 'gamut_mapping.c', 'glsl/spirv.c', 'gpu.c', 'gpu/utils.c', 'log.c', 'options.c', 'pl_alloc.c', 'pl_string.c', 'swapchain.c', 'tone_mapping.c', 'utils/dolbyvision.c', 'utils/frame_queue.c', 'utils/upload.c', ] # Source files that may use GLSL pragmas, we need to use custom_target # to the proper environment and dependency information for these foreach f : ['renderer.c', 'shaders.c'] sources += custom_target(f, command: glsl_preproc, depend_files: glsl_deps, env: python_env, input: f, output: f, ) endforeach # More .c files defined here, we can't put them in this file because of meson # preventing the use of / in custom_target output filenames subdir('shaders') tests = [ 'cache.c', 'colorspace.c', 'common.c', 'dither.c', 'dummy.c', 'lut.c', 'filters.c', 'options.c', 'string.c', 'tone_mapping.c', 'utils.c', ] fuzzers = [ 'lut.c', 'options.c', 'shaders.c', 'user_shaders.c', ] components = configuration_data() ### Optional dependencies / components subdir('glsl') subdir('d3d11') subdir('opengl') subdir('vulkan') lcms = dependency('lcms2', version: '>=2.9', required: get_option('lcms')) components.set('lcms', lcms.found()) if lcms.found() build_deps += lcms tests += 'icc.c' endif # Check to see if libplacebo built this way is sane if not (components.get('vulkan') or components.get('opengl') or components.get('d3d11')) warning('Building without any graphics API. libplacebo built this way still ' + 'has some limited use (e.g. generating GLSL shaders), but most of ' + 'its functionality will be missing or impaired!') endif has_spirv = components.get('shaderc') or components.get('glslang') needs_spirv = components.get('vulkan') or components.get('d3d11') if needs_spirv and not has_spirv warning('Building without any GLSL compiler (shaderc, glslang), but with ' + 'APIs required that require one (vulkan, d3d11). This build is very ' + 'likely to be very limited in functionality!') endif dovi = get_option('dovi') components.set('dovi', dovi.allowed()) libdovi = dependency('dovi', version: '>=1.6.7', required: get_option('libdovi').require(dovi.allowed())) components.set('libdovi', libdovi.found()) if libdovi.found() build_deps += libdovi endif xxhash_inc = include_directories() xxhash = dependency('libxxhash', required: get_option('xxhash')) components.set('xxhash', xxhash.found()) if xxhash.found() xxhash_inc = xxhash.get_variable('includedir') endif # Generate configuration files defs = '' pc_vars = [] foreach comp : components.keys() found = components.get(comp) varname = comp.underscorify().to_upper() summary(comp, found, section: 'Optional features', bool_yn: true) defs += (found ? '#define PL_HAVE_@0@ 1\n' : '#undef PL_HAVE_@0@\n').format(varname) pc_vars += 'pl_has_@0@=@1@'.format(varname.to_lower(), found ? 1 : 0) endforeach conf_public.set('extra_defs', defs) subdir('./include/libplacebo') # generate config.h in the right location sources += configure_file( output: 'config_internal.h', configuration: conf_internal ) version_h = vcs_tag( command: ['git', 'describe', '--dirty'], fallback: version_pretty, replace_string: '@buildver@', input: 'version.h.in', output: 'version.h', ) sources += version_h if host_machine.system() == 'windows' windows = import('windows') sources += windows.compile_resources(libplacebo_rc, depends: version_h, include_directories: meson.project_source_root()/'win32') endif fast_float_inc = include_directories() if fs.is_dir('../3rdparty/fast_float/include') fast_float_inc = include_directories('../3rdparty/fast_float/include') endif ### Main library build process inc = include_directories('./include') lib = library('placebo', sources, c_args: ['-DPL_EXPORT'], install: true, dependencies: build_deps + glad_dep, soversion: apiver, include_directories: [ inc, vulkan_headers_inc, fast_float_inc, xxhash_inc ], link_args: link_args, link_depends: link_depends, gnu_symbol_visibility: 'hidden', name_prefix: 'lib' ) libplacebo = declare_dependency( include_directories: inc, compile_args: get_option('default_library') == 'static' ? ['-DPL_STATIC'] : [], link_with: lib, variables: pc_vars, ) ### Install process proj_name = meson.project_name() foreach h : headers parts = h.split('/') path = proj_name foreach p : parts if p != parts[-1] path = path / p endif endforeach install_headers('include' / proj_name / h, subdir: path) endforeach extra_cflags = [] if get_option('default_library') == 'static' extra_cflags = ['-DPL_STATIC'] elif get_option('default_library') == 'both' # meson doesn't support Cflags.private, insert it forcefully... extra_cflags = ['\nCflags.private:', '-DPL_STATIC'] endif pkg = import('pkgconfig') pkg.generate( name: proj_name, description: 'Reusable library for GPU-accelerated video/image rendering', libraries: lib, version: version, variables: pc_vars, extra_cflags: extra_cflags, ) ### Testing tdep_static = declare_dependency( dependencies: build_deps, include_directories: [ inc, include_directories('.') ], compile_args: '-DPL_STATIC' # TODO: Define objects here once Meson 1.1.0 is ok to use # objects: lib.extract_all_objects(recursive: false) ) tdep_shared = declare_dependency( include_directories: [ inc, include_directories('.') ], compile_args: get_option('default_library') == 'static' ? ['-DPL_STATIC'] : [], link_with: lib, ) if get_option('tests') subdir('tests') endif if get_option('bench') if not components.get('vk-proc-addr') error('Compiling the benchmark suite requires vulkan support!') endif bench = executable('bench', 'tests/bench.c', dependencies: [tdep_shared, vulkan_headers], link_args: link_args, link_depends: link_depends, include_directories: vulkan_headers_inc, ) test('benchmark', bench, is_parallel: false, timeout: 600) endif if get_option('fuzz') foreach f : fuzzers executable('fuzz.' + f, 'tests/fuzz/' + f, objects: lib.extract_all_objects(recursive: false), dependencies: tdep_static, link_args: link_args, link_depends: link_depends, ) endforeach endif pl_thread = declare_dependency( include_directories: include_directories('.'), dependencies: threads, ) pl_clock = declare_dependency( include_directories: include_directories('.'), )