Re: Use -fvisibility=hidden for shared libraries - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Use -fvisibility=hidden for shared libraries
Date
Msg-id 2499085.1641859296@sss.pgh.pa.us
Whole thread Raw
In response to Re: Use -fvisibility=hidden for shared libraries  (Andres Freund <andres@anarazel.de>)
Responses Re: Use -fvisibility=hidden for shared libraries
List pgsql-hackers
Andres Freund <andres@anarazel.de> writes:
> [ v2-0001-Use-hidden-visibility-for-shared-libraries-where-.patch ]

This seems like a good idea, but it's failing to apply right now,
mainly because of some cleanup I did in e04a8059a.  As far as I can
tell given the now-clarified meanings of PGDLLIMPORT/PGDLLEXPORT,
this patch shouldn't be touching PGDLLIMPORT.  The attached revision
works for me under gcc 8.5 and clang 13.

Also, it seemed like you'd maybe been more enthusiastic than necessary
about plastering PGDLLEXPORT on things.  I got through check-world
cleanly without the diffs in either ltree.h or worker_spi.c (although
I confess being confused why I didn't need the latter).  I didn't try
individually removing other diffs.  Those diffs are still in v3 below,
but we should clarify exactly which functions need marking.

            regards, tom lane

diff --git a/configure b/configure
index 3f2aea0d7d..98eabe8b08 100755
--- a/configure
+++ b/configure
@@ -735,6 +735,8 @@ CPP
 CFLAGS_SL
 BITCODE_CXXFLAGS
 BITCODE_CFLAGS
+CXXFLAGS_SL_MOD
+CFLAGS_SL_MOD
 CFLAGS_VECTORIZE
 CFLAGS_UNROLL_LOOPS
 PERMIT_DECLARATION_AFTER_STATEMENT
@@ -6288,6 +6290,154 @@ if test x"$pgac_cv_prog_CC_cflags__ftree_vectorize" = x"yes"; then
 fi


+  #
+  # If the compiler knows how to hide symbols, set CFLAGS_SL_MOD
+  # to the switch needed for that, and define HAVE_VISIBILITY_ATTRIBUTE.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -fvisibility=hidden, for CFLAGS_SL_MOD" >&5
+$as_echo_n "checking whether ${CC} supports -fvisibility=hidden, for CFLAGS_SL_MOD... " >&6; }
+if ${pgac_cv_prog_CC_cflags__fvisibility_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS_SL_MOD} -fvisibility=hidden"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__fvisibility_hidden=yes
+else
+  pgac_cv_prog_CC_cflags__fvisibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__fvisibility_hidden" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__fvisibility_hidden" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__fvisibility_hidden" = x"yes"; then
+  CFLAGS_SL_MOD="${CFLAGS_SL_MOD} -fvisibility=hidden"
+fi
+
+
+  if test "$pgac_cv_prog_CC_cflags__fvisibility_hidden" = yes; then
+
+$as_echo "#define HAVE_VISIBILITY_ATTRIBUTE 1" >>confdefs.h
+
+  fi
+  # For C++ we additionally want -fvisibility-inlines-hidden
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -fvisibility=hidden, for CXXFLAGS_SL_MOD"
>&5
+$as_echo_n "checking whether ${CXX} supports -fvisibility=hidden, for CXXFLAGS_SL_MOD... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__fvisibility_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS_SL_MOD} -fvisibility=hidden"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__fvisibility_hidden=yes
+else
+  pgac_cv_prog_CXX_cxxflags__fvisibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__fvisibility_hidden" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__fvisibility_hidden" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_hidden" = x"yes"; then
+  CXXFLAGS_SL_MOD="${CXXFLAGS_SL_MOD} -fvisibility=hidden"
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -fvisibility-inlines-hidden, for
CXXFLAGS_SL_MOD">&5 
+$as_echo_n "checking whether ${CXX} supports -fvisibility-inlines-hidden, for CXXFLAGS_SL_MOD... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS_SL_MOD} -fvisibility-inlines-hidden"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden=yes
+else
+  pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" = x"yes"; then
+  CXXFLAGS_SL_MOD="${CXXFLAGS_SL_MOD} -fvisibility-inlines-hidden"
+fi
+
   #
   # The following tests want to suppress various unhelpful warnings by adding
   # -Wno-foo switches.  But gcc won't complain about unrecognized -Wno-foo
