From ea53100d5671b5b243f77898b0b04d23c38b2820 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 27 Sep 2018 11:23:43 -0400 Subject: [PATCH] Build src/port files as a library with -fPIC, and use that in libpq. libpq and ecpg need shared-library-friendly versions of assorted src/port/ and src/common/ modules. Up to now, they got those by symlinking the individual source files and compiling them locally. That's baroque, and a pain to maintain, and it results in some amount of duplicated compile work. It might've made sense when only a couple of files were needed, but the list has grown and grown and grown :-( It makes more sense to have the originating directory build a third variant of libpgport.a/libpgcommon.a containing modules built with $(CFLAGS_SL), and just link that into the shared library. Unused files won't get linked, so the end result should be the same. This patch makes a down payment on that idea by having src/port/ build such a library and making libpq use it. If the buildfarm doesn't expose fatal problems with the approach, I'll extend it to the other cases. Discussion: https://postgr.es/m/13022.1538003440@sss.pgh.pa.us --- src/interfaces/libpq/.gitignore | 21 ------------- src/interfaces/libpq/Makefile | 41 +++++++----------------- src/port/.gitignore | 1 + src/port/Makefile | 55 ++++++++++++++++++++++++++------- 4 files changed, 55 insertions(+), 63 deletions(-) diff --git a/src/interfaces/libpq/.gitignore b/src/interfaces/libpq/.gitignore index ce1576e262..8885e91e53 100644 --- a/src/interfaces/libpq/.gitignore +++ b/src/interfaces/libpq/.gitignore @@ -1,27 +1,6 @@ /exports.list /libpq.rc # .c files that are symlinked in from elsewhere -/chklocale.c -/crypt.c -/erand48.c -/getaddrinfo.c -/getpeereid.c -/inet_aton.c -/inet_net_ntop.c -/noblock.c -/open.c -/system.c -/pgsleep.c -/pg_strong_random.c -/pgstrcasecmp.c -/pqsignal.c -/snprintf.c -/strerror.c -/strlcpy.c -/strnlen.c -/thread.c -/win32error.c -/win32setlocale.c /ip.c /md5.c /base64.c diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index ef8abaf301..769c58b386 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -24,27 +24,11 @@ ifneq ($(PORTNAME), win32) override CFLAGS += $(PTHREAD_CFLAGS) endif -# Need to recompile any external C files because we need -# all object files to use the same compile flags as libpq; some -# platforms require special flags. -LIBS := $(LIBS:-lpgport=) - # We can't use Makefile variables here because the MSVC build system scrapes # OBJS from this file. OBJS= fe-auth.o fe-auth-scram.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ fe-protocol2.o fe-protocol3.o pqexpbuffer.o fe-secure.o \ libpq-events.o -# libpgport C files we always use -OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \ - snprintf.o strerror.o thread.o -# libpgport C files that are needed if identified by configure -OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o strlcpy.o strnlen.o win32error.o win32setlocale.o, $(LIBOBJS)) - -ifeq ($(enable_strong_random), yes) -OBJS += pg_strong_random.o -else -OBJS += erand48.o -endif # src/backend/utils/mb OBJS += encnames.o wchar.o @@ -62,8 +46,7 @@ override shlib = cyg$(NAME)$(DLSUFFIX) endif ifeq ($(PORTNAME), win32) -# pgsleep.o is from libpgport -OBJS += pgsleep.o win32.o libpqrc.o +OBJS += win32.o libpqrc.o libpqrc.o: libpq.rc $(WINDRES) -i $< -o $@ @@ -76,11 +59,12 @@ endif # Add libraries that libpq depends (or might depend) on into the # shared library link. (The order in which you list them here doesn't -# matter.) +# matter.) Note that we filter out -lpgport from LIBS and instead +# insert -lpgport_shlib, to get port files that are built correctly. ifneq ($(PORTNAME), win32) -SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi_krb5 -lgss -lgssapi -lssl -lsocket -lnsl -lresolv -lintl -lm, $(LIBS)) $(LDAP_LIBS_FE) $(PTHREAD_LIBS) +SHLIB_LINK += -lpgport_shlib $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi_krb5 -lgss -lgssapi -lssl -lsocket -lnsl -lresolv -lintl -lm, $(LIBS)) $(LDAP_LIBS_FE) $(PTHREAD_LIBS) else -SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl -lm $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE) +SHLIB_LINK += -lpgport_shlib $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl -lm $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE) endif ifeq ($(PORTNAME), win32) SHLIB_LINK += -lshell32 -lws2_32 -lsecur32 $(filter -leay32 -lssleay32 -lcomerr32 -lkrb5_32, $(LIBS)) @@ -90,22 +74,19 @@ SHLIB_EXPORTS = exports.txt all: all-lib +all-lib: | submake-libpgport + # Shared library stuff include $(top_srcdir)/src/Makefile.shlib backend_src = $(top_srcdir)/src/backend -# We use several libpgport and backend modules verbatim, but since we need +# We use a few backend modules verbatim, but since we need # to compile with appropriate options to build a shared lib, we can't -# necessarily use the same object files built for libpgport and the backend. +# use the same object files built for the backend. # Instead, symlink the source files in here and build our own object files. -# For some libpgport modules, this only happens if configure decides -# the module is needed (see filter hack in OBJS, above). # When you add a file here, remember to add it in the "clean" target below. -chklocale.c crypt.c erand48.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pg_strong_random.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c strnlen.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/% - rm -f $@ && $(LN_S) $< . - ip.c md5.c base64.c link-canary.c scram-common.c sha2.c sha2_openssl.c saslprep.c unicode_norm.c: % : $(top_srcdir)/src/common/% rm -f $@ && $(LN_S) $< . @@ -123,6 +104,7 @@ libpq.rc libpq-dist.rc: libpq.rc.in # installations and is only updated by distprep.) libpq.rc: $(top_builddir)/src/Makefile.global +# Make dependencies on pg_config_paths.h visible, too. fe-connect.o: fe-connect.c $(top_builddir)/src/port/pg_config_paths.h fe-misc.o: fe-misc.c $(top_builddir)/src/port/pg_config_paths.h @@ -154,8 +136,7 @@ clean distclean: clean-lib rm -f $(OBJS) pthread.h libpq.rc # Might be left over from a Win32 client-only build rm -f pg_config_paths.h -# Remove files we (may have) symlinked in from src/port and other places - rm -f chklocale.c crypt.c erand48.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pg_strong_random.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c strnlen.c thread.c win32error.c win32setlocale.c +# Remove files we (may have) symlinked in from src/common and other places rm -f ip.c md5.c base64.c link-canary.c scram-common.c sha2.c sha2_openssl.c saslprep.c unicode_norm.c rm -f encnames.c wchar.c diff --git a/src/port/.gitignore b/src/port/.gitignore index 53a4032444..2037b7d2ab 100644 --- a/src/port/.gitignore +++ b/src/port/.gitignore @@ -1,3 +1,4 @@ /libpgport.a +/libpgport_shlib.a /libpgport_srv.a /pg_config_paths.h diff --git a/src/port/Makefile b/src/port/Makefile index a2ee8e2d6d..ec62a31d29 100644 --- a/src/port/Makefile +++ b/src/port/Makefile @@ -1,18 +1,23 @@ #------------------------------------------------------------------------- # # Makefile -# Makefile for the port-specific subsystem of the backend +# Makefile for src/port # -# These files are used in other directories for portability on systems -# with broken/missing library files, and for common code sharing. +# These files are used by the Postgres backend, and also by frontend +# programs. Primarily, they are meant to provide portability on systems +# with broken/missing library files. # -# This makefile generates two outputs: +# This makefile generates three outputs: # # libpgport.a - contains object files with FRONTEND defined, -# for use by client application and libraries +# for use by client applications +# +# libpgport_shlib.a - contains object files with FRONTEND defined, +# built suitably for use in shared libraries; for use +# by libpq and other frontend libraries # # libpgport_srv.a - contains object files without FRONTEND defined, -# for use only by the backend binaries +# for use only by the backend # # LIBOBJS is set by configure (via Makefile.global) to be the list of object # files that are conditionally needed as determined by configure's probing. @@ -40,12 +45,15 @@ ifeq ($(enable_strong_random), yes) OBJS += pg_strong_random.o endif -# foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND +# libpgport.a, libpgport_shlib.a, and libpgport_srv.a contain the same files +# foo.o, foo_shlib.o, and foo_srv.o are all built from foo.c +OBJS_SHLIB = $(OBJS:%.o=%_shlib.o) OBJS_SRV = $(OBJS:%.o=%_srv.o) -all: libpgport.a libpgport_srv.a +all: libpgport.a libpgport_shlib.a libpgport_srv.a # libpgport is needed by some contrib +# currently we don't install libpgport_shlib.a, maybe we should? install: all installdirs $(INSTALL_STLIB) libpgport.a '$(DESTDIR)$(libdir)/libpgport.a' @@ -59,17 +67,37 @@ libpgport.a: $(OBJS) rm -f $@ $(AR) $(AROPT) $@ $^ -# thread.o needs PTHREAD_CFLAGS (but thread_srv.o does not) +# thread.o and thread_shlib.o need PTHREAD_CFLAGS (but thread_srv.o does not) thread.o: CFLAGS+=$(PTHREAD_CFLAGS) +thread_shlib.o: CFLAGS+=$(PTHREAD_CFLAGS) -# pg_crc32c_sse42.o and its _srv.o version need CFLAGS_SSE42 +# all versions of pg_crc32c_sse42.o need CFLAGS_SSE42 pg_crc32c_sse42.o: CFLAGS+=$(CFLAGS_SSE42) +pg_crc32c_sse42_shlib.o: CFLAGS+=$(CFLAGS_SSE42) pg_crc32c_sse42_srv.o: CFLAGS+=$(CFLAGS_SSE42) -# pg_crc32c_armv8.o and its _srv.o version need CFLAGS_ARMV8_CRC32C +# all versions of pg_crc32c_armv8.o need CFLAGS_ARMV8_CRC32C pg_crc32c_armv8.o: CFLAGS+=$(CFLAGS_ARMV8_CRC32C) +pg_crc32c_armv8_shlib.o: CFLAGS+=$(CFLAGS_ARMV8_CRC32C) pg_crc32c_armv8_srv.o: CFLAGS+=$(CFLAGS_ARMV8_CRC32C) +# +# Shared library versions of object files +# + +libpgport_shlib.a: $(OBJS_SHLIB) + rm -f $@ + $(AR) $(AROPT) $@ $^ + +# Because this uses its own compilation rule, it doesn't use the +# dependency tracking logic from Makefile.global. To make sure that +# dependency tracking works anyway for the *_shlib.o files, depend on +# their *.o siblings as well, which do have proper dependencies. It's +# a hack that might fail someday if there is a *_shlib.o without a +# corresponding *.o, but there seems little reason for that. +%_shlib.o: %.c %.o + $(CC) $(CFLAGS) $(CFLAGS_SL) $(CPPFLAGS) -c $< -o $@ + # # Server versions of object files # @@ -92,6 +120,8 @@ libpgport_srv.a: $(OBJS_SRV) path.o: path.c pg_config_paths.h +path_shlib.o: path.c pg_config_paths.h + path_srv.o: path.c pg_config_paths.h # We create a separate file rather than put these in pg_config.h @@ -112,4 +142,5 @@ pg_config_paths.h: $(top_builddir)/src/Makefile.global echo "#define MANDIR \"$(mandir)\"" >>$@ clean distclean maintainer-clean: - rm -f libpgport.a libpgport_srv.a $(OBJS) $(OBJS_SRV) pg_config_paths.h + rm -f libpgport.a libpgport_shlib.a libpgport_srv.a + rm -f $(OBJS) $(OBJS_SHLIB) $(OBJS_SRV) pg_config_paths.h