|
8 | 8 | from toml import loads |
9 | 9 |
|
10 | 10 | from hatch_cpp import HatchCppBuildConfig, HatchCppBuildPlan, HatchCppLibrary, HatchCppPlatform |
| 11 | +from hatch_cpp.toolchains.common import _normalize_rpath |
11 | 12 |
|
12 | 13 |
|
13 | 14 | class TestStructs: |
@@ -168,3 +169,72 @@ def test_hatch_cpp_vcpkg_env_force_on(self): |
168 | 169 | with patch.dict(environ, {"HATCH_CPP_VCPKG": "1"}): |
169 | 170 | hatch_build_plan.generate() |
170 | 171 | assert "vcpkg" in hatch_build_plan._active_toolchains |
| 172 | + |
| 173 | + |
| 174 | +class TestNormalizeRpath: |
| 175 | + def test_origin_to_loader_path_on_darwin(self): |
| 176 | + """$ORIGIN should be translated to @loader_path on macOS.""" |
| 177 | + assert _normalize_rpath("-Wl,-rpath,$ORIGIN", "darwin") == "-Wl,-rpath,@loader_path" |
| 178 | + |
| 179 | + def test_loader_path_to_origin_on_linux(self): |
| 180 | + """@loader_path should be translated to (escaped) $ORIGIN on Linux.""" |
| 181 | + result = _normalize_rpath("-Wl,-rpath,@loader_path", "linux") |
| 182 | + assert result == r"-Wl,-rpath,\$ORIGIN" |
| 183 | + |
| 184 | + def test_origin_escaped_on_linux(self): |
| 185 | + """$ORIGIN should be escaped as \\$ORIGIN on Linux for shell safety.""" |
| 186 | + result = _normalize_rpath("-Wl,-rpath,$ORIGIN", "linux") |
| 187 | + assert result == r"-Wl,-rpath,\$ORIGIN" |
| 188 | + |
| 189 | + def test_already_escaped_origin_on_darwin(self): |
| 190 | + """Already-escaped \\$ORIGIN should still translate to @loader_path on macOS.""" |
| 191 | + assert _normalize_rpath(r"-Wl,-rpath,\$ORIGIN", "darwin") == "-Wl,-rpath,@loader_path" |
| 192 | + |
| 193 | + def test_no_rpath_unchanged(self): |
| 194 | + """Args without rpath values should pass through unchanged.""" |
| 195 | + assert _normalize_rpath("-lfoo", "linux") == "-lfoo" |
| 196 | + assert _normalize_rpath("-lfoo", "darwin") == "-lfoo" |
| 197 | + |
| 198 | + def test_win32_no_transform(self): |
| 199 | + """Windows should not transform rpath values.""" |
| 200 | + assert _normalize_rpath("$ORIGIN", "win32") == "$ORIGIN" |
| 201 | + assert _normalize_rpath("@loader_path", "win32") == "@loader_path" |
| 202 | + |
| 203 | + def test_link_flags_rpath_translation_darwin(self): |
| 204 | + """Full integration: extra_link_args with $ORIGIN produce @loader_path on macOS.""" |
| 205 | + library = HatchCppLibrary( |
| 206 | + name="test", |
| 207 | + sources=["test.cpp"], |
| 208 | + binding="generic", |
| 209 | + extra_link_args=["-Wl,-rpath,$ORIGIN"], |
| 210 | + ) |
| 211 | + platform = HatchCppPlatform( |
| 212 | + cc="clang", |
| 213 | + cxx="clang++", |
| 214 | + ld="ld", |
| 215 | + platform="darwin", |
| 216 | + toolchain="clang", |
| 217 | + disable_ccache=True, |
| 218 | + ) |
| 219 | + flags = platform.get_link_flags(library) |
| 220 | + assert "@loader_path" in flags |
| 221 | + assert "$ORIGIN" not in flags |
| 222 | + |
| 223 | + def test_link_flags_rpath_escaped_linux(self): |
| 224 | + """Full integration: extra_link_args with $ORIGIN are shell-escaped on Linux.""" |
| 225 | + library = HatchCppLibrary( |
| 226 | + name="test", |
| 227 | + sources=["test.cpp"], |
| 228 | + binding="generic", |
| 229 | + extra_link_args=["-Wl,-rpath,$ORIGIN"], |
| 230 | + ) |
| 231 | + platform = HatchCppPlatform( |
| 232 | + cc="gcc", |
| 233 | + cxx="g++", |
| 234 | + ld="ld", |
| 235 | + platform="linux", |
| 236 | + toolchain="gcc", |
| 237 | + disable_ccache=True, |
| 238 | + ) |
| 239 | + flags = platform.get_link_flags(library) |
| 240 | + assert r"\$ORIGIN" in flags |
0 commit comments