diff --git a/docs/api/defs.md b/docs/api/defs.md
index 01490fec..19176249 100755
--- a/docs/api/defs.md
+++ b/docs/api/defs.md
@@ -11,7 +11,7 @@ native_image(name, jni_configuration, initialize_at_build_time, initialize_at_run_time, native_features,
debug, optimization_mode, shared_library, static_zlib, c_compiler_option, data,
extra_args, allow_fallback, check_toolchains, native_image_tool, native_image_settings,
- profiles, kwargs)
+ profiles, out_headers, additional_outputs, default_outputs, kwargs)
Generates and compiles a GraalVM native image from a Java library target.
@@ -43,6 +43,9 @@ Generates and compiles a GraalVM native image from a Java library target.
| native_image_tool | Specific `native-image` executable target to use. | `None` |
| native_image_settings | Suite(s) of Native Image build settings to use. | `[Label("@rules_graalvm//internal/native_image:defaults")]` |
| profiles | Profiles to use for profile-guided optimization (PGO) and obtained from a native image compiled with `--pgo-instrument`. | `[]` |
+| out_headers | Shared library headers expected to be emitted by the rule (in addition to defaults). | `[]` |
+| additional_outputs | Additional outputs to expect from the rule (for example, polyglot language resources). | `[]` |
+| default_outputs | Whether to consider default output files; when `False`, the developer specifies all outputs on top of the binary itself. | `True` |
| kwargs | Extra keyword arguments are passed to the underlying `native_image` rule. | none |
diff --git a/graalvm/nativeimage/rules.bzl b/graalvm/nativeimage/rules.bzl
index 45ba9a7a..de004920 100644
--- a/graalvm/nativeimage/rules.bzl
+++ b/graalvm/nativeimage/rules.bzl
@@ -4,9 +4,12 @@ load(
"@bazel_skylib//lib:dicts.bzl",
"dicts",
)
+load(
+ "@bazel_tools//tools/cpp:toolchain_utils.bzl",
+ "use_cpp_toolchain",
+)
load(
"//internal/native_image:rules.bzl",
- _BAZEL_CPP_TOOLCHAIN_TYPE = "BAZEL_CPP_TOOLCHAIN_TYPE",
_DEBUG = "DEBUG_CONDITION",
_GVM_TOOLCHAIN_TYPE = "GVM_TOOLCHAIN_TYPE",
_NATIVE_IMAGE_ATTRS = "NATIVE_IMAGE_ATTRS",
@@ -53,8 +56,7 @@ _native_image = rule(
"platform",
"xcode",
],
- toolchains = [
- _BAZEL_CPP_TOOLCHAIN_TYPE,
+ toolchains = use_cpp_toolchain() + [
_GVM_TOOLCHAIN_TYPE,
],
)
@@ -83,6 +85,9 @@ def native_image(
native_image_tool = None, # uses toolchains by default
native_image_settings = [_DEFAULT_NATIVE_IMAGE_SETTINGS],
profiles = [],
+ out_headers = [],
+ additional_outputs = [],
+ default_outputs = True,
**kwargs):
"""Generates and compiles a GraalVM native image from a Java library target.
@@ -111,10 +116,14 @@ def native_image(
data: Data files to make available during the compilation. No default; optional.
extra_args: Extra `native-image` args to pass. Last wins. No default; optional.
allow_fallback: Whether to allow fall-back to a partial native image; defaults to `False`.
+ out_headers: Shared library headers expected to be emitted by the rule (in addition to defaults).
+ additional_outputs: Additional outputs to expect from the rule (for example, polyglot language resources).
check_toolchains: Whether to perform toolchain checks in `native-image`; defaults to `True` on Windows, `False` otherwise.
native_image_tool: Specific `native-image` executable target to use.
native_image_settings: Suite(s) of Native Image build settings to use.
profiles: Profiles to use for profile-guided optimization (PGO) and obtained from a native image compiled with `--pgo-instrument`.
+ default_outputs: Whether to consider default output files; when `False`, the developer specifies all outputs on top of the
+ binary itself.
**kwargs: Extra keyword arguments are passed to the underlying `native_image` rule.
"""
@@ -141,5 +150,8 @@ def native_image(
native_image_tool = native_image_tool,
native_image_settings = native_image_settings,
profiles = profiles,
+ out_headers = out_headers,
+ additional_outputs = additional_outputs,
+ default_outputs = default_outputs,
**kwargs
)
diff --git a/internal/native_image/classic.bzl b/internal/native_image/classic.bzl
index f7a78756..82699f47 100644
--- a/internal/native_image/classic.bzl
+++ b/internal/native_image/classic.bzl
@@ -50,13 +50,14 @@ def _graal_binary_classic_implementation(ctx):
)
args = ctx.actions.args()
- binary = _prepare_native_image_rule_context(
+ outputs = _prepare_native_image_rule_context(
ctx,
args,
classpath_depset,
direct_inputs,
native_toolchain.c_compiler_path,
)
+ binary = outputs[0]
inputs = depset(
direct_inputs,
@@ -64,7 +65,7 @@ def _graal_binary_classic_implementation(ctx):
)
ctx.actions.run(
- outputs = [binary],
+ outputs = outputs,
arguments = [args],
executable = graal,
inputs = inputs,
diff --git a/internal/native_image/common.bzl b/internal/native_image/common.bzl
index f13132ea..4dc0e84c 100644
--- a/internal/native_image/common.bzl
+++ b/internal/native_image/common.bzl
@@ -8,11 +8,12 @@ load(
_RULES_REPO = "@rules_graalvm"
_DEFAULT_GVM_REPO = "@graalvm"
_GVM_TOOLCHAIN_TYPE = "%s//graalvm/toolchain" % _RULES_REPO
-_BAZEL_CPP_TOOLCHAIN_TYPE = "@bazel_tools//tools/cpp:toolchain_type"
_BAZEL_CURRENT_CPP_TOOLCHAIN = "@bazel_tools//tools/cpp:current_cc_toolchain"
_LINUX_CONSTRAINT = "@platforms//os:linux"
_MACOS_CONSTRAINT = "@platforms//os:macos"
_WINDOWS_CONSTRAINT = "@platforms//os:windows"
+_GRAALVM_ISOLATE_HEADER = "graal_isolate.h"
+_GRAALVM_ISOLATE_DYNAMIC_HEADER = "graal_isolate_dynamic.h"
# buildifier: disable=name-conventions
_NativeImageOptimization = struct(
@@ -113,6 +114,11 @@ _NATIVE_IMAGE_ATTRS = {
allow_files = True,
mandatory = False,
),
+ "out_headers": attr.output_list(),
+ "additional_outputs": attr.output_list(),
+ "default_outputs": attr.bool(
+ default = True,
+ ),
"_cc_toolchain": attr.label(
default = Label(_BAZEL_CURRENT_CPP_TOOLCHAIN),
),
@@ -154,6 +160,9 @@ def _prepare_native_image_rule_context(
out_bin_name = ctx.attr.executable_name.replace("%target%", ctx.attr.name)
binary = ctx.actions.declare_file(_prepare_bin_name(out_bin_name, bin_postfix))
+ additional_outputs = []
+ outputs = [binary]
+
# TODO: This check really should be on the exec platform, not the target platform, but that
# requires going through a separate rule. Since GraalVM doesn't support cross-compilation, the
# distinction doesn't matter for now.
@@ -162,6 +171,25 @@ def _prepare_native_image_rule_context(
else:
path_list_separator = ":"
+ # if we are building a shared library, headers will be emitted; by default, the `graal_isolate.h`
+ # and `graal_isolate_dynamic.h` files are included. additional headers can be added by the `out_headers`
+ # attribute.
+ if ctx.attr.shared_library and ctx.attr.default_outputs:
+ additional_outputs.append(_GRAALVM_ISOLATE_HEADER)
+ additional_outputs.append(_GRAALVM_ISOLATE_DYNAMIC_HEADER)
+
+ # append all additional outputs
+ if len(additional_outputs) > 0:
+ outputs.extend([ctx.actions.declare_file(f) for f in additional_outputs])
+
+ # append all out headers
+ if len(ctx.attr.out_headers) > 0:
+ outputs.extend(ctx.outputs.out_headers)
+
+ # append all attr additional outputs
+ if len(ctx.attr.additional_outputs) > 0:
+ outputs.extend(ctx.outputs.additional_outputs)
+
_assemble_native_build_options(
ctx,
args,
@@ -173,7 +201,7 @@ def _prepare_native_image_rule_context(
gvm_toolchain,
bin_postfix,
)
- return binary
+ return outputs
## Exports.
@@ -186,7 +214,6 @@ DEBUG_CONDITION = _DEBUG_CONDITION
COVERAGE_CONDITION = _COVERAGE_CONDITION
OPTIMIZATION_MODE_CONDITION = _OPTIMIZATION_MODE_CONDITION
GVM_TOOLCHAIN_TYPE = _GVM_TOOLCHAIN_TYPE
-BAZEL_CPP_TOOLCHAIN_TYPE = _BAZEL_CPP_TOOLCHAIN_TYPE
BAZEL_CURRENT_CPP_TOOLCHAIN = _BAZEL_CURRENT_CPP_TOOLCHAIN
MACOS_CONSTRAINT = _MACOS_CONSTRAINT
WINDOWS_CONSTRAINT = _WINDOWS_CONSTRAINT
diff --git a/internal/native_image/rules.bzl b/internal/native_image/rules.bzl
index 5841baff..b009c110 100644
--- a/internal/native_image/rules.bzl
+++ b/internal/native_image/rules.bzl
@@ -4,9 +4,12 @@ load(
"@build_bazel_apple_support//lib:apple_support.bzl",
"apple_support",
)
+load(
+ "@bazel_tools//tools/cpp:toolchain_utils.bzl",
+ "find_cpp_toolchain",
+)
load(
"//internal/native_image:common.bzl",
- _BAZEL_CPP_TOOLCHAIN_TYPE = "BAZEL_CPP_TOOLCHAIN_TYPE",
_BAZEL_CURRENT_CPP_TOOLCHAIN = "BAZEL_CURRENT_CPP_TOOLCHAIN",
_DEBUG_CONDITION = "DEBUG_CONDITION",
_DEFAULT_GVM_REPO = "DEFAULT_GVM_REPO",
@@ -103,7 +106,7 @@ def _graal_binary_implementation(ctx):
bin_postfix = _BIN_POSTFIX_SO
args = ctx.actions.args().use_param_file("@%s", use_always=False)
- binary = _prepare_native_image_rule_context(
+ all_outputs = _prepare_native_image_rule_context(
ctx,
args,
classpath_depset,
@@ -112,6 +115,7 @@ def _graal_binary_implementation(ctx):
gvm_toolchain,
bin_postfix = bin_postfix,
)
+ binary = all_outputs[0]
# assemble final inputs
inputs = depset(
@@ -119,7 +123,7 @@ def _graal_binary_implementation(ctx):
transitive = transitive_inputs,
)
run_params = {
- "outputs": [binary],
+ "outputs": all_outputs,
"executable": graal,
"inputs": inputs,
"mnemonic": "NativeImage",
@@ -159,14 +163,50 @@ def _graal_binary_implementation(ctx):
**run_params
)
- return [DefaultInfo(
+ # if we are building a shared library, prepare `CcSharedLibraryInfo` for it
+ cc_info = []
+ runfiles = None
+ if ctx.attr.shared_library:
+ cc_toolchain = find_cpp_toolchain(ctx)
+ feature_configuration = cc_common.configure_features(
+ ctx = ctx,
+ cc_toolchain = cc_toolchain,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features,
+ )
+ libraries_to_link = [
+ cc_common.create_library_to_link(
+ actions = ctx.actions,
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ dynamic_library = binary,
+ ),
+ ]
+ cc_info.extend([
+ OutputGroupInfo(
+ main_shared_library_output = depset([binary]),
+ ),
+ CcSharedLibraryInfo(
+ linker_input = cc_common.create_linker_input(
+ owner = ctx.label,
+ libraries = depset(libraries_to_link),
+ ),
+ ),
+ ])
+
+ # prepare all runfiles
+ all_runfiles = ctx.runfiles(
+ collect_data = True,
+ collect_default = True,
+ files = [],
+ )
+ if runfiles != None:
+ all_runfiles = all_runfiles.merge(runfiles)
+
+ return cc_info + [DefaultInfo(
executable = binary,
- files = depset([binary]),
- runfiles = ctx.runfiles(
- collect_data = True,
- collect_default = True,
- files = [],
- ),
+ files = depset(all_outputs),
+ runfiles = all_runfiles,
)]
def _wrap_actions_for_graal(actions):
@@ -198,7 +238,6 @@ def _wrapped_run_for_graal(_original_actions, arguments = [], env = {}, **kwargs
RULES_REPO = _RULES_REPO
DEFAULT_GVM_REPO = _DEFAULT_GVM_REPO
BAZEL_CURRENT_CPP_TOOLCHAIN = _BAZEL_CURRENT_CPP_TOOLCHAIN
-BAZEL_CPP_TOOLCHAIN_TYPE = _BAZEL_CPP_TOOLCHAIN_TYPE
NATIVE_IMAGE_ATTRS = _NATIVE_IMAGE_ATTRS
GVM_TOOLCHAIN_TYPE = _GVM_TOOLCHAIN_TYPE
DEBUG_CONDITION = _DEBUG_CONDITION