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