Skip to content

fix(bazel): symlink structure_test binary to .exe on Windows#559

Open
peakschris wants to merge 1 commit into
GoogleContainerTools:mainfrom
peakschris:fix-windows-exe-extension
Open

fix(bazel): symlink structure_test binary to .exe on Windows#559
peakschris wants to merge 1 commit into
GoogleContainerTools:mainfrom
peakschris:fix-windows-exe-extension

Conversation

@peakschris

Copy link
Copy Markdown

Fixes #557

Problem

On Windows, the downloaded structure_test binary has no file extension.
When the generated .bat launcher tries to invoke it, Windows does not
recognise it as an executable and shows an "Open With" dialog instead of
running it. The test then exits 0 and Bazel marks it PASSED without any
structure tests having actually executed
.

Fix

After resolving the toolchain binary, symlink it to <name>.exe when
building on Windows. The binary is a valid PE regardless of its name, so
the symlink is safe. The generated launcher scripts use rlocation to
resolve the path at runtime and automatically pick up the .exe copy.

is_windows = ctx.target_platform_has_constraint(
    ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
if is_windows and not test_bin.basename.endswith(".exe"):
    test_bin_exe = ctx.actions.declare_file(test_bin.basename + ".exe")
    ctx.actions.symlink(output = test_bin_exe, target_file = test_bin)
    test_bin = test_bin_exe

The change is 11 lines in bazel/container_structure_test.bzl and does
not affect Linux or macOS builds.

On Windows, the downloaded structure_test binary has no file extension.
When a batch script tries to invoke it, Windows does not recognise it as
an executable and shows an "Open With" application picker dialog instead
of running the binary. The test then appears to pass (exit 0) without
actually executing any structure tests.

Fix by symlinking the binary to <name>.exe in the Bazel action graph when
building on Windows. The binary is a valid Windows PE regardless of its
name, so the symlink is safe. The generated launcher scripts already use
rlocation to resolve the path at runtime, so they will automatically pick
up the .exe copy.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a change to bazel/container_structure_test.bzl to handle Windows environments by symlinking the container structure test binary to a '.exe' extension if it is missing. The reviewer identified a critical issue where reassigning the binary variable to the symlink would omit the original binary from the runfiles, causing a dangling symlink and test failures in sandboxed or remote execution environments. The reviewer provided a code suggestion to include both the original binary and the symlink in the runfiles, and to clean up a duplicate 'is_windows' check.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +60 to +64
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
if is_windows and not test_bin.basename.endswith(".exe"):
test_bin_exe = ctx.actions.declare_file(test_bin.basename + ".exe")
ctx.actions.symlink(output = test_bin_exe, target_file = test_bin)
test_bin = test_bin_exe

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

On Windows, reassigning test_bin = test_bin_exe means that only the symlink (test_bin_exe) is added to the test's runfiles (on line 119), while the original binary (test_bin) is omitted.

In sandboxed or remote execution environments, this will result in a dangling symlink at runtime because the target of the symlink is not present in the sandbox, causing the test to fail.

To fix this, both the symlink and the original binary must be included in the runfiles. Additionally, is_windows is calculated twice (here and on line 114); we should define it once and reuse it.

Please also update the runfiles definition around line 119 to include original_test_bin as well:

    runfiles = ctx.runfiles(
        files = image_files + ctx.files.configs + [
            bash_launcher,
            test_bin,
            original_test_bin,
            jq_bin,
        ],
    ).merge(ctx.attr._runfiles.default_runfiles)

And you can remove the duplicate is_windows definition on line 114.

Suggested change
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
if is_windows and not test_bin.basename.endswith(".exe"):
test_bin_exe = ctx.actions.declare_file(test_bin.basename + ".exe")
ctx.actions.symlink(output = test_bin_exe, target_file = test_bin)
test_bin = test_bin_exe
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
original_test_bin = test_bin
if is_windows and not test_bin.basename.endswith(".exe"):
test_bin_exe = ctx.actions.declare_file(test_bin.basename + ".exe")
ctx.actions.symlink(output = test_bin_exe, target_file = test_bin)
test_bin = test_bin_exe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: structure_test binary missing .exe extension causes "Open With" dialog instead of running tests

1 participant