Skip to content

Commit 5b2564a

Browse files
authored
fix: make first default output the executable again (bazel-contrib#2010)
This fixes a small change in behavior identified by some Google regression tests. When precompiling was introduced, the target's executable was no longer the first file in the default outputs depset. While that behavior isn't a strong contract, it is the convention with many other rules, and the existing behavior for Bazel 7+. To fix, put the executable as the first value in the default outputs list. Also adds a test for this behavior.
1 parent 1a225f4 commit 5b2564a

3 files changed

Lines changed: 15 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ A brief description of the categories of changes:
4141
`interpreter_version_info` arg.
4242
* (bzlmod) Correctly pass `isolated`, `quiet` and `timeout` values to `whl_library`
4343
and drop the defaults from the lock file.
44+
* (rules) The first element of the default outputs is now the executable again.
4445

4546
### Removed
4647
* (pip): Removes the `entrypoint` macro that was replaced by `py_console_script_binary` in 0.26.0.

python/private/common/py_executable.bzl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,10 @@ def py_executable_base_impl(ctx, *, semantics, is_test, inherited_environment =
166166
main_py = precompile_result.py_to_pyc_map[main_py]
167167
direct_pyc_files = depset(precompile_result.pyc_files)
168168

169-
default_outputs = precompile_result.keep_srcs + precompile_result.pyc_files
170169
executable = _declare_executable_file(ctx)
171-
default_outputs.append(executable)
170+
default_outputs = [executable]
171+
default_outputs.extend(precompile_result.keep_srcs)
172+
default_outputs.extend(precompile_result.pyc_files)
172173

173174
imports = collect_imports(ctx, semantics)
174175

tests/base_rules/py_executable_base_tests.bzl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config")
1818
load("@rules_testing//lib:analysis_test.bzl", "analysis_test")
1919
load("@rules_testing//lib:truth.bzl", "matching")
2020
load("@rules_testing//lib:util.bzl", rt_util = "util")
21+
load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") # buildifier: disable=bzl-visibility
2122
load("//tests/base_rules:base_tests.bzl", "create_base_tests")
2223
load("//tests/base_rules:util.bzl", "WINDOWS_ATTR", pt_util = "util")
2324
load("//tests/support:support.bzl", "LINUX_X86_64", "WINDOWS_X86_64")
@@ -297,6 +298,16 @@ def _test_files_to_build_impl(env, target):
297298
"{package}/{test_name}_subject.py",
298299
])
299300

301+
if IS_BAZEL_7_OR_HIGHER:
302+
# As of Bazel 7, the first default output is the executable, so
303+
# verify that is the case. rules_testing
304+
# DepsetFileSubject.contains_exactly doesn't provide an in_order()
305+
# call, nor access to the underlying depset, so we have to do things
306+
# manually.
307+
first_default_output = target[DefaultInfo].files.to_list()[0]
308+
executable = target[DefaultInfo].files_to_run.executable
309+
env.expect.that_file(first_default_output).equals(executable)
310+
300311
def _test_name_cannot_end_in_py(name, config):
301312
# Bazel 5 will crash with a Java stacktrace when the native Python
302313
# rules have an error.

0 commit comments

Comments
 (0)