SDL_dlopennote.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. /* WIKI CATEGORY: DlopenNotes */
  19. /**
  20. * # CategoryDlopenNotes
  21. *
  22. * This header allows you to annotate your code so external tools know about
  23. * dynamic shared library dependencies.
  24. *
  25. * If you determine that your toolchain doesn't support dlopen notes, you can
  26. * disable this feature by defining `SDL_DISABLE_DLOPEN_NOTES`. You can use
  27. * this CMake snippet to check for support:
  28. *
  29. * ```cmake
  30. * include(CheckCSourceCompiles)
  31. * find_package(SDL3 REQUIRED CONFIG COMPONENTS Headers)
  32. * list(APPEND CMAKE_REQUIRED_LIBRARIES SDL3::Headers)
  33. * check_c_source_compiles([==[
  34. * #include <SDL3/SDL_dlopennote.h>
  35. * SDL_ELF_NOTE_DLOPEN("sdl-video",
  36. * "Support for video through SDL",
  37. * SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
  38. * "libSDL-1.2.so.0", "libSDL-2.0.so.0", "libSDL3.so.0"
  39. * )
  40. * int main(int argc, char *argv[]) {
  41. * return argc + argv[0][1];
  42. * }
  43. * ]==] COMPILER_SUPPORTS_SDL_ELF_NOTE_DLOPEN)
  44. * if(NOT COMPILER_SUPPORTS_SDL_ELF_NOTE_DLOPEN)
  45. * add_compile_definitions(-DSDL_DISABLE_DLOPEN_NOTE)
  46. * endif()
  47. * ```
  48. */
  49. #ifndef SDL_dlopennote_h
  50. #define SDL_dlopennote_h
  51. /**
  52. * Use this macro with SDL_ELF_NOTE_DLOPEN() to note that a dynamic shared
  53. * library dependency is optional.
  54. *
  55. * Optional functionality uses the dependency, the binary will work and the
  56. * dependency is only needed for full-featured installations.
  57. *
  58. * \since This macro is available since SDL 3.4.0.
  59. *
  60. * \sa SDL_ELF_NOTE_DLOPEN
  61. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED
  62. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED
  63. */
  64. #define SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED "suggested"
  65. /**
  66. * Use this macro with SDL_ELF_NOTE_DLOPEN() to note that a dynamic shared
  67. * library dependency is recommended.
  68. *
  69. * Important functionality needs the dependency, the binary will work but in
  70. * most cases the dependency should be provided.
  71. *
  72. * \since This macro is available since SDL 3.4.0.
  73. *
  74. * \sa SDL_ELF_NOTE_DLOPEN
  75. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
  76. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED
  77. */
  78. #define SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED "recommended"
  79. /**
  80. * Use this macro with SDL_ELF_NOTE_DLOPEN() to note that a dynamic shared
  81. * library dependency is required.
  82. *
  83. * Core functionality needs the dependency, the binary will not work if it
  84. * cannot be found.
  85. *
  86. * \since This macro is available since SDL 3.4.0.
  87. *
  88. * \sa SDL_ELF_NOTE_DLOPEN
  89. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
  90. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED
  91. */
  92. #define SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED "required"
  93. #if !defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_ANDROID)
  94. /* The dlopen note functionality isn't used on this platform */
  95. #ifndef SDL_DISABLE_DLOPEN_NOTES
  96. #define SDL_DISABLE_DLOPEN_NOTES
  97. #endif
  98. #elif defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1))
  99. /* gcc < 3.1 too old */
  100. #ifndef SDL_DISABLE_DLOPEN_NOTES
  101. #define SDL_DISABLE_DLOPEN_NOTES
  102. #endif
  103. #endif /* SDL_PLATFORM_UNIX || SDL_PLATFORM_ANDROID */
  104. #if defined(__ELF__) && !defined(SDL_DISABLE_DLOPEN_NOTES)
  105. #include <SDL3/SDL_stdinc.h>
  106. #define SDL_ELF_NOTE_DLOPEN_VENDOR "FDO"
  107. #define SDL_ELF_NOTE_DLOPEN_TYPE 0x407c0c0aU
  108. #define SDL_ELF_NOTE_INTERNAL2(json, variable_name) \
  109. __attribute__((aligned(4), used, section(".note.dlopen"))) \
  110. static const struct { \
  111. struct { \
  112. Uint32 n_namesz; \
  113. Uint32 n_descsz; \
  114. Uint32 n_type; \
  115. } nhdr; \
  116. char name[4]; \
  117. __attribute__((aligned(4))) char dlopen_json[sizeof(json)]; \
  118. } variable_name = { \
  119. { \
  120. sizeof(SDL_ELF_NOTE_DLOPEN_VENDOR), \
  121. sizeof(json), \
  122. SDL_ELF_NOTE_DLOPEN_TYPE \
  123. }, \
  124. SDL_ELF_NOTE_DLOPEN_VENDOR, \
  125. json \
  126. }
  127. #define SDL_ELF_NOTE_INTERNAL(json, variable_name) \
  128. SDL_ELF_NOTE_INTERNAL2(json, variable_name)
  129. #define SDL_DLNOTE_JSON_ARRAY1(N1) "[\"" N1 "\"]"
  130. #define SDL_DLNOTE_JSON_ARRAY2(N1,N2) "[\"" N1 "\",\"" N2 "\"]"
  131. #define SDL_DLNOTE_JSON_ARRAY3(N1,N2,N3) "[\"" N1 "\",\"" N2 "\",\"" N3 "\"]"
  132. #define SDL_DLNOTE_JSON_ARRAY4(N1,N2,N3,N4) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\"]"
  133. #define SDL_DLNOTE_JSON_ARRAY5(N1,N2,N3,N4,N5) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\"]"
  134. #define SDL_DLNOTE_JSON_ARRAY6(N1,N2,N3,N4,N5,N6) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\",\"" N6 "\"]"
  135. #define SDL_DLNOTE_JSON_ARRAY7(N1,N2,N3,N4,N5,N6,N7) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\",\"" N6 "\",\"" N7 "\"]"
  136. #define SDL_DLNOTE_JSON_ARRAY8(N1,N2,N3,N4,N5,N6,N7,N8) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\",\"" N6 "\",\"" N7 "\",\"" N8 "\"]"
  137. #define SDL_DLNOTE_JSON_ARRAY_GET(N1,N2,N3,N4,N5,N6,N7,N8,NAME,...) NAME
  138. #define SDL_DLNOTE_JSON_ARRAY(...) \
  139. SDL_DLNOTE_JSON_ARRAY_GET( \
  140. __VA_ARGS__, \
  141. SDL_DLNOTE_JSON_ARRAY8, \
  142. SDL_DLNOTE_JSON_ARRAY7, \
  143. SDL_DLNOTE_JSON_ARRAY6, \
  144. SDL_DLNOTE_JSON_ARRAY5, \
  145. SDL_DLNOTE_JSON_ARRAY4, \
  146. SDL_DLNOTE_JSON_ARRAY3, \
  147. SDL_DLNOTE_JSON_ARRAY2, \
  148. SDL_DLNOTE_JSON_ARRAY1 \
  149. )(__VA_ARGS__)
  150. /* Create "unique" variable name using __LINE__,
  151. * so creating multiple elf notes on the same line is not supported
  152. */
  153. #define SDL_DLNOTE_JOIN2(A,B) A##B
  154. #define SDL_DLNOTE_JOIN(A,B) SDL_DLNOTE_JOIN2(A,B)
  155. #define SDL_DLNOTE_UNIQUE_NAME SDL_DLNOTE_JOIN(s_SDL_dlopen_note_, __LINE__)
  156. /**
  157. * Add a note that your application has dynamic shared library dependencies.
  158. *
  159. * You can do this by adding the following to the global scope:
  160. *
  161. * ```c
  162. * SDL_ELF_NOTE_DLOPEN(
  163. * "png",
  164. * "Support for loading PNG images using libpng (required for APNG)",
  165. * SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
  166. * "libpng12.so.0"
  167. * )
  168. * ```
  169. *
  170. * A trailing semicolon is not needed.
  171. *
  172. * Or if you support multiple versions of a library, you can list them:
  173. *
  174. * ```c
  175. * // Our app supports SDL1, SDL2, and SDL3 by dynamically loading them
  176. * SDL_ELF_NOTE_DLOPEN(
  177. * "SDL",
  178. * "Create windows through SDL video backend",
  179. * SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED
  180. * "libSDL-1.2.so.0", "libSDL2-2.0.so.0", "libSDL3.so.0"
  181. * )
  182. * ```
  183. *
  184. * This macro is not available for compilers that do not support variadic
  185. * macro's.
  186. *
  187. * \since This macro is available since SDL 3.4.0.
  188. *
  189. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
  190. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED
  191. * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED
  192. */
  193. #define SDL_ELF_NOTE_DLOPEN(feature, description, priority, ...) \
  194. SDL_ELF_NOTE_INTERNAL( \
  195. "[{\"feature\":\"" feature \
  196. "\",\"description\":\"" description \
  197. "\",\"priority\":\"" priority \
  198. "\",\"soname\":" SDL_DLNOTE_JSON_ARRAY(__VA_ARGS__) "}]", \
  199. SDL_DLNOTE_UNIQUE_NAME);
  200. #elif defined(__GNUC__) && __GNUC__ < 3
  201. #define SDL_ELF_NOTE_DLOPEN(args...)
  202. #elif defined(_MSC_VER) && _MSC_VER < 1400
  203. /* Variadic macros are not supported */
  204. #else
  205. #define SDL_ELF_NOTE_DLOPEN(...)
  206. #endif
  207. #endif /* SDL_dlopennote_h */