From a6983d4e42a243094adc1efd48dfe4f5c26dd3a7 Mon Sep 17 00:00:00 2001
From: AIX-dev <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Date: Tue, 3 Feb 2026 08:08:27 -0600
Subject: [PATCH] AIX support for GNU build.

---
 Makefile                           |  2 --
 configure                          |  1 +
 configure.ac                       |  1 +
 src/Makefile.shlib                 | 42 ++++++++++++++++++++++++++++++
 src/backend/Makefile               | 38 +++++++++++++++++++++++++--
 src/backend/utils/misc/ps_status.c |  4 +--
 src/include/port/aix.h             |  3 +++
 src/makefiles/Makefile.aix         | 16 ------------
 src/template/aix                   | 18 +++++++++++++
 9 files changed, 103 insertions(+), 22 deletions(-)
 mode change 100755 => 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 5adfb3eba45..e9a4b184bfe 100755
--- a/configure
+++ b/configure
@@ -3022,6 +3022,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
diff --git a/configure.ac b/configure.ac
index a5eab2e5fff..9ac827a5b6b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 3825af5b228..6ff8e0d7430 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,33 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+# On AIX, executables donot automatically expose their symbols to shared
+# modules. Extensions therefore cannot call functions in the main Postgres
+# binary unless those symbols are explicitly exported. Unlike other platforms,
+# AIX executables are not default symbol providers each shared module must
+# link against an export list that defines which symbols it can use.
+#
+# The mkldexport.sh script fixes AIXs symbol export issue by generating an
+# explicit export list. It uses nm to gather all symbols from the Postgres
+# object files, then writes them into the export file. When invoked with ".",
+# it outputs #! ., which tells AIX the list applies to the main executable.
+# This way, extension modules can link against that list and resolve their
+# undefined symbols directly from the Postgres binary.
+#
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +281,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +302,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +414,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +432,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 05642dc02e3..cdaec66a9ed 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -85,12 +85,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -117,6 +119,26 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+# AIX builds only 64Bit binaries. The linker builds 64bit either with -b64 flag
+# or watch for OBJECT_MODE=64.
+$(POSTGRES_IMP): $(OBJS)
+	ld -b64 -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
@@ -210,8 +232,12 @@ install-postgres-bitcode: $(OBJS) all
 	$(call install_llvm_module,postgres,$(call expand_subsys, $(filter-out $(top_builddir)/src/timezone/objfiles.txt, $(SUBDIROBJS))))
 endif
 
-install-bin: postgres installdirs
+install-bin: postgres $(POSTGRES_IMP) installdirs
 	$(INSTALL_PROGRAM) postgres$(X) '$(DESTDIR)$(bindir)/postgres$(X)'
+ifeq ($(MAKE_EXPORTS), true)
+	$(INSTALL_DATA) $(POSTGRES_IMP) '$(DESTDIR)$(pkglibdir)/$(POSTGRES_IMP)'
+	$(INSTALL_PROGRAM) $(MKLDEXPORT) '$(DESTDIR)$(pgxsdir)/$(MKLDEXPORT_DIR)/mkldexport.sh'
+endif
 
 .PHONY: install-bin
 
@@ -227,12 +253,20 @@ ifeq ($(MAKE_DLL), true)
 	$(MKDIR_P) '$(DESTDIR)$(libdir)'
 endif
 endif
+ifeq ($(MAKE_EXPORTS), true)
+	$(MKDIR_P) '$(DESTDIR)$(pkglibdir)'
+	$(MKDIR_P) '$(DESTDIR)$(pgxsdir)/$(MKLDEXPORT_DIR)'
+endif
 
 
 ##########################################################################
 
 uninstall:
 	rm -f '$(DESTDIR)$(bindir)/postgres$(X)'
+ifeq ($(MAKE_EXPORTS), true)
+	rm -f '$(DESTDIR)$(pkglibdir)/$(POSTGRES_IMP)'
+	rm -f '$(DESTDIR)$(pgxsdir)/$(MKLDEXPORT_DIR)/mkldexport.sh'
+endif
 ifeq ($(PORTNAME), cygwin)
 ifeq ($(MAKE_DLL), true)
 	rm -f '$(DESTDIR)$(libdir)/libpostgres.a'
@@ -257,7 +291,7 @@ endif
 ##########################################################################
 
 clean:
-	rm -f $(LOCALOBJS) postgres$(X)
+	rm -f $(LOCALOBJS) postgres$(X) $(POSTGRES_IMP)
 ifeq ($(PORTNAME), cygwin)
 	rm -f postgres.dll libpostgres.a
 endif
diff --git a/src/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c
index 9e55be244f7..51dce24947a 100644
--- a/src/backend/utils/misc/ps_status.c
+++ b/src/backend/utils/misc/ps_status.c
@@ -52,7 +52,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 #define PS_USE_SETPROCTITLE_FAST
 #elif defined(HAVE_SETPROCTITLE)
 #define PS_USE_SETPROCTITLE
-#elif defined(__linux__) || defined(__sun) || defined(__darwin__) || defined(__GNU__)
+#elif defined(__linux__) || defined(_AIX) || defined(__sun) || defined(__darwin__) || defined(__GNU__)
 #define PS_USE_CLOBBER_ARGV
 #elif defined(WIN32)
 #define PS_USE_WIN32
@@ -62,7 +62,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 
 
 /* Different systems want the buffer padded differently */
-#if defined(__linux__) || defined(__darwin__) || defined(__GNU__)
+#if defined(_AIX) || defined(__linux__) || defined(__darwin__) || defined(__GNU__)
 #define PS_PADDING '\0'
 #else
 #define PS_PADDING ' '
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
index e69de29bb2d..c86983a4452 100644
--- a/src/include/port/aix.h
+++ b/src/include/port/aix.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/aix.h
+ */
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
old mode 100755
new mode 100644
index 42bdbade5bb..921c22faaaa
--- a/src/makefiles/Makefile.aix
+++ b/src/makefiles/Makefile.aix
@@ -1,19 +1,3 @@
-# -blibpath:
-# The path to be inserted into the default path (Index 0 path) field of the
-# loader section. When this flag is presented, the -L paths will not be stored.
-# AIX uses a stricter, more explicit approach. The runtime linker expects to
-# tell it exactly where to look using -blibpath.
-# -blibpath must contain ALL directories where we should look for libraries
-libpath := $(shell echo $(subst -L,:,$(filter -L/%,$(LDFLAGS))) | sed -e's/ //g'):/usr/lib:/lib
-
-# when building with gcc, need to make sure that libgcc can be found
-ifeq ($(GCC), yes)
-libpath += :$(libpath):$(dir $(shell gcc -print-libgcc-file-name))
-endif
-
-# AIX uses a stricter, more explicit approach. The runtime linker expects
-# to tell it exactly where to look using -blibpath.
-rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
 
 # gcc needs to know it's building a shared lib, otherwise it'll not emit
 # correct code / link to the right support libraries
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..ea66dd83740
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,18 @@
+# This file is referred for specific flags wrt to AIX build process like
+# cflags.
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=" "
+
+if test "$GCC" = yes; then
+  # Only 64bit compilation is supported in AIX. This requires -maix64
+  # to be passed as the default build environment in AIX is 32bit.
+  CFLAGS="$CFLAGS -maix64 "
+  CPPFLAGS="$CPPFLAGS -maix64 "
+  CXXFLAGS="$CXXFLAGS -maix64 "
+
+  # For large binaries/libraries, there will be TOC overflows in AIX. To
+  # avoid this, pass -bbigtoc linker option to enlarge TOC access range.
+  LDFLAGS="$LDFLAGS -maix64 -Wl,-bbigtoc"
+fi
-- 
2.41.0

