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,