Fix building and running the test suite on macOS

Message ID 179251988825.9611.6228224260624404977@norvi.tech
State New
Headers
Series Fix building and running the test suite on macOS |

Commit Message

Spencer Norton 20 Oct 2026, 6:11 p.m. UTC
Restore building libloc, its man pages, and its C, Python, Lua, and Perl
test suites on macOS (Darwin), including with --enable-asan and
--enable-ubsan:

- src/libloc/compat.h: Map st_mtim to st_mtimespec on Apple platforms if
  not already defined, matching the switch to sub-second mtime comparison
  in loc_database_reload(). Also parenthesize (nmemb) * (size) in the
  fallback reallocarray() macro so additive expressions such as
  list->data_size + size do not under-allocate due to operator precedence.
- configure.ac, m4/attributes.m4: Pass -Wl,-not_for_dyld_shared_cache on
  Darwin when supported by the linker so Apple's ld does not reject the
  default /usr/lib install_name on libloc.dylib when linking with
  -undefined dynamic_lookup or non-system libraries such as Homebrew
  OpenSSL. Wrap the CC_CHECK_LDFLAGS test body in AC_LANG_SOURCE. Pass
  [no-xml] to IT_PROG_INTLTOOL so configure does not require the unused
  XML::Parser Perl module. Quote '${prefix}' in the pkg-config calls for
  LUA_INSTALL_LMOD and LUA_INSTALL_CMOD so running configure without
  --prefix defers expansion to Make instead of expanding prefix=NONE.
  Under --enable-asan on Darwin, preload libloc.dylib via
  DYLD_INSERT_LIBRARIES for binding tests.
- Makefile.am: Replace GNU-specific 'ln -s --relative' and brace expansion
  in build-perl with $(MKDIR_P) and a POSIX loop using $(abs_srcdir). Pass
  LD_LIBRARY_PATH and DYLD_LIBRARY_PATH after 'env' in PY_LOG_COMPILER,
  LUA_LOG_COMPILER, testdata.db, and check-perl (via single-quoted
  FULLPERLRUN) so macOS SIP does not strip DYLD_* variables across /bin/sh.
  Invoke $(LUA) explicitly in LUA_LOG_COMPILER instead of relying on the
  #!/usr/bin/lua@LUA_VERSION@ shebang, omit unsupported detect_leaks=1 from
  ASAN_OPTIONS on Darwin, remove libloc*.dylib and Location.bundle on
  uninstall, and include /opt/homebrew/etc/xml/catalog in XML_CATALOG_FILES
  on Darwin for Apple Silicon Homebrew installations.
- autogen.sh: Silence clang's unsupported '-print-multi-os-directory' stderr
  message when computing default libdir.

Fixes: #12400 - Package does not compile on OS X any more
Signed-off-by: Spencer Norton <spencer.norton@norvi.tech>
---
 Makefile.am         | 34 ++++++++++++++++++----------------
 autogen.sh          |  2 +-
 configure.ac        | 20 +++++++++++++++-----
 m4/attributes.m4    |  2 +-
 src/libloc/compat.h |  6 +++++-
 5 files changed, 40 insertions(+), 24 deletions(-)

-- 
2.50.1
  

Patch

diff --git a/Makefile.am b/Makefile.am
index aa0f23b..fa862bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -318,13 +318,10 @@  EXTRA_DIST += \
 	src/perl/typemap
 
 build-perl: src/libloc.la
-	@mkdir -p $(builddir)/src/perl/{lib,t}
-	@test -e $(builddir)/src/perl/Location.xs || ln -s --relative $(srcdir)/src/perl/Location.xs $(builddir)/src/perl/
-	@test -e $(builddir)/src/perl/MANIFEST || ln -s --relative $(srcdir)/src/perl/MANIFEST $(builddir)/src/perl/
-	@test -e $(builddir)/src/perl/Makefile.PL || ln -s --relative $(srcdir)/src/perl/Makefile.PL $(builddir)/src/perl/
-	@test -e $(builddir)/src/perl/lib/Location.pm || ln -s --relative $(srcdir)/src/perl/lib/Location.pm $(builddir)/src/perl/lib/
-	@test -e $(builddir)/src/perl/t/Location.t || ln -s --relative $(srcdir)/src/perl/t/Location.t $(builddir)/src/perl/t/
-	@test -e $(builddir)/src/perl/typemap || ln -s --relative $(srcdir)/src/perl/typemap $(builddir)/src/perl/
+	@$(MKDIR_P) $(builddir)/src/perl/lib $(builddir)/src/perl/t
+	@for file in Location.xs MANIFEST Makefile.PL lib/Location.pm t/Location.t typemap; do \
+		test -e $(builddir)/src/perl/$$file || ln -s $(abs_srcdir)/src/perl/$$file $(builddir)/src/perl/$$file; \
+	done
 
 	cd $(builddir)/src/perl && $(PERL) Makefile.PL NO_PACKLIST=1 NO_PERLLOCAL=1 \
 		INSTALLDIRS=vendor \
