From 7f0f985a1445fb976573c20f9e4cda6bb355adb1 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Thu, 8 Feb 2024 15:20:42 +0000 Subject: [PATCH] support building for macOS and non-linux unixes Also updates build.yml to add macOS runners --- .github/workflows/build.yml | 2 +- include/librashader_ld.h | 50 +++++++++++++++++----------- librashader-build-script/src/main.rs | 10 +++++- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96342eb..e797203 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: build: strategy: matrix: - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest, windows-latest, macos-latest] profile: ['debug', 'release', 'optimized'] fail-fast: false runs-on: ${{ matrix.os }} diff --git a/include/librashader_ld.h b/include/librashader_ld.h index 650d161..c5936ec 100644 --- a/include/librashader_ld.h +++ b/include/librashader_ld.h @@ -48,8 +48,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. } typedef HMODULE _LIBRASHADER_IMPL_HANDLE; #define _LIBRASHADER_LOAD LoadLibraryW(L"librashader.dll") - -#elif defined(__linux__) +#elif defined(__APPLE__) +#include +#define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \ + { \ + void *address = dlsym(HMOD, "libra_" #NAME); \ + if (address != NULL) { \ + (INSTANCE).NAME = (PFN_libra_##NAME)address; \ + } \ + } +typedef void* _LIBRASHADER_IMPL_HANDLE; +#define _LIBRASHADER_LOAD dlopen("librashader.dylib", RTLD_LAZY) +#elif defined(__unix__) || defined (__linux__) #include #define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \ { \ @@ -160,7 +170,7 @@ libra_error_t __librashader__noop_gl_filter_chain_get_active_pass_count( #if defined(LIBRA_RUNTIME_VULKAN) libra_error_t __librashader__noop_vk_filter_chain_create( - libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, + libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out) { *out = NULL; return NULL; @@ -168,7 +178,7 @@ libra_error_t __librashader__noop_vk_filter_chain_create( libra_error_t __librashader__noop_vk_filter_chain_create_deferred( libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, - VkCommandBuffer command_buffer, const struct filter_chain_vk_opt_t *options, + VkCommandBuffer command_buffer, const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out) { *out = NULL; return NULL; @@ -211,7 +221,7 @@ libra_error_t __librashader__noop_vk_filter_chain_get_active_pass_count( #if defined(LIBRA_RUNTIME_D3D11) libra_error_t __librashader__noop_d3d11_filter_chain_create( libra_shader_preset_t *preset, ID3D11Device *device, - const struct filter_chain_d3d11_opt_t *options, + const struct filter_chain_d3d11_opt_t *options, libra_d3d11_filter_chain_t *out) { *out = NULL; return NULL; @@ -319,7 +329,7 @@ typedef struct libra_instance_t { /// The null instance has ABI version 0. Any valid loaded /// instance must have ABI version greater than or equal to 1. PFN_libra_instance_abi_version instance_abi_version; - + /// Get the supported API version of the loaded instance. /// /// The null instance has API version 0. @@ -330,7 +340,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety /// - `filename` must be either null or a valid, aligned pointer to a /// string path to the shader preset. @@ -415,7 +425,7 @@ typedef struct libra_instance_t { /// result in undefined behaviour. PFN_libra_preset_free_runtime_params preset_free_runtime_params; - + /// Get the error code corresponding to this error object. /// /// ## Safety @@ -478,7 +488,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety: /// - `preset` must be either null, or valid and aligned. /// - `options` must be either null, or valid and aligned. @@ -551,7 +561,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety: /// - The handles provided in `vulkan` must be valid for the command buffers /// that @@ -573,7 +583,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety: /// - The handles provided in `vulkan` must be valid for the command buffers /// that @@ -665,7 +675,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety: /// - `preset` must be either null, or valid and aligned. /// - `options` must be either null, or valid and aligned. @@ -685,7 +695,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety: /// - `preset` must be either null, or valid and aligned. /// - `options` must be either null, or valid and aligned. @@ -776,7 +786,7 @@ typedef struct libra_instance_t { /// If this function is not loaded, `out` will unconditionally be set to /// null. If this function returns an error, the state of `out` is /// unspecified. - /// + /// /// ## Safety: /// - `preset` must be either null, or valid and aligned. /// - `options` must be either null, or valid and aligned. @@ -791,9 +801,9 @@ typedef struct libra_instance_t { /// The shader preset is immediately invalidated and must be recreated after /// the filter chain is created. /// - /// If this function is not loaded, `out` will unconditionally be set to null. + /// If this function is not loaded, `out` will unconditionally be set to null. /// If this function returns an error, the state of `out` is unspecified. - /// + /// /// ## Safety: /// - `preset` must be either null, or valid and aligned. /// - `options` must be either null, or valid and aligned. @@ -869,14 +879,14 @@ typedef struct libra_instance_t { /// This flag is not indicative of whether any functions were loaded /// properly or not. The flag is true immediately after the instance /// was created with librashader_load_instance if and only if: - /// + /// /// 1. A librashader library was found in the search path. /// 2. The ABI version of the librashader library in the search path is compatible. - /// + /// /// This flag can only be relied upon when checked immediately after /// librashader_load_instance as there is no protection against mutating /// this flag. - /// + /// /// Regardless of the state of this flag, a librashader instance created /// with librashader_load_instance is always safe to call. An instance /// that fails to load is still valid to call as long as safety invariants @@ -990,7 +1000,7 @@ libra_instance_t __librashader_make_null_instance() { /// \return An `libra_instance_t` struct with loaded function pointers. libra_instance_t librashader_load_instance(); -#if defined(_WIN32) || defined(__linux__) +#if defined(_WIN32) || defined(__linux__) || defined(__unix__) || defined(__APPLE__) libra_instance_t librashader_load_instance() { _LIBRASHADER_IMPL_HANDLE librashader = _LIBRASHADER_LOAD; libra_instance_t instance = __librashader_make_null_instance(); diff --git a/librashader-build-script/src/main.rs b/librashader-build-script/src/main.rs index 299a6b9..9965d58 100644 --- a/librashader-build-script/src/main.rs +++ b/librashader-build-script/src/main.rs @@ -66,7 +66,15 @@ pub fn main() { .expect("Unable to write bindings."); println!("Moving artifacts..."); - if cfg!(target_os = "linux") { + if cfg!(target_os = "macos") { + let artifacts = &["liblibrashader_capi.dylib", "liblibrashader_capi.a"]; + for artifact in artifacts { + let ext = artifact.strip_prefix("lib").unwrap(); + let ext = ext.replace("_capi", ""); + fs::rename(output_dir.join(artifact), output_dir.join(ext)).unwrap(); + } + } + else if cfg!(target_family = "unix") { let artifacts = &["liblibrashader_capi.so", "liblibrashader_capi.a"]; for artifact in artifacts { let ext = artifact.strip_prefix("lib").unwrap();