Skip to content
This repository was archived by the owner on Dec 28, 2024. It is now read-only.

Commit bea47ac

Browse files
committed
Draft graalvm_native_image rule
1 parent bbc7983 commit bea47ac

8 files changed

Lines changed: 140 additions & 12 deletions

File tree

java/common/extract/toolchain_info.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
_JAVA_RUNTIME_TOOLCHAIN_TYPE = "@dwtj_rules_java//java/toolchains/java_runtime_toolchain:toolchain_type"
55
_CHECKSTYLE_TOOLCHAIN_TYPE = '@dwtj_rules_java//java/toolchains/checkstyle_toolchain:toolchain_type'
6+
_GRAALVM_NATIVE_IMAGE_TOOLCHAIN_TYPE = '@dwtj_rules_java//java/toolchains/graalvm_native_image_toolchain:toolchain_type'
67

78
def extract_java_executable(ctx):
89
'''Returns a `File` pointing to the `java` exec in the runtime toolchain.
@@ -19,5 +20,8 @@ def extract_java_runtime_toolchain_info(ctx):
1920
'''
2021
return ctx.toolchains[_JAVA_RUNTIME_TOOLCHAIN_TYPE].java_runtime_toolchain_info
2122

23+
def extract_graalvm_native_image_toolchain_info(ctx):
24+
return ctx.toolchains[_GRAALVM_NATIVE_IMAGE_TOOLCHAIN_TYPE].graalvm_native_image_toolchain_info
25+
2226
def extract_checkstyle_toolchain_info(ctx):
2327
return ctx.toolchains[_CHECKSTYLE_TOOLCHAIN_TYPE].checkstyle_toolchain_info
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
#!/bin/sh -
2+
# This file was generated from a template with the following substitutions:
3+
#
4+
# - NATIVE_IMAGE_EXEC: {NATIVE_IMAGE_EXEC}
5+
# - CLASS_PATH: {CLASS_PATH}
6+
# - MAIN_CLASS: {MAIN_CLASS}
7+
# - OUTPUT_IMAGE: {OUTPUT_IMAGE}
28

3-
echo 'TODO(dwtj): Everything!'
9+
10+
"{NATIVE_IMAGE_EXEC}" --class-path "{CLASS_PATH}" "{MAIN_CLASS}" "{OUTPUT_IMAGE}"

java/rules/graalvm_native_image/defs.bzl

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,84 @@
11
'''Defines the `graalvm_native_image` rule.
22
'''
33

4+
load("//java:providers/JavaDependencyInfo.bzl", "JavaDependencyInfo")
5+
load("//java:common/extract/toolchain_info.bzl", "extract_graalvm_native_image_toolchain_info")
6+
7+
def _build_script_name(ctx):
8+
return ctx.attr.name + ".build_native_image.sh"
9+
10+
# TODO(dwtj): Consider revising control flow so that this is called just once,
11+
# not twice.
12+
def _make_class_path_depset(ctx):
13+
depsets = []
14+
for dep in ctx.attr.deps:
15+
dep_info = dep[JavaDependencyInfo]
16+
depsets.append(dep_info.compile_time_class_path_jars)
17+
return depset([], transitive = depsets)
18+
19+
def _make_class_path_string(ctx):
20+
toolchain_info = extract_graalvm_native_image_toolchain_info(ctx)
21+
jar_depset = _make_class_path_depset(ctx)
22+
jar_list = [jar.path for jar in jar_depset.to_list()]
23+
return toolchain_info.class_path_separator.join(jar_list)
24+
25+
def _make_native_image_build_script(ctx):
26+
toolchain_info = extract_graalvm_native_image_toolchain_info(ctx)
27+
build_script = ctx.actions.declare_file(_build_script_name(ctx))
28+
ctx.actions.expand_template(
29+
template = toolchain_info.graalvm_native_image_script_template,
30+
output = build_script,
31+
substitutions = {
32+
"{NATIVE_IMAGE_EXEC}": toolchain_info.native_image_exec.path,
33+
"{CLASS_PATH}": _make_class_path_string(ctx),
34+
"{MAIN_CLASS}": ctx.attr.main_class,
35+
"{OUTPUT_IMAGE}": ctx.outputs.output_image.path,
36+
},
37+
is_executable = True,
38+
)
39+
return build_script
40+
41+
def _build_native_image(ctx):
42+
toolchain_info = extract_graalvm_native_image_toolchain_info(ctx)
43+
build_script = _make_native_image_build_script(ctx)
44+
ctx.actions.run(
45+
outputs = [ctx.outputs.output_image],
46+
inputs = _make_class_path_depset(ctx),
47+
executable = build_script,
48+
tools = [toolchain_info.native_image_exec],
49+
mnemonic = "GraalVmNativeImage",
50+
progress_message = "Building native image for `{}`".format(ctx.label),
51+
# NOTE(dwtj): Currently, we `use_default_shell_env` so that the
52+
# `native-image` executable can find the system C compiler and
53+
# libraries.
54+
# TODO(dwtj): Set this to `False` to make builds more hermetic. How can
55+
# we help `native-image` find the C compiler and libraries.
56+
use_default_shell_env = True,
57+
)
58+
459
def _graalvm_native_image_impl(ctx):
5-
# TODO(dwtj): Everything!
6-
print("Hello, from `_graalvm_native_image_impl().")
7-
pass
60+
_build_native_image(ctx)
61+
return [
62+
DefaultInfo(
63+
files = depset([ctx.outputs.output_image]),
64+
)
65+
]
866

