field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

commit e251dff19e5d3ae2481968d2400ee8ff4f95a61a
parent 2b33144e628bf10e1ddd29829f801ae94cf922b6
Author: triesap <tyson@radroots.org>
Date:   Wed,  9 Sep 2026 04:40:35 +0000

tera: qualify standalone ownership cutover

- Govern reproducible host library names and debug-map prefixes.
- Scope native linker flags to the owned Tera FFI library.
- Regenerate exact source, artifact and unsigned local evidence.
- Verify independent artifact reproduction and standalone native lanes.

Diffstat:
MTeraFFI/producer.toml | 3+++
MTeraFFI/provenance.json | 28++++++++++++++--------------
MTeraFFI/source.lock | 4++--
MTeraFFI/source/aarch64-apple-darwin.json | 37+++++++++++++++++++++----------------
MTeraFFI/source/aarch64-apple-ios-sim.json | 33+++++++++++++++++----------------
MTeraFFI/source/aarch64-apple-ios.json | 33+++++++++++++++++----------------
Mrelease/provenance.json | 4++--
Mscripts/ffi_build.py | 35+++++++++++++++++++++++------------
Mscripts/ffi_provenance.py | 1+
Mscripts/ffi_source.py | 26++++++++++++++++++++++++++
Mscripts/test_ffi_provenance.py | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 184 insertions(+), 78 deletions(-)

