Skip to content

Commit

Permalink
feat: bazel settings integration
Browse files Browse the repository at this point in the history
- feat: detect and honor `compilation_mode` flag
- feat: build with debug settings if `compilation_mode=dbg`
- feat: ability to build a shared library
- feat: build with `tool:coverage` if coverage is enabled and a
  test-only target is being built
- docs: add doc which explains shared library feature
- docs: add doc for built settings integration (more to come)

Relates-To: #78
Relates-To: #85
Signed-off-by: Sam Gammon <sam@elide.ventures>
  • Loading branch information
sgammon committed Sep 1, 2023
1 parent e21a0f4 commit caf4a64
Show file tree
Hide file tree
Showing 14 changed files with 413 additions and 82 deletions.
4 changes: 2 additions & 2 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ Use [GraalVM](https://graalvm.org) from [Bazel](https://bazel.build), with suppo
- [Installing components with `gu`](./docs/components.md)
- [Using GraalVM as a Bazel Java toolchain](./docs/toolchain.md)
- [Support for Bazel 6, Bazel 7, and Bzlmod](./docs/modern-bazel.md)
- [Support for Bazel 5 and Bazel 4, drop-in replacement for `rules_graal`](./legacy-bazel.md)
- [Support for Bazel 4 and Bazel 5, drop-in replacement for `rules_graal`](./legacy-bazel.md)
- [Run tools from GraalVM directly](./docs/binary-targets.md)
- [Build native shared libraries from Java or polyglot code](./docs/shared-libraries.md)
- [Example projects for each Bazel version](./docs/examples.md)
- Support for macOS, Linux, Windows (including Native Image!)
- [Hermetic compilation on all platforms](./docs/hermeticity.md)
- [Respects conventional Bazel build settings](./docs/build-settings.md)
- Support for macOS, Linux, Windows (including Native Image!) ([support matrix](./docs/modern-bazel.md))
- Support for the latest modern GraalVM releases (Community Edition and Oracle GraalVM)

## Installation
Expand Down Expand Up @@ -243,13 +246,13 @@ If you install GraalVM at a repository named `@graalvm`, the toolchain targets a
**Java toolchain:**

```
@graalvm//:toolchain
@graalvm//:jvm
```

**GraalVM toolchain:**

```
@graalvm//:gvm
@graalvm//:sdk
```

The default `WORKSPACE` and Bzlmod installation instructions register both types of toolchains.
Expand Down
18 changes: 18 additions & 0 deletions docs/build-settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## How Bazel settings integrate with Native Image

Several familiar Bazel settings are integrated into the Native Image build pipeline, so that conventional use of Bazel
features translates relatively well to Native Image option control. See the table below for more information.

### Compilation mode

> Flag: [`--compilation_mode`][1] or [`-c`][1]
| **Flag setting** | **Effective `native-image` options** | **Notes** |
| ---------------- | ------------------------------------ | ------------------------------------------ |
| `dbg` | `-g` | No optimization flag set |
| `fastbuild` | `-Ob` | Activates GraalVM [fast build][2] mode |
| `opt` | `-O2` | Builds with optimizations turned on |
| (None set) | (Nothing passed) | Default GraalVM behavior builds with `-O2` |

[1]: https://bazel.build/docs/user-manual#compilation-mode
[2]: https://www.graalvm.org/latest/reference-manual/native-image/overview/BuildOutput/#build-stages
13 changes: 8 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ Use [GraalVM](https://graalvm.org) from [Bazel](https://bazel.build), with suppo
- [Installing components with `gu`](./components.md)
- [Using GraalVM as a Bazel Java toolchain](./toolchain.md)
- [Support for Bazel 6, Bazel 7, and Bzlmod](./modern-bazel.md)
- [Support for Bazel 5 and Bazel 4, drop-in replacement for `rules_graal`](./legacy-bazel.md)
- [Support for Bazel 4 and Bazel 5, drop-in replacement for `rules_graal`](./legacy-bazel.md)
- [Run GraalVM binaries directly](./binary-targets.md)
- [Build native shared libraries from Java or polyglot code](./shared-libraries.md)
- [Example projects for each Bazel version](./examples.md)
- Support for macOS, Linux, Windows (including Native Image!)
- [Hermetic compilation on all platforms](./hermeticity.md)
- [Respects conventional Bazel build settings](./build-settings.md)
- Support for macOS, Linux, Windows (including Native Image!) ([support matrix](./modern-bazel.md))
- Support for the latest modern GraalVM releases (Community Edition and Oracle GraalVM)

## Installation
Expand Down Expand Up @@ -215,7 +218,7 @@ make sure to add the `native_image_tool` attribute to point to `@yourrepo//:nati

## Examples

See the list of [examples](./docs/examples.md), which are used as continuous integration tests. Examples are available
See the list of [examples](./examples.md), which are used as continuous integration tests. Examples are available
for Bazel 4-7.

## Hermeticity / strictness
Expand All @@ -241,13 +244,13 @@ If you install GraalVM at a repository named `@graalvm`, the toolchain targets a
**Java toolchain:**

```
@graalvm//:toolchain
@graalvm//:jvm
```

**GraalVM toolchain:**

```
@graalvm//:gvm
@graalvm//:sdk
```

The default `WORKSPACE` and Bzlmod installation instructions register both types of toolchains.
Expand Down
34 changes: 34 additions & 0 deletions docs/shared-libraries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## Shared libraries with GraalVM and Bazel

GraalVM can build [native shared libraries][1] from Java or polyglot code. This functionality is integrated with these
rules, via the `shared_library` target attribute on `native_image`:

```python
load("@rules_graalvm//:defs.bzl", "native_image")
```

```python
java_library(
name = "example",
srcs = ["..."],
)

native_image(
name = "some_name",
shared_library = True,
deps = [
":example",
],
)
```

### How `main_class` works with shared libraries

Even when building a shared library, GraalVM typically needs a `main_class`. Instead of becoming a runnable entrypoint,
the `main_class` is used by the Native Image compiler as the starting point for points-to analysis and code gen.

Alternatively, the [`@CEntryPoint` API][2] can be used to define library entrypoints. See [here][3] for more information.

[1]: https://www.graalvm.org/latest/reference-manual/native-image/guides/build-native-shared-library/
[2]: https://www.graalvm.org/sdk/javadoc/org/graalvm/nativeimage/c/function/CEntryPoint.html
[3]: https://www.graalvm.org/latest/reference-manual/native-image/guides/build-native-shared-library/
89 changes: 62 additions & 27 deletions graal/graal.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ load(
)
load(
"//internal/native_image:classic.bzl",
_DEBUG_CONDITION = "DEBUG_CONDITION",
_OPTIMIZATION_MODE_CONDITION = "DEBUG_CONDITION",
_BAZEL_CPP_TOOLCHAIN_TYPE = "BAZEL_CPP_TOOLCHAIN_TYPE",
_BAZEL_CURRENT_CPP_TOOLCHAIN = "BAZEL_CURRENT_CPP_TOOLCHAIN",
_DEFAULT_GVM_REPO = "DEFAULT_GVM_REPO",
Expand All @@ -15,6 +17,10 @@ load(

_DEFAULT_NATIVE_IMAGE_TOOL = Label("%s//:native-image" % _DEFAULT_GVM_REPO)

_DEBUG = select(_DEBUG_CONDITION)

_OPTIMIZATION_MODE = select(_OPTIMIZATION_MODE_CONDITION)

_native_image = rule(
implementation = _graal_binary_implementation,
attrs = dicts.add(_NATIVE_IMAGE_ATTRS, **{
Expand Down Expand Up @@ -42,48 +48,59 @@ _native_image = rule(
def native_image(
name,
deps,
main_class,
main_class = None,
executable_name = select({
"@bazel_tools//src/conditions:windows": "%target%-bin.exe",
"//conditions:default": "%target%-bin",
}),
include_resources = None,
reflection_configuration = None,
jni_configuration = None,
initialize_at_build_time = [],
initialize_at_run_time = [],
native_features = [],
debug = _DEBUG,
optimization_mode = _OPTIMIZATION_MODE,
shared_library = False,
static_zlib = None,
c_compiler_option = [],
data = [],
extra_args = [],
allow_fallback = False,
check_toolchains = select({
"@bazel_tools//src/conditions:windows": True,
"//conditions:default": False,
}),
c_compiler_option = [],
static_zlib = None,
executable_name = select({
"@bazel_tools//src/conditions:windows": "%target%-bin.exe",
"//conditions:default": "%target%-bin",
}),
native_image_tool = _DEFAULT_NATIVE_IMAGE_TOOL,
**kwargs):
"""Generates and compiles a GraalVM native image from a Java library target.
Args:
name: Name of the target; required.
deps: Dependency `java_library` targets to assemble the classpath from. Mandatory.
main_class: Entrypoint main class to build from; mandatory.
main_class: Entrypoint main class to build from; mandatory unless building a shared library.
executable_name: Set the name of the output binary; defaults to `%target%-bin`, or `%target%-bin.exe` on Windows.
The special string `%target%`, if present, is replaced with `name`.
include_resources: Glob to pass to `IncludeResources`. No default; optional.
reflection_configuration: Reflection configuration file. No default; optional.
jni_configuration: JNI configuration file. No default; optional.
initialize_at_build_time: Classes or patterns to pass to `--initialize-at-build-time`. No default; optional.
initialize_at_run_time: Classes or patterns to pass to `--initialize-at-run-time`. No default; optional.
native_features: GraalVM `Feature` classes to include and apply. No default; optional.
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.
check_toolchains: Whether to perform toolchain checks in `native-image`; defaults to `True` on Windows, `False` otherwise.
c_compiler_option: Extra C compiler options to pass through `native-image`. No default; optional.
debug: Whether to include debug symbols; by default, this flag's state is managed by Bazel. Passing
`--compilation_mode=dbg` is sufficient to flip this to `True`, or it can be overridden via this parameter.
optimization_mode: Behaves the same as `debug`; normally, this flag's state is managed by Bazel. Passing
`--compilation_mode=fastbuild|opt|dbg` is sufficient to set this flag, or it can be overridden via this
parameter.
shared_library: Build a shared library binary instead of an executable.
static_zlib: A cc_library or cc_import target that provides zlib as a static library.
On Linux, this is used when Graal statically links zlib into the binary, e.g. with
`-H:+StaticExecutableWithDynamicLibC`.
executable_name: Set the name of the output binary; defaults to `%target%-bin`, or `%target%-bin.exe` on Windows.
The special string `%target%`, if present, is replaced with `name`.
c_compiler_option: Extra C compiler options to pass through `native-image`. No default; optional.
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`.
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.
**kwargs: Extra keyword arguments are passed to the underlying `native_image` rule.
"""
Expand All @@ -98,11 +115,15 @@ def native_image(
initialize_at_build_time = initialize_at_build_time,
initialize_at_run_time = initialize_at_run_time,
native_features = native_features,
debug = debug,
optimization_mode = optimization_mode,
shared_library = shared_library,
data = data,
extra_args = extra_args,
check_toolchains = check_toolchains,
static_zlib = static_zlib,
c_compiler_option = c_compiler_option,
allow_fallback = allow_fallback,
executable_name = executable_name,
native_image_tool = native_image_tool,
**kwargs
Expand All @@ -111,48 +132,59 @@ def native_image(
def graal_binary(
name,
deps,
main_class,
main_class = None,
executable_name = select({
"@bazel_tools//src/conditions:windows": "%target%-bin.exe",
"//conditions:default": "%target%-bin",
}),
include_resources = None,
reflection_configuration = None,
jni_configuration = None,
initialize_at_build_time = [],
initialize_at_run_time = [],
native_features = [],
debug = _DEBUG,
optimization_mode = _OPTIMIZATION_MODE,
shared_library = False,
static_zlib = None,
c_compiler_option = [],
data = [],
extra_args = [],
allow_fallback = False,
check_toolchains = select({
"@bazel_tools//src/conditions:windows": True,
"//conditions:default": False,
}),
c_compiler_option = [],
static_zlib = None,
executable_name = select({
"@bazel_tools//src/conditions:windows": "%target%-bin.exe",
"//conditions:default": "%target%-bin",
}),
native_image_tool = _DEFAULT_NATIVE_IMAGE_TOOL,
**kwargs):
"""Alias for the renamed `native_image` rule. Identical.
Args:
name: Name of the target; required.
deps: Dependency `java_library` targets to assemble the classpath from. Mandatory.
main_class: Entrypoint main class to build from; mandatory.
main_class: Entrypoint main class to build from; mandatory unless building a shared library.
executable_name: Set the name of the output binary; defaults to `%target%-bin`, or `%target%-bin.exe` on Windows.
The special string `%target%`, if present, is replaced with `name`.
include_resources: Glob to pass to `IncludeResources`. No default; optional.
reflection_configuration: Reflection configuration file. No default; optional.
jni_configuration: JNI configuration file. No default; optional.
initialize_at_build_time: Classes or patterns to pass to `--initialize-at-build-time`. No default; optional.
initialize_at_run_time: Classes or patterns to pass to `--initialize-at-run-time`. No default; optional.
native_features: GraalVM `Feature` classes to include and apply. No default; optional.
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.
check_toolchains: Whether to perform toolchain checks in `native-image`; defaults to `True` on Windows, `False` otherwise.
debug: Whether to include debug symbols; by default, this flag's state is managed by Bazel. Passing
`--compilation_mode=dbg` is sufficient to flip this to `True`, or it can be overridden via this parameter.
optimization_mode: Behaves the same as `debug`; normally, this flag's state is managed by Bazel. Passing
`--compilation_mode=fastbuild|opt|dbg` is sufficient to set this flag, or it can be overridden via this
parameter.
shared_library: Build a shared library binary instead of an executable.
static_zlib: A cc_library or cc_import target that provides zlib as a static library.
On Linux, this is used when Graal statically links zlib into the binary, e.g. with
`-H:+StaticExecutableWithDynamicLibC`.
c_compiler_option: Extra C compiler options to pass through `native-image`. No default; optional.
executable_name: Set the name of the output binary; defaults to `%target%-bin`, or `%target%-bin.exe` on Windows.
The special string `%target%`, if present, is replaced with `name`.
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`.
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.
**kwargs: Extra keyword arguments are passed to the underlying `native_image` rule.
"""
Expand All @@ -167,6 +199,9 @@ def graal_binary(
initialize_at_build_time = initialize_at_build_time,
initialize_at_run_time = initialize_at_run_time,
native_features = native_features,
debug = debug,
optimization_mode = optimization_mode,
shared_library = shared_library,
data = data,
extra_args = extra_args,
static_zlib = static_zlib,
Expand Down
Loading

0 comments on commit caf4a64

Please sign in to comment.