1project('libfuse3', ['c'], version: '3.16.1', 2 meson_version: '>= 0.51', 3 default_options: [ 4 'buildtype=debugoptimized', 5 'cpp_std=c++11', 6 'warning_level=2', 7 ]) 8 9 10platform = host_machine.system() 11if platform == 'darwin' 12 error('libfuse does not support OS-X.\n' + 13 'Take a look at http://osxfuse.github.io/ instead') 14elif platform == 'cygwin' or platform == 'windows' 15 error('libfuse does not support Windows.\n' + 16 'Take a look at http://www.secfs.net/winfsp/ instead') 17endif 18 19cc = meson.get_compiler('c') 20 21# 22# Feature detection, only available at libfuse compilation time, 23# but not for application linking to libfuse. 24# 25private_cfg = configuration_data() 26 27# 28# Feature detection, the resulting config file is installed 29# with the package. 30# Note: Symbols need to be care fully named, to avoid conflicts 31# with applications linking to libfuse and including 32# this config. 33# 34public_cfg = configuration_data() 35 36# Default includes when checking for presence of functions and 37# struct members 38include_default = ''' 39#include <stdio.h> 40#include <stdlib.h> 41#include <stddef.h> 42#include <unistd.h> 43#include <sys/types.h> 44#include <sys/stat.h> 45#include <fcntl.h> 46''' 47args_default = [ '-D_GNU_SOURCE' ] 48 49private_cfg.set_quoted('PACKAGE_VERSION', meson.project_version()) 50 51# Test for presence of some functions 52test_funcs = [ 'fork', 'fstatat', 'openat', 'readlinkat', 'pipe2', 53 'splice', 'vmsplice', 'posix_fallocate', 'fdatasync', 54 'utimensat', 'copy_file_range', 'fallocate' ] 55foreach func : test_funcs 56 private_cfg.set('HAVE_' + func.to_upper(), 57 cc.has_function(func, prefix: include_default, args: args_default)) 58endforeach 59private_cfg.set('HAVE_SETXATTR', 60 cc.has_function('setxattr', prefix: '#include <sys/xattr.h>')) 61private_cfg.set('HAVE_ICONV', 62 cc.has_function('iconv', prefix: '#include <iconv.h>')) 63 64# Test if structs have specific member 65private_cfg.set('HAVE_STRUCT_STAT_ST_ATIM', 66 cc.has_member('struct stat', 'st_atim', 67 prefix: include_default, 68 args: args_default)) 69private_cfg.set('HAVE_STRUCT_STAT_ST_ATIMESPEC', 70 cc.has_member('struct stat', 'st_atimespec', 71 prefix: include_default, 72 args: args_default)) 73 74# 75# Compiler configuration 76# 77add_project_arguments('-D_REENTRANT', '-DHAVE_LIBFUSE_PRIVATE_CONFIG_H', '-Wno-sign-compare', '-D_FILE_OFFSET_BITS=64', 78 '-Wstrict-prototypes', '-Wmissing-declarations', '-Wwrite-strings', 79 '-fno-strict-aliasing', language: 'c') 80add_project_arguments('-D_REENTRANT', '-DHAVE_LIBFUSE_PRIVATE_CONFIG_H', '-D_GNU_SOURCE', '-D_FILE_OFFSET_BITS=64', 81 '-Wno-sign-compare', '-Wmissing-declarations', 82 '-Wwrite-strings', '-fno-strict-aliasing', language: 'cpp') 83 84# Some (stupid) GCC versions warn about unused return values even when they are 85# casted to void. This makes -Wunused-result pretty useless, since there is no 86# way to suppress the warning when we really *want* to ignore the value. 87code = ''' 88__attribute__((warn_unused_result)) int get_4() { 89 return 4; 90} 91int main(void) { 92 (void) get_4(); 93 return 0; 94}''' 95if not cc.compiles(code, args: [ '-O0', '-Werror=unused-result' ]) 96 message('Compiler warns about unused result even when casting to void') 97 add_project_arguments('-Wno-unused-result', language: 'c') 98endif 99 100# It is hard to detect if the libc supports versioned symbols. Only gnu-libc 101# seems to provide that, but then glibc is the main target for libfuse, so 102# enable it by default 103versioned_symbols = 1 104 105# This is an attempt to detect if another libc is used. 106code = ''' 107int main(void) { 108#if (defined(__UCLIBC__) || defined(__APPLE__)) 109#error /* libc does not have versioned symbols */ 110#endif 111 return 0; 112}''' 113if not cc.compiles(code, args: [ '-O0' ]) 114 versioned_symbols = 0 115endif 116 117# The detection can be overridden, which is useful for other (above unhandled) 118# libcs and also especially useful for testing 119if get_option('disable-libc-symbol-version') 120 versioned_symbols = 0 121endif 122 123if versioned_symbols == 1 124 message('Enabling versioned libc symbols') 125 public_cfg.set('LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS', 1) 126 127 # gcc-10 and newer support the symver attribute which we need to use if we 128 # want to support LTO 129 # recent clang and gcc both support __has_attribute (and if they are too old 130 # to have __has_attribute, then they are too old to support symver) 131 # other compilers might not have __has_attribute, but in those cases 132 # it is safe for this check to fail and for us to fallback to the old _asm_ 133 # method for symver. Anyway the attributes not supported by __has_attribute() 134 # unfortunately return true giving a false positive. So let's try to build 135 # using __attribute__ ((symver )) and see the result. 136 code = ''' 137 __attribute__ ((symver ("test@TEST"))) 138 void foo(void) { 139 } 140 141 int main(void) { 142 return 0; 143 }''' 144 if cc.compiles(code, args: [ '-O0', '-c', '-Werror']) 145 message('Compiler supports symver attribute') 146 add_project_arguments('-DHAVE_SYMVER_ATTRIBUTE', language: 'c') 147 else 148 message('Compiler does not support symver attribute') 149 endif 150else 151 message('Disabling versioned libc symbols') 152endif 153 154# Older versions of musl libc don't unescape entries in /etc/mtab 155# Try to detect this behaviour, and work around, if necessary. 156detect_getmntent_needs_unescape = ''' 157#define _GNU_SOURCE 158#include <mntent.h> 159#include <stdio.h> 160#include <string.h> 161#include <stdlib.h> 162 163#define dir_space_tab "dir\\040space\\011tab" 164 165int main() 166{ 167 const char *fake_mtab = "name " dir_space_tab " type opts 0 0\n"; 168 FILE *f = fmemopen((void *)fake_mtab, strlen(fake_mtab) + 1, "r"); 169 struct mntent *entp = getmntent(f); 170 fclose(f); 171 if(NULL == entp) 172 exit(EXIT_FAILURE); 173 if (0 == strcmp(entp->mnt_dir, dir_space_tab)) 174 printf("needs escaping\n"); 175 else 176 printf("no need to escape\n"); 177} 178''' 179 180if not meson.is_cross_build() 181 result = cc.run(detect_getmntent_needs_unescape) 182 if result.compiled() and result.returncode() == 0 and result.stdout().strip() == 'needs escaping' 183 message('getmntent does not unescape') 184 add_project_arguments('-DGETMNTENT_NEEDS_UNESCAPING', language: 'c') 185 endif 186endif 187 188# Write private test results into fuse_config.h (stored in build directory) 189configure_file(output: 'fuse_config.h', configuration : private_cfg) 190 191# Write the test results, installed with the package, 192# symbols need to be properly prefixed to avoid 193# symbol (define) conflicts 194configure_file(output: 'libfuse_config.h', 195 configuration : public_cfg, 196 install: true, install_dir: join_paths(get_option('includedir'), 'fuse3')) 197 198# '.' will refer to current build directory, which contains config.h 199include_dirs = include_directories('include', 'lib', '.') 200 201# Common dependencies 202thread_dep = dependency('threads') 203 204# 205# Read build files from sub-directories 206# 207subdirs = [ 'lib', 'include'] 208if get_option('utils') and not platform.endswith('bsd') and platform != 'dragonfly' 209 subdirs += [ 'util', 'doc' ] 210endif 211 212if get_option('examples') 213 subdirs += 'example' 214endif 215 216if get_option('tests') 217 subdirs += 'test' 218endif 219 220foreach n : subdirs 221 subdir(n) 222endforeach 223 224