diff options
author | David Robillard <d@drobilla.net> | 2024-12-10 21:35:13 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2024-12-11 00:22:10 -0500 |
commit | ba2c2a08973cb5eae1feabbb9431c897cded03f6 (patch) | |
tree | e593d0d2298ccc6fef89b624fca098765ac2d768 | |
parent | 6102356198be362e78ebd8ea16dee30a7d370cf8 (diff) | |
download | zix-ba2c2a08973cb5eae1feabbb9431c897cded03f6.tar.gz zix-ba2c2a08973cb5eae1feabbb9431c897cded03f6.tar.bz2 zix-ba2c2a08973cb5eae1feabbb9431c897cded03f6.zip |
Add option to build for older Windows versions
Adds configuration checks for Windows API functions, and a win_ver
configuration option to change the targeted API version.
-rw-r--r-- | .gitlab-ci.yml | 12 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | meson.build | 41 | ||||
-rw-r--r-- | meson_options.txt | 6 | ||||
-rw-r--r-- | src/ring.c | 5 | ||||
-rw-r--r-- | src/win32/filesystem_win32.c | 53 | ||||
-rw-r--r-- | src/zix_config.h | 45 |
7 files changed, 129 insertions, 36 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 081c7b6..ad1dcc9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2019-2022 David Robillard <d@drobilla.net> +# Copyright 2019-2024 David Robillard <d@drobilla.net> # SPDX-License-Identifier: 0BSD OR ISC stages: [build, deploy] @@ -95,6 +95,10 @@ mingw32: - ninja -C build test - meson configure -Dbuildtype=release build - ninja -C build test + - meson configure -Dwin_ver=winxp build + - ninja -C build test + - meson configure -Dwin_ver=nt4 build + - ninja -C build test variables: WINEPATH: "Z:\\usr\\lib\\gcc\\i686-w64-mingw32\\10-win32" @@ -106,6 +110,8 @@ mingw64: - ninja -C build test - meson configure -Dbuildtype=release build - ninja -C build test + - meson configure -Dwin_ver=winxp build + - ninja -C build test variables: WINEPATH: "Z:\\usr\\lib\\gcc\\x86_64-w64-mingw32\\10-win32" @@ -146,6 +152,10 @@ win: - ninja -C build test - meson configure -Dbuildtype=release build - ninja -C build test + - meson configure -Dwin_ver=winxp build + - ninja -C build test + - meson configure -Dwin_ver=nt4 build + - ninja -C build test # Documentation @@ -1,6 +1,7 @@ zix (0.5.1) unstable; urgency=medium * Add ZIX_NODISCARD attribute + * Add option to build for older Windows versions * Add zix_expand_environment_strings() * Add zix_string_view_equals() * Avoid fdatasync() on Darwin @@ -10,7 +11,7 @@ zix (0.5.1) unstable; urgency=medium * Fix ring unit test when mlock() is unavailable * Improve documentation - -- David Robillard <d@drobilla.net> Sun, 24 Nov 2024 15:48:27 +0000 + -- David Robillard <d@drobilla.net> Wed, 11 Dec 2024 05:21:56 +0000 zix (0.4.2) stable; urgency=medium diff --git a/meson.build b/meson.build index d319296..7a6047f 100644 --- a/meson.build +++ b/meson.build @@ -29,15 +29,6 @@ versioned_name = 'zix' + version_suffix pkg = import('pkgconfig') cc = meson.get_compiler('c') -# Restrict Windows API usage to Vista and earlier -if host_machine.system() == 'windows' - if cc.get_id() == 'msvc' - add_project_arguments('/D_WIN32_WINNT=0x0600', language: ['c', 'cpp']) - else - add_project_arguments('-D_WIN32_WINNT=0x0600', language: ['c', 'cpp']) - endif -endif - # Set global warning suppressions warning_level = get_option('warning_level') c_suppressions = [] @@ -171,8 +162,14 @@ elif host_machine.system() in ['dragonfly', 'freebsd', 'netbsd', 'openbsd'] '-D_BSD_SOURCE', ] elif host_machine.system() == 'windows' + winvers = { + 'nt4': '0x0400', + 'winxp': '0x0501', + 'vista': '0x0600', + } system_c_args += [ '-DWIN32_LEAN_AND_MEAN', + '-D_WIN32_WINNT=' + winvers[get_option('win_ver')], ] else system_c_args += [ @@ -251,16 +248,32 @@ else } windows_checks = { + 'CreateHardLink': template.format( + 'windows.h', + 'return CreateHardLink("l", "t", NULL);', + ), 'CreateSymbolicLink': template.format( 'windows.h', 'return CreateSymbolicLink("l", "t", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);', ), + 'GetFinalPathNameByHandle': template.format( + 'windows.h', + 'return GetFinalPathNameByHandle(NULL, NULL, 0U, 0U);', + ), + 'VirtualLock': template.format( + 'windows.h', + 'return VirtualLock(NULL, sizeof(void*));', + ), } + check_c_args = system_c_args if host_machine.system() == 'darwin' checks = posix_checks + mac_checks elif host_machine.system() == 'windows' checks = windows_checks + if cc.get_id() == 'msvc' + check_c_args += ['/Wall', '/WX'] + endif else checks = posix_checks @@ -269,7 +282,7 @@ else '''#include <semaphore.h> #include <time.h> int main(void) { sem_t s; struct timespec t; return sem_timedwait(&s, &t); }''', - args: system_c_args, + args: check_c_args, dependencies: thread_dep, name: 'sem_timedwait', ) @@ -279,7 +292,13 @@ int main(void) { sem_t s; struct timespec t; return sem_timedwait(&s, &t); }''', endif foreach name, check_code : checks - if cc.links(check_code, args: system_c_args, name: name) + is_mingw = host_machine.system() == 'windows' and cc.get_id() == 'gcc' + if is_mingw and name in ['CreateSymbolicLink'] + message('Ignoring MinGW stub @0@'.format(name)) + continue + endif + + if cc.links(check_code, args: check_c_args, name: name) platform_c_args += ['-DHAVE_@0@'.format(name.to_upper())] endif endforeach diff --git a/meson_options.txt b/meson_options.txt index 0ae44d1..f35da04 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,4 @@ -# Copyright 2020-2023 David Robillard <d@drobilla.net> +# Copyright 2020-2024 David Robillard <d@drobilla.net> # SPDX-License-Identifier: 0BSD OR ISC option('benchmarks', type: 'feature', yield: true, @@ -33,3 +33,7 @@ option('tests_cpp', type: 'feature', yield: true, option('title', type: 'string', value: 'Zix', description: 'Project title') + +option('win_ver', type: 'combo', value: 'vista', + choices: ['nt4', 'winxp', 'vista'], + description: 'Latest Windows API version to use') @@ -9,7 +9,7 @@ #include <zix/allocator.h> #include <zix/status.h> -#if defined(_WIN32) +#if USE_VIRTUALLOCK # include <windows.h> #elif USE_MLOCK # include <sys/mman.h> @@ -108,7 +108,7 @@ zix_ring_free(ZixRing* const ring) ZixStatus zix_ring_mlock(ZixRing* const ring) { -#if defined(_WIN32) +#if USE_VIRTUALLOCK return (VirtualLock(ring, sizeof(ZixRing)) && VirtualLock(ring->buf, ring->size)) ? ZIX_STATUS_SUCCESS @@ -119,6 +119,7 @@ zix_ring_mlock(ZixRing* const ring) mlock(ring->buf, ring->size)); #else + (void)ring; return ZIX_STATUS_NOT_SUPPORTED; #endif } diff --git a/src/win32/filesystem_win32.c b/src/win32/filesystem_win32.c index d26d789..d311bf8 100644 --- a/src/win32/filesystem_win32.c +++ b/src/win32/filesystem_win32.c @@ -183,13 +183,14 @@ zix_file_unlock(FILE* const file, const ZixFileLockMode mode) char* zix_canonical_path(ZixAllocator* const allocator, const char* const path) { - char full[MAX_PATH] = {0}; - if (!path || !GetFullPathName(path, MAX_PATH, full, NULL)) { + if (!path) { return NULL; } +#if USE_GETFINALPATHNAMEBYHANDLE // Vista+ + const HANDLE h = - CreateFile(full, + CreateFile(path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -197,27 +198,39 @@ zix_canonical_path(ZixAllocator* const allocator, const char* const path) FILE_FLAG_BACKUP_SEMANTICS, NULL); - const DWORD flags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS; - const DWORD final_size = GetFinalPathNameByHandle(h, NULL, 0U, flags); - if (!final_size) { - CloseHandle(h); + if (h == INVALID_HANDLE_VALUE) { return NULL; } - char* const final = (char*)zix_calloc(allocator, (size_t)final_size + 1U, 1U); - if (!final || !GetFinalPathNameByHandle(h, final, final_size + 1U, flags)) { - zix_free(allocator, final); - CloseHandle(h); - return NULL; - } - - if (final_size > 4U && !strncmp(final, "\\\\?\\", 4)) { - memmove(final, final + 4U, final_size - 4U); - final[final_size - 4U] = '\0'; + const DWORD flags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS; + const DWORD length = GetFinalPathNameByHandle(h, NULL, 0U, flags); + TCHAR* final = NULL; + if (length) { + final = (TCHAR*)zix_calloc(allocator, (size_t)length + 1U, sizeof(TCHAR)); + if (final) { + GetFinalPathNameByHandle(h, final, length + 1U, flags); + } } CloseHandle(h); return final; + +#else // Fall back to "full path iff it exists" for older Windows + + TCHAR* full = NULL; + if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES) { + const DWORD length = GetFullPathName(path, 0U, NULL, NULL); + if (length) { + full = (TCHAR*)zix_calloc(allocator, (size_t)length + 1U, sizeof(TCHAR)); + if (full) { + GetFullPathName(path, length + 1U, full, NULL); + } + } + } + + return full; + +#endif } static ZixFileType @@ -312,7 +325,13 @@ zix_create_directory_symlink(const char* const target_path, ZixStatus zix_create_hard_link(const char* const target_path, const char* const link_path) { +#if USE_CREATEHARDLINK return zix_windows_status(CreateHardLink(link_path, target_path, NULL)); +#else + (void)target_path; + (void)link_path; + return ZIX_STATUS_NOT_SUPPORTED; +#endif } char* diff --git a/src/zix_config.h b/src/zix_config.h index 0aab586..6bbc92b 100644 --- a/src/zix_config.h +++ b/src/zix_config.h @@ -1,4 +1,4 @@ -// Copyright 2021-2023 David Robillard <d@drobilla.net> +// Copyright 2021-2024 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC /* @@ -78,9 +78,16 @@ # endif # endif -// Windows: CreateSymbolicLink() +// Windows XP: CreateHardLink() +# ifndef HAVE_CREATEHARDLINK +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501 +# define HAVE_CREATEHARDLINK 1 +# endif +# endif + +// Windows Vista: CreateSymbolicLink() # ifndef HAVE_CREATESYMBOLICLINK -# if defined(_MSC_VER) && _MSC_VER >= 1910 +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && !defined(__MINGW32__) # define HAVE_CREATESYMBOLICLINK 1 # endif # endif @@ -99,6 +106,13 @@ # endif # endif +// Windows Vista: GetFinalPathNameByHandle() +# ifndef HAVE_GETFINALPATHNAMEBYHANDLE +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 +# define HAVE_GETFINALPATHNAMEBYHANDLE 1 +# endif +# endif + // POSIX.1-2001: mlock() # ifndef HAVE_MLOCK # if ZIX_POSIX_VERSION >= 200112L @@ -148,6 +162,13 @@ # endif # endif +// Windows XP: VirtualLock +# ifndef HAVE_VIRTUALLOCK +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501 +# define HAVE_VIRTUALLOCK 1 +# endif +# endif + #endif // !defined(ZIX_NO_DEFAULT_CONFIG) /* @@ -176,6 +197,12 @@ # define USE_COPY_FILE_RANGE 0 #endif +#if defined(HAVE_CREATEHARDLINK) && HAVE_CREATEHARDLINK +# define USE_CREATEHARDLINK 1 +#else +# define USE_CREATEHARDLINK 0 +#endif + #if defined(HAVE_CREATESYMBOLICLINK) && HAVE_CREATESYMBOLICLINK # define USE_CREATESYMBOLICLINK 1 #else @@ -194,6 +221,12 @@ # define USE_FLOCK 0 #endif +#if defined(HAVE_GETFINALPATHNAMEBYHANDLE) && HAVE_GETFINALPATHNAMEBYHANDLE +# define USE_GETFINALPATHNAMEBYHANDLE 1 +#else +# define USE_GETFINALPATHNAMEBYHANDLE 0 +#endif + #if defined(HAVE_MLOCK) && HAVE_MLOCK # define USE_MLOCK 1 #else @@ -236,4 +269,10 @@ # define USE_SYSCONF 0 #endif +#if defined(HAVE_VIRTUALLOCK) && HAVE_VIRTUALLOCK +# define USE_VIRTUALLOCK 1 +#else +# define USE_VIRTUALLOCK 0 +#endif + #endif // ZIX_CONFIG_H |