@@ -6940,6 +7090,8 @@ fi



+
+
 # Determine flags used to emit bitcode for JIT inlining.
 # 1. We must duplicate any behaviour-changing compiler flags used above,
 # to keep compatibility with the compiler used for normal Postgres code.
diff --git a/configure.ac b/configure.ac
index 95287705f6..b39d9c64f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -523,6 +523,17 @@ if test "$GCC" = yes -a "$ICC" = no; then
   # Optimization flags for specific files that benefit from vectorization
   PGAC_PROG_CC_VAR_OPT(CFLAGS_VECTORIZE, [-ftree-vectorize])
   #
+  # If the compiler knows how to hide symbols, set CFLAGS_SL_MOD
+  # to the switch needed for that, and define HAVE_VISIBILITY_ATTRIBUTE.
+  PGAC_PROG_CC_VAR_OPT(CFLAGS_SL_MOD, [-fvisibility=hidden])
+  if test "$pgac_cv_prog_CC_cflags__fvisibility_hidden" = yes; then
+     AC_DEFINE([HAVE_VISIBILITY_ATTRIBUTE], 1,
+               [Define to 1 if your compiler knows the visibility("hidden") attribute.])
+  fi
+  # For C++ we additionally want -fvisibility-inlines-hidden
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MOD, [-fvisibility=hidden])
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MOD, [-fvisibility-inlines-hidden])
+  #
   # The following tests want to suppress various unhelpful warnings by adding
   # -Wno-foo switches.  But gcc won't complain about unrecognized -Wno-foo
   # switches, so we have to test for the positive form and if that works,
@@ -576,6 +587,8 @@ fi

 AC_SUBST(CFLAGS_UNROLL_LOOPS)
 AC_SUBST(CFLAGS_VECTORIZE)
+AC_SUBST(CFLAGS_SL_MOD)
+AC_SUBST(CXXFLAGS_SL_MOD)

 # Determine flags used to emit bitcode for JIT inlining.
 # 1. We must duplicate any behaviour-changing compiler flags used above,
diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index bf4a565ed9..625134c9f6 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -147,7 +147,7 @@ typedef struct
     } while (0)

 /* DatumGetHStoreP includes support for reading old-format hstore values */
-extern HStore *hstoreUpgrade(Datum orig);
+extern PGDLLEXPORT HStore *hstoreUpgrade(Datum orig);

 #define DatumGetHStoreP(d) hstoreUpgrade(d)

@@ -168,14 +168,14 @@ typedef struct
     bool        needfree;        /* need to pfree the value? */
 } Pairs;

-extern int    hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen);
-extern HStore *hstorePairs(Pairs *pairs, int32 pcount, int32 buflen);
+extern PGDLLEXPORT int    hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen);
+extern PGDLLEXPORT HStore *hstorePairs(Pairs *pairs, int32 pcount, int32 buflen);

-extern size_t hstoreCheckKeyLen(size_t len);
-extern size_t hstoreCheckValLen(size_t len);
+extern PGDLLEXPORT size_t hstoreCheckKeyLen(size_t len);
+extern PGDLLEXPORT size_t hstoreCheckValLen(size_t len);

-extern int    hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
-extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
+extern PGDLLEXPORT int    hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
+extern PGDLLEXPORT Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);

 #define HStoreContainsStrategyNumber    7
 #define HStoreExistsStrategyNumber        9
@@ -194,7 +194,7 @@ extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
 #if HSTORE_POLLUTE_NAMESPACE
 #define HSTORE_POLLUTE(newname_,oldname_) \
     PG_FUNCTION_INFO_V1(oldname_);          \
-    Datum newname_(PG_FUNCTION_ARGS);      \
+    extern PGDLLEXPORT Datum newname_(PG_FUNCTION_ARGS);      \
     Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
     extern int no_such_variable
 #else
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index 5b4be5e680..d8bcdedbdb 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -176,30 +176,30 @@ typedef struct


 /* use in array iterator */
