## Problem Solved
`xlsynth-sys` needed a Bazel-friendly way to receive the XLS DSO and
DSLX stdlib as one declared input instead of two separate environment
variables. It also needed a mode where `build.rs` records those artifact
paths without emitting its own native link directives, so an external
build system can own the final link step.
## Review Focus
`XLSYNTH_ARTIFACT_CONFIG` precedence, declared-link mode, and
compatibility with the legacy `XLS_DSO_PATH` + `DSLX_STDLIB_PATH`
override.
## Mental Model
`XLSYNTH_ARTIFACT_CONFIG` is now the preferred declared-input contract:
a TOML file with `dso_path` and `dslx_stdlib_path`. `build.rs` resolves
that config first, writes the selected paths into generated Rust
constants, and then either emits native link directives or only
publishes the DSO path depending on `XLSYNTH_SYS_LINK_MODE`.
If that config is absent, `build.rs` deliberately falls back to the
older paired `XLS_DSO_PATH` plus `DSLX_STDLIB_PATH` override, the local
workspace override, and the download fallback so existing users who
cannot or will not migrate immediately still keep working.
## Non-goals
- This does not change the public `xlsynth` Rust API.
- This does not remove the legacy paired environment-variable override.
- This does not make Cargo-only consumers adopt Bazel-specific wiring.
## Tradeoffs
- `build.rs` now owns more validation and precedence logic.
- `declared` link mode is stricter: it preserves artifact discovery but
leaves final native link ownership to the orchestrator.
## Architecture
- Add `XLSYNTH_ARTIFACT_CONFIG` parsing, precedence, and relative-path
resolution from an absolute config path.
- Keep generating `artifact_paths.rs` so Rust code still sees one
resolved artifact choice.
- Add `XLSYNTH_SYS_LINK_MODE={native,declared}` so managed and explicit
artifact paths can skip native `-l...` emission when the caller already
declares the link inputs.
- Continue emitting `cargo:DSO_PATH` so dependent build scripts can
consume the resolved runtime location through Cargo's normal
`DEP_XLSYNTH_DSO_PATH` mechanism.
- Preserve the existing paired env override and download-backed fallback
for non-Bazel callers.
## Observability
- `build.rs` now reports which artifact source won: config file, paired
env override, local workspace, or download.
- Bad config shapes fail with targeted messages, including
relative-config-path rejection and invalid shared-library-path
rejection.
- `XLSYNTH_SYS_LINK_MODE=declared` is explicit in the build output when
native link directives are intentionally skipped.
# Related PRs in the other repos
- `xlsynth/rules_xlsynth`: [PR
#52](https://github.com/xlsynth/rules_xlsynth/pull/52)
- `xlsynth/xlsynth-crate`: [PR
#851](https://github.com/xlsynth/xlsynth-crate/pull/851)
- `xlsynth/topstitch`: [PR
#141](https://github.com/xlsynth/topstitch/pull/141)