From 4a096cd5503eecc9fc02d82ae4035bb521b3b037 Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Fri, 8 May 2026 04:46:52 +0000 Subject: [PATCH] fix: resolve same-build pcfile dependencies --- src/hatch_nativelib/plugin.py | 25 +++++++++---------- .../demo-editable-chain/pyproject.toml | 24 ++++++++++++++++++ .../src/demo_pkg/__init__.py | 0 tests/test_integration_build_backend.py | 18 +++++++++++++ 4 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 tests/packages/demo-editable-chain/pyproject.toml create mode 100644 tests/packages/demo-editable-chain/src/demo_pkg/__init__.py diff --git a/src/hatch_nativelib/plugin.py b/src/hatch_nativelib/plugin.py index a79f603..3684e08 100644 --- a/src/hatch_nativelib/plugin.py +++ b/src/hatch_nativelib/plugin.py @@ -38,21 +38,20 @@ def initialize(self, version: str, build_data: T.Dict[str, T.Any]) -> None: # for pkg in WheelBuilder(self.root).config.packages # ] - pcpaths: T.Set[str] = set() for pcfg in self._pcfiles: pcfile = self._generate_pcfile(pcfg, build_data) - pcpaths.add(str(pcfile.parent)) - - if pcpaths: - # Add to PKG_CONFIG_PATH so that it can be resolved by other hatchling - # plugins if desired - pkg_config_path = os.environ.get("PKG_CONFIG_PATH") - if pkg_config_path is not None: - os.environ["PKG_CONFIG_PATH"] = os.pathsep.join( - (pkg_config_path, *pcpaths) - ) - else: - os.environ["PKG_CONFIG_PATH"] = os.pathsep.join(pcpaths) + self._add_pkg_config_path(str(pcfile.parent)) + + def _add_pkg_config_path(self, *paths: str) -> None: + current = os.environ.get("PKG_CONFIG_PATH") + entries = current.split(os.pathsep) if current else [] + + for path in paths: + if path not in entries: + entries.append(path) + + if entries: + os.environ["PKG_CONFIG_PATH"] = os.pathsep.join(entries) def clean(self, versions: T.List[str]) -> None: root = pathlib.Path(self.root) diff --git a/tests/packages/demo-editable-chain/pyproject.toml b/tests/packages/demo-editable-chain/pyproject.toml new file mode 100644 index 0000000..3f77477 --- /dev/null +++ b/tests/packages/demo-editable-chain/pyproject.toml @@ -0,0 +1,24 @@ +[build-system] +requires = ["hatchling", "hatch-nativelib"] +build-backend = "hatchling.build" + +[project] +name = "demo-editable-chain" +version = "1.2.3" +description = "Demo editable dependency chain" + +[tool.hatch.build.targets.wheel] +packages = ["src/demo_pkg"] + +[[tool.hatch.build.hooks.nativelib.pcfile]] +pcfile = "src/demo_pkg/provider.pc" +name = "provider" +libdir = "src/demo_pkg/lib" +shared_libraries = ["provider"] + +[[tool.hatch.build.hooks.nativelib.pcfile]] +pcfile = "src/demo_pkg/consumer.pc" +name = "consumer" +libdir = "src/demo_pkg/lib" +shared_libraries = ["consumer"] +requires = ["provider"] diff --git a/tests/packages/demo-editable-chain/src/demo_pkg/__init__.py b/tests/packages/demo-editable-chain/src/demo_pkg/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_integration_build_backend.py b/tests/test_integration_build_backend.py index 97486c2..cfd15bb 100644 --- a/tests/test_integration_build_backend.py +++ b/tests/test_integration_build_backend.py @@ -101,3 +101,21 @@ def test_build_generates_init_module_for_multiple_shared_libraries( assert shared_library_filename("demo") in init_module assert shared_library_filename("helper") in init_module assert "return libs" in init_module + + +def test_build_resolves_intra_project_requires_on_first_run(project_factory) -> None: + project_factory.copy_package_fixture("demo-editable-chain") + project_factory.write( + f"src/demo_pkg/lib/{shared_library_filename('provider')}", + "not-a-real-library", + ) + project_factory.write( + f"src/demo_pkg/lib/{shared_library_filename('consumer')}", + "not-a-real-library", + ) + + result = project_factory.build_wheel() + + assert result.returncode == 0, result.stdout + result.stderr + init_module = project_factory.read("src/demo_pkg/_init_consumer.py") + assert "import demo_pkg._init_provider" in init_module