From cd78cbac8610f0b72d60f97aca2382365694b158 Mon Sep 17 00:00:00 2001
From: Xavier Claessens <xavier.claessens@collabora.com>
Date: Tue, 13 Dec 2022 08:58:43 -0500
Subject: [PATCH] Fix API visibility macros

This copies the logic from GLib discussed there:
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2936

Beside being simpler, it also fix all public symbols being annotated
with dllexport when doing a static build, as discovered there:
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3540#note_1678335

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3567>
---
 subprojects/gst-devtools/validate/meson.build | 10 +--
 subprojects/gst-editing-services/meson.build  | 10 +--
 subprojects/gst-plugins-bad/meson.build       | 10 +--
 subprojects/gst-plugins-base/meson.build      | 10 +--
 subprojects/gst-rtsp-server/meson.build       | 10 +--
 subprojects/gstreamer/gst/gstconfig.h.in      | 76 ++++++++-----------
 .../libs/gst/check/libcheck/meson.build       | 10 +--
 subprojects/gstreamer/meson.build             | 18 +----
 8 files changed, 42 insertions(+), 112 deletions(-)

diff --git a/subprojects/gst-devtools/validate/meson.build b/subprojects/gst-devtools/validate/meson.build
index 17ca36a578..a7d1f3b841 100644
--- a/subprojects/gst-devtools/validate/meson.build
+++ b/subprojects/gst-devtools/validate/meson.build
@@ -17,18 +17,10 @@ if cc.has_header('unistd.h')
 endif
 
 # Symbol visibility
-if cc.get_id() == 'msvc'
-  export_define = '__declspec(dllexport) extern'
-elif cc.has_argument('-fvisibility=hidden')
+if cc.has_argument('-fvisibility=hidden')
   add_project_arguments('-fvisibility=hidden', language: 'c')
-  export_define = 'extern __attribute__ ((visibility ("default")))'
-else
-  export_define = 'extern'
 endif
 
-# Passing this through the command line would be too messy
-cdata.set('GST_API_EXPORT', export_define)
-
 configure_file(output : 'config.h', configuration : cdata)
 
 validate_plugins_install_dir = '@0@/gstreamer-1.0/validate'.format(get_option('libdir'))
diff --git a/subprojects/gst-editing-services/meson.build b/subprojects/gst-editing-services/meson.build
index d747094918..1fe7e6cc0c 100644
--- a/subprojects/gst-editing-services/meson.build
+++ b/subprojects/gst-editing-services/meson.build
@@ -74,18 +74,10 @@ if cc.has_link_argument('-Wl,-z,nodelete')
 endif
 
 # Symbol visibility
-if cc.get_id() == 'msvc'
-  export_define = '__declspec(dllexport) extern'
-elif cc.has_argument('-fvisibility=hidden')
+if cc.has_argument('-fvisibility=hidden')
   add_project_arguments('-fvisibility=hidden', language: 'c')
-  export_define = 'extern __attribute__ ((visibility ("default")))'
-else
-  export_define = 'extern'
 endif
 
-# Passing this through the command line would be too messy
-cdata.set('GST_API_EXPORT', export_define)
-
 # Disable strict aliasing
 if cc.has_argument('-fno-strict-aliasing')
   add_project_arguments('-fno-strict-aliasing', language: 'c')
diff --git a/subprojects/gst-plugins-bad/meson.build b/subprojects/gst-plugins-bad/meson.build
index 723d4d8918..afe9e1b58a 100644
--- a/subprojects/gst-plugins-bad/meson.build
+++ b/subprojects/gst-plugins-bad/meson.build
@@ -112,22 +112,14 @@ if cxx.has_link_argument('-Wl,-z,nodelete')
 endif
 
 # Symbol visibility
-if cc.get_id() == 'msvc'
-  export_define = '__declspec(dllexport) extern'
-elif cc.has_argument('-fvisibility=hidden')
+if cc.has_argument('-fvisibility=hidden')
   add_project_arguments('-fvisibility=hidden', language: 'c')
   add_project_arguments('-fvisibility=hidden', language: 'cpp')
   if have_objc
     add_project_arguments('-fvisibility=hidden', language: 'objc')
   endif
-  export_define = 'extern __attribute__ ((visibility ("default")))'
-else
-  export_define = 'extern'
 endif
 
-# Passing this through the command line would be too messy
-cdata.set('GST_API_EXPORT', export_define)
-
 # Disable strict aliasing
 if cc.has_argument('-fno-strict-aliasing')
   add_project_arguments('-fno-strict-aliasing', language: 'c')
