Previous discussions on macOS SIP:

https://www.postgresql.org/message-id/flat/561E73AB.8060800%40gmx.net
https://www.postgresql.org/message-id/flat/CA%2BTgmoYGi5oR8Rvb2-SY1_WEjd76H5gCqSukxFQ66qR7MewWAQ%40mail.gmail.com
https://www.postgresql.org/message-id/flat/6a4d6124-41f0-756b-0811-c5c5def7ef4b%402ndquadrant.com

Tests that use a temporary installation (i.e., make check) use a platform-specific environment variable to make programs and libraries find shared libraries in the temporary installation rather than in the actual configured installation target directory. On macOS, this is DYLD_LIBRARY_PATH. Ever since System Integrity Protection (SIP) arrived, this hasn't worked anymore, because DYLD_LIBRARY_PATH gets disabled by the system (in somewhat obscure ways). The workaround was to either disable SIP or to do make install before make check.

The solution here is to use install_name_tool to edit the shared library path in the binaries (programs and libraries) after installation into the temporary prefix.

The solution is, I think, correct in principle, but the implementation is hackish, since it hardcodes the names and versions of the interesting shared libraries in an unprincipled way. More refinement is needed here. Ideas welcome.

In order to allow all that, we need to link everything with the option -headerpad_max_install_names so that there is enough room in the binaries to put in the temporary path in place of the original one. (The temporary path is strictly longer than the original one.) This bloats the binaries, so it might only be appropriate for development builds and should perhaps be hidden behind some option. Ideas also welcome here.

The attached patch works for me. You can see that it disables setting DYLD_LIBRARY_PATH, but the tests still work. Verification on other system variantions welcome, of course.

Comments welcome. I think this direction is promising, but some details need to be addressed.
From 28f2f9fc2234e3d993027fb014f1c85f7b3db6be Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Wed, 2 Dec 2020 14:49:53 +0100
Subject: [PATCH] WIP: Fix temp-install tests to work with macOS SIP

Tests that use a temporary installation (i.e., make check) use a
platform-specific environment variable to make programs and libraries
find shared libraries in the temporary installation rather than in the
actual configured installation target directory.  On macOS, this is
DYLD_LIBRARY_PATH.  Ever since System Integrity Protection (SIP)
arrived, this hasn't worked anymore, because DYLD_LIBRARY_PATH gets
disabled by the system (in somewhat obscure ways).  The workaround was
to either disable SIP or to do make install before make check.

The solution here is to use install_name_tool to edit the shared
library path in the binaries (programs and libraries) after
installation into the temporary prefix.

XXX The solution is, I think, correct in principle, but the
implementation is hackish, since it hardcodes the names and versions
of the interesting shared libraries in an unprincipled way.

In order to allow that, we need to link everything with the option
-headerpad_max_install_names so that there is enough room in the
binaries to put in the temporary path in place of the original
one.  (The temporary path is strictly longer than the original one.)
This bloats the binaries, so it might only be appropriate for
development builds and should perhaps be hidden behind some option.
---
 src/Makefile.global.in            |  1 +
 src/interfaces/ecpg/test/Makefile |  1 +
 src/makefiles/Makefile.darwin     | 13 ++++++++++++-
 src/test/isolation/Makefile       |  3 +++
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 7ca1e9aac5..a2349c814b 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -409,6 +409,7 @@ ifeq ($(MAKELEVEL),0)
        $(MKDIR_P) '$(abs_top_builddir)'/tmp_install/log
        $(MAKE) -C '$(top_builddir)' DESTDIR='$(abs_top_builddir)'/tmp_install 
install >'$(abs_top_builddir)'/tmp_install/log/install.log 2>&1
        $(MAKE) -j1 $(if $(CHECKPREP_TOP),-C $(CHECKPREP_TOP),) checkprep 
>>'$(abs_top_builddir)'/tmp_install/log/install.log 2>&1
+       $(call 
temp_install_postprocess,'$(abs_top_builddir)/tmp_install/$(bindir)'/* 
'$(abs_top_builddir)/tmp_install/$(libdir)'/*.so 
'$(abs_top_builddir)/tmp_install/$(libdir)'/*.dylib)
 endif
 endif
 endif
diff --git a/src/interfaces/ecpg/test/Makefile 
b/src/interfaces/ecpg/test/Makefile
index be53b7b94d..468e3076ad 100644
--- a/src/interfaces/ecpg/test/Makefile
+++ b/src/interfaces/ecpg/test/Makefile
@@ -80,6 +80,7 @@ endif
 REGRESS_OPTS = --dbname=ecpg1_regression,ecpg2_regression 
--create-role=regress_ecpg_user1,regress_ecpg_user2 $(EXTRA_REGRESS_OPTS)
 
 check: all
+       $(call temp_install_postprocess,$(patsubst %.pgc,%,$(wildcard 
compat_informix/*.pgc compat_oracle/*.pgc connect/*.pgc pgtypeslib/*.pgc 
preproc/*.pgc sql/*.pgc thread/*.pgc)))
        $(with_temp_install) ./pg_regress $(REGRESS_OPTS) 
--temp-instance=./tmp_check $(TEMP_CONF) --bindir= $(pg_regress_locale_flags) 
$(THREAD) --schedule=$(srcdir)/ecpg_schedule sql/twophase
 
 # Connect to the server using TCP, and add a TCP-specific test.
diff --git a/src/makefiles/Makefile.darwin b/src/makefiles/Makefile.darwin
index b17598f058..def6ef0b00 100644
--- a/src/makefiles/Makefile.darwin
+++ b/src/makefiles/Makefile.darwin
@@ -3,7 +3,18 @@ AROPT = crs
 DLSUFFIX = .so
 
 # env var name to use in place of LD_LIBRARY_PATH
-ld_library_path_var = DYLD_LIBRARY_PATH
+#ld_library_path_var = DYLD_LIBRARY_PATH
+
+LDFLAGS += -Wl,-headerpad_max_install_names
+
+define temp_install_postprocess
+       for file in $(1); do \
+         for lib in libpq.5 libecpg.6 libecpg_compat.3 libpgtypes.3; do \
+           install_name_tool -change '$(libdir)'/$$lib.dylib 
'$(abs_top_builddir)/tmp_install/$(libdir)'/$$lib.dylib $$file || exit; \
+         done; \
+       done
+endef
+
 
 ifdef PGXS
   BE_DLLLIBS = -bundle_loader $(bindir)/postgres
diff --git a/src/test/isolation/Makefile b/src/test/isolation/Makefile
index d23e2cec64..7cb6626b8b 100644
--- a/src/test/isolation/Makefile
+++ b/src/test/isolation/Makefile
@@ -40,6 +40,9 @@ pg_isolation_regress$(X): isolation_main.o pg_regress.o 
$(WIN32RES)
 
 isolationtester$(X): $(OBJS) | submake-libpq submake-libpgport
        $(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o 
$@
+ifeq ($(PORTNAME), darwin)
+       install_name_tool -change '$(libdir)'/libpq.5.dylib 
$(abs_top_builddir)/src/interfaces/libpq/libpq.5.dylib $@
+endif
 
 distprep: specparse.c specscanner.c
 
-- 
2.29.2

Reply via email to