Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

native image instructions #91

Merged
merged 2 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading