Static linking libexpat, libhacl, and libmpdec

I am curious what the expected technique for statically linking libexpat, libhacl, and libmpdec is. Python builds them and leaves them in the build tree in the corresponding Modules subdirectories.

But make install doesn’t seem to put them into python-<version>/lib and it also doesn’t seem to create a .pc file so there is no way to inquire what extra libs we need to link. Presumably I’m doing something wrong, does anyone have tips?

What platform are you building for?
I would have assumed that those libs would come from your platform.

Emscripten, so we can’t use the system libraries. But it seems to be handled by the following code in configure.ac:

AS_VAR_IF([with_system_expat], [yes], [
  LIBEXPAT_CFLAGS=${LIBEXPAT_CFLAGS-""}
  LIBEXPAT_LDFLAGS=${LIBEXPAT_LDFLAGS-"-lexpat"}
  LIBEXPAT_INTERNAL=
], [
  LIBEXPAT_CFLAGS="-I\$(srcdir)/Modules/expat"
  LIBEXPAT_LDFLAGS="-lm \$(LIBEXPAT_A)"
  LIBEXPAT_INTERNAL="\$(LIBEXPAT_HEADERS) \$(LIBEXPAT_A)"
])

These LIBEXPAT_LDFLAGS go into MODULE_PYEXPAT_LDFLAGS which go into LOCALMODLIBS which go into MODLIBS which go into the flags to link the .so file. So it seems that the issue is that we’re using the libpython.a target and then linking an executable directly from that, and we’d have the same problem even if we were linking a linux binary. I wonder if we should be getting the MODLIBS variable out of the Makefile and passing that at link time.

Doesn’t this

means that you have statically linked expat into python?

You could checked to see if libpython.a contains the expat symbols?

means that you have statically linked expat into python?

I think what it means is that when you link libpython.a into an executable/shared library you should pass -lm cpython/Modules/expat/libexpat.a as link arguments. So the resulting libpython.so will contain statically linked expat but libpython.a does not include the expat objects.

You could checked to see if libpython.a contains the expat symbols?

I checked and it doesn’t contain them. Instead, these symbols are added when libpython.so is linked from libpython.a. I think it would be helpful if libpython.a did include them though – it seems to me that taking libpython.a and linking it into your own executable / shared lib currently requires some guessing to figure out the appropriate link args.

There is a target in the Makefile called libainstall that I am using to install libpython.a into the install directory, but it doesn’t seem to install libexpat, libhacl, libmpdec etc. Perhaps it should?

This worked for me on 3.11.3

From 7557a0b12db8c894589a4329f4dc16e8a750c474 Mon Sep 17 00:00:00 2001
From: Michael Allwright <allsey87@gmail.com>
Date: Fri, 7 Jun 2024 15:55:16 +0200
Subject: [PATCH] Install vendored static libraries

---
 Makefile.pre.in | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Makefile.pre.in b/Makefile.pre.in
index 68c55a356a..d43b5a1aa3 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -2193,6 +2193,8 @@ libainstall: all python-config
 					$(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \
 				else \
 					$(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
+					$(INSTALL_DATA) -D $(LIBMPDEC_A) $(DESTDIR)$(LIBPL)/$(LIBMPDEC_A) ; \
+					$(INSTALL_DATA) -D $(LIBEXPAT_A) $(DESTDIR)$(LIBPL)/$(LIBEXPAT_A) ; \
 				fi; \
 			else \
 				echo Skip install of $(LIBRARY) - use make frameworkinstall; \
-- 
2.45.1