fix: Add libdir to library search path (#2476)

We discovered when dealing with libraries such as `psycopg2` that the
wheel would attempt to link against `libpython.a`. This fix points the
linker at the correct python version being used.

---------

Co-authored-by: Ignas Anikevicius <240938+aignas@users.noreply.github.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c05204d..e59d225 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -77,6 +77,8 @@
 * {obj}`//python/bin:python`: convenience target for directly running an
   interpreter. {obj}`--//python/bin:python_src` can be used to specify a
   binary whose interpreter to use.
+* (pypi) An extra argument to add the interpreter lib dir to `LDFLAGS` when
+  building wheels from `sdist`.
 
 {#v0-0-0-removed}
 ### Removed
diff --git a/python/private/pypi/attrs.bzl b/python/private/pypi/attrs.bzl
index c9b7ea6..6717e95 100644
--- a/python/private/pypi/attrs.bzl
+++ b/python/private/pypi/attrs.bzl
@@ -15,6 +15,15 @@
 "common attributes for whl_library and pip_repository"
 
 ATTRS = {
+    "add_libdir_to_library_search_path": attr.bool(
+        default = False,
+        doc = """
+If true, add the lib dir of the bundled interpreter to the library search path via `LDFLAGS`.
+
+:::{versionadded} VERSION_NEXT_FEATURE
+:::
+""",
+    ),
     "download_only": attr.bool(
         doc = """
 Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of
diff --git a/python/private/pypi/extension.bzl b/python/private/pypi/extension.bzl
index 1a7d1e1..be00bf8 100644
--- a/python/private/pypi/extension.bzl
+++ b/python/private/pypi/extension.bzl
@@ -203,6 +203,7 @@
         )
         maybe_args = dict(
             # The following values are safe to omit if they have false like values
+            add_libdir_to_library_search_path = pip_attr.add_libdir_to_library_search_path,
             annotation = whl_modifications.get(whl_name),
             download_only = pip_attr.download_only,
             enable_implicit_namespace_pkgs = pip_attr.enable_implicit_namespace_pkgs,
diff --git a/python/private/pypi/whl_library.bzl b/python/private/pypi/whl_library.bzl
index bdcf784..dea61b2 100644
--- a/python/private/pypi/whl_library.bzl
+++ b/python/private/pypi/whl_library.bzl
@@ -140,11 +140,28 @@
     if rctx.attr.enable_implicit_namespace_pkgs:
         args.append("--enable_implicit_namespace_pkgs")
 
+    env = {}
     if rctx.attr.environment != None:
-        args += [
-            "--environment",
-            json.encode(struct(arg = rctx.attr.environment)),
-        ]
+        for key, value in rctx.attr.environment.items():
+            env[key] = value
+
+    # This is super hacky, but working out something nice is tricky.
+    # This is in particular needed for psycopg2 which attempts to link libpython.a,
+    # in order to point the linker at the correct python intepreter.
+    if rctx.attr.add_libdir_to_library_search_path:
+        if "LDFLAGS" in env:
+            fail("Can't set both environment LDFLAGS and add_libdir_to_library_search_path")
+        command = [pypi_repo_utils.resolve_python_interpreter(rctx), "-c", "import sys ; sys.stdout.write('{}/lib'.format(sys.exec_prefix))"]
+        result = rctx.execute(command)
+        if result.return_code != 0:
+            fail("Failed to get LDFLAGS path: command: {}, exit code: {}, stdout: {}, stderr: {}".format(command, result.return_code, result.stdout, result.stderr))
+        libdir = result.stdout
+        env["LDFLAGS"] = "-L{}".format(libdir)
+
+    args += [
+        "--environment",
+        json.encode(struct(arg = env)),
+    ]
 
     return args
 
diff --git a/tests/pypi/extension/extension_tests.bzl b/tests/pypi/extension/extension_tests.bzl
index 5916a27..8c01a02 100644
--- a/tests/pypi/extension/extension_tests.bzl
+++ b/tests/pypi/extension/extension_tests.bzl
@@ -77,6 +77,7 @@
         hub_name,
         python_version,
         _evaluate_markers_srcs = [],
+        add_libdir_to_library_search_path = False,
         auth_patterns = {},
         download_only = False,
         enable_implicit_namespace_pkgs = False,
@@ -105,6 +106,7 @@
     return struct(
         _evaluate_markers_srcs = _evaluate_markers_srcs,
         auth_patterns = auth_patterns,
+        add_libdir_to_library_search_path = add_libdir_to_library_search_path,
         download_only = download_only,
         enable_implicit_namespace_pkgs = enable_implicit_namespace_pkgs,
         environment = environment,