diff --git a/subprojects/gst-plugins-base/meson.build b/subprojects/gst-plugins-base/meson.build
index e1ad9e1f33..1529aa74e7 100644
--- a/subprojects/gst-plugins-base/meson.build
+++ b/subprojects/gst-plugins-base/meson.build
@@ -105,21 +105,13 @@ core_conf = configuration_data()
 core_conf.set('ENABLE_NLS', 1)
 
 # Symbol visibility
-if cc.get_id() == 'msvc'
-  export_define = '__declspec(dllexport) extern'
-elif cc.has_argument('-fvisibility=hidden')
+if cc.has_argument('-fvisibility=hidden')
   add_project_arguments('-fvisibility=hidden', language: 'c')
   if have_objc
     add_project_arguments('-fvisibility=hidden', language: 'objc')
   endif
-  export_define = 'extern __attribute__ ((visibility ("default")))'
-else
-  export_define = 'extern'
 endif
 
-# Passing this through the command line would be too messy
-core_conf.set('GST_API_EXPORT', export_define)
-
 # Disable strict aliasing
 if cc.has_argument('-fno-strict-aliasing')
   add_project_arguments('-fno-strict-aliasing', language: 'c')
diff --git a/subprojects/gst-rtsp-server/meson.build b/subprojects/gst-rtsp-server/meson.build
index dd859f63b2..152b67813a 100644
--- a/subprojects/gst-rtsp-server/meson.build
+++ b/subprojects/gst-rtsp-server/meson.build
@@ -49,18 +49,10 @@ if cc.has_link_argument('-Wl,-z,nodelete')
 endif
 
 # Symbol visibility
-if cc.get_id() == 'msvc'
-  export_define = '__declspec(dllexport) extern'
-elif cc.has_argument('-fvisibility=hidden')
+if cc.has_argument('-fvisibility=hidden')
   add_project_arguments('-fvisibility=hidden', language: 'c')
-  export_define = 'extern __attribute__ ((visibility ("default")))'
-else
-  export_define = 'extern'
 endif
 
-# Passing this through the command line would be too messy
-cdata.set('GST_API_EXPORT', export_define)
-
 # Disable strict aliasing
 if cc.has_argument('-fno-strict-aliasing')
   add_project_arguments('-fno-strict-aliasing', language: 'c')
diff --git a/subprojects/gstreamer/gst/gstconfig.h.in b/subprojects/gstreamer/gst/gstconfig.h.in
index 19f680d4bc..df35b239c0 100644
--- a/subprojects/gstreamer/gst/gstconfig.h.in
+++ b/subprojects/gstreamer/gst/gstconfig.h.in
@@ -132,14 +132,26 @@
 #  error "Could not detect architecture; don't know whether it supports unaligned access! Please file a bug."
 #endif
 
-/**
- * GST_EXPORT:
- *
- * Export the given variable from the built shared object.
- *
- * On Windows, this exports the variable from the DLL.
- * On other platforms, this gets defined to "extern".
- */
+#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(GST_STATIC_COMPILATION)
+#  define _GST_EXPORT __declspec(dllexport)
+#  define _GST_IMPORT __declspec(dllimport)
+#elif __GNUC__ >= 4
+#  define _GST_EXPORT __attribute__((visibility("default")))
+#  define _GST_IMPORT
+#else
+#  define _GST_EXPORT
+#  define _GST_IMPORT
+#endif
+
+#define GST_API_EXPORT _GST_EXPORT extern
+#define GST_API_IMPORT _GST_IMPORT extern
+
+#ifdef BUILDING_GST
+#  define GST_API GST_API_EXPORT
+#else
+#  define GST_API GST_API_IMPORT
+#endif
+
 /**
  * GST_PLUGIN_EXPORT:
  *
@@ -148,45 +160,21 @@
  * On Windows, this exports the plugin definition from the DLL.
  * On other platforms, this gets defined as a no-op.
  */
-/* Only use __declspec(dllexport/import) when we have been built with MSVC or
- * the user is linking to us with MSVC. The only remaining case is when we were
- * built with MinGW and are linking with MinGW in which case we rely on the
- * linker to auto-export/import symbols. Of course all this is only used when
- * not linking statically.
+#define GST_PLUGIN_EXPORT _GST_EXPORT
+
+/**
+ * GST_EXPORT:
  *
- * NOTE: To link to GStreamer statically on Windows, you must define
- * GST_STATIC_COMPILATION or the prototypes will cause the compiler to search
- * for the symbol inside a DLL.
+ * Export the given variable from the built shared object.
+ *
+ * On Windows, this exports the variable from the DLL.
+ * On other platforms, this gets defined to "extern".
+ * Deprecated: 1.22: Applications should define their own export macros.
  */
