1 // 2 // Copyright 2020 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // SoftLinking.h: Macros for soft-linking Frameworks and Functions. 8 9 #ifndef SOFT_LINKING_APPLE_H_ 10 #define SOFT_LINKING_APPLE_H_ 11 12 #include "common/platform.h" 13 14 #if defined(ANGLE_PLATFORM_APPLE) 15 16 # include "common/debug.h" 17 18 # import <dispatch/dispatch.h> 19 # import <dlfcn.h> 20 # import <objc/runtime.h> 21 22 # define RELEASE_ASSERT(expression, message) \ 23 (expression \ 24 ? static_cast<void>(0) \ 25 : (FATAL() << "\t! Assert failed in " << __FUNCTION__ << " (" << __FILE__ << ":" \ 26 << __LINE__ << "): " << #expression << "\n\t! Message: " << message)) 27 28 # ifdef __cplusplus 29 # define EXTERN_C_BEGIN extern "C" { 30 # define EXTERN_C_END } 31 # else 32 # define EXTERN_C_BEGIN 33 # define EXTERN_C_END 34 # endif 35 36 # define SOFT_LINK_FRAMEWORK_HEADER(framework) extern void *framework##Library(); 37 38 # define SOFT_LINK_FRAMEWORK_SOURCE(framework) \ 39 void *framework##Library() \ 40 { \ 41 static dispatch_once_t once = 0; \ 42 static void *frameworkLibrary = NULL; \ 43 dispatch_once(&once, ^{ \ 44 frameworkLibrary = dlopen( \ 45 "/System/Library/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \ 46 RELEASE_ASSERT(frameworkLibrary, "Unable to load " #framework ".framework"); \ 47 }); \ 48 return frameworkLibrary; \ 49 } 50 51 # define SOFT_LINK_FUNCTION_HEADER(framework, functionName, resultType, parameterDeclarations, \ 52 parameterNames) \ 53 EXTERN_C_BEGIN \ 54 resultType functionName parameterDeclarations; \ 55 EXTERN_C_END \ 56 extern resultType init##framework##functionName parameterDeclarations; \ 57 extern resultType(*softLink##framework##functionName) parameterDeclarations; \ 58 inline __attribute__((__always_inline__)) resultType functionName parameterDeclarations \ 59 { \ 60 return softLink##framework##functionName parameterNames; \ 61 } 62 63 # define SOFT_LINK_FUNCTION_SOURCE(framework, functionName, resultType, parameterDeclarations, \ 64 parameterNames) \ 65 resultType(*softLink##framework##functionName) parameterDeclarations = \ 66 init##framework##functionName; \ 67 resultType init##framework##functionName parameterDeclarations \ 68 { \ 69 static dispatch_once_t once; \ 70 dispatch_once(&once, ^{ \ 71 softLink##framework##functionName = \ 72 (resultType(*) parameterDeclarations)dlsym(framework##Library(), #functionName); \ 73 }); \ 74 return softLink##framework##functionName parameterNames; \ 75 } 76 77 # define SOFT_LINK_CLASS_HEADER(className) \ 78 @class className; \ 79 extern Class (*get##className##Class)(); \ 80 className *alloc##className##Instance(); \ 81 inline className *alloc##className##Instance() { return [get##className##Class() alloc]; } 82 83 # define SOFT_LINK_CLASS(framework, className) \ 84 @class className; \ 85 static Class init##className(); \ 86 Class (*get##className##Class)() = init##className; \ 87 static Class class##className; \ 88 \ 89 static Class className##Function() { return class##className; } \ 90 \ 91 static Class init##className() \ 92 { \ 93 static dispatch_once_t once; \ 94 dispatch_once(&once, ^{ \ 95 framework##Library(); \ 96 class##className = objc_getClass(#className); \ 97 RELEASE_ASSERT(class##className, "objc_getClass failed for " #className); \ 98 get##className##Class = className##Function; \ 99 }); \ 100 return class##className; \ 101 } \ 102 _Pragma("clang diagnostic push") \ 103 _Pragma("clang diagnostic ignored \"-Wunused-function\"") static className \ 104 *alloc##className##Instance() \ 105 { \ 106 return [get##className##Class() alloc]; \ 107 } \ 108 _Pragma("clang diagnostic pop") 109 110 #endif // defined(ANGLE_PLATFORM_APPLE) 111 112 #endif // SOFT_LINKING_APPLE_H_ 113