diff --git a/cargo/private/BUILD.bazel b/cargo/private/BUILD.bazel index 6a1aab653c..15d6286820 100644 --- a/cargo/private/BUILD.bazel +++ b/cargo/private/BUILD.bazel @@ -1,4 +1,12 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load("//rust:defs.bzl", "rust_binary") + +rust_binary( + name = "copy_file", + srcs = ["copy_file.rs"], + edition = "2021", + visibility = ["//visibility:public"], +) bzl_library( name = "bzl_lib", diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_script.bzl index 59632270be..eb91b0ac90 100644 --- a/cargo/private/cargo_build_script.bzl +++ b/cargo/private/cargo_build_script.bzl @@ -40,11 +40,26 @@ def _cargo_build_script_runfiles_impl(ctx): is_windows = script.extension == "exe" exe = ctx.actions.declare_file("{}{}".format(ctx.label.name, ".exe" if is_windows else "")) - ctx.actions.symlink( - output = exe, - target_file = script, - is_executable = True, - ) + + # Avoid the following issue on Windows when using builds-without-the-bytes. + # https://github.com/bazelbuild/bazel/issues/21747 + if is_windows: + args = ctx.actions.args() + args.add(script) + args.add(exe) + + ctx.actions.run( + executable = ctx.executable._copy_file, + arguments = [args], + inputs = [script], + outputs = [exe], + ) + else: + ctx.actions.symlink( + output = exe, + target_file = script, + is_executable = True, + ) # Tools are ommitted here because they should be within the `script` # attribute's runfiles. @@ -95,6 +110,11 @@ https://github.com/bazelbuild/bazel/issues/15486 allow_files = True, cfg = "exec", ), + "_copy_file": attr.label( + cfg = "exec", + executable = True, + default = Label("//cargo/private:copy_file"), + ), }, executable = True, ) diff --git a/cargo/private/copy_file.rs b/cargo/private/copy_file.rs new file mode 100644 index 0000000000..aca2f71af6 --- /dev/null +++ b/cargo/private/copy_file.rs @@ -0,0 +1,20 @@ +//! A tool for copying files and avoiding +//! https://github.com/bazelbuild/bazel/issues/21747 + +use std::env; +use std::fs; +use std::path::PathBuf; + +fn main() { + let src = PathBuf::from(std::env::args().nth(1).expect("No source file provided")); + let dest = PathBuf::from(env::args().nth(2).expect("No destination provided")); + + fs::copy(&src, &dest).unwrap_or_else(|e| { + panic!( + "Failed to copy file `{} -> {}`\n{:?}", + src.display(), + dest.display(), + e + ) + }); +}