-#if (@GSTCONFIG_BUILT_WITH_MSVC@ || defined(_MSC_VER)) && !defined(GST_STATIC_COMPILATION)
-# define GST_PLUGIN_EXPORT __declspec(dllexport)
-# ifdef GST_EXPORTS
-#  define GST_EXPORT __declspec(dllexport)
-# else
-#  define GST_EXPORT __declspec(dllimport) extern
-# endif
+#ifdef GST_EXPORTS
+#  define GST_EXPORT GST_API_EXPORT
 #else
-# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
-#  define GST_PLUGIN_EXPORT __attribute__ ((visibility ("default")))
-#  define GST_EXPORT extern __attribute__ ((visibility ("default")))
-# else
-#  define GST_PLUGIN_EXPORT
-#  define GST_EXPORT extern
-# endif
-#endif
-
-#if defined(_MSC_VER) && !defined(GST_STATIC_COMPILATION)
-# define GST_API_IMPORT __declspec(dllimport) extern
-#else
-# define GST_API_IMPORT extern
-#endif
-
-#ifndef GST_API
-# ifdef BUILDING_GST
-#  define GST_API GST_API_EXPORT        /* from config.h */
-# else
-#  define GST_API GST_API_IMPORT
-# endif
+#  define GST_EXPORT GST_API_IMPORT
 #endif
 
 /* These macros are used to mark deprecated functions in GStreamer headers,
diff --git a/subprojects/gstreamer/libs/gst/check/libcheck/meson.build b/subprojects/gstreamer/libs/gst/check/libcheck/meson.build
index 253d81878e..af6210b0a0 100644
--- a/subprojects/gstreamer/libs/gst/check/libcheck/meson.build
+++ b/subprojects/gstreamer/libs/gst/check/libcheck/meson.build
@@ -55,14 +55,12 @@ configure_file(input : 'check.h.in',
 internal_check_h_inc = include_directories('..')
 
 # Must explicitly make symbols public if default visibility is hidden
-if have_visibility_hidden
+if host_system in ['windows', 'cygwin'] and not static_build
+  libcheck_visibility_args = ['-DCK_DLL_EXP=extern __declspec(dllexport)']
+elif have_visibility_hidden
   libcheck_visibility_args = ['-DCK_DLL_EXP=extern __attribute__ ((visibility ("default")))']
 else
-  if host_system == 'windows'
-    libcheck_visibility_args = ['-DCK_DLL_EXP=__declspec(dllexport)']
-  else
-    libcheck_visibility_args = ['-DCK_DLL_EXP=extern']
-  endif
+  libcheck_visibility_args = ['-DCK_DLL_EXP=extern']
 endif
 
 no_warn_args = []
diff --git a/subprojects/gstreamer/meson.build b/subprojects/gstreamer/meson.build
index 32cb7aef9a..f6ea86c18a 100644
--- a/subprojects/gstreamer/meson.build
+++ b/subprojects/gstreamer/meson.build
@@ -93,19 +93,11 @@ endif
 
 # Symbol visibility
 have_visibility_hidden = false
-if cc.get_id() == 'msvc'
-  export_define = '__declspec(dllexport) extern'
-elif cc.has_argument('-fvisibility=hidden')
+if cc.has_argument('-fvisibility=hidden')
   add_project_arguments('-fvisibility=hidden', language: 'c')
-  export_define = 'extern __attribute__ ((visibility ("default")))'
   have_visibility_hidden = true
-else
-  export_define = 'extern'
 endif
 
-# Passing this through the command line would be too messy
-cdata.set('GST_API_EXPORT', export_define)
-
 # Disable strict aliasing
 if cc.has_argument('-fno-strict-aliasing')
   add_project_arguments('-fno-strict-aliasing', language: 'c')
@@ -362,14 +354,6 @@ endif
 # All supported platforms have long long now
 cdata.set('HAVE_LONG_LONG', 1)
 
-# We only want to use the __declspec(dllexport/import) dance in GST_EXPORT when
-# building with MSVC
-if cc.get_id() == 'msvc'
-  cdata.set('GSTCONFIG_BUILT_WITH_MSVC', 1)
-else
-  cdata.set('GSTCONFIG_BUILT_WITH_MSVC', 0)
-endif
-
 # -------------------------------------------------------------------------------------
 # config.h things needed by libcheck
 # -------------------------------------------------------------------------------------