@@ -334,8 +331,8 @@  build-perl: src/libloc.la
 
 .PHONY: check-perl
 check-perl: testdata.db build-perl
-	cd $(builddir)/src/perl && env $(BINDINGS_TEST_ENV) \
-		$(MAKE) LD_LIBRARY_PATH="$(abs_builddir)/src/.libs" test \
+	cd $(builddir)/src/perl && \
+		$(MAKE) FULLPERLRUN='env $(BINDINGS_TEST_ENV) "$(PERL)"' test \
 		database="../../$<" keyfile="$(abs_srcdir)/examples/public-key.pem"
 
 .PHONY: install-perl
@@ -352,6 +349,7 @@  uninstall-perl:
 	rm -vf \
 		$(DESTDIR)/@PERL_MODPATH@/Location.pm \
 		$(DESTDIR)/@PERL_MODPATH@/auto/Location/Location.so \
+		$(DESTDIR)/@PERL_MODPATH@/auto/Location/Location.bundle \
 		$(DESTDIR)/@PERL_MANPATH@/Location.3pm
 	-rmdir $(DESTDIR)/@PERL_MODPATH@/auto/Location
 
@@ -384,7 +382,7 @@  install-exec-hook:
 # libtool needs those files to find what it has installed, so that
 # we have to remove the libraries and modules ourselves.
 uninstall-hook:
-	rm -f "$(DESTDIR)$(libdir)"/libloc.so*
+	rm -f "$(DESTDIR)$(libdir)"/libloc.so* "$(DESTDIR)$(libdir)"/libloc*.dylib
 	rm -f "$(DESTDIR)$(pyexecdir)/_location.so"
 if ENABLE_LUA
 	rm -f "$(DESTDIR)$(luaexecdir)/location.so"
@@ -466,10 +464,10 @@  TESTS_ENVIRONMENT = \
 	ABS_BUILDDIR="$(abs_builddir)" \
 	ABS_SRCDIR="$(abs_srcdir)"
 
-# Make the address sanitizer fail any test that leaks memory
-# and use libunwind for better stack traces
+# Make the address sanitizer fail any test that leaks memory (except on Darwin
+# where LeakSanitizer is not supported) and use libunwind for better stack traces
 TESTS_ENVIRONMENT += \
-	ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0
+	ASAN_OPTIONS=$(if $(filter Darwin,$(OS)),,detect_leaks=1:)fast_unwind_on_malloc=0
 
 TESTS = \
 	$(check_PROGRAMS) \
@@ -479,14 +477,18 @@  TESTS = \
 # Run the tests of the bindings with whatever environment their interpreter needs
 TEST_EXTENSIONS = .py .lua
 
+BINDINGS_TEST_ENV = \
+	LD_LIBRARY_PATH="$(abs_builddir)/src/.libs" \
+	DYLD_LIBRARY_PATH="$(abs_builddir)/src/.libs" \
+	@BINDINGS_TEST_ENV@
+
 PY_LOG_COMPILER = env $(BINDINGS_TEST_ENV) $(PYTHON)
-LUA_LOG_COMPILER = env $(BINDINGS_TEST_ENV)
+LUA_LOG_COMPILER = env $(BINDINGS_TEST_ENV) $(LUA)
 
 CLEANFILES += \
 	testdata.db
 
 testdata.db: examples/python/create-database.py src/python/_location.la
-	LD_LIBRARY_PATH="$(abs_builddir)/src/.libs" \
 	PYTHONPATH=$(abs_srcdir)/src/python:$(abs_builddir)/src/python/.libs \
 	ABS_SRCDIR="$(abs_srcdir)" \
 		env $(BINDINGS_TEST_ENV) $(PYTHON) $< $@
@@ -1076,7 +1078,7 @@  XSLTPROC_COMMAND_MAN = \
 
 # Let XSLT find its source on Mac OS X
  ifeq ($(OS),Darwin)
-export XML_CATALOG_FILES = /usr/local/etc/xml/catalog
+export XML_CATALOG_FILES ?= $(firstword $(wildcard /usr/local/etc/xml/catalog /opt/homebrew/etc/xml/catalog))
  endif
 
 man/%.xml: man/%.txt man/asciidoc.conf