-Datum        ltree_isparent(PG_FUNCTION_ARGS);
-Datum        ltree_risparent(PG_FUNCTION_ARGS);
-Datum        ltq_regex(PG_FUNCTION_ARGS);
-Datum        ltq_rregex(PG_FUNCTION_ARGS);
-Datum        lt_q_regex(PG_FUNCTION_ARGS);
-Datum        lt_q_rregex(PG_FUNCTION_ARGS);
-Datum        ltxtq_exec(PG_FUNCTION_ARGS);
-Datum        ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum        _ltq_regex(PG_FUNCTION_ARGS);
-Datum        _ltq_rregex(PG_FUNCTION_ARGS);
-Datum        _lt_q_regex(PG_FUNCTION_ARGS);
-Datum        _lt_q_rregex(PG_FUNCTION_ARGS);
-Datum        _ltxtq_exec(PG_FUNCTION_ARGS);
-Datum        _ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum        _ltree_isparent(PG_FUNCTION_ARGS);
-Datum        _ltree_risparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltree_isparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltree_risparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltq_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltq_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        lt_q_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        lt_q_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltxtq_exec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltxtq_rexec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _ltq_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _ltq_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _lt_q_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _lt_q_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _ltxtq_exec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _ltxtq_rexec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _ltree_isparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        _ltree_risparent(PG_FUNCTION_ARGS);

 /* Concatenation functions */
