1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# libjava — embed a JVM in a Nim process and call Java from it, via JNI
#
# The nimble tasks remain the source of truth; these recipes are thin wrappers
# so the common loop is one word. `just -l` lists everything.
default: test
# Compile the example Java classes into build/classes
java:
nimble java
# Run the test suite (compiles the Java fixtures first)
test:
nimble test
# Run the example program
demo:
nimble demo
# Resolve the Clojure classpath from deps.edn into build/clojure-classpath
clojure-cp:
#!/usr/bin/env bash
set -euo pipefail
mkdir -p build
clojure -Spath > build/clojure-classpath
# Run the Clojure interop example (needs the `clojure` CLI on PATH)
clojure: clojure-cp
nim c -r --path:src examples/clojure_demo.nim
# Compile the example binary into out/ (release build, nothing left in-tree)
build: java
nim c -d:release --path:src --nimcache:build/nimcache -o:out/demo examples/demo.nim
# Type-check the library without producing a binary
check:
#!/usr/bin/env bash
set -euo pipefail
# `nim check` does not run `staticExec`, so config.nim's PATH-based JDK
# fallback is unavailable there — resolve the home here and pass it in.
home="${JAVA_HOME:-$(dirname "$(dirname "$(readlink -f "$(command -v javac)")")")}"
nim check --path:src -d:javaHome="$home" src/libjava.nim
# Build the library's documentation into build/docs
docs:
nim doc --project --index:on --outdir:build/docs --path:src src/libjava.nim
# Remove build outputs and compiled test/example binaries
clean:
rm -rf build nimcache out .cpcache
rm -f tests/tlibjava examples/demo
# Print the JDK this build will link against
jdk:
#!/usr/bin/env bash
set -euo pipefail
d=$(mktemp -d)
trap 'rm -rf "$d"' EXIT
printf 'import libjava/config\necho javaHome\n' > "$d/jdk.nim"
nim c -r --path:src --hints:off -d:libjavaNoLink --nimcache:"$d/cache" -o:"$d/jdk" "$d/jdk.nim"
# The AppImage carries its own jlink'd Java runtime, so the demo binary is
# linked against $ORIGIN/../lib/jvm rather than the build machine's JDK.
# appimagetool is downloaded to build/tools on first use; set APPIMAGETOOL to
# point at your own copy instead.
#
# Bundle the example into a self-contained AppImage in out/
appimage: java
#!/usr/bin/env bash
set -euo pipefail
home="${JAVA_HOME:-$(dirname "$(dirname "$(readlink -f "$(command -v javac)")")")}"
arch=$(uname -m)
tool="${APPIMAGETOOL:-build/tools/appimagetool}"
if [ ! -x "$tool" ]; then
mkdir -p "$(dirname "$tool")"
curl -fsSL -o "$tool" \
"https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$arch.AppImage"
chmod +x "$tool"
fi
rm -rf build/AppDir
mkdir -p build/AppDir/usr/bin build/AppDir/build
# A minimal runtime: the demo only touches java.base.
"$home/bin/jlink" --add-modules java.base \
--strip-debug --no-header-files --no-man-pages --compress=2 \
--output build/AppDir/usr/lib/jvm
# Headers from the build JDK; libjvm resolved next to the binary at runtime.
# (nim links through a shell, so $ORIGIN needs escaping twice over.)
nim c -d:release --path:src -d:libjavaNoLink --nimcache:build/nimcache \
--passL:"-L$home/lib/server -ljvm -Wl,-rpath,\\\$ORIGIN/../lib/jvm/lib/server" \
-o:build/AppDir/usr/bin/demo examples/demo.nim
# demo.nim looks for its classes at the relative path build/classes,
# so AppRun runs from the AppDir root.
cp -r build/classes build/AppDir/build/classes
printf '%s\n' \
'#!/usr/bin/env bash' \
'cd "$(dirname "$(readlink -f "$0")")"' \
'exec ./usr/bin/demo "$@"' > build/AppDir/AppRun
chmod +x build/AppDir/AppRun
printf '%s\n' \
'[Desktop Entry]' \
'Type=Application' \
'Name=libjava demo' \
'Exec=AppRun' \
'Icon=libjava-demo' \
'Categories=Development;' \
'Terminal=true' > build/AppDir/libjava-demo.desktop
printf '%s\n' \
'<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">' \
' <rect width="256" height="256" rx="32" fill="#1b1f23"/>' \
' <text x="128" y="164" font-family="sans-serif" font-size="104"' \
' font-weight="bold" fill="#ffe873" text-anchor="middle">Jn</text>' \
'</svg>' > build/AppDir/libjava-demo.svg
ln -sf libjava-demo.svg build/AppDir/.DirIcon
mkdir -p out
ARCH="$arch" "$tool" build/AppDir "out/libjava-demo-$arch.AppImage"
|