Hi, Currently postgres builds extension shared libraries (i.e. pretty much everything but libpq) with global visibilty. I.e. symbols that are not static will be visible from outside the shared library.
On the one platform where that behaviour is not available, namely windows, we emulate it by analyzing the input files to the shared library and exporting all the symbols therein. For the meson build [1] proposal that turned out to be a bit more verbose to implement than I'd liked. Thinking about the problem I realized that, at least I think so, there's really no good reason to force-export symbols in our shared libraries: Because the number of symbols required from shared libraries is typically small, and the majority of the symbols are generated via PG_FUNCTION_INFO_V1, it isn't a lot of work to explicitly export the necessary symbols. I think this is a much more feasible proposal than, as has been suggested in the past, using explicit visibility for the entire backend. The amount of functions that'd need to be annotated in the backend is huge, and I don't think we have a reasonable starting point for limiting what we'd export. There are a few extension libs that need manual export annotations. These are libraries that are not just referenced by the backend, but also from other extensions, e.g. for transforms. The patch e.g. reduces the number of exported symbols for - plpython: 61 -> 29 - plperl: 32 -> 17 - llvmjit: 84 -> 5 - postgres_fdw: 48 -> 15 - dict_snowball: 182 -> 8 Besides the smaller number of symbols (which can impact library load times a bit, although the numbers here are likely small enough to not matter), using -fvisibility=hidden also can improve code generation, because it allows the compiler & linker to generate a plain function call, rather than having to go through the elf symbol-interposition table. The attached patch is a prototype of this idea. Greetings, Andres Freund [1] https://www.postgresql.org/message-id/20211012083721.hvixq4pnh2pixr3j%40alap3.anarazel.de
>From a5a1d25c3e9773edda5fbb73c04c4c13fece72e2 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sun, 31 Oct 2021 18:02:16 -0700 Subject: [PATCH v2 1/3] Use hidden visibility for shared libraries where possible. --- configure | 153 +++++++++++++++++++++ configure.ac | 14 ++ contrib/hstore/hstore.h | 16 +-- contrib/ltree/ltree.h | 40 +++--- src/Makefile.global.in | 2 + src/Makefile.shlib | 13 ++ src/include/c.h | 15 +- src/include/fmgr.h | 12 +- src/include/jit/jit.h | 2 +- src/include/pg_config.h.in | 3 + src/include/replication/output_plugin.h | 2 + src/pl/plpython/plpy_elog.h | 8 +- src/pl/plpython/plpy_typeio.h | 18 +-- src/pl/plpython/plpy_util.h | 8 +- src/test/modules/test_shm_mq/test_shm_mq.h | 2 +- src/test/modules/worker_spi/worker_spi.c | 2 +- src/tools/msvc/Solution.pm | 1 + 17 files changed, 258 insertions(+), 53 deletions(-) diff --git a/configure b/configure index 4ffefe46552..9057791eb00 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 @@ -6421,6 +6423,155 @@ fi if test -n "$NOT_THE_CFLAGS"; then CFLAGS="$CFLAGS -Wno-stringop-truncation" fi + + # If the compiler knows how to hide symbols, use that. But only for shared libraries, + # for postgres itself that'd be too verbose for now. + { $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 + + elif test "$ICC" = yes; then # Intel's compiler has a bug/misoptimization in checking for # division by NAN (NaN == 0), -mp1 fixes it, so add it to the CFLAGS. @@ -6890,6 +7041,8 @@ fi + + # Determine flags used to emit bitcode for JIT inlining. Need to test # for behaviour changing compiler flags, to keep compatibility with # compiler used for normal postgres code. diff --git a/configure.ac b/configure.ac index 44ee3ebe2f1..b5cc312c3d5 100644 --- a/configure.ac +++ b/configure.ac @@ -541,6 +541,18 @@ if test "$GCC" = yes -a "$ICC" = no; then if test -n "$NOT_THE_CFLAGS"; then CFLAGS="$CFLAGS -Wno-stringop-truncation" fi + + # If the compiler knows how to hide symbols, use that. But only for shared libraries, + # for postgres itself that'd be too verbose for now. + 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]) + elif test "$ICC" = yes; then # Intel's compiler has a bug/misoptimization in checking for # division by NAN (NaN == 0), -mp1 fixes it, so add it to the CFLAGS. @@ -564,6 +576,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. Need to test # for behaviour changing compiler flags, to keep compatibility with diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h index bf4a565ed9b..625134c9f69 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 5b4be5e680a..d8bcdedbdbe 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 533c12fef95..fbd2f2eab3d 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 551023c6fb0..9119e9bb5d6 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 c8ede082739..9b539a2657b 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -1312,11 +1312,18 @@ extern long long strtoll(const char *str, char **endptr, int base); extern unsigned long long strtoull(const char *str, char **endptr, int base); #endif -/* no special DLL markers on most ports */ -#ifndef PGDLLIMPORT -#define PGDLLIMPORT +/* + * If the platform knows __attribute__((visibility("*"))), i.e. gcc like + * compilers, we use that. + */ +#if !defined(PGDLLIMPORT) && defined(HAVE_VISIBILITY_ATTRIBUTE) +#define PGDLLIMPORT __attribute__((visibility("default"))) +#define PGDLLEXPORT __attribute__((visibility("default"))) #endif -#ifndef PGDLLEXPORT + +/* No special DLL markers on the remaining ports. */ +#if !defined(PGDLLIMPORT) +#define PGDLLIMPORT #define PGDLLEXPORT #endif diff --git a/src/include/fmgr.h b/src/include/fmgr.h index ab7b85c86e1..e200a4170a9 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 b634df30b98..74617ad1b64 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 15ffdd895aa..e3ab1c7752f 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -710,6 +710,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 810495ed0e4..a087f14dadd 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 e02ef4ffe9f..aeade82ce10 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 d11e6ae1b89..87e3b2c464e 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 c9ba7edc0ec..6927601e0be 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 a6661218347..a7a36714a48 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 0b6246676b6..e267bc3cffa 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 43fd1be0888..7ce250ea332 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -432,6 +432,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, -- 2.23.0.385.gbc12974a89