-Datum        ltree_addltree(PG_FUNCTION_ARGS);
-Datum        ltree_addtext(PG_FUNCTION_ARGS);
-Datum        ltree_textadd(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltree_addltree(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltree_addtext(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltree_textadd(PG_FUNCTION_ARGS);

 /* Util function */
-Datum        ltree_in(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum        ltree_in(PG_FUNCTION_ARGS);

 bool        ltree_execute(ITEM *curitem, void *checkval,
                           bool calcnot, bool (*chkcond) (void *checkval, ITEM *val));
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 05c54b27de..aa153faaaf 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -259,6 +259,8 @@ SUN_STUDIO_CC = @SUN_STUDIO_CC@
 CXX = @CXX@
 CFLAGS = @CFLAGS@
 CFLAGS_SL = @CFLAGS_SL@
+CFLAGS_SL_MOD = @CFLAGS_SL_MOD@
+CXXFLAGS_SL_MOD = @CXXFLAGS_SL_MOD@
 CFLAGS_UNROLL_LOOPS = @CFLAGS_UNROLL_LOOPS@
 CFLAGS_VECTORIZE = @CFLAGS_VECTORIZE@
 CFLAGS_SSE42 = @CFLAGS_SSE42@
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 551023c6fb..9119e9bb5d 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -253,6 +253,19 @@ ifeq ($(PORTNAME), win32)
 endif


+# If the shared library doesn't have an export file, mark all symbols not
+# explicitly exported using PGDLLEXPORT as hidden. We can't pass these flags
+# when building a library with explicit exports, as the symbols would be
+# hidden before the linker script / exported symbol list takes effect.
+#
+# XXX: This probably isn't the best location, but not clear where else
+# instead?
+ifeq ($(SHLIB_EXPORTS),)
+  LDFLAGS += $(CFLAGS_SL_MOD)
+  override CFLAGS += $(CFLAGS_SL_MOD)
+  override CXXFLAGS += $(CXXFLAGS_SL_MOD)
+endif
+

 ##
 ## BUILD
diff --git a/src/include/c.h b/src/include/c.h
index 4f16e589b3..b713123b61 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1336,14 +1336,19 @@ extern unsigned long long strtoull(const char *str, char **endptr, int base);

 /*
  * Use "extern PGDLLEXPORT ..." to declare functions that are defined in
- * loadable modules and need to be callable by the core backend.  (Usually,
- * this is not necessary because our build process automatically exports
- * such symbols, but sometimes manual marking is required.)
- * No special marking is required on most ports.
+ * loadable modules and need to be callable by the core backend or other
+ * loadable modules.
+ * If the compiler knows __attribute__((visibility("*"))), we use that,
+ * unless we already have a platform-specific definition.  Otherwise,
+ * no special marking is required.
  */
 #ifndef PGDLLEXPORT
+#ifdef HAVE_VISIBILITY_ATTRIBUTE
+#define PGDLLEXPORT __attribute__((visibility("default")))
+#else
 #define PGDLLEXPORT
 #endif
+#endif

 /*
  * The following is used as the arg list for signal handlers.  Any ports
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 6560e462d6..3c813559f3 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -413,7 +413,7 @@ typedef const Pg_finfo_record *(*PGFInfoFunction) (void);
  *    info function, since authors shouldn't need to be explicitly aware of it.
  */
 #define PG_FUNCTION_INFO_V1(funcname) \
-extern Datum funcname(PG_FUNCTION_ARGS); \
+extern PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS); \
 extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
 const Pg_finfo_record * \
 CppConcat(pg_finfo_,funcname) (void) \
@@ -424,6 +424,16 @@ CppConcat(pg_finfo_,funcname) (void) \
 extern int no_such_variable


+/*
+ * Declare _PG_init/_PG_fini centrally. Historically each shared library had
+ * its own declaration, but now that we want to mark the symbols PGDLLEXPORT,
+ * the central declaration helps find extensions with local declarations
+ * missing PGDLLEXPORT.
+ */
+extern PGDLLEXPORT void _PG_init(void);
+extern PGDLLEXPORT void _PG_fini(void);
+
+
 /*-------------------------------------------------------------------------
  *        Support for verifying backend compatibility of loaded modules
  *
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index 707176d9ed..5870ec6d7b 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -63,7 +63,7 @@ typedef struct JitContext

 typedef struct JitProviderCallbacks JitProviderCallbacks;

-extern void _PG_jit_provider_init(JitProviderCallbacks *cb);
+extern PGDLLEXPORT void _PG_jit_provider_init(JitProviderCallbacks *cb);
 typedef void (*JitProviderInit) (JitProviderCallbacks *cb);
 typedef void (*JitProviderResetAfterErrorCB) (void);
 typedef void (*JitProviderReleaseContextCB) (JitContext *context);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 9d9bd6b9ef..28b22bd8d6 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -701,6 +701,9 @@
 /* Define to 1 if you have the <uuid/uuid.h> header file. */
 #undef HAVE_UUID_UUID_H

+/* Define to 1 if your compiler knows the visibility("hidden") attribute. */
+#undef HAVE_VISIBILITY_ATTRIBUTE
+
 /* Define to 1 if you have the `wcstombs_l' function. */
 #undef HAVE_WCSTOMBS_L

diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h
index 41157fda7c..490aa50825 100644
--- a/src/include/replication/output_plugin.h
+++ b/src/include/replication/output_plugin.h
@@ -35,6 +35,8 @@ typedef struct OutputPluginOptions
  */
 typedef void (*LogicalOutputPluginInit) (struct OutputPluginCallbacks *cb);

+extern PGDLLEXPORT void _PG_output_plugin_init(struct OutputPluginCallbacks *cb);
+
 /*
  * Callback that gets called in a user-defined plugin. ctx->private_data can
  * be set to some private data.
diff --git a/src/pl/plpython/plpy_elog.h b/src/pl/plpython/plpy_elog.h
index e02ef4ffe9..aeade82ce1 100644
--- a/src/pl/plpython/plpy_elog.h
+++ b/src/pl/plpython/plpy_elog.h
@@ -34,13 +34,13 @@ extern PyObject *PLy_exc_spi_error;
     } while(0)
 #endif                            /* HAVE__BUILTIN_CONSTANT_P */

-extern void PLy_elog_impl(int elevel, const char *fmt,...) pg_attribute_printf(2, 3);
+extern PGDLLEXPORT void PLy_elog_impl(int elevel, const char *fmt,...) pg_attribute_printf(2, 3);

-extern void PLy_exception_set(PyObject *exc, const char *fmt,...) pg_attribute_printf(2, 3);
+extern PGDLLEXPORT void PLy_exception_set(PyObject *exc, const char *fmt,...) pg_attribute_printf(2, 3);

-extern void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural,
+extern PGDLLEXPORT void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural,
                                      unsigned long n,...) pg_attribute_printf(2, 5) pg_attribute_printf(3, 5);

-extern void PLy_exception_set_with_details(PyObject *excclass, ErrorData *edata);
+extern PGDLLEXPORT void PLy_exception_set_with_details(PyObject *excclass, ErrorData *edata);

 #endif                            /* PLPY_ELOG_H */
diff --git a/src/pl/plpython/plpy_typeio.h b/src/pl/plpython/plpy_typeio.h
index d11e6ae1b8..87e3b2c464 100644
--- a/src/pl/plpython/plpy_typeio.h
+++ b/src/pl/plpython/plpy_typeio.h
@@ -147,29 +147,29 @@ struct PLyObToDatum
 };


-extern PyObject *PLy_input_convert(PLyDatumToOb *arg, Datum val);
-extern Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val,
+extern PGDLLEXPORT PyObject *PLy_input_convert(PLyDatumToOb *arg, Datum val);
+extern PGDLLEXPORT Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val,
                                 bool *isnull);