967
graalvm_native_image = rule(
1068
implementation = _graalvm_native_image_impl,
1169
attrs = {
12-
# TODO(dwtj): Everything!
70+
"main_class": attr.string(
71+
mandatory = True,
72+
),
73+
"deps": attr.label_list(
74+
allow_empty = False,
75+
providers = [JavaDependencyInfo],
76+
mandatory = True,
77+
),
78+
"output_image": attr.output(
79+
# TODO(dwtj): Make this optional.
80+
mandatory = True,
81+
),
1382
},
1483
toolchains = [
1584
"@dwtj_rules_java//java/toolchains/graalvm_native_image_toolchain:toolchain_type",

java/rules/toolchains/graalvm_native_image_toolchain.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
GraalVmNativeImageToolchainInfo = provider(
55
fields = {
66
"native_image_exec": "A `File` pointing to a GraalVM `native-image` executable.",
7+
"graalvm_native_image_script_template": "",
8+
"class_path_separator": "",
79
},
810
)
911

1012
def _graalvm_native_image_toolchain(ctx):
1113
toolchain_info = platform_common.ToolchainInfo(
1214
graalvm_native_image_toolchain_info = GraalVmNativeImageToolchainInfo(
1315
native_image_exec = ctx.file.native_image_exec,
16+
class_path_separator = ctx.attr.class_path_separator,
17+
graalvm_native_image_script_template = ctx.file._graalvm_native_image_script_template,
1418
),
1519
)
1620
return [toolchain_info]
@@ -24,6 +28,9 @@ graalvm_native_image_toolchain = rule(
2428
mandatory = True,
2529
cfg = "host",
2630
),
31+
"class_path_separator": attr.string(
32+
default = ":",
33+
),
2734
"_graalvm_native_image_script_template": attr.label(
2835
allow_single_file = True,
2936
default = Label("@dwtj_rules_java//java:rules/graalvm_native_image/TEMPLATE.build_graalvm_native_image.sh")

test/workspaces/smoke_test_graalvm_native_image_rule/WORKSPACE

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@ local_repository(
99

1010
load(
1111
"@dwtj_rules_java//java:repositories.bzl",
12-
"dwtj_local_openjdk_repository",
1312
"local_graalvm_repository",
1413
)
1514

16-
# CONFIGURE `@dwtj_local_openjdk` ##############################################
15+
# CONFIGURE JAVA TOOLCHAINS ####################################################
1716

18-
dwtj_local_openjdk_repository(
19-
name = "dwtj_local_openjdk",
17+
# TODO(dwtj): Figure out how to make this test workspace more portable.
18+
# (E.g., make this test runnable on macOS or different CPU architectures).
19+
load(
20+
"@dwtj_rules_java//test/workspaces:external_repositories.bzl",
21+
"adoptopenjdk_linux_v11_0_8_10",
2022
)
2123

22-
load("@dwtj_local_openjdk//:defs.bzl", "register_java_toolchains")
24+
adoptopenjdk_linux_v11_0_8_10()
25+
26+
load("@adoptopenjdk_linux_v11_0_8_10//:defs.bzl", "register_java_toolchains")
2327

2428
register_java_toolchains()
2529

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1-
load("@dwtj_rules_java//java:defs.bzl", "graalvm_native_image")
1+
load(
2+
"@dwtj_rules_java//java:defs.bzl",
3+
"graalvm_native_image",
4+
"dwtj_java_library",
5+
)
6+
7+
dwtj_java_library(
8+
name = "hello_java_library",
9+
srcs = ["Hello.java"],
10+
)
211

312
graalvm_native_image(
4-
name = "pkg",
13+
name = "hello_native_exec",
14+
main_class = "pkg.Hello",
15+
deps = [":hello_java_library"],
16+
output_image = "hello",
17+
)
18+
19+
sh_test(
20+
name = "hello_world_test",
21+
srcs = [":hello_test.sh"],
22+
data = [":hello"],
23+
args = ["$(location :hello)"],
524
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package pkg;
2+
3+
class Hello {
4+
public static void main(String[] args) {
5+
System.out.println("Hello, world!");
6+
}
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh -
2+
3+
set -e
4+
5+
HELLO_EXEC="$1"
6+
7+
./"$HELLO_EXEC" | tee hello.log
8+
9+
# NOTE(dwtj): Because `set -e` is set, this will fail the test if `grep` does
10+
# not find this string in this log file.
11+
grep 'Hello, world!' hello.log

0 commit comments

Comments
 (0)