Skip to content

Commit 808f849

Browse files
fmeumrules_java Copybara
authored andcommitted
Use the launcher_maker toolchain if available (#294)
This avoids an unnecessary dependency on a C++ toolchain matching the target platform when not building for Windows. Also fix the configuration of the launcher, which should be built for the target platform. Closes #294 COPYBARA_INTEGRATE_REVIEW=#294 from fmeum:cross-compile-to-unix 13f097a PiperOrigin-RevId: 762307907 Change-Id: I1e172a81bd198b02032a705c459ead48b0012aea
1 parent 042e9a6 commit 808f849

File tree

10 files changed

+132
-36
lines changed

10 files changed

+132
-36
lines changed

.bazelci/presubmit.yml

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,33 @@ test_target_integration: &test_target_integration
4242
flags_workspace_integration: &flags_workspace_integration
4343
- "--noenable_bzlmod"
4444
- "--enable_workspace"
45+
# TODO(hvd): remove after Bazel 8.3.0
46+
- "--repositories_without_autoloads=bazel_features_version,bazel_features_globals"
4547

4648
buildifier: latest
4749

4850
matrix:
4951
all_platforms: ["ubuntu2004", "macos", "macos_arm64", "windows"]
50-
integration_platforms: ["ubuntu2004", "macos", "macos_arm64", "windows"]
5152
bazel: ["7.6.1", "8.2.1", "last_green"] # Bazel 6 tested separately, needs different flags
52-
modern_bazel: ["8.2.1", "last_green"] # Fully supported Bazel versions
53+
modern_bazel: ["last_green"] # Fully supported Bazel versions
5354

5455
tasks:
56+
# Bazel 9+
57+
build_and_test:
58+
name: "Bazel {modern_bazel}"
59+
bazel: ${{ modern_bazel }}
60+
platform: ${{ all_platforms }}
61+
build_targets: *build_targets
62+
test_targets: *test_targets
63+
# Bazel 8.x
64+
build_and_test_bazel8:
65+
name: "Bazel 8.2.1"
66+
bazel: "8.2.1"
67+
platform: ${{ all_platforms }}
68+
build_targets: *build_targets
69+
test_targets: *test_targets
70+
test_flags:
71+
- "--test_tag_filters=-min_bazel_9"
5572
# Bazel 7.x
5673
build_and_test_bazel7:
5774
name: "Bazel 7.6.1"
@@ -60,14 +77,7 @@ tasks:
6077
build_targets: *build_targets
6178
test_targets: *test_targets
6279
test_flags:
63-
- "--test_tag_filters=-min_bazel_8"
64-
# Bazel 8+
65-
build_and_test:
66-
name: "Bazel {modern_bazel}"
67-
bazel: ${{ modern_bazel }}
68-
platform: ${{ all_platforms }}
69-
build_targets: *build_targets
70-
test_targets: *test_targets
80+
- "--test_tag_filters=-min_bazel_8,-min_bazel_9"
7181
# Bazel 6.x
7282
build_and_test_bazel6:
7383
name: "Bazel 6.5.0"
@@ -76,11 +86,11 @@ tasks:
7686
build_targets: *build_targets_bazel6
7787
test_targets: *test_targets_bazel6
7888
test_flags:
79-
- "--test_tag_filters=-min_bazel_7,-min_bazel_8"
89+
- "--test_tag_filters=-min_bazel_7,-min_bazel_8,-min_bazel_9"
8090
ubuntu2004_integration_bazel6:
8191
name: "Integration w/ Bazel 6.5.0"
8292
bazel: 6.5.0
83-
platform: ${{ integration_platforms }}
93+
platform: ${{ all_platforms }}
8494
working_directory: "test/repo"
8595
shell_commands:
8696
- sh setup.sh
@@ -93,7 +103,7 @@ tasks:
93103
integration_build_and_test:
94104
name: "Integration w/ Bazel {bazel}"
95105
bazel: ${{ bazel }}
96-
platform: ${{ integration_platforms }}
106+
platform: ${{ all_platforms }}
97107
working_directory: "test/repo"
98108
shell_commands:
99109
- sh setup.sh
@@ -104,7 +114,7 @@ tasks:
104114
integration_build_and_test_workspace:
105115
name: "Integration (WORKSPACE) w/ Bazel {bazel}"
106116
bazel: ${{ bazel }}
107-
platform: ${{ integration_platforms }}
117+
platform: ${{ all_platforms }}
108118
working_directory: "test/repo"
109119
shell_commands:
110120
- sh setup.sh

MODULE.bazel

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,7 @@ module(
77

88
bazel_dep(name = "platforms", version = "0.0.11")
99
bazel_dep(name = "rules_cc", version = "0.0.15")
10-
bazel_dep(name = "bazel_features", version = "1.28.0")
11-
archive_override(
12-
module_name = "bazel_features",
13-
integrity = "sha256-SOPLvKDy+RN7GHKN8eFjQ+58Wx4Isj+vcXoUluBqxLo=",
14-
strip_prefix = "bazel_features-59915eb2ca215c7b2266c83c49bb7522a5b6737f",
15-
urls = ["https://github.com/bazel-contrib/bazel_features/archive/59915eb2ca215c7b2266c83c49bb7522a5b6737f.zip"],
16-
)
17-
10+
bazel_dep(name = "bazel_features", version = "1.30.0")
1811
bazel_dep(name = "bazel_skylib", version = "1.6.1")
1912
bazel_dep(name = "protobuf", version = "27.0", repo_name = "com_google_protobuf")
2013
bazel_dep(name = "zlib", version = "1.3.1.bcr.5")

WORKSPACE

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ load("//java:rules_java_deps.bzl", "rules_java_dependencies")
4141

4242
rules_java_dependencies()
4343

44+
load("@bazel_features//:deps.bzl", "bazel_features_deps")
45+
46+
bazel_features_deps()
47+
4448
load("@com_google_protobuf//bazel/private:proto_bazel_features.bzl", "proto_bazel_features") # buildifier: disable=bzl-visibility
4549

4650
proto_bazel_features(name = "proto_bazel_features")
@@ -63,14 +67,3 @@ http_archive(
6367
load("//test:repositories.bzl", "test_repositories")
6468

6569
test_repositories()
66-
67-
http_archive(
68-
name = "bazel_features",
69-
sha256 = "48e3cbbca0f2f9137b18728df1e16343ee7c5b1e08b23faf717a1496e06ac4ba",
70-
strip_prefix = "bazel_features-59915eb2ca215c7b2266c83c49bb7522a5b6737f",
71-
url = "https://github.com/bazel-contrib/bazel_features/archive/59915eb2ca215c7b2266c83c49bb7522a5b6737f.zip",
72-
)
73-
74-
load("@bazel_features//:deps.bzl", "bazel_features_deps")
75-
76-
bazel_features_deps()

distro/relnotes.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ bazel_dep(name = "rules_java", version = "{VERSION}")
1818
~~~
1919
2020
**WORKSPACE setup**
21+
22+
With Bazel 8.0.0 and before 8.3.0, add the following to your `.bazelrc` file:
23+
24+
~~~
25+
# https://github.com/bazelbuild/bazel/pull/26119
26+
common --repositories_without_autoloads=bazel_features_version,bazel_features_globals
27+
~~~
28+
29+
In all cases, add the following to your `WORKSPACE` file:
30+
2131
~~~
2232
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
2333
http_archive(
@@ -31,6 +41,9 @@ http_archive(
3141
load("@rules_java//java:rules_java_deps.bzl", "rules_java_dependencies")
3242
rules_java_dependencies()
3343
44+
load("@bazel_features//:deps.bzl", "bazel_features_deps")
45+
bazel_features_deps()
46+
3447
# note that the following line is what is minimally required from protobuf for the java rules
3548
# consider using the protobuf_deps() public API from @com_google_protobuf//:protobuf_deps.bzl
3649
load("@com_google_protobuf//bazel/private:proto_bazel_features.bzl", "proto_bazel_features") # buildifier: disable=bzl-visibility

java/bazel/rules/bazel_java_binary.bzl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414
"""Bazel java_binary rule"""
1515

16+
load("@bazel_features//:features.bzl", "bazel_features")
1617
load("@bazel_skylib//lib:paths.bzl", "paths")
1718
load("@rules_cc//cc:find_cc_toolchain.bzl", "use_cc_toolchain")
1819
load("//java/common:java_semantics.bzl", "semantics")
@@ -202,6 +203,14 @@ def _get_executable(ctx):
202203

203204
return ctx.actions.declare_file(executable_name)
204205

206+
_LAUNCHER_MAKER_TOOLCHAIN_TYPE = "@bazel_tools//tools/launcher:launcher_maker_toolchain_type"
207+
_LAUNCHER_MAKER_TOOLCHAIN = config_common.toolchain_type(_LAUNCHER_MAKER_TOOLCHAIN_TYPE, mandatory = True)
208+
209+
def _find_launcher_maker(ctx):
210+
if bazel_features.rules._has_launcher_maker_toolchain:
211+
return ctx.toolchains[_LAUNCHER_MAKER_TOOLCHAIN_TYPE].binary
212+
return ctx.executable._windows_launcher_maker
213+
205214
def _create_stub(ctx, java_attrs, launcher, executable, jvm_flags, main_class, coverage_main_class):
206215
java_runtime_toolchain = semantics.find_java_runtime_toolchain(ctx)
207216
java_executable = helper.get_java_executable(ctx, java_runtime_toolchain, launcher)
@@ -282,11 +291,13 @@ def _create_windows_exe_launcher(ctx, java_executable, classpath, main_class, jv
282291
# TODO(b/295221112): Change to use the "launcher" attribute (only windows use a fixed _launcher attribute)
283292
launcher_artifact = ctx.executable._launcher
284293
ctx.actions.run(
285-
executable = ctx.executable._windows_launcher_maker,
294+
executable = _find_launcher_maker(ctx),
286295
inputs = [launcher_artifact],
287296
outputs = [executable],
288297
arguments = [launcher_artifact.path, launch_info, executable.path],
289298
use_default_shell_env = True,
299+
toolchain = _LAUNCHER_MAKER_TOOLCHAIN_TYPE if bazel_features.rules._has_launcher_maker_toolchain else None,
300+
mnemonic = "JavaLauncherMaker",
290301
)
291302
return executable
292303

@@ -308,6 +319,8 @@ def make_binary_rule(implementation, *, doc, attrs, executable = False, test = F
308319
provides = [JavaInfo],
309320
toolchains = [semantics.JAVA_TOOLCHAIN] + use_cc_toolchain() + (
310321
[semantics.JAVA_RUNTIME_TOOLCHAIN] if executable or test else []
322+
) + (
323+
[_LAUNCHER_MAKER_TOOLCHAIN] if bazel_features.rules._has_launcher_maker_toolchain else []
311324
),
312325
# TODO(hvd): replace with filegroups?
313326
outputs = {
@@ -340,16 +353,18 @@ logic as the Java package of source files. For example, a source file at
340353
),
341354
"_test_support": attr.label(default = _compute_test_support),
342355
"_launcher": attr.label(
343-
cfg = "exec",
356+
cfg = "target",
344357
executable = True,
345358
default = "@bazel_tools//tools/launcher:launcher",
346359
),
360+
},
361+
{
347362
"_windows_launcher_maker": attr.label(
348363
default = "@bazel_tools//tools/launcher:launcher_maker",
349364
cfg = "exec",
350365
executable = True,
351366
),
352-
},
367+
} if not bazel_features.rules._has_launcher_maker_toolchain else {},
353368
)
354369

355370
def make_java_binary(executable):

java/rules_java_deps.bzl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ def rules_license_repo():
210210
],
211211
)
212212

213+
def bazel_features_repo():
214+
maybe(
215+
http_archive,
216+
name = "bazel_features",
217+
sha256 = "a660027f5a87f13224ab54b8dc6e191693c554f2692fcca46e8e29ee7dabc43b",
218+
strip_prefix = "bazel_features-1.30.0",
219+
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.30.0/bazel_features-v1.30.0.tar.gz",
220+
)
221+
213222
def rules_java_dependencies():
214223
"""An utility method to load non-toolchain dependencies of rules_java.
215224
@@ -223,3 +232,4 @@ def rules_java_dependencies():
223232
zlib_repo()
224233
absl_repo()
225234
rules_license_repo()
235+
bazel_features_repo()

test/java/bazel/BUILD.bazel

Whitespace-only changes.

test/java/bazel/rules/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
load(":java_binary_tests.bzl", "java_binary_tests")
2+
3+
java_binary_tests(name = "java_binary_tests")
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Tests for the Bazel java_binary rule"""
2+
3+
load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
4+
load("@rules_testing//lib:util.bzl", "util")
5+
load("//java:java_binary.bzl", "java_binary")
6+
7+
def _test_java_binary_cross_compilation_to_unix(name):
8+
# A Unix platform that:
9+
# - has a JDK
10+
# - does not require a launcher
11+
# - is not supported by the default C++ toolchain
12+
util.helper_target(
13+
native.platform,
14+
name = name + "/platform",
15+
constraint_values = [
16+
"@platforms//os:linux",
17+
"@platforms//cpu:s390x",
18+
],
19+
)
20+
21+
util.helper_target(
22+
java_binary,
23+
name = name + "/bin",
24+
srcs = ["java/C.java"],
25+
main_class = "C",
26+
)
27+
28+
analysis_test(
29+
name = name,
30+
impl = _test_java_binary_cross_compilation_to_unix_impl,
31+
target = name + "/bin",
32+
config_settings = {
33+
"//command_line_option:platforms": [Label(name + "/platform")],
34+
},
35+
# Requires the launcher_maker toolchain.
36+
attr_values = {"tags": ["min_bazel_9"]},
37+
)
38+
39+
def _test_java_binary_cross_compilation_to_unix_impl(env, target):
40+
# The main assertion is that analysis succeeds, but verify the absence of a
41+
# binary launcher for good measure. We do this by checking that the output
42+
# executable is the stub script, and not a bespoke launcher
43+
executable = target[DefaultInfo].files_to_run.executable.short_path
44+
assert_action = env.expect.that_target(target).action_generating(executable)
45+
assert_action.mnemonic().equals("TemplateExpand")
46+
assert_action.substitutions().keys().contains("%jvm_flags%")
47+
assert_action.inputs().contains_exactly(["java/bazel/rules/java_stub_template.txt"])
48+
49+
def java_binary_tests(name):
50+
test_suite(
51+
name = name,
52+
tests = [
53+
_test_java_binary_cross_compilation_to_unix,
54+
],
55+
)

test/repo/WORKSPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ load("@rules_java//java:rules_java_deps.bzl", "rules_java_dependencies")
99

1010
rules_java_dependencies()
1111

12+
load("@bazel_features//:deps.bzl", "bazel_features_deps")
13+
14+
bazel_features_deps()
15+
1216
load("@com_google_protobuf//bazel/private:proto_bazel_features.bzl", "proto_bazel_features") # buildifier: disable=bzl-visibility
1317

1418
proto_bazel_features(name = "proto_bazel_features")

0 commit comments

Comments
 (0)