| # Copyright © 2018-2022, VideoLAN and dav1d authors | 
 | # All rights reserved. | 
 | # | 
 | # Redistribution and use in source and binary forms, with or without | 
 | # modification, are permitted provided that the following conditions are met: | 
 | # | 
 | # 1. Redistributions of source code must retain the above copyright notice, this | 
 | #    list of conditions and the following disclaimer. | 
 | # | 
 | # 2. Redistributions in binary form must reproduce the above copyright notice, | 
 | #    this list of conditions and the following disclaimer in the documentation | 
 | #    and/or other materials provided with the distribution. | 
 | # | 
 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 
 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | 
 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  | 
 | project('dav1d', ['c'], | 
 |     version: '1.1.0', | 
 |     default_options: ['c_std=c99', | 
 |                       'warning_level=2', | 
 |                       'buildtype=release', | 
 |                       'b_ndebug=if-release'], | 
 |     meson_version: '>= 0.49.0') | 
 |  | 
 | dav1d_soname_version       = '6.8.0' | 
 | dav1d_api_version_array    = dav1d_soname_version.split('.') | 
 | dav1d_api_version_major    = dav1d_api_version_array[0] | 
 | dav1d_api_version_minor    = dav1d_api_version_array[1] | 
 | dav1d_api_version_revision = dav1d_api_version_array[2] | 
 |  | 
 | dav1d_src_root = meson.current_source_dir() | 
 | cc = meson.get_compiler('c') | 
 |  | 
 | # Configuratin data for config.h | 
 | cdata = configuration_data() | 
 |  | 
 | # Configuration data for config.asm | 
 | cdata_asm = configuration_data() | 
 |  | 
 | # Include directories | 
 | dav1d_inc_dirs = include_directories(['.', 'include/dav1d', 'include']) | 
 |  | 
 |  | 
 |  | 
 | # | 
 | # Option handling | 
 | # | 
 |  | 
 | # Bitdepth option | 
 | dav1d_bitdepths = get_option('bitdepths') | 
 | foreach bitdepth : ['8', '16'] | 
 |     cdata.set10('CONFIG_@0@BPC'.format(bitdepth), dav1d_bitdepths.contains(bitdepth)) | 
 | endforeach | 
 |  | 
 | # ASM option | 
 | is_asm_enabled = (get_option('enable_asm') == true and | 
 |     (host_machine.cpu_family() == 'x86' or | 
 |      (host_machine.cpu_family() == 'x86_64' and cc.get_define('__ILP32__').strip() == '') or | 
 |      host_machine.cpu_family() == 'aarch64'      or | 
 |      host_machine.cpu_family().startswith('arm') or | 
 |      host_machine.cpu() == 'ppc64le')) | 
 | cdata.set10('HAVE_ASM', is_asm_enabled) | 
 |  | 
 | if is_asm_enabled and get_option('b_sanitize') == 'memory' | 
 |     error('asm causes false positive with memory sanitizer. Use \'-Denable_asm=false\'.') | 
 | endif | 
 |  | 
 | cdata.set10('TRIM_DSP_FUNCTIONS', get_option('trim_dsp') == 'true' or | 
 |     (get_option('trim_dsp') == 'if-release' and get_option('buildtype') == 'release')) | 
 |  | 
 | # Logging option | 
 | cdata.set10('CONFIG_LOG', get_option('logging')) | 
 |  | 
 | # | 
 | # OS/Compiler checks and defines | 
 | # | 
 |  | 
 | # Arguments in test_args will be used even on feature tests | 
 | test_args = [] | 
 |  | 
 | optional_arguments = [] | 
 | optional_link_arguments = [] | 
 |  | 
 | if host_machine.system() in ['linux', 'gnu'] | 
 |     test_args += '-D_GNU_SOURCE' | 
 |     add_project_arguments('-D_GNU_SOURCE', language: 'c') | 
 | endif | 
 |  | 
 | if host_machine.system() == 'windows' | 
 |     cdata.set('_WIN32_WINNT',           '0x0601') | 
 |     cdata.set('UNICODE',                1) # Define to 1 for Unicode (Wide Chars) APIs | 
 |     cdata.set('_UNICODE',               1) # Define to 1 for Unicode (Wide Chars) APIs | 
 |     cdata.set('__USE_MINGW_ANSI_STDIO', 1) # Define to force use of MinGW printf | 
 |     cdata.set('_CRT_DECLARE_NONSTDC_NAMES', 1) # Define to get off_t from sys/types.h on MSVC | 
 |     if cc.has_function('fseeko', prefix : '#include <stdio.h>', args : test_args) | 
 |         cdata.set('_FILE_OFFSET_BITS', 64) # Not set by default by Meson on Windows | 
 |     else | 
 |         cdata.set('fseeko', '_fseeki64') | 
 |         cdata.set('ftello', '_ftelli64') | 
 |     endif | 
 |  | 
 |     if host_machine.cpu_family() == 'x86_64' | 
 |         if cc.get_argument_syntax() != 'msvc' | 
 |             optional_link_arguments += '-Wl,--dynamicbase,--nxcompat,--tsaware,--high-entropy-va' | 
 |         endif | 
 |     elif host_machine.cpu_family() == 'x86' or host_machine.cpu_family() == 'arm' | 
 |         if cc.get_argument_syntax() == 'msvc' | 
 |             optional_link_arguments += '/largeaddressaware' | 
 |         else | 
 |             optional_link_arguments += '-Wl,--dynamicbase,--nxcompat,--tsaware,--large-address-aware' | 
 |         endif | 
 |     endif | 
 |  | 
 |     # On Windows, we use a compatibility layer to emulate pthread | 
 |     thread_dependency = [] | 
 |     thread_compat_dep = declare_dependency(sources : files('src/win32/thread.c')) | 
 |  | 
 |     rt_dependency = [] | 
 |  | 
 |     rc_version_array = meson.project_version().split('.') | 
 |     winmod = import('windows') | 
 |     rc_data = configuration_data() | 
 |     rc_data.set('PROJECT_VERSION_MAJOR', rc_version_array[0]) | 
 |     rc_data.set('PROJECT_VERSION_MINOR', rc_version_array[1]) | 
 |     rc_data.set('PROJECT_VERSION_REVISION', rc_version_array[2]) | 
 |     rc_data.set('API_VERSION_MAJOR', dav1d_api_version_major) | 
 |     rc_data.set('API_VERSION_MINOR', dav1d_api_version_minor) | 
 |     rc_data.set('API_VERSION_REVISION', dav1d_api_version_revision) | 
 |     rc_data.set('COPYRIGHT_YEARS', '2018-2023') | 
 | else | 
 |     thread_dependency = dependency('threads') | 
 |     thread_compat_dep = [] | 
 |  | 
 |     rt_dependency = [] | 
 |     if cc.has_function('clock_gettime', prefix : '#include <time.h>', args : test_args) | 
 |         cdata.set('HAVE_CLOCK_GETTIME', 1) | 
 |     elif host_machine.system() not in ['darwin', 'ios', 'tvos'] | 
 |         rt_dependency = cc.find_library('rt', required: false) | 
 |         if not cc.has_function('clock_gettime', prefix : '#include <time.h>', args : test_args, dependencies : rt_dependency) | 
 |             error('clock_gettime not found') | 
 |         endif | 
 |         cdata.set('HAVE_CLOCK_GETTIME', 1) | 
 |     endif | 
 | endif | 
 |  | 
 | # check for fseeko on android. It is not always available if _FILE_OFFSET_BITS is defined to 64 | 
 | have_fseeko = true | 
 | if host_machine.system() == 'android' | 
 |     if not cc.has_function('fseeko', prefix : '#include <stdio.h>', args : test_args) | 
 |         if cc.has_function('fseeko', prefix : '#include <stdio.h>', args : test_args + ['-U_FILE_OFFSET_BITS']) | 
 |             warning('Files larger than 2 gigabytes might not be supported in the dav1d CLI tool.') | 
 |             add_project_arguments('-U_FILE_OFFSET_BITS', language: 'c') | 
 |         elif get_option('enable_tools') | 
 |             error('dav1d CLI tool needs fseeko()') | 
 |         else | 
 |             have_fseeko = false | 
 |         endif | 
 |     endif | 
 | endif | 
 |  | 
 | libdl_dependency = [] | 
 | if host_machine.system() == 'linux' | 
 |     libdl_dependency = cc.find_library('dl', required : false) | 
 |     if cc.has_function('dlsym', prefix : '#include <dlfcn.h>', args : test_args, dependencies : libdl_dependency) | 
 |         cdata.set('HAVE_DLSYM', 1) | 
 |     endif | 
 | endif | 
 |  | 
 | libm_dependency = cc.find_library('m', required: false) | 
 |  | 
 |  | 
 | # Header checks | 
 |  | 
 | stdatomic_dependencies = [] | 
 | if not cc.check_header('stdatomic.h') | 
 |     if cc.get_id() == 'msvc' | 
 |         # we have a custom replacement for MSVC | 
 |         stdatomic_dependencies += declare_dependency( | 
 |             include_directories : include_directories('include/compat/msvc'), | 
 |         ) | 
 |     elif cc.compiles('''int main() { int v = 0; return __atomic_fetch_add(&v, 1, __ATOMIC_SEQ_CST); }''', | 
 |                      name : 'GCC-style atomics', args : test_args) | 
 |         stdatomic_dependencies += declare_dependency( | 
 |             include_directories : include_directories('include/compat/gcc'), | 
 |         ) | 
 |     else | 
 |         error('Atomics not supported') | 
 |     endif | 
 | endif | 
 |  | 
 | if host_machine.cpu_family().startswith('wasm') | 
 |     # enable atomics + bulk-memory features | 
 |     stdatomic_dependencies += thread_dependency.partial_dependency(compile_args: true) | 
 | endif | 
 |  | 
 | if cc.check_header('unistd.h') | 
 |     cdata.set('HAVE_UNISTD_H', 1) | 
 | endif | 
 |  | 
 | if cc.check_header('io.h') | 
 |     cdata.set('HAVE_IO_H', 1) | 
 | endif | 
 |  | 
 | if cc.check_header('pthread_np.h') | 
 |     cdata.set('HAVE_PTHREAD_NP_H', 1) | 
 |     test_args += '-DHAVE_PTHREAD_NP_H' | 
 | endif | 
 |  | 
 |  | 
 | # Function checks | 
 |  | 
 | if not cc.has_function('getopt_long', prefix : '#include <getopt.h>', args : test_args) | 
 |     getopt_dependency = declare_dependency( | 
 |         sources: files('tools/compat/getopt.c'), | 
 |         include_directories : include_directories('include/compat'), | 
 |     ) | 
 | else | 
 |     getopt_dependency = [] | 
 | endif | 
 |  | 
 | if cc.has_function('_aligned_malloc', prefix : '#include <malloc.h>', args : test_args) | 
 |     cdata.set('HAVE_ALIGNED_MALLOC', 1) | 
 | elif cc.has_function('posix_memalign', prefix : '#include <stdlib.h>', args : test_args) | 
 |     cdata.set('HAVE_POSIX_MEMALIGN', 1) | 
 | elif cc.has_function('memalign', prefix : '#include <malloc.h>', args : test_args) | 
 |     cdata.set('HAVE_MEMALIGN', 1) | 
 | endif | 
 |  | 
 | if (host_machine.cpu_family() == 'aarch64' or | 
 |     host_machine.cpu_family().startswith('arm') or | 
 |     host_machine.cpu() == 'ppc64le') | 
 |     if cc.has_function('getauxval', prefix : '#include <sys/auxv.h>', args : test_args) | 
 |         cdata.set('HAVE_GETAUXVAL', 1) | 
 |     endif | 
 |     if cc.has_function('elf_aux_info', prefix : '#include <sys/auxv.h>', args : test_args) | 
 |         cdata.set('HAVE_ELF_AUX_INFO', 1) | 
 |     endif | 
 | endif | 
 |  | 
 | pthread_np_prefix = ''' | 
 | #include <pthread.h> | 
 | #ifdef HAVE_PTHREAD_NP_H | 
 | #include <pthread_np.h> | 
 | #endif | 
 | ''' | 
 | if cc.has_function('pthread_getaffinity_np', prefix : pthread_np_prefix, args : test_args, dependencies : thread_dependency) | 
 |     cdata.set('HAVE_PTHREAD_GETAFFINITY_NP', 1) | 
 | endif | 
 | if cc.has_function('pthread_setaffinity_np', prefix : pthread_np_prefix, args : test_args, dependencies : thread_dependency) | 
 |     cdata.set('HAVE_PTHREAD_SETAFFINITY_NP', 1) | 
 | endif | 
 |  | 
 | if cc.compiles('int x = _Generic(0, default: 0);', name: '_Generic', args: test_args) | 
 |     cdata.set('HAVE_C11_GENERIC', 1) | 
 | endif | 
 |  | 
 | # Compiler flag tests | 
 |  | 
 | if cc.has_argument('-fvisibility=hidden') | 
 |     add_project_arguments('-fvisibility=hidden', language: 'c') | 
 | else | 
 |     warning('Compiler does not support -fvisibility=hidden, all symbols will be public!') | 
 | endif | 
 |  | 
 | # Compiler flags that should be set | 
 | # But when the compiler does not supports them | 
 | # it is not an error and silently tolerated | 
 | if cc.get_argument_syntax() != 'msvc' | 
 |     optional_arguments += [ | 
 |       '-Wundef', | 
 |       '-Werror=vla', | 
 |       '-Wno-maybe-uninitialized', | 
 |       '-Wno-missing-field-initializers', | 
 |       '-Wno-unused-parameter', | 
 |       '-Wstrict-prototypes', | 
 |       '-Werror=missing-prototypes', | 
 |       '-Wshorten-64-to-32', | 
 |     ] | 
 |     if host_machine.cpu_family() == 'x86' | 
 |         optional_arguments += [ | 
 |           '-msse2', | 
 |           '-mfpmath=sse', | 
 |         ] | 
 |     endif | 
 | else | 
 |     optional_arguments += [ | 
 |       '-wd4028', # parameter different from declaration | 
 |       '-wd4090', # broken with arrays of pointers | 
 |       '-wd4996'  # use of POSIX functions | 
 |     ] | 
 | endif | 
 |  | 
 | if (get_option('buildtype') != 'debug' and get_option('buildtype') != 'plain') | 
 |     optional_arguments += '-fomit-frame-pointer' | 
 |     optional_arguments += '-ffast-math' | 
 | endif | 
 |  | 
 | if (host_machine.system() in ['darwin', 'ios', 'tvos'] and cc.get_id() == 'clang' and | 
 |     cc.version().startswith('11')) | 
 |     # Workaround for Xcode 11 -fstack-check bug, see #301 | 
 |     optional_arguments += '-fno-stack-check' | 
 | endif | 
 |  | 
 | add_project_arguments(cc.get_supported_arguments(optional_arguments), language : 'c') | 
 | add_project_link_arguments(cc.get_supported_link_arguments(optional_link_arguments), language : 'c') | 
 |  | 
 | # libFuzzer related things | 
 | fuzzing_engine = get_option('fuzzing_engine') | 
 | if fuzzing_engine == 'libfuzzer' | 
 |     if not cc.has_argument('-fsanitize=fuzzer') | 
 |         error('fuzzing_engine libfuzzer requires "-fsanitize=fuzzer"') | 
 |     endif | 
 |     fuzzer_args = ['-fsanitize=fuzzer-no-link', '-fsanitize=fuzzer'] | 
 |     add_project_arguments(cc.first_supported_argument(fuzzer_args), language : 'c') | 
 | endif | 
 |  | 
 | cdata.set10('ENDIANNESS_BIG', host_machine.endian() == 'big') | 
 |  | 
 | if host_machine.cpu_family().startswith('x86') | 
 |     if get_option('stack_alignment') > 0 | 
 |         stack_alignment = get_option('stack_alignment') | 
 |     elif host_machine.cpu_family() == 'x86_64' or host_machine.system() in ['linux', 'darwin', 'ios', 'tvos'] | 
 |         stack_alignment = 16 | 
 |     else | 
 |         stack_alignment = 4 | 
 |     endif | 
 |     cdata_asm.set('STACK_ALIGNMENT', stack_alignment) | 
 | endif | 
 |  | 
 | cdata.set10('ARCH_AARCH64', host_machine.cpu_family() == 'aarch64' or host_machine.cpu() == 'arm64') | 
 | cdata.set10('ARCH_ARM',     host_machine.cpu_family().startswith('arm') and host_machine.cpu() != 'arm64') | 
 | if (is_asm_enabled and | 
 |     (host_machine.cpu_family() == 'aarch64' or | 
 |      host_machine.cpu_family().startswith('arm'))) | 
 |  | 
 |    as_func_code = '''__asm__ ( | 
 | ".func meson_test" | 
 | ".endfunc" | 
 | ); | 
 | ''' | 
 |     have_as_func = cc.compiles(as_func_code) | 
 |     cdata.set10('HAVE_AS_FUNC', have_as_func) | 
 |  | 
 |     # fedora package build infrastructure uses a gcc specs file to enable | 
 |     # '-fPIE' by default. The chosen way only adds '-fPIE' to the C compiler | 
 |     # with integrated preprocessor. It is not added to the standalone | 
 |     # preprocessor or the preprocessing stage of '.S' files. So we have to | 
 |     # compile code to check if we have to define PIC for the arm asm to | 
 |     # avoid absolute relocations when building for example checkasm. | 
 |     check_pic_code = ''' | 
 | #if defined(PIC) | 
 | #error "PIC already defined" | 
 | #elif !(defined(__PIC__) || defined(__pic__)) | 
 | #error "no pic" | 
 | #endif | 
 | ''' | 
 |     if cc.compiles(check_pic_code) | 
 |         cdata.set('PIC', '3') | 
 |     endif | 
 | endif | 
 |  | 
 | cdata.set10('ARCH_X86', host_machine.cpu_family().startswith('x86')) | 
 | cdata.set10('ARCH_X86_64', host_machine.cpu_family() == 'x86_64') | 
 | cdata.set10('ARCH_X86_32', host_machine.cpu_family() == 'x86') | 
 |  | 
 | if host_machine.cpu_family().startswith('x86') | 
 |     cdata_asm.set('private_prefix', 'dav1d') | 
 |     cdata_asm.set10('ARCH_X86_64', host_machine.cpu_family() == 'x86_64') | 
 |     cdata_asm.set10('ARCH_X86_32', host_machine.cpu_family() == 'x86') | 
 |     cdata_asm.set10('PIC', true) | 
 |  | 
 |     # Convert SSE asm into (128-bit) AVX when compiler flags are set to use AVX instructions | 
 |     cdata_asm.set10('FORCE_VEX_ENCODING', cc.get_define('__AVX__').strip() != '') | 
 | endif | 
 |  | 
 | cdata.set10('ARCH_PPC64LE', host_machine.cpu() == 'ppc64le') | 
 |  | 
 | # meson's cc.symbols_have_underscore_prefix() is unfortunately unrelieably | 
 | # when additional flags like '-fprofile-instr-generate' are passed via CFLAGS | 
 | # see following meson issue https://github.com/mesonbuild/meson/issues/5482 | 
 | if (host_machine.system() in ['darwin', 'ios', 'tvos'] or | 
 |    (host_machine.system() == 'windows' and host_machine.cpu_family() == 'x86')) | 
 |     cdata.set10('PREFIX', true) | 
 |     cdata_asm.set10('PREFIX', true) | 
 | endif | 
 |  | 
 | # | 
 | # ASM specific stuff | 
 | # | 
 | if is_asm_enabled and host_machine.cpu_family().startswith('x86') | 
 |  | 
 |     # NASM compiler support | 
 |  | 
 |     nasm = find_program('nasm') | 
 |  | 
 |     # check NASM version | 
 |     if nasm.found() | 
 |         nasm_r = run_command(nasm, '-v', check: true) | 
 |  | 
 |         out = nasm_r.stdout().strip().split() | 
 |         if out[1].to_lower() == 'version' | 
 |             if out[2].version_compare('<2.14') | 
 |                 error('nasm 2.14 or later is required, found nasm @0@'.format(out[2])) | 
 |             endif | 
 |         else | 
 |             error('unexpected nasm version string: @0@'.format(nasm_r.stdout())) | 
 |         endif | 
 |     endif | 
 |  | 
 |     # Generate config.asm | 
 |     config_asm_target = configure_file(output: 'config.asm', output_format: 'nasm', configuration: cdata_asm) | 
 |  | 
 |     if host_machine.system() == 'windows' | 
 |         nasm_format = 'win' | 
 |     elif host_machine.system() in ['darwin', 'ios', 'tvos'] | 
 |         nasm_format = 'macho' | 
 |     else | 
 |         nasm_format = 'elf' | 
 |     endif | 
 |     if host_machine.cpu_family() == 'x86_64' | 
 |         nasm_format += '64' | 
 |     else | 
 |         nasm_format += '32' | 
 |     endif | 
 |  | 
 |     nasm_gen = generator(nasm, | 
 |         output: '@BASENAME@.obj', | 
 |         depfile: '@BASENAME@.obj.ndep', | 
 |         arguments: [ | 
 |             '-f', nasm_format, | 
 |             '-I', '@0@/src/'.format(dav1d_src_root), | 
 |             '-I', '@0@/'.format(meson.current_build_dir()), | 
 |             '-MQ', '@OUTPUT@', '-MF', '@DEPFILE@', | 
 |             '@EXTRA_ARGS@', | 
 |             '@INPUT@', | 
 |             '-o', '@OUTPUT@' | 
 |         ]) | 
 | endif | 
 |  | 
 | use_gaspp = false | 
 | if (is_asm_enabled and | 
 |     (host_machine.cpu_family() == 'aarch64' or | 
 |      host_machine.cpu_family().startswith('arm')) and | 
 |     cc.get_argument_syntax() == 'msvc' and | 
 |     (cc.get_id() != 'clang-cl' or meson.version().version_compare('<0.58.0'))) | 
 |     gaspp = find_program('gas-preprocessor.pl') | 
 |     use_gaspp = true | 
 |     gaspp_gen = generator(gaspp, | 
 |         output: '@BASENAME@.obj', | 
 |         arguments: [ | 
 |             '-as-type', 'armasm', | 
 |             '-arch', host_machine.cpu_family(), | 
 |             '--', | 
 |             host_machine.cpu_family() == 'aarch64' ? 'armasm64' : 'armasm', | 
 |             '-nologo', | 
 |             '-I@0@'.format(dav1d_src_root), | 
 |             '-I@0@/'.format(meson.current_build_dir()), | 
 |             '@INPUT@', | 
 |             '-c', | 
 |             '-o', '@OUTPUT@' | 
 |         ]) | 
 | endif | 
 |  | 
 | # Generate config.h | 
 | config_h_target = configure_file(output: 'config.h', configuration: cdata) | 
 |  | 
 |  | 
 |  | 
 | # | 
 | # Include subdir meson.build files | 
 | # The order is important! | 
 |  | 
 | subdir('include') | 
 |  | 
 | subdir('doc') | 
 |  | 
 | subdir('src') | 
 |  | 
 | subdir('tools') | 
 |  | 
 | subdir('examples') | 
 |  | 
 | subdir('tests') |