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