diff options
-rw-r--r-- | meson.build | 203 | ||||
-rw-r--r-- | meson_options.txt | 4 | ||||
-rw-r--r-- | src/ring.c | 16 | ||||
-rw-r--r-- | src/zix_config.h | 124 |
4 files changed, 156 insertions, 191 deletions
diff --git a/meson.build b/meson.build index 55e460f..545d759 100644 --- a/meson.build +++ b/meson.build @@ -45,9 +45,10 @@ endif # Platform Configuration # ########################## +# Determine system dependencies of the library +dependencies = [] thread_dep = dependency('threads', required: get_option('threads')) - -platform_c_args = [] +dependencies = [thread_dep] # Use versioned name everywhere to support parallel major version installations if host_machine.system() == 'windows' @@ -59,145 +60,119 @@ else soversion = meson.project_version().split('.')[0] endif -# Determine whether to use POSIX -no_posix = get_option('posix').disabled() or host_machine.system() == 'windows' -if no_posix - platform_c_args += ['-DZIX_NO_POSIX'] -elif host_machine.system() == 'darwin' - platform_c_args += [ +# Request POSIX and system APIs from standard headers if necessary +system_c_args = [] +if host_machine.system() == 'darwin' + system_c_args += [ '-D_DARWIN_C_SOURCE', ] elif host_machine.system() in ['gnu', 'linux'] - platform_c_args += [ + system_c_args += [ '-D_GNU_SOURCE', '-D_POSIX_C_SOURCE=200809L', '-D_XOPEN_SOURCE=600', ] elif host_machine.system() in ['dragonfly', 'freebsd', 'netbsd', 'openbsd'] - platform_c_args += [ + system_c_args += [ '-D_BSD_SOURCE', ] else - platform_c_args += [ + system_c_args += [ '-D_POSIX_C_SOURCE=200809L', '-D_XOPEN_SOURCE=600', ] endif -# Check for platform features with the build system -if get_option('checks') - clock_gettime_code = '''#include <time.h> -int main(void) { struct timespec t; return clock_gettime(CLOCK_MONOTONIC, &t); } -''' +# Build platform-specific configuration arguments +platform_c_args = [] +if get_option('checks').disabled() + # Generic build without platform-specific features + platform_c_args += ['-DZIX_NO_DEFAULT_CONFIG'] +elif get_option('checks').auto() + # Statically detect configuration from the build environment + platform_c_args += system_c_args +else + # Only use the features detected by the build system + platform_c_args += ['-DZIX_NO_DEFAULT_CONFIG'] + system_c_args - clonefile_code = '''#include <sys/attr.h> -#include <sys/clonefile.h> -int main(void) { return clonefile("/src", "/dst", 0); }''' + # Define HAVE_SOMETHING symbols for all detected features + template = '#include <@0@>\nint main(void) { @1@ }' - copy_file_range_code = '''#include <unistd.h> -int main(void) { return copy_file_range(0, NULL, 1, NULL, 0U, 0U); }''' + mac_checks = { + 'clonefile': + template.format( + 'sys/clonefile.h', + 'return clonefile("/src", "/dst", 0);'), + } - CreateSymbolicLink_code = '''#include <windows.h> -int main(void) { - return CreateSymbolicLink( - "l", "t", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); -}''' + posix_checks = { + 'clock_gettime': + template.format( + 'time.h', + 'struct timespec t; return clock_gettime(CLOCK_MONOTONIC, &t);'), - fileno_code = '''#include <stdio.h> -int main(void) { return fileno(stdin); }''' + 'copy_file_range': + template.format( + 'unistd.h', + 'return copy_file_range(0, NULL, 1, NULL, 0U, 0U);'), - flock_code = '''#include <sys/file.h> -int main(void) { return flock(0, 0); }''' + 'fileno': template.format('stdio.h', 'return fileno(stdin);'), + 'flock': template.format('sys/file.h', 'return flock(0, 0);'), - lstat_code = '''#include <sys/stat.h> -int main(void) { struct stat s; return lstat("/", &s); }''' + 'lstat': + template.format('sys/stat.h', 'struct stat s; return lstat("/", &s);'), - mlock_code = '''#include <sys/mman.h> -int main(void) { return mlock(0, 0); }''' + 'mlock': template.format('sys/mman.h', 'return mlock(0, 0);'), - pathconf_code = '''#include <unistd.h> -int main(void) { return pathconf("/", _PC_PATH_MAX) > 0L; }''' + 'pathconf': + template.format('unistd.h', 'return pathconf("/", _PC_PATH_MAX) > 0L;'), - posix_fadvise_code = '''#include <fcntl.h> -int main(void) { posix_fadvise(0, 0, 4096, POSIX_FADV_SEQUENTIAL); }''' + 'posix_fadvise': template.format( + 'fcntl.h', + 'posix_fadvise(0, 0, 4096, POSIX_FADV_SEQUENTIAL);'), - posix_memalign_code = '''#include <stdlib.h> -int main(void) { void* mem; posix_memalign(&mem, 8, 8); }''' + 'posix_memalign': + template.format('stdlib.h', 'void* mem; posix_memalign(&mem, 8, 8);'), - realpath_code = '''#include <stdlib.h> -int main(void) { return realpath("/", NULL) != NULL; }''' + 'realpath': + template.format('stdlib.h', 'return realpath("/", NULL) != NULL;'), + + 'sysconf': + template.format('unistd.h', 'return sysconf(_SC_PAGE_SIZE) > 0L;'), + } + + windows_checks = { + 'CreateSymbolicLink': + template.format( + 'windows.h', + 'return CreateSymbolicLink(' + + '"l", "t", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);'), + } + + if host_machine.system() == 'darwin' + checks = posix_checks + mac_checks + elif host_machine.system() == 'windows' + checks = windows_checks + else + checks = posix_checks - sem_timedwait_code = '''#include <semaphore.h> + if thread_dep.found() + if cc.links('''#include <semaphore.h> #include <time.h> -int main(void) { sem_t s; struct timespec t; return sem_timedwait(&s, &t); }''' - - sysconf_code = '''#include <unistd.h> -int main(void) { return sysconf(_SC_PAGE_SIZE) > 0L; }''' - - platform_c_args += [ - '-DZIX_NO_DEFAULT_CONFIG', - '-DHAVE_CLOCK_GETTIME=@0@'.format( - cc.links(clock_gettime_code, - args: platform_c_args, - name: 'clock_gettime').to_int()), - '-DHAVE_CLONEFILE=@0@'.format( - (host_machine.system() == 'darwin' and - cc.links(clonefile_code, - args: platform_c_args, - name: 'clonefile')).to_int()), - '-DHAVE_COPY_FILE_RANGE=@0@'.format( - (host_machine.system() not in ['darwin', 'windows'] and - cc.links(copy_file_range_code, - args: platform_c_args, - name: 'copy_file_range')).to_int()), - '-DHAVE_CREATESYMBOLICLINK=@0@'.format( - (host_machine.system() == 'windows' and - cc.links(CreateSymbolicLink_code, - args: platform_c_args, - name: 'CreateSymbolicLink')).to_int()), - '-DHAVE_FILENO=@0@'.format( - cc.links(fileno_code, - args: platform_c_args, - name: 'fileno').to_int()), - '-DHAVE_FLOCK=@0@'.format( - (host_machine.system() != 'windows' and - cc.links(flock_code, - args: platform_c_args, - name: 'flock')).to_int()), - '-DHAVE_MLOCK=@0@'.format( - cc.links(mlock_code, - args: platform_c_args, - name: 'mlock').to_int()), - '-DHAVE_PATHCONF=@0@'.format( - (host_machine.system() != 'windows' and - cc.links(pathconf_code, - args: platform_c_args, - name: 'pathconf')).to_int()), - '-DHAVE_POSIX_FADVISE=@0@'.format( - cc.links(posix_fadvise_code, - args: platform_c_args, - name: 'posix_fadvise').to_int()), - '-DHAVE_POSIX_MEMALIGN=@0@'.format( - cc.links(posix_memalign_code, - args: platform_c_args, - name: 'posix_memalign').to_int()), - '-DHAVE_REALPATH=@0@'.format( - (host_machine.system() != 'windows' and - cc.links(realpath_code, - args: platform_c_args, - name: 'realpath')).to_int()), - '-DHAVE_SEM_TIMEDWAIT=@0@'.format( - (host_machine.system() not in ['darwin', 'windows'] and - cc.links(sem_timedwait_code, - args: platform_c_args, - dependencies: [thread_dep], - name: 'sem_timedwait')).to_int()), - '-DHAVE_SYSCONF=@0@'.format( - (host_machine.system() != 'windows' and - cc.links(sysconf_code, - args: platform_c_args, - name: 'sysconf')).to_int()), - ] +int main(void) { sem_t s; struct timespec t; return sem_timedwait(&s, &t); }''', + args: system_c_args, + dependencies: thread_dep, + name: 'sem_timedwait') + platform_c_args += ['-DHAVE_SEM_TIMEDWAIT'] + endif + endif + endif + + foreach name, check_code : checks + if cc.links(check_code, args: system_c_args, name: name) + platform_c_args += ['-DHAVE_@0@'.format(name.to_upper())] + endif + endforeach endif ########### @@ -317,7 +292,7 @@ libzix = library( versioned_name, sources, c_args: c_suppressions + library_c_args, - dependencies: [thread_dep], + dependencies: dependencies, gnu_symbol_visibility: 'hidden', include_directories: include_dirs, install: true, @@ -340,7 +315,7 @@ pkg.generate( extra_cflags: extra_c_args, filebase: versioned_name, name: 'Zix', - requires: [thread_dep], + requires: dependencies, subdirs: [versioned_name], version: meson.project_version(), ) diff --git a/meson_options.txt b/meson_options.txt index 975eb3b..0912856 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,8 +1,8 @@ option('benchmarks', type: 'feature', value: 'auto', yield: true, description: 'Build benchmarks') -option('checks', type: 'boolean', value: true, yield: true, - description: 'Check for features with the build system') +option('checks', type: 'feature', value: 'enabled', yield: true, + description: 'Check for platform-specific features') option('docs', type: 'feature', value: 'auto', yield: true, description: 'Build documentation') @@ -9,10 +9,10 @@ #include "zix/allocator.h" #include "zix/status.h" -#if USE_MLOCK -# include <sys/mman.h> -#elif defined(_WIN32) +#if defined(_WIN32) # include <windows.h> +#elif USE_MLOCK +# include <sys/mman.h> #endif /* @@ -108,16 +108,16 @@ zix_ring_free(ZixRing* const ring) ZixStatus zix_ring_mlock(ZixRing* const ring) { -#if USE_MLOCK - return zix_errno_status_if(mlock(ring, sizeof(ZixRing)) + - mlock(ring->buf, ring->size)); - -#elif defined(_WIN32) +#if defined(_WIN32) return (VirtualLock(ring, sizeof(ZixRing)) && VirtualLock(ring->buf, ring->size)) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; +#elif USE_MLOCK + return zix_errno_status_if(mlock(ring, sizeof(ZixRing)) + + mlock(ring->buf, ring->size)); + #else return ZIX_STATUS_NOT_SUPPORTED; #endif diff --git a/src/zix_config.h b/src/zix_config.h index 7b87826..0aab586 100644 --- a/src/zix_config.h +++ b/src/zix_config.h @@ -1,26 +1,35 @@ -// Copyright 2021-2022 David Robillard <d@drobilla.net> +// Copyright 2021-2023 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC /* - Configuration header that defines reasonable defaults at compile time. - - This allows compile-time configuration from the command line, while still - allowing the source to be built "as-is" without any configuration. The idea - is to support an advanced build system with configuration checks, while still - allowing the code to be simply "thrown at a compiler" with features - determined from the compiler or system headers. Everything can be - overridden, so it should never be necessary to edit this file to build - successfully. - - To ensure that all configure checks are performed, the build system can - define ZIX_NO_DEFAULT_CONFIG to disable defaults. In this case, it must - define all HAVE_FEATURE symbols below to 1 or 0 to enable or disable - features. Any missing definitions will generate a compiler warning. - - To ensure that this header is always included properly, all code that uses - configuration variables includes this header and checks their value with #if - (not #ifdef). Variables like USE_FEATURE are internal and should never be - defined on the command line. + Configuration header that defines reasonable defaults at compile-time. + + This allows configuration from the command-line (usually by the build system) + while still allowing the code to compile "as-is" with reasonable default + features on supported platforms. + + This system is designed so that, ideally, no command-line or build-system + configuration is needed, but automatic feature detection can be disabled or + overridden for maximum control. It should never be necessary to edit the + source code to achieve a given configuration. + + Usage: + + - By default, features are enabled if they can be detected or assumed to be + available from the build environment, unless `ZIX_NO_DEFAULT_CONFIG` is + defined, which disables everything by default. + + - If a symbol like `HAVE_SOMETHING` is defined to non-zero, then the + "something" feature is assumed to be available. + + Code rules: + + - To check for a feature, this header must be included, and the symbol + `USE_SOMETHING` used as a boolean in an `#if` expression. + + - None of the other configuration symbols described here may be used + directly. In particular, this header should be the only place in the + source code that touches `HAVE` symbols. */ #ifndef ZIX_CONFIG_H @@ -39,12 +48,17 @@ # endif # endif +// Define ZIX_POSIX_VERSION unconditionally for convenience +# if defined(_POSIX_VERSION) +# define ZIX_POSIX_VERSION _POSIX_VERSION +# else +# define ZIX_POSIX_VERSION 0 +# endif + // POSIX.1-2001: clock_gettime() # ifndef HAVE_CLOCK_GETTIME -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_CLOCK_GETTIME 1 -# else -# define HAVE_CLOCK_GETTIME 0 # endif # endif @@ -52,8 +66,6 @@ # ifndef HAVE_CLONEFILE # if defined(__APPLE__) && __has_include(<sys/clonefile.h>) # define HAVE_CLONEFILE 1 -# else -# define HAVE_CLONEFILE 0 # endif # endif @@ -63,8 +75,6 @@ (defined(__GLIBC__) && \ (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 27)) # define HAVE_COPY_FILE_RANGE 1 -# else -# define HAVE_COPY_FILE_RANGE 0 # endif # endif @@ -72,8 +82,6 @@ # ifndef HAVE_CREATESYMBOLICLINK # if defined(_MSC_VER) && _MSC_VER >= 1910 # define HAVE_CREATESYMBOLICLINK 1 -# else -# define HAVE_CREATESYMBOLICLINK 0 # endif # endif @@ -81,8 +89,6 @@ # ifndef HAVE_FILENO # if defined(_WIN32) || defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L # define HAVE_FILENO 1 -# else -# define HAVE_FILENO 0 # endif # endif @@ -90,71 +96,55 @@ # ifndef HAVE_FLOCK # if defined(__APPLE__) || defined(__unix__) # define HAVE_FLOCK 1 -# else -# define HAVE_FLOCK 0 # endif # endif // POSIX.1-2001: mlock() # ifndef HAVE_MLOCK -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_MLOCK 1 -# else -# define HAVE_MLOCK 0 # endif # endif // POSIX.1-2001: pathconf() # ifndef HAVE_PATHCONF -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_PATHCONF 1 -# else -# define HAVE_PATHCONF 0 # endif # endif // POSIX.1-2001: posix_fadvise() # ifndef HAVE_POSIX_FADVISE -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_POSIX_FADVISE 1 -# else -# define HAVE_POSIX_FADVISE 0 # endif # endif // POSIX.1-2001: posix_memalign() # ifndef HAVE_POSIX_MEMALIGN -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_POSIX_MEMALIGN 1 -# else -# define HAVE_POSIX_MEMALIGN 0 # endif # endif // POSIX.1-2001: realpath() # ifndef HAVE_REALPATH -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_REALPATH 1 -# else -# define HAVE_REALPATH 0 # endif # endif // POSIX.1-2001: sem_timedwait() # ifndef HAVE_SEM_TIMEDWAIT -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_SEM_TIMEDWAIT 1 -# else -# define HAVE_SEM_TIMEDWAIT 0 # endif # endif // POSIX.1-2001: sysconf() # ifndef HAVE_SYSCONF -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# if ZIX_POSIX_VERSION >= 200112L # define HAVE_SYSCONF 1 -# else -# define HAVE_SYSCONF 0 # endif # endif @@ -168,79 +158,79 @@ if the build system defines them all. */ -#if HAVE_CLOCK_GETTIME +#if defined(HAVE_CLOCK_GETTIME) && HAVE_CLOCK_GETTIME # define USE_CLOCK_GETTIME 1 #else # define USE_CLOCK_GETTIME 0 #endif -#if HAVE_CLONEFILE +#if defined(HAVE_CLONEFILE) && HAVE_CLONEFILE # define USE_CLONEFILE 1 #else # define USE_CLONEFILE 0 #endif -#if HAVE_COPY_FILE_RANGE +#if defined(HAVE_COPY_FILE_RANGE) && HAVE_COPY_FILE_RANGE # define USE_COPY_FILE_RANGE 1 #else # define USE_COPY_FILE_RANGE 0 #endif -#if HAVE_CREATESYMBOLICLINK +#if defined(HAVE_CREATESYMBOLICLINK) && HAVE_CREATESYMBOLICLINK # define USE_CREATESYMBOLICLINK 1 #else # define USE_CREATESYMBOLICLINK 0 #endif -#if HAVE_FILENO +#if defined(HAVE_FILENO) && HAVE_FILENO # define USE_FILENO 1 #else # define USE_FILENO 0 #endif -#if HAVE_FLOCK +#if defined(HAVE_FLOCK) && HAVE_FLOCK # define USE_FLOCK 1 #else # define USE_FLOCK 0 #endif -#if HAVE_MLOCK +#if defined(HAVE_MLOCK) && HAVE_MLOCK # define USE_MLOCK 1 #else # define USE_MLOCK 0 #endif -#if HAVE_PATHCONF +#if defined(HAVE_PATHCONF) && HAVE_PATHCONF # define USE_PATHCONF 1 #else # define USE_PATHCONF 0 #endif -#if HAVE_POSIX_FADVISE +#if defined(HAVE_POSIX_FADVISE) && HAVE_POSIX_FADVISE # define USE_POSIX_FADVISE 1 #else # define USE_POSIX_FADVISE 0 #endif -#if HAVE_POSIX_MEMALIGN +#if defined(HAVE_POSIX_MEMALIGN) && HAVE_POSIX_MEMALIGN # define USE_POSIX_MEMALIGN 1 #else # define USE_POSIX_MEMALIGN 0 #endif -#if HAVE_REALPATH +#if defined(HAVE_REALPATH) && HAVE_REALPATH # define USE_REALPATH 1 #else # define USE_REALPATH 0 #endif -#if HAVE_SEM_TIMEDWAIT +#if defined(HAVE_SEM_TIMEDWAIT) && HAVE_SEM_TIMEDWAIT # define USE_SEM_TIMEDWAIT 1 #else # define USE_SEM_TIMEDWAIT 0 #endif -#if HAVE_SYSCONF +#if defined(HAVE_SYSCONF) && HAVE_SYSCONF # define USE_SYSCONF 1 #else # define USE_SYSCONF 0 |