Relevant area(s)
Linux, macOS, Windows
Brief description of your issue
mxc_build_common::embed_version_info decides whether to embed Windows
VersionInfo using #[cfg(windows)]. In a build script that cfg describes
the host, not the target — build scripts are compiled for and run on the
host machine. So when cross-compiling from a Windows host to any non-Windows
target, the guard is still true, the Windows resource compiler is invoked for a
non-Windows target, and the build script panics.
The function's own doc comment states the opposite of what the code does:
/// Embed Windows VersionInfo resource metadata into the binary being compiled.
///
/// On non-Windows targets this is a no-op.
pub fn embed_version_info(file_description: &str, original_filename: &str) {
...
#[cfg(windows)]
embed_version_info_windows(file_description, original_filename);
It is a no-op on non-Windows hosts, not on non-Windows targets.
The correct signal for a build script is the target, exposed by Cargo as the
CARGO_CFG_TARGET_OS environment variable (or CARGO_CFG_TARGET_ENV), not
cfg!(windows).
Scope: this is not specific to one crate. Every build.rs calling
embed_version_info does so unconditionally, so all of them fail to
cross-compile from Windows to a non-Windows target:
core/mxc_darwin (the macOS executor, mxc-exec-mac)
core/lxc (the Linux executor, lxc-exec)
core/wxc, backends/windows_sandbox/{daemon,guest},
host/plm, host/wxc_host_prep, host/wxc_winhttp_proxy_shim,
testing/wxc_test_driver, testing/wxc_test_proxy,
tools/mxc_diagnostic_console (Windows-only, so unaffected in practice)
The practical impact is on the first two: a Windows developer cannot
type-check the macOS or Linux executor binaries locally, even with the
appropriate Rust targets installed. That removes the cheapest available
guard against breaking a #[cfg(target_os = ...)] code path that CI only
compiles on another OS.
Steps to reproduce
From a Windows host, with the cross targets installed
(rustup target add aarch64-apple-darwin x86_64-unknown-linux-gnu):
cd src
cargo check -p mxc_darwin --target aarch64-apple-darwin
cargo check -p lxc --target x86_64-unknown-linux-gnu
Reproduced on main-based commit 8977c188 in a clean worktree, so this is
long-standing and not introduced by any in-flight branch.
Expected behavior
Both commands succeed. embed_version_info embeds the resource only when the
target is Windows and is a no-op otherwise, exactly as its doc comment
claims — so the macOS and Linux executors can be cross-checked from any host.
Actual behavior
Both fail in the build script, with the host's toolchain state deciding which
error surfaces:
cargo check -p mxc_darwin --target aarch64-apple-darwin:
error: failed to run custom build command for `mxc_darwin v0.7.0`
Caused by:
process didn't exit successfully: `...\build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at core\mxc_build_common\src\lib.rs:54:10:
failed to embed Windows version info: Custom { kind: Other, error:
"Can only compile resource file when target_env is \"gnu\" or \"msvc\"" }
cargo check -p lxc --target x86_64-unknown-linux-gnu:
error: failed to run custom build command for `lxc v0.7.0`
failed to embed Windows version info: Error { kind: NotFound,
message: "program not found" }
Suggested fix
The two cfgs need to be separated, because they answer different questions:
- host — is
winresource even available? It is declared under
[target.'cfg(windows)'.dependencies] in mxc_build_common/Cargo.toml, and
for a build-dependency Cargo resolves that against the host. So
embed_version_info_windows must stay #[cfg(windows)] or non-Windows hosts
fail to compile the helper.
- target — should the resource actually be embedded? That is
CARGO_CFG_TARGET_OS, and it is the check currently missing.
So keep the existing host gating and add a target check at the call site:
#[cfg(windows)]
{
// `cfg(windows)` above is the HOST (build scripts run on the host);
// whether to embed the resource depends on the TARGET.
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
embed_version_info_windows(file_description, original_filename);
} else {
let _ = (file_description, original_filename);
}
}
This fixes every caller at once and keeps the call sites uniform, so no
individual build.rs needs its own guard.
Also worth correcting the doc comment either way, since it currently documents
behaviour the code does not have.
Additional context
Found while cross-checking the macOS code paths of a change that touches
#[cfg(target_os = "macos")] code (the version-windows work). The macOS paths
of mxc_engine, wxc_common and mxc-sdk do cross-check cleanly today —
only crates whose build.rs calls embed_version_info are blocked.
Relevant area(s)
Linux, macOS, Windows
Brief description of your issue
mxc_build_common::embed_version_infodecides whether to embed WindowsVersionInfo using
#[cfg(windows)]. In a build script thatcfgdescribesthe host, not the target — build scripts are compiled for and run on the
host machine. So when cross-compiling from a Windows host to any non-Windows
target, the guard is still true, the Windows resource compiler is invoked for a
non-Windows target, and the build script panics.
The function's own doc comment states the opposite of what the code does:
It is a no-op on non-Windows hosts, not on non-Windows targets.
The correct signal for a build script is the target, exposed by Cargo as the
CARGO_CFG_TARGET_OSenvironment variable (orCARGO_CFG_TARGET_ENV), notcfg!(windows).Scope: this is not specific to one crate. Every
build.rscallingembed_version_infodoes so unconditionally, so all of them fail tocross-compile from Windows to a non-Windows target:
core/mxc_darwin(the macOS executor,mxc-exec-mac)core/lxc(the Linux executor,lxc-exec)core/wxc,backends/windows_sandbox/{daemon,guest},host/plm,host/wxc_host_prep,host/wxc_winhttp_proxy_shim,testing/wxc_test_driver,testing/wxc_test_proxy,tools/mxc_diagnostic_console(Windows-only, so unaffected in practice)The practical impact is on the first two: a Windows developer cannot
type-check the macOS or Linux executor binaries locally, even with the
appropriate Rust targets installed. That removes the cheapest available
guard against breaking a
#[cfg(target_os = ...)]code path that CI onlycompiles on another OS.
Steps to reproduce
From a Windows host, with the cross targets installed
(
rustup target add aarch64-apple-darwin x86_64-unknown-linux-gnu):cd srccargo check -p mxc_darwin --target aarch64-apple-darwincargo check -p lxc --target x86_64-unknown-linux-gnuReproduced on
main-based commit8977c188in a clean worktree, so this islong-standing and not introduced by any in-flight branch.
Expected behavior
Both commands succeed.
embed_version_infoembeds the resource only when thetarget is Windows and is a no-op otherwise, exactly as its doc comment
claims — so the macOS and Linux executors can be cross-checked from any host.
Actual behavior
Both fail in the build script, with the host's toolchain state deciding which
error surfaces:
cargo check -p mxc_darwin --target aarch64-apple-darwin:cargo check -p lxc --target x86_64-unknown-linux-gnu:Suggested fix
The two
cfgs need to be separated, because they answer different questions:winresourceeven available? It is declared under[target.'cfg(windows)'.dependencies]inmxc_build_common/Cargo.toml, andfor a build-dependency Cargo resolves that against the host. So
embed_version_info_windowsmust stay#[cfg(windows)]or non-Windows hostsfail to compile the helper.
CARGO_CFG_TARGET_OS, and it is the check currently missing.So keep the existing host gating and add a target check at the call site:
This fixes every caller at once and keeps the call sites uniform, so no
individual
build.rsneeds its own guard.Also worth correcting the doc comment either way, since it currently documents
behaviour the code does not have.
Additional context
Found while cross-checking the macOS code paths of a change that touches
#[cfg(target_os = "macos")]code (the version-windows work). The macOS pathsof
mxc_engine,wxc_commonandmxc-sdkdo cross-check cleanly today —only crates whose
build.rscallsembed_version_infoare blocked.