mirror of
https://github.com/libfuse/libfuse.git
synced 2026-07-07 14:47:41 +08:00
d454f681fd
It was very hard to see until now what was actually enabled/disabled. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
406 lines
13 KiB
Meson
406 lines
13 KiB
Meson
project('libfuse3', ['c'],
|
|
version: '3.19.0-rc0',
|
|
meson_version: '>= 0.60.0',
|
|
default_options: [
|
|
'buildtype=debugoptimized',
|
|
'c_std=gnu11',
|
|
'cpp_std=c++20',
|
|
'warning_level=2',
|
|
])
|
|
|
|
# Would be better to create the version string
|
|
# from integers, i.e. concatenating strings instead
|
|
# of splitting a string, but 'project' needs to be
|
|
# the first meson.build keyword...
|
|
|
|
# split version into base and rc
|
|
version_parts = meson.project_version().split('-')
|
|
base_version = version_parts[0]
|
|
|
|
version_list = base_version.split('.')
|
|
FUSE_MAJOR_VERSION = version_list[0]
|
|
FUSE_MINOR_VERSION = version_list[1]
|
|
FUSE_HOTFIX_VERSION = version_list[2]
|
|
FUSE_RC_VERSION = version_parts.length() > 1 ? version_parts[1] : ''
|
|
|
|
platform = host_machine.system()
|
|
if platform == 'darwin'
|
|
error('libfuse does not support OS-X.\n' +
|
|
'Take a look at http://osxfuse.github.io/ or the more recent\n' +
|
|
'https://www.fuse-t.org/ instead')
|
|
elif platform == 'cygwin' or platform == 'windows'
|
|
error('libfuse does not support Windows.\n' +
|
|
'Take a look at http://www.secfs.net/winfsp/ instead')
|
|
endif
|
|
|
|
cc = meson.get_compiler('c')
|
|
|
|
#
|
|
# Feature detection, the resulting config file is installed
|
|
# with the package.
|
|
# Note: Symbols need to be care fully named, to avoid conflicts
|
|
# with applications linking to libfuse and including
|
|
# this config.
|
|
#
|
|
public_cfg = configuration_data()
|
|
|
|
public_cfg.set('FUSE_MAJOR_VERSION', FUSE_MAJOR_VERSION)
|
|
public_cfg.set('FUSE_MINOR_VERSION', FUSE_MINOR_VERSION)
|
|
public_cfg.set('FUSE_HOTFIX_VERSION', FUSE_HOTFIX_VERSION)
|
|
public_cfg.set('FUSE_RC_VERSION', FUSE_RC_VERSION)
|
|
|
|
# Default includes when checking for presence of functions and
|
|
# struct members
|
|
include_default = '''
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h> /* For pthread_setname_np */
|
|
'''
|
|
args_default = [ '-D_GNU_SOURCE' ]
|
|
|
|
#
|
|
# Feature detection, only available at libfuse compilation time,
|
|
# but not for application linking to libfuse.
|
|
#
|
|
private_cfg = configuration_data()
|
|
private_cfg.set_quoted('PACKAGE_VERSION', meson.project_version())
|
|
service_socket_dir = get_option('service-socket-dir')
|
|
service_socket_perms = get_option('service-socket-perms')
|
|
if service_socket_dir == ''
|
|
service_socket_dir = '/run/filesystems'
|
|
endif
|
|
if service_socket_perms == ''
|
|
service_socket_perms = '0220'
|
|
endif
|
|
private_cfg.set('FUSE_SERVICE_SOCKET_DIR_RAW', service_socket_dir)
|
|
private_cfg.set_quoted('FUSE_SERVICE_SOCKET_DIR', service_socket_dir)
|
|
private_cfg.set('FUSE_SERVICE_SOCKET_PERMS', service_socket_perms)
|
|
|
|
# Test for presence of some functions
|
|
test_funcs = [ 'fork', 'fstatat', 'openat', 'readlinkat', 'pipe2',
|
|
'splice', 'vmsplice', 'posix_fallocate', 'fdatasync',
|
|
'utimensat', 'copy_file_range', 'fallocate', 'fspacectl',
|
|
'faccessat' ]
|
|
foreach func : test_funcs
|
|
private_cfg.set('HAVE_' + func.to_upper(),
|
|
cc.has_function(func, prefix: include_default, args: args_default))
|
|
endforeach
|
|
|
|
# Special case checks that need custom code
|
|
special_funcs = {
|
|
'pthread_setname_np': '''
|
|
#include <pthread.h>
|
|
int main(void) {
|
|
pthread_t thread = pthread_self();
|
|
pthread_setname_np(thread, "test");
|
|
return 0;
|
|
}
|
|
''',
|
|
'close_range': '''
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#ifdef linux
|
|
#include <linux/close_range.h>
|
|
#endif
|
|
int main(void) {
|
|
unsigned int flags = CLOSE_RANGE_UNSHARE;
|
|
return close_range(3, ~0U, flags);
|
|
}
|
|
''',
|
|
'listmount': '''
|
|
#include <syscall.h>
|
|
#include <linux/mount.h>
|
|
#include <unistd.h>
|
|
#include <stdint.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
struct mnt_id_req req = {
|
|
.size = sizeof(struct mnt_id_req),
|
|
.mnt_id = LSMT_ROOT,
|
|
};
|
|
uint64_t mnt_ids[1];
|
|
|
|
int n = syscall(SYS_listmount, &req, &mnt_ids, 1, 0);
|
|
if (n == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
''',
|
|
'new_mount_api': '''
|
|
#define _GNU_SOURCE
|
|
#include <sys/mount.h>
|
|
#include <linux/mount.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
|
|
int main(void) {
|
|
int fsfd = fsopen("fuse", FSOPEN_CLOEXEC);
|
|
int res = fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "test", 0);
|
|
int mntfd = fsmount(fsfd, FSMOUNT_CLOEXEC, 0);
|
|
res = move_mount(mntfd, "", AT_FDCWD, "/mnt", MOVE_MOUNT_F_EMPTY_PATH);
|
|
return 0;
|
|
}
|
|
''',
|
|
'systemd_headers': '''
|
|
#include <systemd/sd-daemon.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
return SD_LISTEN_FDS_START;
|
|
}
|
|
''',
|
|
}
|
|
|
|
foreach name, code : special_funcs
|
|
private_cfg.set('HAVE_' + name.to_upper(),
|
|
cc.links(code, args: args_default,
|
|
name: name + ' check'))
|
|
endforeach
|
|
|
|
# Headers checks
|
|
test_headers = [ 'sys/xattr.h', 'linux/limits.h' ]
|
|
foreach header : test_headers
|
|
private_cfg.set('HAVE_' + header.underscorify().to_upper(),
|
|
cc.has_header(header))
|
|
endforeach
|
|
|
|
# Regular function checks
|
|
private_cfg.set('HAVE_SETXATTR',
|
|
cc.has_function('setxattr', prefix: '#include <sys/xattr.h>'))
|
|
private_cfg.set('HAVE_ICONV',
|
|
cc.has_function('iconv', prefix: '#include <iconv.h>'))
|
|
private_cfg.set('HAVE_BACKTRACE',
|
|
cc.has_function('backtrace', prefix: '#include <execinfo.h>'))
|
|
private_cfg.set('HAVE_STATX',
|
|
cc.has_function('statx', prefix : '#define _GNU_SOURCE\n#include <sys/stat.h>'))
|
|
|
|
# Struct member checks
|
|
private_cfg.set('HAVE_STRUCT_STAT_ST_ATIM',
|
|
cc.has_member('struct stat', 'st_atim',
|
|
prefix: include_default + '#include <sys/stat.h>',
|
|
args: args_default))
|
|
private_cfg.set('HAVE_STRUCT_STAT_ST_ATIMESPEC',
|
|
cc.has_member('struct stat', 'st_atimespec',
|
|
prefix: include_default + '#include <sys/stat.h>',
|
|
args: args_default))
|
|
|
|
private_cfg.set('USDT_ENABLED', get_option('enable-usdt'))
|
|
|
|
# Check for liburing with SQE128 support
|
|
code = '''
|
|
#include <liburing.h>
|
|
#include <stdio.h>
|
|
int main(void) {
|
|
struct io_uring ring;
|
|
int ret = io_uring_queue_init(1, &ring, 0);
|
|
#ifndef IORING_SETUP_SQE128
|
|
#error "No SQE128 support"
|
|
#endif
|
|
return ret;
|
|
}'''
|
|
|
|
liburing = dependency('liburing', required: false)
|
|
libnuma = dependency('numa', required: false)
|
|
|
|
if get_option('enable-io-uring') and liburing.found() and libnuma.found()
|
|
if cc.links(code,
|
|
name: 'liburing linking and SQE128 support',
|
|
dependencies: [liburing])
|
|
private_cfg.set('HAVE_URING', true)
|
|
endif
|
|
endif
|
|
|
|
# Check for systemd support
|
|
systemd_system_unit_dir = get_option('systemd-system-unit-dir')
|
|
if systemd_system_unit_dir == ''
|
|
systemd = dependency('systemd', required: false)
|
|
if systemd.found()
|
|
systemd_system_unit_dir = systemd.get_variable(pkgconfig: 'systemd_system_unit_dir')
|
|
endif
|
|
endif
|
|
|
|
if systemd_system_unit_dir == '' or private_cfg.get('HAVE_SYSTEMD_HEADERS', false) == false
|
|
if systemd_system_unit_dir == ''
|
|
warning('systemd service support will not be built: systemd unit directory not found')
|
|
elif private_cfg.get('HAVE_SYSTEMD_HEADERS', false) == false
|
|
warning('systemd service support will not be built: systemd headers (libsystemd-dev) not found')
|
|
else
|
|
warning('systemd service support will not be built')
|
|
endif
|
|
else
|
|
private_cfg.set_quoted('SYSTEMD_SYSTEM_UNIT_DIR', systemd_system_unit_dir)
|
|
private_cfg.set('HAVE_SYSTEMD', true)
|
|
private_cfg.set('HAVE_SERVICEMOUNT', true)
|
|
endif
|
|
|
|
#
|
|
# Compiler configuration
|
|
#
|
|
add_project_arguments('-D_REENTRANT', '-DHAVE_LIBFUSE_PRIVATE_CONFIG_H', '-Wno-sign-compare', '-D_FILE_OFFSET_BITS=64',
|
|
'-Wstrict-prototypes', '-Wmissing-declarations', '-Wwrite-strings',
|
|
'-fno-strict-aliasing', language: 'c')
|
|
add_project_arguments('-D_REENTRANT', '-DHAVE_LIBFUSE_PRIVATE_CONFIG_H', '-D_GNU_SOURCE', '-D_FILE_OFFSET_BITS=64',
|
|
'-Wno-sign-compare', '-Wmissing-declarations',
|
|
'-Wwrite-strings', '-fno-strict-aliasing', language: 'cpp')
|
|
|
|
# Some (stupid) GCC versions warn about unused return values even when they are
|
|
# casted to void. This makes -Wunused-result pretty useless, since there is no
|
|
# way to suppress the warning when we really *want* to ignore the value.
|
|
code = '''
|
|
__attribute__((warn_unused_result)) int get_4() {
|
|
return 4;
|
|
}
|
|
int main(void) {
|
|
(void) get_4();
|
|
return 0;
|
|
}'''
|
|
if not cc.compiles(code, args: [ '-O0', '-Werror=unused-result' ])
|
|
message('Compiler warns about unused result even when casting to void')
|
|
add_project_arguments('-Wno-unused-result', language: 'c')
|
|
endif
|
|
|
|
# It is hard to detect if the libc supports versioned symbols. Only gnu-libc
|
|
# seems to provide that, but then glibc is the main target for libfuse, so
|
|
# enable it by default
|
|
versioned_symbols = 1
|
|
|
|
# This is an attempt to detect if another libc is used.
|
|
code = '''
|
|
int main(void) {
|
|
#if (defined(__UCLIBC__) || defined(__APPLE__))
|
|
#error /* libc does not have versioned symbols */
|
|
#endif
|
|
return 0;
|
|
}'''
|
|
if not cc.compiles(code, args: [ '-O0' ])
|
|
versioned_symbols = 0
|
|
endif
|
|
|
|
# The detection can be overridden, which is useful for other (above unhandled)
|
|
# libcs and also especially useful for testing
|
|
if get_option('disable-libc-symbol-version')
|
|
versioned_symbols = 0
|
|
endif
|
|
|
|
if versioned_symbols == 1
|
|
message('Enabling versioned libc symbols')
|
|
public_cfg.set('LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS', 1)
|
|
|
|
# gcc-10 and newer support the symver attribute which we need to use if we
|
|
# want to support LTO
|
|
# recent clang and gcc both support __has_attribute (and if they are too old
|
|
# to have __has_attribute, then they are too old to support symver)
|
|
# other compilers might not have __has_attribute, but in those cases
|
|
# it is safe for this check to fail and for us to fallback to the old _asm_
|
|
# method for symver. Anyway the attributes not supported by __has_attribute()
|
|
# unfortunately return true giving a false positive. So let's try to build
|
|
# using __attribute__ ((symver )) and see the result.
|
|
code = '''
|
|
__attribute__ ((symver ("test@TEST")))
|
|
void foo(void) {
|
|
}
|
|
|
|
int main(void) {
|
|
return 0;
|
|
}'''
|
|
if cc.compiles(code, args: [ '-O0', '-c', '-Werror'])
|
|
message('Compiler supports symver attribute')
|
|
add_project_arguments('-DHAVE_SYMVER_ATTRIBUTE', language: 'c')
|
|
else
|
|
message('Compiler does not support symver attribute')
|
|
endif
|
|
else
|
|
message('Disabling versioned libc symbols')
|
|
endif
|
|
|
|
# Older versions of musl libc don't unescape entries in /etc/mtab
|
|
# Try to detect this behaviour, and work around, if necessary.
|
|
detect_getmntent_needs_unescape = '''
|
|
#define _GNU_SOURCE
|
|
#include <mntent.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#define dir_space_tab "dir\\040space\\011tab"
|
|
|
|
int main()
|
|
{
|
|
const char *fake_mtab = "name " dir_space_tab " type opts 0 0\n";
|
|
FILE *f = fmemopen((void *)fake_mtab, strlen(fake_mtab) + 1, "r");
|
|
struct mntent *entp = getmntent(f);
|
|
fclose(f);
|
|
if(NULL == entp)
|
|
exit(EXIT_FAILURE);
|
|
if (0 == strcmp(entp->mnt_dir, dir_space_tab))
|
|
printf("needs escaping\n");
|
|
else
|
|
printf("no need to escape\n");
|
|
}
|
|
'''
|
|
|
|
if not meson.is_cross_build()
|
|
result = cc.run(detect_getmntent_needs_unescape)
|
|
if result.compiled() and result.returncode() == 0 and result.stdout().strip() == 'needs escaping'
|
|
message('getmntent does not unescape')
|
|
add_project_arguments('-DGETMNTENT_NEEDS_UNESCAPING', language: 'c')
|
|
endif
|
|
endif
|
|
|
|
# Write private test results into fuse_config.h (stored in build directory)
|
|
configure_file(output: 'fuse_config.h', configuration : private_cfg)
|
|
|
|
# Write the test results, installed with the package,
|
|
# symbols need to be properly prefixed to avoid
|
|
# symbol (define) conflicts
|
|
configure_file(output: 'libfuse_config.h',
|
|
configuration : public_cfg,
|
|
install: true, install_dir: join_paths(get_option('includedir'), 'fuse3'))
|
|
|
|
# '.' will refer to current build directory, which contains config.h
|
|
include_dirs = include_directories('include', 'lib', '.')
|
|
|
|
# Common dependencies
|
|
thread_dep = dependency('threads')
|
|
|
|
#
|
|
# Read build files from sub-directories
|
|
#
|
|
subdirs = [ 'lib', 'include']
|
|
if get_option('utils') and not platform.endswith('bsd') and platform != 'dragonfly'
|
|
subdirs += [ 'util', 'doc' ]
|
|
endif
|
|
|
|
if get_option('examples')
|
|
subdirs += 'example'
|
|
endif
|
|
|
|
if get_option('tests')
|
|
subdirs += 'test'
|
|
endif
|
|
|
|
foreach n : subdirs
|
|
subdir(n)
|
|
endforeach
|
|
|
|
#
|
|
# Configuration summary
|
|
#
|
|
summary({
|
|
'Examples': get_option('examples'),
|
|
'Tests': get_option('tests'),
|
|
'Utils': get_option('utils'),
|
|
}, section: 'Build Options')
|
|
|
|
summary({
|
|
'io_uring support': private_cfg.get('HAVE_URING', false),
|
|
'USDT tracing': private_cfg.get('USDT_ENABLED', false),
|
|
'systemd service support': private_cfg.get('HAVE_SYSTEMD', false),
|
|
'systemd headers': private_cfg.get('HAVE_SYSTEMD_HEADERS', false),
|
|
'systemd unit directory': systemd_system_unit_dir != '' ? systemd_system_unit_dir : '(not found)',
|
|
}, section: 'Features')
|