Skip to content

Commit

Permalink
native image instructions (#91)
Browse files Browse the repository at this point in the history
* native image instructions

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Build failure

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

---------

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>
  • Loading branch information
prabhu authored Nov 11, 2023
1 parent 685dd1e commit ddeb18d
Show file tree
Hide file tree
Showing 13 changed files with 2,354 additions and 4 deletions.
82 changes: 82 additions & 0 deletions .github/workflows/containers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Upload Container image

on:
push:
branches:
- main
tags:
- 'v*'
workflow_dispatch: # allow to manually trigger this workflow

env:
REGISTRY: ghcr.io
IMAGE_NAME: appthreat/atom

jobs:
deploy:
if: github.repository_owner == 'appthreat'
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '21'
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '21.x'
- name: Delete `.rustup` directory
run: rm -rf /home/runner/.rustup # to save disk space
if: runner.os == 'Linux'
- name: Delete `.cargo` directory # to save disk space
run: rm -rf /home/runner/.cargo
if: runner.os == 'Linux'
- uses: actions/cache@v3
with:
path: |
~/.sbt
~/.coursier
key: ${{ runner.os }}-sbt-${{ hashfiles('**/build.sbt') }}
- run: |
git apply --ignore-space-change --ignore-whitespace contrib/java21.patch
if [ $? != 0 ]; then
echo "Unable to patch the codebase correctly."
exit 1
fi
sbt stage createDistribution
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: |
ghcr.io/appthreat/atom
- name: Build and push Docker images
uses: docker/build-push-action@v4
with:
file: ci/Dockerfile
context: .
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=atom
cache-to: type=gha,mode=max,scope=atom
8 changes: 4 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name := "atom"
ThisBuild / organization := "io.appthreat"
ThisBuild / version := "1.6.0"
ThisBuild / version := "1.6.1"
ThisBuild / scalaVersion := "3.3.1"

val chenVersion = "1.0.0"
Expand Down Expand Up @@ -55,7 +55,7 @@ Universal / mappings := (Universal / mappings).value.filter {
case (_, path) => !path.contains("org.scala-lang.scala3-compiler") && !path.contains("io.get-coursier") && !path.contains("com.michaelpollmeier.scala-repl-pp")
}

enablePlugins(JavaAppPackaging, ClasspathJarPlugin)
enablePlugins(JavaAppPackaging, ClasspathJarPlugin, GraalVMNativeImagePlugin)

lazy val AstgenWin = "astgen-win.exe"
lazy val AstgenLinux = "astgen-linux"
Expand Down Expand Up @@ -157,8 +157,6 @@ ThisBuild / resolvers ++= Seq(
)

ThisBuild / assemblyMergeStrategy := {
case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first
case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first
case "application.conf" => MergeStrategy.concat
case x => MergeStrategy.preferProject
}
Expand All @@ -182,3 +180,5 @@ credentials +=
"appthreat",
sys.env.getOrElse("GITHUB_TOKEN", "N/A")
)
graalVMNativeImageGraalVersion := Some("22")
graalVMNativeImageOptions := Seq("-H:+UnlockExperimentalVMOptions", "--no-fallback")
73 changes: 73 additions & 0 deletions ci/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
FROM almalinux:9.2-minimal

LABEL maintainer="appthreat" \
org.opencontainers.image.authors="Team AppThreat <cloud@appthreat.com>" \
org.opencontainers.image.source="https://github.com/appthreat/chen" \
org.opencontainers.image.url="https://github.com/appthreat/atom" \
org.opencontainers.image.version="1.6.x" \
org.opencontainers.image.vendor="appthreat" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="atom" \
org.opencontainers.image.description="Container image for AppThreat atom" \
org.opencontainers.docker.cmd="docker run --rm -v /tmp:/tmp -v $HOME:$HOME -v $(pwd):/app:rw -it ghcr.io/appthreat/atom atom"

ARG MAVEN_VERSION=3.9.5
ARG JAVA_VERSION=21.0.1-graalce

ENV JAVA_VERSION=$JAVA_VERSION \
MAVEN_VERSION=$MAVEN_VERSION \
JAVA_HOME="/opt/java/${JAVA_VERSION}" \
MAVEN_HOME="/opt/maven/${MAVEN_VERSION}" \
JAVA_OPTS="-XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:+ParallelRefProcEnabled -XX:+UseStringDeduplication -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:+UnlockDiagnosticVMOptions -XX:G1SummarizeRSetStatsPeriod=1" \
ANDROID_HOME=/opt/android-sdk-linux \
JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8"

ENV PATH=${PATH}:/opt/bin:${JAVA_HOME}/bin:${MAVEN_HOME}/bin:/usr/local/bin/:/root/.local/bin:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools:

WORKDIR /opt

