|
1 | 1 | #!/usr/bin/env bash |
2 | | -# build-jar.sh — Build a runnable fat JAR for NitroWebExpress quick deployment |
3 | | -# Output: nwe.jar in project root. Launch via: bash scripts/run-jar.sh |
| 2 | +# build-jar.sh — Build a runnable fat JAR for NitroWebExpress quick deployment. |
| 3 | +# The script is location-independent: it may be invoked from any working directory. |
4 | 4 | set -euo pipefail |
5 | 5 |
|
6 | | -ROOT="$(cd "$(dirname "$0")/.." && pwd)" |
| 6 | +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" |
| 7 | +ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd -P)" |
7 | 8 | SRC="$ROOT/source" |
8 | 9 | OUT="$ROOT/out" |
9 | 10 | JAR_OUT="$ROOT/nwe.jar" |
10 | 11 | MYSQL_JAR="$ROOT/jars/mysql/mysql-connector-j-9.7.0.jar" |
11 | 12 | LANTERNA_JAR="$ROOT/jars/lanterna-3.1.5.jar" |
12 | 13 | DJL_DIR="$ROOT/jars/djl" |
| 14 | +JPCAP_DIR="$ROOT/jars/jpcap" |
| 15 | + |
| 16 | +require_command() { |
| 17 | + command -v "$1" >/dev/null 2>&1 || { |
| 18 | + echo "[FAIL] Required command not found: $1" >&2 |
| 19 | + exit 1 |
| 20 | + } |
| 21 | +} |
| 22 | + |
| 23 | +require_command javac |
| 24 | +require_command jar |
| 25 | +require_command unzip |
| 26 | + |
| 27 | +[[ -d "$SRC" ]] || { echo "[FAIL] Source directory missing: $SRC" >&2; exit 1; } |
| 28 | +[[ -f "$MYSQL_JAR" ]] || { echo "[FAIL] Missing dependency: $MYSQL_JAR" >&2; exit 1; } |
| 29 | +[[ -f "$LANTERNA_JAR" ]] || { echo "[FAIL] Missing dependency: $LANTERNA_JAR" >&2; exit 1; } |
| 30 | + |
| 31 | +if [[ -n "${JAVA_HOME:-}" && -x "$JAVA_HOME/bin/javac" ]]; then |
| 32 | + export PATH="$JAVA_HOME/bin:$PATH" |
| 33 | +fi |
| 34 | + |
| 35 | +CP="$OUT:$MYSQL_JAR:$LANTERNA_JAR" |
| 36 | +if [[ -d "$DJL_DIR" ]]; then |
| 37 | + while IFS= read -r -d '' dep; do CP+="${CP:+:}$dep"; done < <(find "$DJL_DIR" -type f -name '*.jar' -print0) |
| 38 | +fi |
| 39 | +if [[ -d "$JPCAP_DIR" ]]; then |
| 40 | + while IFS= read -r -d '' dep; do CP+="${CP:+:}$dep"; done < <(find "$JPCAP_DIR" -type f -name '*.jar' -print0) |
| 41 | +fi |
| 42 | + |
| 43 | +TMP_ROOT="${TMPDIR:-/tmp}" |
| 44 | +SOURCE_LIST="$(mktemp "$TMP_ROOT/nwe-sources.XXXXXX")" |
| 45 | +STAGING="$(mktemp -d "$TMP_ROOT/nwe-jar-staging.XXXXXX")" |
| 46 | +cleanup() { rm -f "$SOURCE_LIST"; rm -rf "$STAGING"; } |
| 47 | +trap cleanup EXIT |
13 | 48 |
|
14 | 49 | echo "=== NitroWebExpress — JAR Builder ===" |
15 | 50 | echo "ROOT: $ROOT" |
16 | 51 |
|
17 | | -# ── 1. Compile ──────────────────────────────────────────────────────────────── |
18 | 52 | echo "[1/3] Compiling sources..." |
19 | 53 | mkdir -p "$OUT" |
20 | | -DJL_CP=$(find "$DJL_DIR" -name "*.jar" 2>/dev/null | tr '\n' ':') |
21 | | -JPCAP_CP=$(find "$ROOT/jars/jpcap" -name "*.jar" 2>/dev/null | tr '\n' ':') |
22 | | -CP="$OUT:$MYSQL_JAR:${DJL_CP}${JPCAP_CP}$LANTERNA_JAR" |
23 | | - |
24 | | -find "$SRC" -name "*.java" > /tmp/nwe-sources.txt |
25 | | -javac --release 21 -cp "$CP" -sourcepath "$SRC" -d "$OUT" @/tmp/nwe-sources.txt 2>&1 |
26 | | -rm -f /tmp/nwe-sources.txt |
| 54 | +find "$SRC" -type f -name '*.java' -print > "$SOURCE_LIST" |
| 55 | +[[ -s "$SOURCE_LIST" ]] || { echo "[FAIL] No Java sources found under $SRC" >&2; exit 1; } |
| 56 | +javac --release 21 -cp "$CP" -sourcepath "$SRC" -d "$OUT" "@$SOURCE_LIST" |
27 | 57 | echo " Compiled." |
28 | 58 |
|
29 | | -# ── 2. Assemble fat JAR ────────────────────────────────────────────────────── |
30 | 59 | echo "[2/3] Assembling fat JAR..." |
31 | | -STAGING=$(mktemp -d) |
32 | | -trap "rm -rf $STAGING" EXIT |
33 | | - |
34 | | -# Copy application classes |
35 | 60 | cp -a "$OUT"/. "$STAGING/" |
36 | 61 |
|
37 | | -# Extract dependency JARs into staging (fat jar approach) |
38 | | -for dep in "$MYSQL_JAR" "$LANTERNA_JAR"; do |
39 | | - [ -f "$dep" ] && unzip -qo "$dep" -d "$STAGING" -x 'META-INF/MANIFEST.MF' 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA' |
40 | | -done |
41 | | - |
42 | | -# DJL jars (excluding the huge native blob — that stays external) |
43 | | -for dep in $(find "$DJL_DIR" -name "*.jar" ! -name "*native*" 2>/dev/null); do |
44 | | - unzip -qo "$dep" -d "$STAGING" -x 'META-INF/MANIFEST.MF' 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA' |
45 | | -done |
| 62 | +extract_jar() { |
| 63 | + local dep="$1" |
| 64 | + [[ -f "$dep" ]] || return 0 |
| 65 | + unzip -qo "$dep" -d "$STAGING" \ |
| 66 | + -x 'META-INF/MANIFEST.MF' 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA' |
| 67 | +} |
46 | 68 |
|
47 | | -# Jpcap (network packet capture library) |
48 | | -for dep in $(find "$ROOT/jars/jpcap" -name "*.jar" 2>/dev/null); do |
49 | | - unzip -qo "$dep" -d "$STAGING" -x 'META-INF/MANIFEST.MF' 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA' |
50 | | -done |
| 69 | +extract_jar "$MYSQL_JAR" |
| 70 | +extract_jar "$LANTERNA_JAR" |
| 71 | +if [[ -d "$DJL_DIR" ]]; then |
| 72 | + while IFS= read -r -d '' dep; do |
| 73 | + [[ "$dep" == *native* ]] && continue |
| 74 | + extract_jar "$dep" |
| 75 | + done < <(find "$DJL_DIR" -type f -name '*.jar' -print0) |
| 76 | +fi |
| 77 | +if [[ -d "$JPCAP_DIR" ]]; then |
| 78 | + while IFS= read -r -d '' dep; do extract_jar "$dep"; done < <(find "$JPCAP_DIR" -type f -name '*.jar' -print0) |
| 79 | +fi |
51 | 80 |
|
52 | | -# Write manifest |
53 | 81 | mkdir -p "$STAGING/META-INF" |
54 | | -cat > "$STAGING/META-INF/MANIFEST.MF" <<EOF |
| 82 | +cat > "$STAGING/META-INF/MANIFEST.MF" <<'EOF' |
55 | 83 | Manifest-Version: 1.0 |
56 | 84 | Main-Class: Main |
57 | 85 | Class-Path: jars/djl/pytorch-native-cpu-2.5.1-linux-x86_64.jar |
58 | 86 | EOF |
59 | 87 |
|
60 | | -# ── 3. Create JAR ──────────────────────────────────────────────────────────── |
61 | 88 | echo "[3/3] Creating $JAR_OUT..." |
62 | 89 | jar cfm "$JAR_OUT" "$STAGING/META-INF/MANIFEST.MF" -C "$STAGING" . |
63 | 90 | echo " Done. Size: $(du -h "$JAR_OUT" | cut -f1)" |
64 | | -echo "" |
65 | | -echo "=== Run with: bash scripts/run-jar.sh ===" |
| 91 | +echo "=== Run with: java -jar nwe.jar ===" |
0 commit comments