Skip to content

Commit

Permalink
Build native images using GraalVM
Browse files Browse the repository at this point in the history
Closes #1123
  • Loading branch information
ScalaWilliam committed Oct 18, 2018
1 parent fdcf581 commit a242081
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cache:
- $HOME/.sbt
- $HOME/.m2
- $HOME/.ivy2
- $HOME/graalvm

env:
global:
Expand All @@ -28,6 +29,14 @@ env:
before_install:
# travis sets the java options which breaks tests that check the applied memory settings
- unset _JAVA_OPTIONS
- if [[ ! -d graalvm ]]; then
# Make `native-image` available and nothing else
wget https://github.com/oracle/graal/releases/download/vm-1.0.0-rc7/graalvm-ce-1.0.0-rc7-linux-amd64.tar.gz;
tar zxf graalvm-ce-1.0.0-rc7-linux-amd64.tar.gz;
mkdir -p ~/.bin;
ln -s ~/graalvm-ee-1.0.0-rc7/bin/native-image ~/.bin/native-image;
export PATH=~/.bin:$PATH;
fi
- if [[ "$TRAVIS_OS_NAME" = "osx" ]]; then
brew update;
brew install xz;
Expand Down Expand Up @@ -58,6 +67,9 @@ jobs:
- script: sbt "^validateAsh"
name: "scripted ash tests"
if: type = pull_request OR (type = push AND branch = master)
- script: sbt "^validateGraalVMNativeImage"
name: "scripted GraalVM native-image tests"
if: type = pull_request OR (type = push AND branch = master)
- script: sbt "^validateRpm"
name: "scripted rpm tests"
if: type = pull_request OR (type = push AND branch = master)
Expand Down
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ addCommandAlias("validateUniversal", "scripted universal/*")
addCommandAlias("validateJar", "scripted jar/*")
addCommandAlias("validateBash", "scripted bash/*")
addCommandAlias("validateAsh", "scripted ash/*")
addCommandAlias("validateGraalVMNativeImage", "scripted graalvm-native-image/*")
addCommandAlias("validateRpm", "scripted rpm/*")
addCommandAlias("validateDebian", "scripted debian/*")
addCommandAlias("validateDocker", "scripted docker/*")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.typesafe.sbt
package packager
package graalvmnativeimage

import sbt._

/**
* GraalVM settings
*/
trait GraalVMNativeImageKeys {
val graalVMNativeImageOptions =
SettingKey[Seq[String]]("graalvm-native-image-options", "GraalVM native-image options")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.typesafe.sbt.packager.graalvmnativeimage

import sbt._
import sbt.Keys._
import java.nio.charset.Charset

import com.typesafe.sbt.packager.SettingsHelper
import com.typesafe.sbt.packager.Keys._
import com.typesafe.sbt.packager.linux._
import com.typesafe.sbt.packager.Compat._
import com.typesafe.sbt.packager.validation._

/**
* Plugin to compile ahead-of-time native executables.
*
* @example Enable the plugin in the `build.sbt`
* {{{
* enablePlugins(GraalVMNativeImagePlugin)
* }}}
*/
object GraalVMNativeImagePlugin extends AutoPlugin {

object autoImport extends GraalVMNativeImageKeys {
val GraalVMNativeImage: Configuration = config("graalvm-native-image")
}

private val GraalVMNativeImageCommand = "native-image"

import autoImport._

override def projectConfigurations: Seq[Configuration] = Seq(GraalVMNativeImage)

override lazy val projectSettings = Seq(
target in GraalVMNativeImage := target.value / "graalvm-native-image",
graalVMNativeImageOptions := Seq.empty,
packageBin in GraalVMNativeImage := {
val targetDirectory = (target in GraalVMNativeImage).value
targetDirectory.mkdirs()
val binaryName = name.value
val command = {
val nativeImageArguments = {
val className = (mainClass in Compile).value.getOrElse(sys.error("Could not find a main class."))
val classpathJars = Seq((packageBin in Compile).value) ++ (dependencyClasspath in Compile).value.map(_.data)
val classpath = classpathJars.mkString(":")
val extraOptions = graalVMNativeImageOptions.value
Seq("--class-path", classpath, s"-H:Name=$binaryName") ++ extraOptions ++ Seq(className)
}
Seq(GraalVMNativeImageCommand) ++ nativeImageArguments
}
sys.process.Process(command, targetDirectory) ! streams.value.log match {
case 0 => targetDirectory / binaryName
case x => sys.error(s"Failed to run $GraalVMNativeImageCommand, exit status: " + x)
}
}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enablePlugins(GraalVMNativeImagePlugin)

name := "simple-test"

version := "0.1.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object Main {
def main(args: Array[String]): Unit = {
println("Hello world")
}
}
3 changes: 3 additions & 0 deletions src/sbt-test/graalvm-native-image/simple-native-image/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Generate the GraalVM native image
> show graalvm-native-image:packageBin
$ exists target/graalvm-native-image/simple-testx
45 changes: 45 additions & 0 deletions src/sphinx/formats/graalvm-native-image.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.. _graalvm-native-image-plugin:

GraalVM Native Image Plugin
=============

GraalVM's ``native-image`` compiles Java programs AOT (ahead-of-time) into native binaries.

https://www.graalvm.org/docs/reference-manual/aot-compilation/ documents the AOT compilation of GraalVM.

Requirements
------------

You must have ``native-image`` of GraalVM in your ``PATH``.

Build
-----

.. code-block:: bash
sbt 'show graalvm-native-image:packageBin'
Required Settings
~~~~~~~~~~~~~~~~~

.. code-block:: scala
enablePlugins(GraalVMNativeImagePlugin)
Settings
--------

Publishing Settings
~~~~~~~~~~~~~~~~~~~

``graalVMNativeImageOptions``
Extra options that will be passed to the ``native-image`` command. By default, this includes the name of the main class.

Tasks
-----
The GraalVM Native Image plugin provides the following commands:

``graalvm-native-image:packageBin``
Generates a native image using GraalVM.

0 comments on commit a242081

Please sign in to comment.