diff --git a/TeraFFI/producer.toml b/TeraFFI/producer.toml @@ -30,4 +30,7 @@ rust_flags = [ ] source_date_epoch = 1787871027 host = "aarch64-apple-darwin" +host_dylib_install_name = "@rpath/libtera_ffi.dylib" +host_linker_reproducible = true +host_oso_prefix = "{extbuild_root}" targets = ["aarch64-apple-ios", "aarch64-apple-ios-sim", "aarch64-apple-darwin"] diff --git a/TeraFFI/provenance.json b/TeraFFI/provenance.json @@ -79,7 +79,7 @@ { "bytes": 19797472, "path": "native/aarch64-apple-darwin/libtera_ffi.dylib", - "sha256": "7fc22f57a70b0c46d62dfdcd2521c670f6c77ef37ad44c27688c5625af1c7175" + "sha256": "fc24bae706f1577093e7671b57cd290be588701e4c98c0520fe9dfc72ad9d150" }, { "bytes": 71177128, @@ -92,19 +92,19 @@ "sha256": "005a6f155fb78da2e1d560fd1bc5f62a1ff17dfa101419b1b7fe33ca86c9a458" }, { - "bytes": 53557, + "bytes": 53746, "path": "source/aarch64-apple-darwin.json", - "sha256": "dce04cf1b608641658cc4ab3cfec8d6a7c050e744ebc208c96811f0c72b31ccf" + "sha256": "9d1b04aef4fd2376df5cbcd201364ba939a86c81b8ad477df180c12405b598ab" }, { - "bytes": 53558, + "bytes": 53590, "path": "source/aarch64-apple-ios-sim.json", - "sha256": "f3532c471ab814083d80dba6f2f1630a42daa97152d14c36ba403893ec815daf" + "sha256": "6db7eb95aeb6a31b6a27892818398f6738dca6a85dbdc58e1af5377259299ac5" }, { - "bytes": 53554, + "bytes": 53586, "path": "source/aarch64-apple-ios.json", - "sha256": "272da0800b5c6a4f11994a0156dda3973d2db3d56fa5b5ede71e26e8f412ad4a" + "sha256": "ed84372beba812566226a673b6fee5d210765c08756adda1b3e08c87fb74b636" } ], "language": "swift", @@ -112,7 +112,7 @@ "schema": "radroots.artifact-manifest.v2", "source": { "repository": "https://github.com/radrootslabs/tera", - "tree": "5364e38f7c08b01eef0d63a2eb48383215e887d8" + "tree": "ed13f3efac75566f8f21f1fcc0f9cea938d21d53" }, "source_records": { "aarch64-apple-darwin": "source/aarch64-apple-darwin.json", @@ -174,19 +174,19 @@ "sha256": "6542c8294920b3c41e987619de58690e2af16896079910b657129d3573b34e68" }, { - "bytes": 53557, + "bytes": 53746, "path": "TeraFFI/source/aarch64-apple-darwin.json", - "sha256": "dce04cf1b608641658cc4ab3cfec8d6a7c050e744ebc208c96811f0c72b31ccf" + "sha256": "9d1b04aef4fd2376df5cbcd201364ba939a86c81b8ad477df180c12405b598ab" }, { - "bytes": 53558, + "bytes": 53590, "path": "TeraFFI/source/aarch64-apple-ios-sim.json", - "sha256": "f3532c471ab814083d80dba6f2f1630a42daa97152d14c36ba403893ec815daf" + "sha256": "6db7eb95aeb6a31b6a27892818398f6738dca6a85dbdc58e1af5377259299ac5" }, { - "bytes": 53554, + "bytes": 53586, "path": "TeraFFI/source/aarch64-apple-ios.json", - "sha256": "272da0800b5c6a4f11994a0156dda3973d2db3d56fa5b5ede71e26e8f412ad4a" + "sha256": "ed84372beba812566226a673b6fee5d210765c08756adda1b3e08c87fb74b636" } ], "schema": "tera.installed-native-artifacts.v1" diff --git a/TeraFFI/source.lock b/TeraFFI/source.lock @@ -1,7 +1,7 @@ schema = "tera.installed-source.v1" repository = "https://github.com/radrootslabs/tera" -source_tree = "5364e38f7c08b01eef0d63a2eb48383215e887d8" -manifest_sha256 = "c338c32c516a767f1e1215f5c6b8841927d86c38cdd88ca5c598986a0ca2de89" +source_tree = "ed13f3efac75566f8f21f1fcc0f9cea938d21d53" +manifest_sha256 = "5ee596b004f9c633f044ed91530f9cdd60427e3828b38f237d327ca5161d42d0" source_date_epoch = 1787871027 [foundation] diff --git a/TeraFFI/source/aarch64-apple-darwin.json b/TeraFFI/source/aarch64-apple-darwin.json @@ -367,6 +367,11 @@ "features": [], "ios_deployment_target": "18.0", "package": "tera_ffi", + "package_rust_flags": [ + "-Clink-arg=-Wl,-install_name,@rpath/libtera_ffi.dylib", + "-Clink-arg=-Wl,-reproducible", + "-Clink-arg=-Wl,-oso_prefix,{extbuild_root}" + ], "profile": "release", "rust_flags": [ "--remap-path-prefix={producer_root}=/tera", @@ -518,10 +523,10 @@ "sha256": "7e9bc238cc27041e3f6b63d40d28712f3276bf0b3f3deb7609f4fb962db4f4c1" }, "TeraFFI/producer.toml": { - "bytes": 963, - "git_blob": "87e4526a6595ded35ea62b6ef1b3aa67b923b515", + "bytes": 1084, + "git_blob": "23e07f3d818f7f3d57a77fca3bca6b32b9218e74", "mode": "100644", - "sha256": "c497212bfb54d997bbf5938cd04c7a41c3ef2ce7adaef861fc07e2565cd26661" + "sha256": "eebaf5b181e9b27c3854201c6f6ac1662b7a7045168f960a5c1dac8c5de29013" }, "TeraFFI/scripts/verify-installed-artifacts.sh": { "bytes": 255, @@ -986,10 +991,10 @@ "sha256": "568ee230a99a907cc9063c203fbecc80e6ba4aca3db6c1e3af93abdbc904b7d5" }, "scripts/ffi_build.py": { - "bytes": 12781, - "git_blob": "dfa9f484fd6d2206e9729c8f121facb0489b7cff", + "bytes": 13121, + "git_blob": "0e4f11cd56003b562bccb90eeb30ca706a272863", "mode": "100644", - "sha256": "b58076013b5a4187c048aa5de8007d259404cc38cee5d72636edd0e3722dc3f3" + "sha256": "eafe2189e97a436522fdf18909aa494392ab0347da28b338cc999b30044fc90d" }, "scripts/ffi_installed.py": { "bytes": 8207, @@ -998,16 +1003,16 @@ "sha256": "2f14e83fe08d70b4c92361d9bccd08dd6c480eebd767a692a8b5f03fdb0e5380" }, "scripts/ffi_provenance.py": { - "bytes": 6732, - "git_blob": "482e69d766c7d76c9fee438b5661f35e070b085c", + "bytes": 6808, + "git_blob": "de2c086a110501f8bd11f1e5b26b2473c468ce28", "mode": "100644", - "sha256": "e032f5d2f92de7b5e9761196c30ff2209108231d664a95a25a653c353b16f9fa" + "sha256": "2a1a89db83bfd1b1a2e80c1fbd31288dcf2f75a1439ba3446633c755dec0255f" }, "scripts/ffi_source.py": { - "bytes": 12532, - "git_blob": "9287d6f6f3f924f2a6572def96dd3d3bf9554c7f", + "bytes": 13386, + "git_blob": "eec045f0fce4a6be04416519bd1f2d71c689fcf3", "mode": "100644", - "sha256": "8470f7dba319fad00e7ed257d144917e7084330285b1bd706540c554899c5d34" + "sha256": "08f5fdfa58c7a3ef89838e6c1c08bc9156e86be36a6ada127aa0cb307711dde3" }, "scripts/generate-project.sh": { "bytes": 2964, @@ -1106,10 +1111,10 @@ "sha256": "1a60456d7780dfb26dbc71c3c3a07190f6d78c44521f264e0d8aa3ee41c7ff59" }, "scripts/test_ffi_provenance.py": { - "bytes": 7905, - "git_blob": "5e01f74aeef97593ca6ac38091e137501d046c01", + "bytes": 10601, + "git_blob": "288809fab06c2af2a0cafe157b021772da3d754e", "mode": "100644", - "sha256": "6f0196a26af8c1e63ce400ca351c56e95f1122142cecb5fd8d09f4bdc9a2fb83" + "sha256": "707cf2cfc9de12e7409247c875289efc4a7b08c6df845ea10c337b84bb98e39b" }, "scripts/test_legacy_identifiers.py": { "bytes": 5760, @@ -1155,6 +1160,6 @@ } }, "policy": "staged_inputs", - "tree": "5364e38f7c08b01eef0d63a2eb48383215e887d8" + "tree": "ed13f3efac75566f8f21f1fcc0f9cea938d21d53" } } diff --git a/TeraFFI/source/aarch64-apple-ios-sim.json b/TeraFFI/source/aarch64-apple-ios-sim.json @@ -367,6 +367,7 @@ "features": [], "ios_deployment_target": "18.0", "package": "tera_ffi", + "package_rust_flags": [], "profile": "release", "rust_flags": [ "--remap-path-prefix={producer_root}=/tera", @@ -518,10 +519,10 @@ "sha256": "7e9bc238cc27041e3f6b63d40d28712f3276bf0b3f3deb7609f4fb962db4f4c1" }, "TeraFFI/producer.toml": { - "bytes": 963, - "git_blob": "87e4526a6595ded35ea62b6ef1b3aa67b923b515", + "bytes": 1084, + "git_blob": "23e07f3d818f7f3d57a77fca3bca6b32b9218e74", "mode": "100644", - "sha256": "c497212bfb54d997bbf5938cd04c7a41c3ef2ce7adaef861fc07e2565cd26661" + "sha256": "eebaf5b181e9b27c3854201c6f6ac1662b7a7045168f960a5c1dac8c5de29013" }, "TeraFFI/scripts/verify-installed-artifacts.sh": { "bytes": 255, @@ -986,10 +987,10 @@ "sha256": "568ee230a99a907cc9063c203fbecc80e6ba4aca3db6c1e3af93abdbc904b7d5" }, "scripts/ffi_build.py": { - "bytes": 12781, - "git_blob": "dfa9f484fd6d2206e9729c8f121facb0489b7cff", + "bytes": 13121, + "git_blob": "0e4f11cd56003b562bccb90eeb30ca706a272863", "mode": "100644", - "sha256": "b58076013b5a4187c048aa5de8007d259404cc38cee5d72636edd0e3722dc3f3" + "sha256": "eafe2189e97a436522fdf18909aa494392ab0347da28b338cc999b30044fc90d" }, "scripts/ffi_installed.py": { "bytes": 8207, @@ -998,16 +999,16 @@ "sha256": "2f14e83fe08d70b4c92361d9bccd08dd6c480eebd767a692a8b5f03fdb0e5380" }, "scripts/ffi_provenance.py": { - "bytes": 6732, - "git_blob": "482e69d766c7d76c9fee438b5661f35e070b085c", + "bytes": 6808, + "git_blob": "de2c086a110501f8bd11f1e5b26b2473c468ce28", "mode": "100644", - "sha256": "e032f5d2f92de7b5e9761196c30ff2209108231d664a95a25a653c353b16f9fa" + "sha256": "2a1a89db83bfd1b1a2e80c1fbd31288dcf2f75a1439ba3446633c755dec0255f" }, "scripts/ffi_source.py": { - "bytes": 12532, - "git_blob": "9287d6f6f3f924f2a6572def96dd3d3bf9554c7f", + "bytes": 13386, + "git_blob": "eec045f0fce4a6be04416519bd1f2d71c689fcf3", "mode": "100644", - "sha256": "8470f7dba319fad00e7ed257d144917e7084330285b1bd706540c554899c5d34" + "sha256": "08f5fdfa58c7a3ef89838e6c1c08bc9156e86be36a6ada127aa0cb307711dde3" }, "scripts/generate-project.sh": { "bytes": 2964, @@ -1106,10 +1107,10 @@ "sha256": "1a60456d7780dfb26dbc71c3c3a07190f6d78c44521f264e0d8aa3ee41c7ff59" }, "scripts/test_ffi_provenance.py": { - "bytes": 7905, - "git_blob": "5e01f74aeef97593ca6ac38091e137501d046c01", + "bytes": 10601, + "git_blob": "288809fab06c2af2a0cafe157b021772da3d754e", "mode": "100644", - "sha256": "6f0196a26af8c1e63ce400ca351c56e95f1122142cecb5fd8d09f4bdc9a2fb83" + "sha256": "707cf2cfc9de12e7409247c875289efc4a7b08c6df845ea10c337b84bb98e39b" }, "scripts/test_legacy_identifiers.py": { "bytes": 5760, @@ -1155,6 +1156,6 @@ } }, "policy": "staged_inputs", - "tree": "5364e38f7c08b01eef0d63a2eb48383215e887d8" + "tree": "ed13f3efac75566f8f21f1fcc0f9cea938d21d53" } } diff --git a/TeraFFI/source/aarch64-apple-ios.json b/TeraFFI/source/aarch64-apple-ios.json @@ -367,6 +367,7 @@ "features": [], "ios_deployment_target": "18.0", "package": "tera_ffi", + "package_rust_flags": [], "profile": "release", "rust_flags": [ "--remap-path-prefix={producer_root}=/tera", @@ -518,10 +519,10 @@ "sha256": "7e9bc238cc27041e3f6b63d40d28712f3276bf0b3f3deb7609f4fb962db4f4c1" }, "TeraFFI/producer.toml": { - "bytes": 963, - "git_blob": "87e4526a6595ded35ea62b6ef1b3aa67b923b515", + "bytes": 1084, + "git_blob": "23e07f3d818f7f3d57a77fca3bca6b32b9218e74", "mode": "100644", - "sha256": "c497212bfb54d997bbf5938cd04c7a41c3ef2ce7adaef861fc07e2565cd26661" + "sha256": "eebaf5b181e9b27c3854201c6f6ac1662b7a7045168f960a5c1dac8c5de29013" }, "TeraFFI/scripts/verify-installed-artifacts.sh": { "bytes": 255, @@ -986,10 +987,10 @@ "sha256": "568ee230a99a907cc9063c203fbecc80e6ba4aca3db6c1e3af93abdbc904b7d5" }, "scripts/ffi_build.py": { - "bytes": 12781, - "git_blob": "dfa9f484fd6d2206e9729c8f121facb0489b7cff", + "bytes": 13121, + "git_blob": "0e4f11cd56003b562bccb90eeb30ca706a272863", "mode": "100644", - "sha256": "b58076013b5a4187c048aa5de8007d259404cc38cee5d72636edd0e3722dc3f3" + "sha256": "eafe2189e97a436522fdf18909aa494392ab0347da28b338cc999b30044fc90d" }, "scripts/ffi_installed.py": { "bytes": 8207, @@ -998,16 +999,16 @@ "sha256": "2f14e83fe08d70b4c92361d9bccd08dd6c480eebd767a692a8b5f03fdb0e5380" }, "scripts/ffi_provenance.py": { - "bytes": 6732, - "git_blob": "482e69d766c7d76c9fee438b5661f35e070b085c", + "bytes": 6808, + "git_blob": "de2c086a110501f8bd11f1e5b26b2473c468ce28", "mode": "100644", - "sha256": "e032f5d2f92de7b5e9761196c30ff2209108231d664a95a25a653c353b16f9fa" + "sha256": "2a1a89db83bfd1b1a2e80c1fbd31288dcf2f75a1439ba3446633c755dec0255f" }, "scripts/ffi_source.py": { - "bytes": 12532, - "git_blob": "9287d6f6f3f924f2a6572def96dd3d3bf9554c7f", + "bytes": 13386, + "git_blob": "eec045f0fce4a6be04416519bd1f2d71c689fcf3", "mode": "100644", - "sha256": "8470f7dba319fad00e7ed257d144917e7084330285b1bd706540c554899c5d34" + "sha256": "08f5fdfa58c7a3ef89838e6c1c08bc9156e86be36a6ada127aa0cb307711dde3" }, "scripts/generate-project.sh": { "bytes": 2964, @@ -1106,10 +1107,10 @@ "sha256": "1a60456d7780dfb26dbc71c3c3a07190f6d78c44521f264e0d8aa3ee41c7ff59" }, "scripts/test_ffi_provenance.py": { - "bytes": 7905, - "git_blob": "5e01f74aeef97593ca6ac38091e137501d046c01", + "bytes": 10601, + "git_blob": "288809fab06c2af2a0cafe157b021772da3d754e", "mode": "100644", - "sha256": "6f0196a26af8c1e63ce400ca351c56e95f1122142cecb5fd8d09f4bdc9a2fb83" + "sha256": "707cf2cfc9de12e7409247c875289efc4a7b08c6df845ea10c337b84bb98e39b" }, "scripts/test_legacy_identifiers.py": { "bytes": 5760, @@ -1155,6 +1156,6 @@ } }, "policy": "staged_inputs", - "tree": "5364e38f7c08b01eef0d63a2eb48383215e887d8" + "tree": "ed13f3efac75566f8f21f1fcc0f9cea938d21d53" } } diff --git a/release/provenance.json b/release/provenance.json @@ -2,7 +2,7 @@ "artifacts": { "app_api_sha256": "020924097c0d7efc33128cb8fd3d3b2026d95f57c44da71880e585aff80f070b", "ffi_api_sha256": "6542c8294920b3c41e987619de58690e2af16896079910b657129d3573b34e68", - "ffi_provenance_sha256": "c338c32c516a767f1e1215f5c6b8841927d86c38cdd88ca5c598986a0ca2de89", + "ffi_provenance_sha256": "5ee596b004f9c633f044ed91530f9cdd60427e3828b38f237d327ca5161d42d0", "info_plist_sha256": "15ef08b1cdd1096cfb9eeaf5be5bf8f814807a7ca9350bbbb47860fa72ec13ef", "privacy_manifest_sha256": "a331d51864743ebe4e00dd22360b4a538b6b3ac26a6b3eb54094e60a36959a12", "sbom_sha256": "6b5ce897d5273290febc8b831663e12dea759cb0084f182ba7949e1c593fc410", @@ -22,7 +22,7 @@ "lib_revision": "ad17b7d3455a7147cfa303d976fc5c70c3a4c0cb", "source_date_epoch": 1787871027, "swift_package_lock_sha256": "94ae067a374726cdaf6b4ca0a5e44663c57fcdc5334060c5ffef5e79cfbf04c0", - "tera_ffi_source_tree": "5364e38f7c08b01eef0d63a2eb48383215e887d8", + "tera_ffi_source_tree": "ed13f3efac75566f8f21f1fcc0f9cea938d21d53", "xcode_package_lock_sha256": "c7f41934ea25f7a287bdc4f3a6ecabbf09a3a0bdd0f5a3e58183f355ca814096" }, "version": "0.1.0-alpha" diff --git a/scripts/ffi_build.py b/scripts/ffi_build.py @@ -84,6 +84,28 @@ def run( return log +def library_command(root: Path, target: str, project: Path) -> list[str]: + config = source.producer_contract(root) + flags = [ + flag.format(extbuild_root=project) + for flag in source.library_rust_flags(config["build"], target) + ] + command = [ + "cargo", + "rustc" if flags else "build", + "--manifest-path", + str(root / "Cargo.toml"), + "-p", + "tera_ffi", + "--lib", + "--release", + "--locked", + "--target", + target, + ] + return command + (["--", *flags] if flags else []) + + def build_libraries( root: Path, bundle: Path, target_root: Path, logs: Path, env: dict[str, str] ) -> None: @@ -92,18 +114,7 @@ def build_libraries( root, logs, "build-" + target, - [ - "cargo", - "build", - "--manifest-path", - str(root / "Cargo.toml"), - "-p", - "tera_ffi", - "--release", - "--locked", - "--target", - target, - ], + library_command(root, target, Path(env["EXT_BUILD_PROJECT_DIR"])), env, ) extension = "dylib" if target == artifacts.TARGETS[-1] else "a" diff --git a/scripts/ffi_provenance.py b/scripts/ffi_provenance.py @@ -44,6 +44,7 @@ def capture(root: Path, target: str) -> dict[str, Any]: "profile": build["profile"], "ios_deployment_target": build["ios_deployment_target"], "rust_flags": build["rust_flags"], + "package_rust_flags": source.library_rust_flags(build, target), "source_date_epoch": build["source_date_epoch"], "rustc": rustc, "symbol_reader": source.command( diff --git a/scripts/ffi_source.py b/scripts/ffi_source.py @@ -133,6 +133,9 @@ def validate_build(value: Any) -> None: "rust_flags", "source_date_epoch", "host", + "host_dylib_install_name", + "host_linker_reproducible", + "host_oso_prefix", "targets", }, "producer build fields", @@ -144,6 +147,19 @@ def validate_build(value: Any) -> None: ) contract._exact(value["host"], "aarch64-apple-darwin", "producer host") contract._exact( + value["host_dylib_install_name"], + "@rpath/libtera_ffi.dylib", + "producer host dylib install name", + ) + contract._exact( + value["host_linker_reproducible"] is True, + True, + "producer host linker reproducibility", + ) + contract._exact( + value["host_oso_prefix"], "{extbuild_root}", "producer host debug-map prefix" + ) + contract._exact( value["rust_flags"], [ "--remap-path-prefix={producer_root}=/tera", @@ -165,6 +181,16 @@ def validate_build(value: Any) -> None: raise ProvenanceError("producer source epoch is invalid") +def library_rust_flags(build: dict[str, Any], target: str) -> list[str]: + if target == build["host"]: + return [ + f"-Clink-arg=-Wl,-install_name,{build['host_dylib_install_name']}", + "-Clink-arg=-Wl,-reproducible", + f"-Clink-arg=-Wl,-oso_prefix,{build['host_oso_prefix']}", + ] + return [] + + def validate_foundation(cargo: dict[str, Any], lock: dict[str, Any]) -> None: contract._exact( lock.get("schema"), "radroots.lib.source-lock.v1", "foundation schema" diff --git a/scripts/test_ffi_provenance.py b/scripts/test_ffi_provenance.py @@ -13,6 +13,7 @@ SCRIPTS = Path(__file__).resolve().parent if str(SCRIPTS) not in sys.path: sys.path.insert(0, str(SCRIPTS)) +import ffi_build as builder # noqa: E402 import ffi_provenance as provenance # noqa: E402 import ffi_source as source # noqa: E402 import package_contract as contract # noqa: E402 @@ -99,6 +100,7 @@ class ProducerSourceTests(unittest.TestCase): "target": "aarch64-apple-ios", "rustc": "rustc 1.97.1", "features": [], + "package_rust_flags": [], "feature_graph": ["tera_core|mobile-social"], }, } @@ -109,6 +111,7 @@ class ProducerSourceTests(unittest.TestCase): ("build", "target", "aarch64-apple-ios-sim"), ("build", "rustc", "rustc 1.96.0"), ("build", "features", ["extra"]), + ("build", "package_rust_flags", ["-Copt-level=0"]), ("build", "feature_graph", []), ): with self.subTest(section=section, key=key): @@ -176,6 +179,61 @@ class ProducerSourceTests(unittest.TestCase): ): source.validate_foundation(changed, lock) + def test_host_install_name_is_fixed_and_scoped_to_the_ffi_library(self) -> None: + config = source.producer_contract(SCRIPTS.parent) + build = config["build"] + flags = [ + "-Clink-arg=-Wl,-install_name,@rpath/libtera_ffi.dylib", + "-Clink-arg=-Wl,-reproducible", + "-Clink-arg=-Wl,-oso_prefix,{extbuild_root}", + ] + project = Path("/external/test-producer") + for target in build["targets"]: + with self.subTest(target=target): + command = builder.library_command(SCRIPTS.parent, target, project) + self.assertIn("--lib", command) + self.assertEqual(command[command.index("-p") + 1], "tera_ffi") + if target == build["host"]: + self.assertEqual(command[1], "rustc") + self.assertEqual( + command[-4:], + ["--", *(flag.format(extbuild_root=project) for flag in flags)], + ) + self.assertEqual(source.library_rust_flags(build, target), flags) + else: + self.assertEqual(command[1], "build") + self.assertNotIn("--", command) + self.assertEqual(source.library_rust_flags(build, target), []) + self.assertFalse(any("install_name" in flag for flag in build["rust_flags"])) + for install_name in ( + "/tmp/libtera_ffi.dylib", + "libtera_ffi.dylib", + "@rpath/other.dylib", + ): + changed = copy.deepcopy(build) + changed["host_dylib_install_name"] = install_name + with ( + self.subTest(install_name=install_name), + self.assertRaises(contract.PackageContractError), + ): + source.validate_build(changed) + for prefix in ("/tmp", "{producer_root}", ""): + changed = copy.deepcopy(build) + changed["host_oso_prefix"] = prefix + with ( + self.subTest(prefix=prefix), + self.assertRaises(contract.PackageContractError), + ): + source.validate_build(changed) + for reproducible in (False, 1, "true"): + changed = copy.deepcopy(build) + changed["host_linker_reproducible"] = reproducible + with ( + self.subTest(reproducible=reproducible), + self.assertRaises(contract.PackageContractError), + ): + source.validate_build(changed) + if __name__ == "__main__": unittest.main()