-extern PyObject *PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple,
+extern PGDLLEXPORT PyObject *PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple,
                                       TupleDesc desc, bool include_generated);

-extern void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
+extern PGDLLEXPORT void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
                                  Oid typeOid, int32 typmod,
                                  struct PLyProcedure *proc);
-extern void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
+extern PGDLLEXPORT void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
                                   Oid typeOid, int32 typmod,
                                   struct PLyProcedure *proc);

-extern void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc,
+extern PGDLLEXPORT void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc,
                                   struct PLyProcedure *proc);
-extern void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc,
+extern PGDLLEXPORT void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc,
                                    struct PLyProcedure *proc);

-extern void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc,
+extern PGDLLEXPORT void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc,
                                     struct PLyProcedure *proc);

 /* conversion from Python objects to C strings --- exported for transforms */
-extern char *PLyObject_AsString(PyObject *plrv);
+extern PGDLLEXPORT char *PLyObject_AsString(PyObject *plrv);

 #endif                            /* PLPY_TYPEIO_H */
diff --git a/src/pl/plpython/plpy_util.h b/src/pl/plpython/plpy_util.h
index c9ba7edc0e..6927601e0b 100644
--- a/src/pl/plpython/plpy_util.h
+++ b/src/pl/plpython/plpy_util.h
@@ -8,12 +8,12 @@

 #include "plpython.h"

-extern PyObject *PLyUnicode_Bytes(PyObject *unicode);
-extern char *PLyUnicode_AsString(PyObject *unicode);
+extern PGDLLEXPORT PyObject *PLyUnicode_Bytes(PyObject *unicode);
+extern PGDLLEXPORT char *PLyUnicode_AsString(PyObject *unicode);

 #if PY_MAJOR_VERSION >= 3
-extern PyObject *PLyUnicode_FromString(const char *s);
-extern PyObject *PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size);
+extern PGDLLEXPORT PyObject *PLyUnicode_FromString(const char *s);
+extern PGDLLEXPORT PyObject *PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size);
 #endif

 #endif                            /* PLPY_UTIL_H */
diff --git a/src/test/modules/test_shm_mq/test_shm_mq.h b/src/test/modules/test_shm_mq/test_shm_mq.h
index 0310caf50b..8f97be78d3 100644
--- a/src/test/modules/test_shm_mq/test_shm_mq.h
+++ b/src/test/modules/test_shm_mq/test_shm_mq.h
@@ -40,6 +40,6 @@ extern void test_shm_mq_setup(int64 queue_size, int32 nworkers,
                               shm_mq_handle **input);

 /* Main entrypoint for a worker. */
-extern void test_shm_mq_main(Datum) pg_attribute_noreturn();
+extern PGDLLEXPORT void test_shm_mq_main(Datum) pg_attribute_noreturn();

 #endif
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 05ced63780..a1f4dbaf3f 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -47,7 +47,7 @@ PG_MODULE_MAGIC;
 PG_FUNCTION_INFO_V1(worker_spi_launch);

 void        _PG_init(void);
-void        worker_spi_main(Datum) pg_attribute_noreturn();
+PGDLLEXPORT void worker_spi_main(Datum) pg_attribute_noreturn();

 /* GUC variables */
 static int    worker_spi_naptime = 10;
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index e47c2d648c..e076fa2a92 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -429,6 +429,7 @@ sub GenerateFiles
         HAVE_WINLDAP_H                           => undef,
         HAVE_WCSTOMBS_L                          => 1,
         HAVE_WCTYPE_H                            => 1,
+        HAVE_VISIBILITY_ATTRIBUTE                => undef,
         HAVE_WRITEV                              => undef,
         HAVE_X509_GET_SIGNATURE_NID              => 1,
         HAVE_X86_64_POPCNTQ                      => undef,

pgsql-hackers by date:

Previous
From: Zhihong Yu
Date:
Subject: Re: null iv parameter passed to combo_init()
Next
From: Jacob Champion
Date:
Subject: Re: sepgsql logging