e008322375a72933263b0bd4ecae6abfc78db539
[WebKit-https.git] / Source / WTF / wtf / cocoa / SoftLinking.h
1 /*
2  * Copyright (C) 2007-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #pragma once
26
27 #import <wtf/Assertions.h>
28 #import <dlfcn.h>
29 #import <objc/runtime.h>
30
31 #pragma mark - Soft-link macros for use within a single source file
32
33 #define SOFT_LINK_LIBRARY(lib) \
34     static void* lib##Library() \
35     { \
36         static void* dylib = ^{ \
37             void *result = dlopen("/usr/lib/" #lib ".dylib", RTLD_NOW); \
38             RELEASE_ASSERT_WITH_MESSAGE(result, "%s", dlerror()); \
39             return result; \
40         }(); \
41         return dylib; \
42     }
43
44 #define SOFT_LINK_FRAMEWORK(framework) \
45     static void* framework##Library() \
46     { \
47         static void* frameworkLibrary = ^{ \
48             void* result = dlopen("/System/Library/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \
49             RELEASE_ASSERT_WITH_MESSAGE(result, "%s", dlerror()); \
50             return result; \
51         }(); \
52         return frameworkLibrary; \
53     }
54
55 #define SOFT_LINK_PRIVATE_FRAMEWORK(framework) \
56     static void* framework##Library() \
57     { \
58         static void* frameworkLibrary = ^{ \
59             void* result = dlopen("/System/Library/PrivateFrameworks/" #framework ".framework/" #framework, RTLD_NOW); \
60             RELEASE_ASSERT_WITH_MESSAGE(result, "%s", dlerror()); \
61             return result; \
62         }(); \
63         return frameworkLibrary; \
64     }
65
66 #define SOFT_LINK_FRAMEWORK_OPTIONAL_PREFLIGHT(framework) \
67     static bool framework##LibraryIsAvailable() \
68     { \
69         static bool frameworkLibraryIsAvailable = dlopen_preflight("/System/Library/Frameworks/" #framework ".framework/" #framework); \
70         return frameworkLibraryIsAvailable; \
71     }
72
73 #define SOFT_LINK_FRAMEWORK_OPTIONAL(framework) \
74     static void* framework##Library() \
75     { \
76         static void* frameworkLibrary = dlopen("/System/Library/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \
77         return frameworkLibrary; \
78     }
79
80 #define SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(framework) \
81     static void* framework##Library() \
82     { \
83         static void* frameworkLibrary = dlopen("/System/Library/PrivateFrameworks/" #framework ".framework/" #framework, RTLD_NOW); \
84         return frameworkLibrary; \
85     }
86
87 #define SOFT_LINK_STAGED_FRAMEWORK(framework, unstagedLocation, version) \
88     static void* framework##Library() \
89     { \
90         static void* frameworkLibrary = ^{ \
91             void* result = dlopen("/System/Library/" #unstagedLocation "/" #framework ".framework/Versions/" #version "/" #framework, RTLD_LAZY); \
92             if (!result) \
93                 result = dlopen("/System/Library/StagedFrameworks/Safari/" #framework ".framework/Versions/" #version "/" #framework, RTLD_LAZY); \
94             RELEASE_ASSERT_WITH_MESSAGE(result, "%s", dlerror()); \
95             return result; \
96         }(); \
97         return frameworkLibrary; \
98     }
99
100 #define SOFT_LINK_FRAMEWORK_IN_UMBRELLA(umbrella, framework) \
101     static void* framework##Library() \
102     { \
103         static void* frameworkLibrary = ^{ \
104             void* result = dlopen("/System/Library/Frameworks/" #umbrella ".framework/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \
105             RELEASE_ASSERT_WITH_MESSAGE(result, "%s", dlerror()); \
106             return result; \
107         }(); \
108         return frameworkLibrary; \
109     }
110
111 #define SOFT_LINK(framework, functionName, resultType, parameterDeclarations, parameterNames) \
112     WTF_EXTERN_C_BEGIN \
113     resultType functionName parameterDeclarations; \
114     WTF_EXTERN_C_END \
115     static resultType init##functionName parameterDeclarations; \
116     static resultType (*softLink##functionName) parameterDeclarations = init##functionName; \
117     \
118     static resultType init##functionName parameterDeclarations \
119     { \
120         softLink##functionName = (resultType (*) parameterDeclarations) dlsym(framework##Library(), #functionName); \
121         RELEASE_ASSERT_WITH_MESSAGE(softLink##functionName, "%s", dlerror()); \
122         return softLink##functionName parameterNames; \
123     } \
124     \
125     inline __attribute__((__always_inline__)) resultType functionName parameterDeclarations \
126     { \
127         return softLink##functionName parameterNames; \
128     }
129
130 #define SOFT_LINK_MAY_FAIL(framework, functionName, resultType, parameterDeclarations, parameterNames) \
131     WTF_EXTERN_C_BEGIN \
132     resultType functionName parameterDeclarations; \
133     WTF_EXTERN_C_END \
134     static resultType (*softLink##functionName) parameterDeclarations = 0; \
135     \
136     static bool init##functionName() \
137     { \
138         ASSERT(!softLink##functionName); \
139         softLink##functionName = (resultType (*) parameterDeclarations) dlsym(framework##Library(), #functionName); \
140         return !!softLink##functionName; \
141     } \
142     \
143     static bool canLoad##functionName() \
144     { \
145         static bool loaded = init##functionName(); \
146         return loaded; \
147     } \
148     \
149     inline __attribute__((__always_inline__)) __attribute__((visibility("hidden"))) resultType functionName parameterDeclarations \
150     { \
151         ASSERT(softLink##functionName); \
152         return softLink##functionName parameterNames; \
153     }
154
155 /* callingConvention is unused on Mac but is here to keep the macro prototype the same between Mac and Windows. */
156 #define SOFT_LINK_OPTIONAL(framework, functionName, resultType, callingConvention, parameterDeclarations) \
157     WTF_EXTERN_C_BEGIN \
158     resultType functionName parameterDeclarations; \
159     WTF_EXTERN_C_END \
160     typedef resultType (*functionName##PtrType) parameterDeclarations; \
161     \
162     static functionName##PtrType functionName##Ptr() \
163     { \
164         static functionName##PtrType ptr = reinterpret_cast<functionName##PtrType>(dlsym(framework##Library(), #functionName)); \
165         return ptr; \
166     }
167
168 #define SOFT_LINK_CLASS(framework, className) \
169     @class className; \
170     static Class init##className(); \
171     static Class (*get##className##Class)() = init##className; \
172     static Class class##className; \
173     \
174     static Class className##Function() \
175     { \
176         return class##className; \
177     } \
178     \
179     static Class init##className() \
180     { \
181         framework##Library(); \
182         class##className = objc_getClass(#className); \
183         RELEASE_ASSERT(class##className); \
184         get##className##Class = className##Function; \
185         return class##className; \
186     } \
187     _Pragma("clang diagnostic push") \
188     _Pragma("clang diagnostic ignored \"-Wunused-function\"") \
189     static className *alloc##className##Instance() \
190     { \
191         return [get##className##Class() alloc]; \
192     } \
193     _Pragma("clang diagnostic pop")
194
195 #define SOFT_LINK_CLASS_OPTIONAL(framework, className) \
196     @class className; \
197     static Class init##className(); \
198     static Class (*get##className##Class)() = init##className; \
199     static Class class##className; \
200     \
201     static Class className##Function() \
202     { \
203         return class##className; \
204     } \
205     \
206     static Class init##className() \
207     { \
208         framework##Library(); \
209         class##className = objc_getClass(#className); \
210         get##className##Class = className##Function; \
211         return class##className; \
212     } \
213     _Pragma("clang diagnostic push") \
214     _Pragma("clang diagnostic ignored \"-Wunused-function\"") \
215     static className *alloc##className##Instance() \
216     { \
217         return [get##className##Class() alloc]; \
218     } \
219     _Pragma("clang diagnostic pop")
220
221 #define SOFT_LINK_POINTER(framework, name, type) \
222     static type init##name(); \
223     static type (*get##name)() = init##name; \
224     static type pointer##name; \
225     \
226     static type name##Function() \
227     { \
228         return pointer##name; \
229     } \
230     \
231     static type init##name() \
232     { \
233         void** pointer = static_cast<void**>(dlsym(framework##Library(), #name)); \
234         RELEASE_ASSERT_WITH_MESSAGE(pointer, "%s", dlerror()); \
235         pointer##name = static_cast<type>(*pointer); \
236         get##name = name##Function; \
237         return pointer##name; \
238     }
239
240 #define SOFT_LINK_POINTER_OPTIONAL(framework, name, type) \
241     static type init##name(); \
242     static type (*get##name)() = init##name; \
243     static type pointer##name; \
244     \
245     static type name##Function() \
246     { \
247         return pointer##name; \
248     } \
249     \
250     static type init##name() \
251     { \
252         void** pointer = static_cast<void**>(dlsym(framework##Library(), #name)); \
253         if (pointer) \
254             pointer##name = static_cast<type>(*pointer); \
255         get##name = name##Function; \
256         return pointer##name; \
257     }
258
259 #define SOFT_LINK_CONSTANT(framework, name, type) \
260     static type init##name(); \
261     static type (*get##name)() = init##name; \
262     static type constant##name; \
263     \
264     static type name##Function() \
265     { \
266         return constant##name; \
267     } \
268     \
269     static type init##name() \
270     { \
271         void* constant = dlsym(framework##Library(), #name); \
272         RELEASE_ASSERT_WITH_MESSAGE(constant, "%s", dlerror()); \
273         constant##name = *static_cast<type const *>(constant); \
274         get##name = name##Function; \
275         return constant##name; \
276     }
277
278 #define SOFT_LINK_CONSTANT_MAY_FAIL(framework, name, type) \
279     static bool init##name(); \
280     static type (*get##name)() = 0; \
281     static type constant##name; \
282     \
283     static type name##Function() \
284     { \
285         return constant##name; \
286     } \
287     \
288     static bool canLoad##name() \
289     { \
290         static bool loaded = init##name(); \
291         return loaded; \
292     } \
293     \
294     static bool init##name() \
295     { \
296         ASSERT(!get##name); \
297         void* constant = dlsym(framework##Library(), #name); \
298         if (!constant) \
299             return false; \
300         constant##name = *static_cast<type const *>(constant); \
301         get##name = name##Function; \
302         return true; \
303     }
304
305 #pragma mark - Soft-link macros for sharing across multiple source files
306
307 // See Source/WebCore/platform/cf/CoreMediaSoftLink.{cpp,h} for an example implementation.
308
309
310 #define SOFT_LINK_LIBRARY_FOR_HEADER(functionNamespace, lib) \
311     namespace functionNamespace { \
312     extern void* lib##Library(bool isOptional = false); \
313     inline bool is##lib##LibaryAvailable() { \
314         return lib##Library(true) != nullptr; \
315     } \
316     }
317
318 #define SOFT_LINK_LIBRARY_FOR_SOURCE(functionNamespace, lib) \
319     namespace functionNamespace { \
320     void* lib##Library(bool isOptional); \
321     void* lib##Library(bool isOptional) \
322     { \
323         static void* library; \
324         static dispatch_once_t once; \
325         dispatch_once(&once, ^{ \
326             library = dlopen("/usr/lib/" #lib ".dylib", RTLD_NOW); \
327             if (!isOptional) \
328                 RELEASE_ASSERT_WITH_MESSAGE(library, "%s", dlerror()); \
329         }); \
330         return library; \
331     } \
332     }
333
334 #define SOFT_LINK_FRAMEWORK_FOR_HEADER(functionNamespace, framework) \
335     namespace functionNamespace { \
336     extern void* framework##Library(bool isOptional = false); \
337     bool is##framework##FrameworkAvailable(); \
338     inline bool is##framework##FrameworkAvailable() { \
339         return framework##Library(true) != nullptr; \
340     } \
341     }
342
343 #define SOFT_LINK_FRAMEWORK_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, export) \
344     namespace functionNamespace { \
345     export void* framework##Library(bool isOptional = false); \
346     void* framework##Library(bool isOptional) \
347     { \
348         static void* frameworkLibrary; \
349         static dispatch_once_t once; \
350         dispatch_once(&once, ^{ \
351             frameworkLibrary = dlopen("/System/Library/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \
352             if (!isOptional) \
353                 RELEASE_ASSERT_WITH_MESSAGE(frameworkLibrary, "%s", dlerror()); \
354         }); \
355         return frameworkLibrary; \
356     } \
357     }
358
359 #define SOFT_LINK_FRAMEWORK_FOR_SOURCE(functionNamespace, framework) \
360     SOFT_LINK_FRAMEWORK_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, )
361
362 #define SOFT_LINK_PRIVATE_FRAMEWORK_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, export) \
363     namespace functionNamespace { \
364     export void* framework##Library(bool isOptional = false); \
365     void* framework##Library(bool isOptional) \
366     { \
367         static void* frameworkLibrary; \
368         static dispatch_once_t once; \
369         dispatch_once(&once, ^{ \
370             frameworkLibrary = dlopen("/System/Library/PrivateFrameworks/" #framework ".framework/" #framework, RTLD_NOW); \
371             if (!isOptional) \
372                 RELEASE_ASSERT_WITH_MESSAGE(frameworkLibrary, "%s", dlerror()); \
373         }); \
374         return frameworkLibrary; \
375     } \
376     }
377
378 #define SOFT_LINK_PRIVATE_FRAMEWORK_FOR_SOURCE(functionNamespace, framework) \
379     SOFT_LINK_PRIVATE_FRAMEWORK_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, )
380
381 #define SOFT_LINK_CLASS_FOR_HEADER(functionNamespace, className) \
382     @class className; \
383     namespace functionNamespace { \
384     extern Class (*get##className##Class)(); \
385     className *alloc##className##Instance(); \
386     inline className *alloc##className##Instance() \
387     { \
388         return [get##className##Class() alloc]; \
389     } \
390     }
391
392 #define SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT_AND_IS_OPTIONAL(functionNamespace, framework, className, export, isOptional) \
393     @class className; \
394     namespace functionNamespace { \
395     static Class init##className(); \
396     export Class (*get##className##Class)() = init##className; \
397     static Class class##className; \
398     \
399     static Class className##Function() \
400     { \
401         return class##className; \
402     } \
403     \
404     static Class init##className() \
405     { \
406         static dispatch_once_t once; \
407         dispatch_once(&once, ^{ \
408             framework##Library(isOptional); \
409             class##className = objc_getClass(#className); \
410             if (!isOptional) \
411                 RELEASE_ASSERT(class##className); \
412             get##className##Class = className##Function; \
413         }); \
414         return class##className; \
415     } \
416     }
417
418 #define SOFT_LINK_IS_OPTIONAL true
419 #define SOFT_LINK_IS_NOT_OPTIONAL false
420
421 #define SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, className, export) \
422     SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT_AND_IS_OPTIONAL(functionNamespace, framework, className, export, SOFT_LINK_IS_NOT_OPTIONAL)
423
424 #define SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(functionNamespace, framework, className, export) \
425     SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT_AND_IS_OPTIONAL(functionNamespace, framework, className, export, SOFT_LINK_IS_OPTIONAL)
426
427 #define SOFT_LINK_CLASS_FOR_SOURCE(functionNamespace, framework, className) \
428     SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT_AND_IS_OPTIONAL(functionNamespace, framework, className, , SOFT_LINK_IS_NOT_OPTIONAL)
429
430 #define SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL(functionNamespace, framework, className) \
431     SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT_AND_IS_OPTIONAL(functionNamespace, framework, className, , SOFT_LINK_IS_OPTIONAL)
432
433 #define SOFT_LINK_CONSTANT_FOR_HEADER(functionNamespace, framework, variableName, variableType) \
434     namespace functionNamespace { \
435     variableType get_##framework##_##variableName(); \
436     }
437
438 #define SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, variableName, variableType, export) \
439     namespace functionNamespace { \
440     export variableType get_##framework##_##variableName(); \
441     variableType get_##framework##_##variableName() \
442     { \
443         static variableType constant##framework##variableName; \
444         static dispatch_once_t once; \
445         dispatch_once(&once, ^{ \
446             void* constant = dlsym(framework##Library(), #variableName); \
447             RELEASE_ASSERT_WITH_MESSAGE(constant, "%s", dlerror()); \
448             constant##framework##variableName = *static_cast<variableType const *>(constant); \
449         }); \
450         return constant##framework##variableName; \
451     } \
452     }
453
454 #define SOFT_LINK_CONSTANT_FOR_SOURCE(functionNamespace, framework, variableName, variableType) \
455     SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, variableName, variableType, )
456
457 #define SOFT_LINK_CONSTANT_MAY_FAIL_FOR_HEADER(functionNamespace, framework, variableName, variableType) \
458     namespace functionNamespace { \
459     bool canLoad_##framework##_##variableName(); \
460     bool init_##framework##_##variableName(); \
461     variableType get_##framework##_##variableName(); \
462     }
463
464 #define SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, variableName, variableType, export) \
465     namespace functionNamespace { \
466     static variableType constant##framework##variableName; \
467     bool init_##framework##_##variableName(); \
468     bool init_##framework##_##variableName() \
469     { \
470         void* constant = dlsym(framework##Library(), #variableName); \
471         if (!constant) \
472             return false; \
473         constant##framework##variableName = *static_cast<variableType const *>(constant); \
474         return true; \
475     } \
476     export bool canLoad_##framework##_##variableName(); \
477     bool canLoad_##framework##_##variableName() \
478     { \
479         static bool loaded = init_##framework##_##variableName(); \
480         return loaded; \
481     } \
482     export variableType get_##framework##_##variableName(); \
483     variableType get_##framework##_##variableName() \
484     { \
485         return constant##framework##variableName; \
486     } \
487     }
488
489 #define SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE(functionNamespace, framework, variableName, variableType) \
490     SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, variableName, variableType, )
491
492 #define SOFT_LINK_FUNCTION_FOR_HEADER(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \
493     WTF_EXTERN_C_BEGIN \
494     resultType functionName parameterDeclarations; \
495     WTF_EXTERN_C_END \
496     namespace functionNamespace { \
497     extern resultType (*softLink##framework##functionName) parameterDeclarations; \
498     inline resultType softLink_##framework##_##functionName parameterDeclarations \
499     { \
500         return softLink##framework##functionName parameterNames; \
501     } \
502     } \
503     inline __attribute__((__always_inline__)) resultType functionName parameterDeclarations \
504     {\
505         return functionNamespace::softLink##framework##functionName parameterNames; \
506     }
507
508 #define SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames, export) \
509     WTF_EXTERN_C_BEGIN \
510     resultType functionName parameterDeclarations; \
511     WTF_EXTERN_C_END \
512     namespace functionNamespace { \
513     static resultType init##framework##functionName parameterDeclarations; \
514     export resultType(*softLink##framework##functionName) parameterDeclarations = init##framework##functionName; \
515     static resultType init##framework##functionName parameterDeclarations \
516     { \
517         static dispatch_once_t once; \
518         dispatch_once(&once, ^{ \
519             softLink##framework##functionName = (resultType (*) parameterDeclarations) dlsym(framework##Library(), #functionName); \
520             RELEASE_ASSERT_WITH_MESSAGE(softLink##framework##functionName, "%s", dlerror()); \
521         }); \
522         return softLink##framework##functionName parameterNames; \
523     } \
524     }
525
526 #define SOFT_LINK_FUNCTION_FOR_SOURCE(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \
527     SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames, )
528
529 #define SOFT_LINK_FUNCTION_MAY_FAIL_FOR_HEADER(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \
530     WTF_EXTERN_C_BEGIN \
531     resultType functionName parameterDeclarations; \
532     WTF_EXTERN_C_END \
533     namespace functionNamespace { \
534     extern resultType (*softLink##framework##functionName) parameterDeclarations; \
535     bool canLoad_##framework##_##functionName(); \
536     bool init_##framework##_##functionName(); \
537     resultType softLink_##framework##_##functionName parameterDeclarations; \
538     }
539
540 #define SOFT_LINK_FUNCTION_MAY_FAIL_FOR_SOURCE(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \
541     WTF_EXTERN_C_BEGIN \
542     resultType functionName parameterDeclarations; \
543     WTF_EXTERN_C_END \
544     namespace functionNamespace { \
545     resultType (*softLink##framework##functionName) parameterDeclarations = 0; \
546     bool init_##framework##_##functionName(); \
547     bool init_##framework##_##functionName() \
548     { \
549         ASSERT(!softLink##framework##functionName); \
550         softLink##framework##functionName = (resultType (*) parameterDeclarations) dlsym(framework##Library(), #functionName); \
551         return !!softLink##framework##functionName; \
552     } \
553     \
554     bool canLoad_##framework##_##functionName(); \
555     bool canLoad_##framework##_##functionName() \
556     { \
557         static bool loaded = init_##framework##_##functionName(); \
558         return loaded; \
559     } \
560     \
561     resultType softLink_##framework##_##functionName parameterDeclarations; \
562     resultType softLink_##framework##_##functionName parameterDeclarations \
563     { \
564         ASSERT(softLink##framework##functionName); \
565         return softLink##framework##functionName parameterNames; \
566     } \
567     }
568
569 #define SOFT_LINK_POINTER_FOR_HEADER(functionNamespace, framework, variableName, variableType) \
570     namespace functionNamespace { \
571     extern variableType (*get_##framework##_##variableName)(); \
572     }
573
574 #define SOFT_LINK_POINTER_FOR_SOURCE(functionNamespace, framework, variableName, variableType) \
575     namespace functionNamespace { \
576     static variableType init##framework##variableName(); \
577     variableType (*get_##framework##_##variableName)() = init##framework##variableName; \
578     static variableType pointer##framework##variableName; \
579     \
580     static variableType pointer##framework##variableName##Function() \
581     { \
582         return pointer##framework##variableName; \
583     } \
584     \
585     static variableType init##framework##variableName() \
586     { \
587         static dispatch_once_t once; \
588         dispatch_once(&once, ^{ \
589             void** pointer = static_cast<void**>(dlsym(framework##Library(), #variableName)); \
590             RELEASE_ASSERT_WITH_MESSAGE(pointer, "%s", dlerror()); \
591             pointer##framework##variableName = static_cast<variableType>(*pointer); \
592             get_##framework##_##variableName = pointer##framework##variableName##Function; \
593         }); \
594         return pointer##framework##variableName; \
595     } \
596     }
597
598 #define SOFT_LINK_VARIABLE_FOR_HEADER(functionNamespace, framework, variableName, variableType) \
599     WTF_EXTERN_C_BEGIN \
600     extern variableType variableName; \
601     WTF_EXTERN_C_END \
602     namespace functionNamespace { \
603     variableType * get_##framework##_##variableName(); \
604     }
605
606 #define SOFT_LINK_VARIABLE_FOR_SOURCE(functionNamespace, framework, variableName, variableType) \
607     WTF_EXTERN_C_BEGIN \
608     extern variableType variableName; \
609     WTF_EXTERN_C_END \
610     namespace functionNamespace { \
611     variableType * get_##framework##_##variableName(); \
612     variableType * get_##framework##_##variableName() \
613     { \
614         static variableType * variable##framework##variableName; \
615         static dispatch_once_t once; \
616         dispatch_once(&once, ^{ \
617             void* variable = dlsym(framework##Library(), #variableName); \
618             RELEASE_ASSERT_WITH_MESSAGE(variable, "%s", dlerror()); \
619             variable##framework##variableName = static_cast<variableType *>(variable); \
620         }); \
621         return variable##framework##variableName; \
622     } \
623     }