From d65666b8d663710ed3389f37b0c8089336e6d9dc Mon Sep 17 00:00:00 2001 From: dank-openai Date: Sat, 9 May 2026 23:04:12 -0400 Subject: [PATCH] aot: carry standalone runtime link metadata Materialize the runtime link manifest with the archive and keep the generated artifact config pair self-contained for downstream consumers. branch:dank-spr/rules-xlsynth-aot-runtime-link-metadata --- BUILD.bazel | 2 +- DESIGN.md | 1 + README.md | 16 ++++-- artifact_resolution_test.py | 53 ++++++++++++++++++ download_release.py | 25 ++++++++- download_release_test.py | 8 +++ extensions.bzl | 27 ++++++++- materialize_xls_bundle.py | 107 ++++++++++++++++++++++++++++++++++-- xls_toolchain.bzl | 24 +++++++- 9 files changed, 244 insertions(+), 19 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index dc324de..80eb9c8 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -89,9 +89,9 @@ py_test( ":xlsynth_sys_dep_probe", ":xlsynth_sys_legacy_inputs_probe", ":xlsynth_sys_runtime_probe", - "@rules_xlsynth_selftest_xls_toolchain", "@rules_xlsynth_selftest_xls_runtime//:dslx_stdlib", "@rules_xlsynth_selftest_xls_runtime//:xlsynth_sys_artifact_config", + "@rules_xlsynth_selftest_xls_toolchain", ], deps = ["@rules_python//python/runfiles"], ) diff --git a/DESIGN.md b/DESIGN.md index 8e12094..c3ce690 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -25,6 +25,7 @@ is: - `@_runtime//:libxls_link` - `@_runtime//:xls_aot_runtime` when the selected XLS line provides the archive - `@_runtime//:xls_aot_runtime_file` when the selected XLS line provides the archive +- `@_runtime//:xls_aot_runtime_link_config_file` when the selected XLS line provides the archive - `@_runtime//:dslx_stdlib` - `@_runtime//:xlsynth_sys_artifact_config` - `@_runtime//:xlsynth_sys_legacy_stdlib` diff --git a/README.md b/README.md index b53bb34..38df74b 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,11 @@ do not use that repo directly or publish it with `use_repo(...)`. The runtime repo exposes: - `@_runtime//:libxls` and `@_runtime//:libxls_link` for native consumers -- `@_runtime//:xls_aot_runtime` and `@_runtime//:xls_aot_runtime_file` - when the selected XLS line provides the standalone AOT static runtime archive +- `@_runtime//:xls_aot_runtime`, + `@_runtime//:xls_aot_runtime_file`, and + `@_runtime//:xls_aot_runtime_link_config_file` when the selected XLS + line provides the standalone AOT static runtime archive plus its producer-owned + link metadata - `@_runtime//:dslx_stdlib` for packages that need the standard library tree - `@_runtime//:xlsynth_sys_artifact_config` for the modern single-file build-script contract shared by `xlsynth-sys` and `xlsynth-aot-runtime` @@ -124,10 +127,11 @@ The runtime repo exposes: `artifact_config`, `libxls_file`, `libxls`, or `dslx_stdlib` directly in downstream `MODULE.bazel` files. `xlsynth-aot-runtime` consumers should reuse the same artifact-config export so their build scripts receive the matching -standalone runtime archive without a second bundle contract. Older bundles may -omit the archive entirely; that keeps non-AOT consumers on old XLS lines valid -while making an AOT consumer fail locally if it selects a bundle that cannot -provide the archive it needs. +standalone runtime archive and its producer-owned link config without a second +bundle contract. Older bundles may omit the archive pair entirely; that keeps +non-AOT consumers on old XLS lines valid while making an AOT consumer fail +locally if it selects a bundle that cannot provide the runtime artifacts it +needs. Supported DSLX rules may opt out of the registered default bundle with `xls_bundle = "@_toolchain//:bundle"`. Today that escape hatch is available on diff --git a/artifact_resolution_test.py b/artifact_resolution_test.py index 0c9c5a0..ef43835 100644 --- a/artifact_resolution_test.py +++ b/artifact_resolution_test.py @@ -69,6 +69,7 @@ def exists_fn(path): "/tools/xlsynth/v0.38.0/xls/dslx/stdlib", "/tools/xlsynth/v0.38.0/libxls.dylib" if sys.platform == "darwin" else "/tools/xlsynth/v0.38.0/libxls.so", "/tools/xlsynth/v0.38.0/libxls_aot_runtime.a", + "/tools/xlsynth/v0.38.0/libxls_aot_runtime_link.toml", ], ) @@ -105,6 +106,17 @@ def test_installed_only_requires_installed_paths(self): exists_fn = lambda path: False, ) + def test_installed_paths_require_static_aot_runtime_pair(self): + with self.assertRaisesRegex(ValueError, "together"): + materialize_xls_bundle.resolve_artifact_plan( + artifact_source = "installed_only", + xls_version = "0.38.0", + driver_version = "0.33.0", + installed_tools_root_prefix = "/tools/xlsynth", + installed_driver_root_prefix = "/tools/xlsynth-driver", + exists_fn = lambda path: not path.endswith("libxls_aot_runtime_link.toml"), + ) + def test_download_only_skips_installed_probe(self): observed_paths = [] @@ -131,6 +143,7 @@ def test_local_paths_bypass_versioned_selection(self): local_driver_path = "/tmp/xls-local-dev/xlsynth-driver", local_libxls_path = "/tmp/xls-local-dev/libxls.so", local_xls_aot_runtime_path = "/tmp/xls-local-dev/libxls_aot_runtime.a", + local_xls_aot_runtime_link_config_path = "/tmp/xls-local-dev/libxls_aot_runtime_link.toml", ) self.assertEqual(plan["mode"], "local_paths") self.assertEqual( @@ -141,6 +154,10 @@ def test_local_paths_bypass_versioned_selection(self): plan["xls_aot_runtime"], Path("/tmp/xls-local-dev/libxls_aot_runtime.a"), ) + self.assertEqual( + plan["xls_aot_runtime_link_config"], + Path("/tmp/xls-local-dev/libxls_aot_runtime_link.toml"), + ) def test_local_paths_allow_bundle_without_static_aot_runtime(self): plan = materialize_xls_bundle.resolve_artifact_plan( @@ -153,6 +170,20 @@ def test_local_paths_allow_bundle_without_static_aot_runtime(self): local_libxls_path = "/tmp/xls-local-dev/libxls.so", ) self.assertIsNone(plan["xls_aot_runtime"]) + self.assertIsNone(plan["xls_aot_runtime_link_config"]) + + def test_local_paths_require_static_aot_runtime_pair(self): + with self.assertRaisesRegex(ValueError, "together"): + materialize_xls_bundle.resolve_artifact_plan( + artifact_source = "local_paths", + xls_version = "", + driver_version = "", + local_tools_path = "/tmp/xls-local-dev/tools", + local_dslx_stdlib_path = "/tmp/xls-local-dev/stdlib", + local_driver_path = "/tmp/xls-local-dev/xlsynth-driver", + local_libxls_path = "/tmp/xls-local-dev/libxls.so", + local_xls_aot_runtime_path = "/tmp/xls-local-dev/libxls_aot_runtime.a", + ) def test_resolve_driver_plan_prefers_installed_driver(self): plan = materialize_xls_bundle.resolve_driver_plan( @@ -305,6 +336,10 @@ def test_installed_paths_use_live_version_pattern(self): expected_name = "libxls.dylib" if sys.platform == "darwin" else "libxls.so" self.assertEqual(plan["libxls"].name, expected_name) self.assertEqual(plan["xls_aot_runtime"].name, "libxls_aot_runtime.a") + self.assertEqual( + plan["xls_aot_runtime_link_config"].name, + "libxls_aot_runtime_link.toml", + ) def test_build_driver_environment_sets_runtime_library_search_path(self): libxls_path = "/tmp/xls-bundle/libxls.dylib" if sys.platform == "darwin" else "/tmp/xls-bundle/libxls.so" @@ -414,6 +449,7 @@ def test_download_versioned_artifacts_reuses_valid_cache(self): (download_root / binary).write_text("", encoding = "utf-8") (download_root / "libxls-v0.38.0-arm64.dylib").write_text("", encoding = "utf-8") (download_root / "libxls_aot_runtime-arm64.a").write_text("", encoding = "utf-8") + (download_root / "libxls_aot_runtime_link-arm64.toml").write_text("", encoding = "utf-8") with mock.patch.object(materialize_xls_bundle, "detect_host_platform", return_value = "arm64"): with mock.patch.object(materialize_xls_bundle.subprocess, "run") as mock_run: @@ -429,6 +465,10 @@ def test_download_versioned_artifacts_reuses_valid_cache(self): resolved["xls_aot_runtime"], download_root / "libxls_aot_runtime-arm64.a", ) + self.assertEqual( + resolved["xls_aot_runtime_link_config"], + download_root / "libxls_aot_runtime_link-arm64.toml", + ) self.assertEqual(resolved["runtime_files"], []) mock_run.assert_not_called() @@ -447,6 +487,7 @@ def test_download_versioned_artifacts_reuses_valid_cache_without_aot_runtime(sel resolved = materialize_xls_bundle.download_versioned_artifacts(repo_root, "0.38.0") self.assertIsNone(resolved["xls_aot_runtime"]) + self.assertIsNone(resolved["xls_aot_runtime_link_config"]) mock_run.assert_not_called() def test_load_runtime_manifest_returns_runtime_files(self): @@ -615,6 +656,8 @@ def test_stage_runtime_payload_records_runtime_metadata(self): libxls_path.write_text("xls\n", encoding = "utf-8") xls_aot_runtime_path = input_root / "libxls_aot_runtime.a" xls_aot_runtime_path.write_text("aot\n", encoding = "utf-8") + xls_aot_runtime_link_config_path = input_root / "libxls_aot_runtime_link.toml" + xls_aot_runtime_link_config_path.write_text("format_version = 1\n", encoding = "utf-8") runtime_companion = input_root / "libc++.so.1" runtime_companion.write_text("runtime\n", encoding = "utf-8") @@ -630,6 +673,7 @@ def test_stage_runtime_payload_records_runtime_metadata(self): "dslx_stdlib_root": stdlib_root, "libxls": libxls_path, "xls_aot_runtime": xls_aot_runtime_path, + "xls_aot_runtime_link_config": xls_aot_runtime_link_config_path, "runtime_files": [runtime_companion], }, ) @@ -644,10 +688,19 @@ def test_stage_runtime_payload_records_runtime_metadata(self): ) self.assertEqual(metadata["libxls_name"], "libxls.so") self.assertEqual(metadata["xls_aot_runtime_name"], "libxls_aot_runtime.a") + self.assertEqual( + metadata["xls_aot_runtime_link_config_name"], + "libxls_aot_runtime_link.toml", + ) self.assertEqual(metadata["libxls_runtime_aliases"], "libxls-v0.38.0.so") self.assertEqual(metadata["libxls_runtime_files"], "libc++.so.1") self.assertIn('aot_runtime_path = "libxls_aot_runtime.a"', artifact_config) + self.assertIn( + 'aot_runtime_link_config_path = "libxls_aot_runtime_link.toml"', + artifact_config, + ) self.assertTrue((repo_root / "libxls_aot_runtime.a").is_file()) + self.assertTrue((repo_root / "libxls_aot_runtime_link.toml").is_file()) self.assertTrue((repo_root / "libc++.so.1").is_file()) def test_materialize_toolchain_surface_records_driver_capabilities(self): diff --git a/download_release.py b/download_release.py index fcd8f73..09982c3 100644 --- a/download_release.py +++ b/download_release.py @@ -60,6 +60,10 @@ def build_static_aot_runtime_release_filename(platform): return "libxls_aot_runtime-{}.a".format(platform) +def build_static_aot_runtime_link_config_release_filename(platform): + return "libxls_aot_runtime_link-{}.toml".format(platform) + + def build_runtime_tarball_release_filename(platform): return "libxls-runtime-{}.tar.gz".format(platform) @@ -264,13 +268,30 @@ def main(): high_integrity_download(base_url, artifact, options.output_dir, options.max_attempts, is_binary, options.platform) if options.dso: - try_high_integrity_download( + static_aot_runtime = build_static_aot_runtime_release_filename(options.platform) + static_aot_runtime_link_config = build_static_aot_runtime_link_config_release_filename( + options.platform + ) + archive_present = try_high_integrity_download( base_url, - build_static_aot_runtime_release_filename(options.platform), + static_aot_runtime, options.output_dir, options.max_attempts, is_binary = False, ) + link_config_present = try_high_integrity_download( + base_url, + static_aot_runtime_link_config, + options.output_dir, + options.max_attempts, + is_binary = False, + ) + if archive_present != link_config_present: + print("Ignoring partial standalone AOT runtime asset set for {}".format(options.platform)) + for partial_name in [static_aot_runtime, static_aot_runtime_link_config]: + partial_path = os.path.join(options.output_dir, partial_name) + if os.path.exists(partial_path): + os.remove(partial_path) # Download and extract dslx_stdlib.tar.gz stdlib_filename = "dslx_stdlib.tar.gz" diff --git a/download_release_test.py b/download_release_test.py index ac88959..4bfc7c1 100644 --- a/download_release_test.py +++ b/download_release_test.py @@ -81,6 +81,14 @@ def test_static_aot_runtime_release_filename_is_platform_scoped(self): download_release.build_static_aot_runtime_release_filename("ubuntu2004"), "libxls_aot_runtime-ubuntu2004.a", ) + self.assertEqual( + download_release.build_static_aot_runtime_link_config_release_filename("arm64"), + "libxls_aot_runtime_link-arm64.toml", + ) + self.assertEqual( + download_release.build_static_aot_runtime_link_config_release_filename("ubuntu2004"), + "libxls_aot_runtime_link-ubuntu2004.toml", + ) def test_copy_url_to_path_retries_after_stream_reset(self): with tempfile.TemporaryDirectory() as temp_dir: diff --git a/extensions.bzl b/extensions.bzl index c31a38f..26cf88b 100644 --- a/extensions.bzl +++ b/extensions.bzl @@ -76,11 +76,17 @@ def _driver_supports_sv_struct_field_ordering(driver_version): return True return _version_at_least(driver_version, "0.36.0") -def _runtime_build_file(libxls_name, xls_aot_runtime_name, runtime_files, runtime_aliases): +def _runtime_build_file( + libxls_name, + xls_aot_runtime_name, + xls_aot_runtime_link_config_name, + runtime_files, + runtime_aliases): tool_list = ",\n ".join(['"{}"'.format(name) for name in _TOOL_BINARIES]) exported_names = _TOOL_BINARIES + [libxls_name] + runtime_files + runtime_aliases if xls_aot_runtime_name: exported_names.append(xls_aot_runtime_name) + exported_names.append(xls_aot_runtime_link_config_name) exported_files = ",\n ".join(['"{}"'.format(name) for name in exported_names]) runtime_file_srcs = ",\n ".join(['"{}"'.format(name) for name in runtime_files]) runtime_alias_srcs = ",\n ".join(['"{}"'.format(name) for name in runtime_aliases]) @@ -91,6 +97,11 @@ filegroup( srcs = ["{xls_aot_runtime_name}"], visibility = ["//visibility:public"], ) +filegroup( + name = "xls_aot_runtime_link_config_file", + srcs = ["{xls_aot_runtime_link_config_name}"], + visibility = ["//visibility:public"], +) cc_import( name = "xls_aot_runtime", static_library = ":xls_aot_runtime_file", @@ -98,6 +109,7 @@ cc_import( ) """.format( xls_aot_runtime_name = xls_aot_runtime_name, + xls_aot_runtime_link_config_name = xls_aot_runtime_link_config_name, ) if xls_aot_runtime_name else "" lib_file_rule = """ filegroup( @@ -158,6 +170,7 @@ xlsynth_artifact_config( dslx_stdlib = ":dslx_stdlib", shared_library = ":libxls_file", static_aot_runtime = {static_aot_runtime}, + static_aot_runtime_link_config = {static_aot_runtime_link_config}, visibility = ["//visibility:public"], ) @@ -217,6 +230,7 @@ xls_runtime_surface( lib_file_rule = lib_file_rule.strip(), aot_runtime_rule = aot_runtime_rule.strip(), static_aot_runtime = '":xls_aot_runtime_file"' if xls_aot_runtime_name else "None", + static_aot_runtime_link_config = '":xls_aot_runtime_link_config_file"' if xls_aot_runtime_name else "None", ) def _string_attr_line(name, value): @@ -369,6 +383,11 @@ def _materialize_bundle_args(repo_ctx, surface): args.extend(["--local-libxls-path", repo_ctx.attr.local_libxls_path]) if repo_ctx.attr.local_xls_aot_runtime_path: args.extend(["--local-xls-aot-runtime-path", repo_ctx.attr.local_xls_aot_runtime_path]) + if repo_ctx.attr.local_xls_aot_runtime_link_config_path: + args.extend([ + "--local-xls-aot-runtime-link-config-path", + repo_ctx.attr.local_xls_aot_runtime_link_config_path, + ]) return args def _runtime_repo_impl(repo_ctx): @@ -398,6 +417,7 @@ def _runtime_repo_impl(repo_ctx): _runtime_build_file( libxls_name = metadata["libxls_name"], xls_aot_runtime_name = metadata["xls_aot_runtime_name"], + xls_aot_runtime_link_config_name = metadata["xls_aot_runtime_link_config_name"], runtime_files = runtime_files, runtime_aliases = runtime_aliases, ), @@ -439,6 +459,7 @@ _runtime_repo_attrs = { "local_dslx_stdlib_path": attr.string(), "local_libxls_path": attr.string(), "local_xls_aot_runtime_path": attr.string(), + "local_xls_aot_runtime_link_config_path": attr.string(), "local_tools_path": attr.string(), "xls_version": attr.string(), "xlsynth_driver_version": attr.string(), @@ -453,6 +474,7 @@ _toolchain_repo_attrs = { "local_dslx_stdlib_path": attr.string(), "local_libxls_path": attr.string(), "local_xls_aot_runtime_path": attr.string(), + "local_xls_aot_runtime_link_config_path": attr.string(), "local_tools_path": attr.string(), "repo_alias": attr.string(mandatory = True), "runtime_repo_name": attr.string(mandatory = True), @@ -496,6 +518,7 @@ _toolchain_tag = tag_class(attrs = { "local_dslx_stdlib_path": attr.string(), "local_libxls_path": attr.string(), "local_xls_aot_runtime_path": attr.string(), + "local_xls_aot_runtime_link_config_path": attr.string(), "local_tools_path": attr.string(), "name": attr.string(mandatory = True), "xls_version": attr.string(), @@ -517,6 +540,7 @@ def _xls_extension_impl(module_ctx): local_dslx_stdlib_path = toolchain.local_dslx_stdlib_path, local_libxls_path = toolchain.local_libxls_path, local_xls_aot_runtime_path = toolchain.local_xls_aot_runtime_path, + local_xls_aot_runtime_link_config_path = toolchain.local_xls_aot_runtime_link_config_path, local_tools_path = toolchain.local_tools_path, xls_version = toolchain.xls_version, xlsynth_driver_version = toolchain.xlsynth_driver_version, @@ -536,6 +560,7 @@ def _xls_extension_impl(module_ctx): local_dslx_stdlib_path = toolchain.local_dslx_stdlib_path, local_libxls_path = toolchain.local_libxls_path, local_xls_aot_runtime_path = toolchain.local_xls_aot_runtime_path, + local_xls_aot_runtime_link_config_path = toolchain.local_xls_aot_runtime_link_config_path, local_tools_path = toolchain.local_tools_path, repo_alias = toolchain_name, runtime_repo_name = runtime_name, diff --git a/materialize_xls_bundle.py b/materialize_xls_bundle.py index 47ec1a4..a3f22f4 100644 --- a/materialize_xls_bundle.py +++ b/materialize_xls_bundle.py @@ -65,6 +65,10 @@ def static_aot_runtime_name(): return "libxls_aot_runtime.a" +def static_aot_runtime_link_config_name(): + return "libxls_aot_runtime_link.toml" + + def derive_installed_paths( xls_version, driver_version, @@ -80,6 +84,7 @@ def derive_installed_paths( "driver": Path(installed_driver_root_prefix) / normalized_driver_version / "bin" / "xlsynth-driver", "libxls": tools_root / libxls_name_for_platform(sys_platform), "xls_aot_runtime": tools_root / static_aot_runtime_name(), + "xls_aot_runtime_link_config": tools_root / static_aot_runtime_link_config_name(), } @@ -94,6 +99,7 @@ def derive_installed_runtime_paths( "dslx_stdlib_root": tools_root / "xls" / "dslx" / "stdlib", "libxls": tools_root / libxls_name_for_platform(sys_platform), "xls_aot_runtime": tools_root / static_aot_runtime_name(), + "xls_aot_runtime_link_config": tools_root / static_aot_runtime_link_config_name(), } @@ -119,6 +125,7 @@ def resolve_artifact_plan( local_driver_path = "", local_libxls_path = "", local_xls_aot_runtime_path = "", + local_xls_aot_runtime_link_config_path = "", exists_fn = os.path.exists, ): if surface not in ("runtime", "toolchain"): @@ -138,12 +145,22 @@ def resolve_artifact_plan( missing = [name for name, value in required.items() if not value] if missing: raise ValueError("local_paths requires {}".format(", ".join(sorted(missing)))) + if bool(local_xls_aot_runtime_path) != bool(local_xls_aot_runtime_link_config_path): + raise ValueError( + "local_paths requires local_xls_aot_runtime_path and " + "local_xls_aot_runtime_link_config_path together" + ) plan = { "mode": "local_paths", "tools_root": Path(local_tools_path), "dslx_stdlib_root": Path(local_dslx_stdlib_path), "libxls": Path(local_libxls_path), "xls_aot_runtime": Path(local_xls_aot_runtime_path) if local_xls_aot_runtime_path else None, + "xls_aot_runtime_link_config": ( + Path(local_xls_aot_runtime_link_config_path) + if local_xls_aot_runtime_link_config_path + else None + ), } if include_driver: plan["driver"] = Path(local_driver_path) @@ -161,6 +178,7 @@ def resolve_artifact_plan( or local_driver_path or local_libxls_path or local_xls_aot_runtime_path + or local_xls_aot_runtime_link_config_path ): raise ValueError("{} does not accept local_paths attrs".format(artifact_source)) if artifact_source == "download_only": @@ -199,8 +217,17 @@ def resolve_artifact_plan( installed_paths_present = all( exists_fn(str(path)) for name, path in installed_paths.items() - if name != "xls_aot_runtime" + if name not in ("xls_aot_runtime", "xls_aot_runtime_link_config") ) + installed_aot_runtime_present = exists_fn(str(installed_paths["xls_aot_runtime"])) + installed_aot_runtime_link_config_present = exists_fn( + str(installed_paths["xls_aot_runtime_link_config"]) + ) + if installed_aot_runtime_present != installed_aot_runtime_link_config_present: + raise ValueError( + "installed paths require libxls_aot_runtime.a and " + "libxls_aot_runtime_link.toml together" + ) if artifact_source == "auto" and installed_paths_present: plan = { "mode": "installed", @@ -209,7 +236,12 @@ def resolve_artifact_plan( "libxls": installed_paths["libxls"], "xls_aot_runtime": ( installed_paths["xls_aot_runtime"] - if exists_fn(str(installed_paths["xls_aot_runtime"])) + if installed_aot_runtime_present + else None + ), + "xls_aot_runtime_link_config": ( + installed_paths["xls_aot_runtime_link_config"] + if installed_aot_runtime_link_config_present else None ), } @@ -231,7 +263,12 @@ def resolve_artifact_plan( "libxls": installed_paths["libxls"], "xls_aot_runtime": ( installed_paths["xls_aot_runtime"] - if exists_fn(str(installed_paths["xls_aot_runtime"])) + if installed_aot_runtime_present + else None + ), + "xls_aot_runtime_link_config": ( + installed_paths["xls_aot_runtime_link_config"] + if installed_aot_runtime_link_config_present else None ), } @@ -733,11 +770,32 @@ def resolve_downloaded_artifacts(download_root): static_aot_runtime_candidates, ) ) + static_aot_runtime_link_config_candidates = sorted( + download_root.glob("libxls_aot_runtime_link-*.toml") + ) + if len(static_aot_runtime_link_config_candidates) > 1: + raise RuntimeError( + "Expected at most one libxls_aot_runtime link config artifact in {}, found {}".format( + download_root, + static_aot_runtime_link_config_candidates, + ) + ) + if bool(static_aot_runtime_candidates) != bool(static_aot_runtime_link_config_candidates): + raise RuntimeError( + "Expected libxls_aot_runtime archive and link config together in {}".format( + download_root + ) + ) return { "tools_root": download_root, "dslx_stdlib_root": stdlib_root, "libxls": libxls_candidates[0], "xls_aot_runtime": static_aot_runtime_candidates[0] if static_aot_runtime_candidates else None, + "xls_aot_runtime_link_config": ( + static_aot_runtime_link_config_candidates[0] + if static_aot_runtime_link_config_candidates + else None + ), "runtime_files": load_runtime_manifest(download_root), } @@ -777,7 +835,12 @@ def resolve_materialization_inputs(repo_root, plan): return resolved -def write_artifact_config(repo_root, libxls_dest, xls_aot_runtime_dest): +def write_artifact_config( + repo_root, + libxls_dest, + xls_aot_runtime_dest, + xls_aot_runtime_link_config_dest, +): artifact_config_path = repo_root / "xlsynth_artifact_config.toml" config_lines = [ "dso_path = \"{}\"\n".format(libxls_dest.name), @@ -785,10 +848,22 @@ def write_artifact_config(repo_root, libxls_dest, xls_aot_runtime_dest): ] if xls_aot_runtime_dest is not None: config_lines.append("aot_runtime_path = \"{}\"\n".format(xls_aot_runtime_dest.name)) + config_lines.append( + "aot_runtime_link_config_path = \"{}\"\n".format( + xls_aot_runtime_link_config_dest.name + ) + ) artifact_config_path.write_text("".join(config_lines), encoding = "utf-8") -def write_runtime_metadata(repo_root, libxls_dest, xls_aot_runtime_dest, runtime_aliases, runtime_files): +def write_runtime_metadata( + repo_root, + libxls_dest, + xls_aot_runtime_dest, + xls_aot_runtime_link_config_dest, + runtime_aliases, + runtime_files, +): metadata_path = repo_root / "runtime_metadata.txt" metadata_path.write_text( "".join([ @@ -796,6 +871,11 @@ def write_runtime_metadata(repo_root, libxls_dest, xls_aot_runtime_dest, runtime "xls_aot_runtime_name={}\n".format( xls_aot_runtime_dest.name if xls_aot_runtime_dest is not None else "", ), + "xls_aot_runtime_link_config_name={}\n".format( + xls_aot_runtime_link_config_dest.name + if xls_aot_runtime_link_config_dest is not None + else "", + ), "libxls_runtime_aliases={}\n".format(",".join(runtime_aliases)), "libxls_runtime_files={}\n".format(",".join(sorted(runtime_files))), ]), @@ -824,9 +904,15 @@ def stage_runtime_payload(repo_root, resolved): libxls_dest = repo_root / normalized_libxls_name(resolved["libxls"]) copy_path(resolved["libxls"], libxls_dest) xls_aot_runtime_dest = None + xls_aot_runtime_link_config_dest = None if resolved.get("xls_aot_runtime") is not None: xls_aot_runtime_dest = repo_root / static_aot_runtime_name() copy_path(resolved["xls_aot_runtime"], xls_aot_runtime_dest) + xls_aot_runtime_link_config_dest = repo_root / static_aot_runtime_link_config_name() + copy_path( + resolved["xls_aot_runtime_link_config"], + xls_aot_runtime_link_config_dest, + ) staged_runtime_files = [] for runtime_file in resolved.get("runtime_files", []): @@ -836,17 +922,24 @@ def stage_runtime_payload(repo_root, resolved): staged_runtime_files.append(runtime_dest.name) runtime_aliases = normalize_runtime_library_identity(libxls_dest) - write_artifact_config(repo_root, libxls_dest, xls_aot_runtime_dest) + write_artifact_config( + repo_root, + libxls_dest, + xls_aot_runtime_dest, + xls_aot_runtime_link_config_dest, + ) write_runtime_metadata( repo_root, libxls_dest, xls_aot_runtime_dest, + xls_aot_runtime_link_config_dest, runtime_aliases, staged_runtime_files, ) return { "libxls_dest": libxls_dest, "xls_aot_runtime_dest": xls_aot_runtime_dest, + "xls_aot_runtime_link_config_dest": xls_aot_runtime_link_config_dest, "runtime_aliases": runtime_aliases, "runtime_files": staged_runtime_files, } @@ -976,6 +1069,7 @@ def parse_args(argv): parser.add_argument("--driver-runtime-stdlib", default = "") parser.add_argument("--rustup-path", default = "") parser.add_argument("--local-xls-aot-runtime-path", default = "") + parser.add_argument("--local-xls-aot-runtime-link-config-path", default = "") return parser.parse_args(argv) @@ -1014,6 +1108,7 @@ def main(argv): local_driver_path = args.local_driver_path, local_libxls_path = args.local_libxls_path, local_xls_aot_runtime_path = args.local_xls_aot_runtime_path, + local_xls_aot_runtime_link_config_path = args.local_xls_aot_runtime_link_config_path, ) if args.surface == "runtime": materialize_runtime_surface(repo_root, plan) diff --git a/xls_toolchain.bzl b/xls_toolchain.bzl index 629d595..64d7a56 100644 --- a/xls_toolchain.bzl +++ b/xls_toolchain.bzl @@ -558,21 +558,33 @@ def _xlsynth_artifact_config_impl(ctx): config_output = ctx.actions.declare_file("{}/xlsynth_artifact_config.toml".format(bundle_root)) dso_output = ctx.actions.declare_file("{}/{}".format(bundle_root, ctx.attr.dso_name)) aot_runtime_output = None + aot_runtime_link_config_output = None if ctx.file.static_aot_runtime: + if not ctx.file.static_aot_runtime_link_config: + fail("static_aot_runtime_link_config is required with static_aot_runtime") aot_runtime_output = ctx.actions.declare_file( "{}/{}".format(bundle_root, ctx.file.static_aot_runtime.basename), ) + aot_runtime_link_config_output = ctx.actions.declare_file( + "{}/{}".format(bundle_root, ctx.file.static_aot_runtime_link_config.basename), + ) + elif ctx.file.static_aot_runtime_link_config: + fail("static_aot_runtime is required with static_aot_runtime_link_config") stdlib_output = ctx.actions.declare_directory("{}/dslx_stdlib".format(bundle_root)) dslx_stdlib = _single_directory_artifact(ctx.attr.dslx_stdlib, "dslx_stdlib") shared_library = ctx.file.shared_library static_aot_runtime = ctx.file.static_aot_runtime - optional_inputs = [static_aot_runtime] if static_aot_runtime else [] - optional_outputs = [aot_runtime_output] if aot_runtime_output else [] + static_aot_runtime_link_config = ctx.file.static_aot_runtime_link_config + optional_inputs = [static_aot_runtime, static_aot_runtime_link_config] if static_aot_runtime else [] + optional_outputs = [aot_runtime_output, aot_runtime_link_config_output] if aot_runtime_output else [] optional_arguments = [ static_aot_runtime.path, aot_runtime_output.path, static_aot_runtime.basename, - ] if static_aot_runtime else ["", "", ""] + static_aot_runtime_link_config.path, + aot_runtime_link_config_output.path, + static_aot_runtime_link_config.basename, + ] if static_aot_runtime else ["", "", "", "", "", ""] ctx.actions.run_shell( inputs = [dslx_stdlib, shared_library] + optional_inputs, outputs = [config_output, dso_output, stdlib_output] + optional_outputs, @@ -595,6 +607,9 @@ def _xlsynth_artifact_config_impl(ctx): static_aot_runtime="$7" aot_runtime_output="$8" aot_runtime_name="$9" + static_aot_runtime_link_config="${10}" + aot_runtime_link_config_output="${11}" + aot_runtime_link_config_name="${12}" mkdir -p "$(dirname "$dso_output")" "$(dirname "$config_output")" "$stdlib_output" cp "$shared_library" "$dso_output" @@ -603,7 +618,9 @@ def _xlsynth_artifact_config_impl(ctx): "$dso_name" > "$config_output" if [[ -n "$static_aot_runtime" ]]; then cp "$static_aot_runtime" "$aot_runtime_output" + cp "$static_aot_runtime_link_config" "$aot_runtime_link_config_output" printf 'aot_runtime_path = "%s"\\n' "$aot_runtime_name" >> "$config_output" + printf 'aot_runtime_link_config_path = "%s"\\n' "$aot_runtime_link_config_name" >> "$config_output" fi """, progress_message = "Packaging xlsynth artifact config for {}".format(ctx.label), @@ -621,6 +638,7 @@ xlsynth_artifact_config = rule( "dslx_stdlib": attr.label(mandatory = True), "shared_library": attr.label(allow_single_file = True, mandatory = True), "static_aot_runtime": attr.label(allow_single_file = True), + "static_aot_runtime_link_config": attr.label(allow_single_file = True), }, )