diff --git a/autogen.sh b/autogen.sh
index 578c52f..6bab7ba 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -16,7 +16,7 @@  autoreconf --force --install --symlink
 intltoolize --force --automake
 
 libdir() {
-        echo $(cd $1/$(gcc -print-multi-os-directory); pwd)
+        echo $(cd $1/$(gcc -print-multi-os-directory 2>/dev/null); pwd)
 }
 
 args="--prefix=/usr \
diff --git a/configure.ac b/configure.ac
index 5c4323f..942d584 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,7 @@  gl_LD_VERSION_SCRIPT
 AM_GNU_GETTEXT_VERSION(0.21)
 AM_GNU_GETTEXT([external])
 
-IT_PROG_INTLTOOL([0.40.0])
+IT_PROG_INTLTOOL([0.40.0], [no-xml])
 
 # Interpret embedded Python in HTML files
 XGETTEXT="${XGETTEXT} -L Python --keyword=_:1,2 --keyword=N_:1,2 --no-location"
@@ -213,8 +213,13 @@  CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
 
 # --as-needed / --gc-sections are GNU ld flags. Apple's ld ignores them with a
 # warning, which the link probe can't detect, so only offer them off-Darwin.
+# On Darwin, opt out of the dyld shared cache so ld permits a /usr/lib
+# install_name to link with -undefined dynamic_lookup or non-system libraries.
 AS_CASE([$host_os],
-	[darwin*], [],
+	[darwin*], [
+		CC_CHECK_LDFLAGS([-Wl,-not_for_dyld_shared_cache],
+			[with_ldflags="$with_ldflags -Wl,-not_for_dyld_shared_cache"])
+	],
 	[
 		CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
 			-Wl,--as-needed \
@@ -277,7 +282,12 @@  if test "x${enable_asan}" = "xyes"; then
 		asan_runtime="$(${CC} -print-file-name=libclang_rt.asan-$(uname -m).so)"
 	])
 
-	bindings_test_env="LD_PRELOAD=${asan_runtime} ASAN_OPTIONS=detect_leaks=0"
+	AS_CASE([$host_os],
+		[darwin*], [
+			bindings_test_env='DYLD_INSERT_LIBRARIES="$(abs_builddir)/src/.libs/libloc.dylib" ASAN_OPTIONS=detect_leaks=0'
+		],
+		[bindings_test_env="LD_PRELOAD=${asan_runtime} ASAN_OPTIONS=detect_leaks=0"]
+	)
 fi
 
 AC_SUBST([BINDINGS_TEST_ENV], ${bindings_test_env})
@@ -363,13 +373,13 @@  AS_IF(
 
 		AC_SUBST(LUA_VERSION)
 
-		LUA_INSTALL_LMOD=$($PKG_CONFIG --define-variable=prefix=${prefix} --variable=INSTALL_LMOD ${lua})
+		LUA_INSTALL_LMOD=$($PKG_CONFIG --define-variable=prefix='${prefix}' --variable=INSTALL_LMOD ${lua})
 		if test -z "${LUA_INSTALL_LMOD}"; then
 			LUA_INSTALL_LMOD="${datadir}/lua/${LUA_VERSION}"
 		fi
 		AC_SUBST(LUA_INSTALL_LMOD)
 
-		LUA_INSTALL_CMOD=$($PKG_CONFIG --define-variable=prefix=${prefix} --variable=INSTALL_CMOD ${lua})
+		LUA_INSTALL_CMOD=$($PKG_CONFIG --define-variable=prefix='${prefix}' --variable=INSTALL_CMOD ${lua})
 		if test -z "${LUA_INSTALL_CMOD}"; then
 			LUA_INSTALL_CMOD="${libdir}/lua/${LUA_VERSION}"
 		fi
diff --git a/m4/attributes.m4 b/m4/attributes.m4
index 72db816..6518f12 100644
--- a/m4/attributes.m4
+++ b/m4/attributes.m4
@@ -64,7 +64,7 @@  AC_DEFUN([CC_CHECK_LDFLAGS], [
     AS_TR_SH([cc_cv_ldflags_$1]),
     [ac_save_LDFLAGS="$LDFLAGS"
      LDFLAGS="$LDFLAGS $1"
-     AC_LINK_IFELSE([int main() { return 1; }],
+     AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) { return 1; }])],
        [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
        [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
      LDFLAGS="$ac_save_LDFLAGS"
diff --git a/src/libloc/compat.h b/src/libloc/compat.h
index cd16a24..1060b63 100644
--- a/src/libloc/compat.h
+++ b/src/libloc/compat.h
@@ -45,7 +45,11 @@ 
 #endif
 
 #ifndef reallocarray
-#  define reallocarray(ptr, nmemb, size) realloc(ptr, nmemb * size)
+#  define reallocarray(ptr, nmemb, size) realloc(ptr, (nmemb) * (size))
+#endif
+
+#ifndef st_mtim
+#  define st_mtim st_mtimespec
 #endif
 
 #endif