RUN set -e; \
ARCH_NAME="$(rpm --eval '%{_arch}')"; \
url=; \
case "${ARCH_NAME##*-}" in \
'x86_64') \
OS_ARCH_SUFFIX=''; \
;; \
'aarch64') \
OS_ARCH_SUFFIX='-aarch64'; \
;; \
*) echo >&2 "error: unsupported architecture: '$ARCH_NAME'"; exit 1 ;; \
esac; \
echo -e "[nodejs]\nname=nodejs\nstream=21\nprofiles=\nstate=enabled\n" > /etc/dnf/modules.d/nodejs.module \
&& microdnf install -y gcc git-core wget bash glibc-common glibc-all-langpacks \
pcre2 findutils which tar gzip zip unzip sudo nodejs \
&& curl -s "https://get.sdkman.io" | bash \
&& source "$HOME/.sdkman/bin/sdkman-init.sh" \
&& echo -e "sdkman_auto_answer=true\nsdkman_selfupdate_feature=false\nsdkman_auto_env=true" >> $HOME/.sdkman/etc/config \
&& sdk install java $JAVA_VERSION \
&& sdk install maven $MAVEN_VERSION \
&& sdk offline enable \
&& mv /root/.sdkman/candidates/* /opt/ \
&& rm -rf /root/.sdkman \
&& mkdir -p ${ANDROID_HOME}/cmdline-tools \
&& curl -L https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip -o ${ANDROID_HOME}/cmdline-tools/android_tools.zip \
&& unzip ${ANDROID_HOME}/cmdline-tools/android_tools.zip -d ${ANDROID_HOME}/cmdline-tools/ \
&& rm ${ANDROID_HOME}/cmdline-tools/android_tools.zip \
&& mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \
&& yes | /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager --licenses --sdk_root=/opt/android-sdk-linux \
&& /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager 'platform-tools' --sdk_root=/opt/android-sdk-linux \
&& /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager 'platforms;android-34' --sdk_root=/opt/android-sdk-linux \
&& /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager 'build-tools;34.0.0' --sdk_root=/opt/android-sdk-linux \
&& sudo npm install -g @cyclonedx/cdxgen --omit=optional

ENV LC_ALL=en_US.UTF-8 \
LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8
COPY ./target/atom.zip .
COPY ./wrapper .
RUN unzip -q atom.zip \
&& sudo npm install -g /opt/nodejs \
&& rm -rf atom.zip nodejs \
&& microdnf clean all

CMD ["atom"]
19 changes: 19 additions & 0 deletions ci/native-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# bash ci/native-image.sh

echo "Applying Java 21 patch"
git apply --ignore-space-change --ignore-whitespace contrib/java21.patch
if [ $? != 0 ]; then
echo "Unable to patch the codebase correctly. Please file a bug report for atom."
fi
echo "About to build the native image. This would take a few minutes ..."
sbt clean stage scalafmt "GraalVMNativeImage / packageBin"

if [ -f "target/graalvm-native-image/atom" ]; then
chmod +x target/graalvm-native-image/atom
target/graalvm-native-image/atom --help
echo "atom native-image was built successfully."
echo "Using Oracle GraalVM 21? Adhere to the terms of the license - https://www.oracle.com/downloads/licenses/graal-free-license.html"
else
echo "atom native-image was not built correctly. Check if you have Oracle GraalVM 21 installed."
fi
13 changes: 13 additions & 0 deletions ci/trace-native-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

# Trace the atom executable using Graal native-image-agent to produce an optimized native binary
#
# bash ci/trace-native-image.sh java <file path>
# bash ci/trace-native-image.sh js <file path>
# bash ci/trace-native-image.sh py <file path>
# bash ci/trace-native-image.sh c <file path>

sbt stage
./atom.sh -J-agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image reachables -l $1 -o /tmp/app.atom -s /tmp/reachables.slices.json $2

# bash ci/native-image.sh
70 changes: 70 additions & 0 deletions contrib/Dockerfile-graalvm21
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# https://www.oracle.com/downloads/licenses/graal-free-license.html
FROM container-registry.oracle.com/graalvm/jdk:21

LABEL maintainer="appthreat" \
org.opencontainers.image.authors="Team AppThreat <cloud@appthreat.com>" \
org.opencontainers.image.source="https://github.com/appthreat/chen" \
org.opencontainers.image.url="https://github.com/appthreat/atom" \
org.opencontainers.image.version="1.6.0" \
org.opencontainers.image.vendor="appthreat" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="atom" \
org.opencontainers.image.description="Container image for testing AppThreat atom with Oracle GraalVM" \
org.opencontainers.docker.cmd="docker run --rm -v /tmp:/tmp -v $HOME:$HOME -v $(pwd):/app:rw -it ghcr.io/appthreat/atom"

ARG MAVEN_VERSION=3.9.5

ENV MAVEN_VERSION=$MAVEN_VERSION \
MAVEN_HOME="/opt/maven/${MAVEN_VERSION}" \
JAVA_OPTS="-XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:+ParallelRefProcEnabled -XX:+UseStringDeduplication -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:+UnlockDiagnosticVMOptions -XX:G1SummarizeRSetStatsPeriod=1" \
ANDROID_HOME=/opt/android-sdk-linux \
JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8"

ENV PATH=${PATH}:/opt/bin:${MAVEN_HOME}/bin:/usr/local/bin/:/root/.local/bin:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools:

WORKDIR /opt

RUN set -e; \
ARCH_NAME="$(rpm --eval '%{_arch}')"; \
url=; \
case "${ARCH_NAME##*-}" in \
'x86_64') \
OS_ARCH_SUFFIX=''; \
;; \
'aarch64') \
OS_ARCH_SUFFIX='-aarch64'; \
;; \
*) echo >&2 "error: unsupported architecture: '$ARCH_NAME'"; exit 1 ;; \
esac; \
echo -e "[nodejs]\nname=nodejs\nstream=21\nprofiles=\nstate=enabled\n" > /etc/dnf/modules.d/nodejs.module \
&& microdnf install -y gcc git-core wget bash glibc-common glibc-all-langpacks \
pcre2 findutils which tar gzip zip unzip sudo nodejs \
&& curl -s "https://get.sdkman.io" | bash \
&& source "$HOME/.sdkman/bin/sdkman-init.sh" \
&& echo -e "sdkman_auto_answer=true\nsdkman_selfupdate_feature=false\nsdkman_auto_env=true" >> $HOME/.sdkman/etc/config \
&& sdk install maven $MAVEN_VERSION \
&& sdk offline enable \
&& mv /root/.sdkman/candidates/* /opt/ \
&& rm -rf /root/.sdkman \
&& mkdir -p ${ANDROID_HOME}/cmdline-tools \
&& curl -L https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip -o ${ANDROID_HOME}/cmdline-tools/android_tools.zip \
&& unzip ${ANDROID_HOME}/cmdline-tools/android_tools.zip -d ${ANDROID_HOME}/cmdline-tools/ \
&& rm ${ANDROID_HOME}/cmdline-tools/android_tools.zip \
&& mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \
&& yes | /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager --licenses --sdk_root=/opt/android-sdk-linux \
&& /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager 'platform-tools' --sdk_root=/opt/android-sdk-linux \
&& /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager 'platforms;android-34' --sdk_root=/opt/android-sdk-linux \
&& /opt/android-sdk-linux/cmdline-tools/latest/bin/sdkmanager 'build-tools;34.0.0' --sdk_root=/opt/android-sdk-linux \
&& sudo npm install -g @cyclonedx/cdxgen --omit=optional

ENV LC_ALL=en_US.UTF-8 \
LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8
COPY ./target/atom.zip .
COPY ./wrapper .
RUN unzip -q atom.zip \
&& sudo npm install -g /opt/nodejs \
&& rm -rf atom.zip nodejs \
&& microdnf clean all

ENTRYPOINT ["atom"]
8 changes: 8 additions & 0 deletions contrib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

Atom works better under Java 21 with virtual threads. Use the provided patch for Java 21.

## Steps

```shell
git apply --ignore-space-change --ignore-whitespace contrib/java21.patch
sbt clean stage createDistribution
```

## Consideration

Atom performs well under Oracle GraalVM 21. When using this version, consider the terms of the [license](https://www.oracle.com/downloads/licenses/graal-free-license.html)

If in doubt, use the image `ghcr.io/appthreat/atom` which is equally performant and uses the GraalVM Community Edition.
28 changes: 28 additions & 0 deletions src/main/resources/META-INF/native-image/jni-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
{
"name":"[Lcom.sun.management.internal.DiagnosticCommandArgumentInfo;"
},
{
"name":"[Lcom.sun.management.internal.DiagnosticCommandInfo;"
},
{
"name":"com.sun.management.internal.DiagnosticCommandArgumentInfo",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","boolean","boolean","boolean","int"] }]
},
{
"name":"com.sun.management.internal.DiagnosticCommandInfo",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String","boolean","java.util.List"] }]
},
{
"name":"java.lang.Boolean",
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.util.Arrays",
"methods":[{"name":"asList","parameterTypes":["java.lang.Object[]"] }]
},
{
"name":"sun.management.VMManagementImpl",
"fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"type":"agent-extracted",
"classes":[
]
}
]

2 changes: 2 additions & 0 deletions src/main/resources/META-INF/native-image/proxy-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[
]
Loading

0 comments on commit ddeb18d

Please sign in to comment.