800 lines
25 KiB
Bash
Executable File
800 lines
25 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
function print_help {
|
|
echo
|
|
echo 'Usage: warp4j [options] <app.jar>'
|
|
echo
|
|
echo 'Turn JAR (java archive) into self-contained executable'
|
|
echo
|
|
echo 'Options:'
|
|
echo ' -j, --java-version <version>'
|
|
echo ' override JDK/JRE version'
|
|
echo ' examples: "17", "17.0", "17.0.2", "17.0.2+9"'
|
|
echo ' (default: 17)'
|
|
echo ' -cp, --class-path <classpath>'
|
|
echo ' adds additional classpaths to the jdeps call'
|
|
echo ' --auto-class-path extract and get class-path values from jar file'
|
|
echo ' ignored when -cp, --class-path is set'
|
|
echo ' -o, --output <directory>'
|
|
echo ' override output directory;'
|
|
echo ' this is relative to current PWD'
|
|
echo ' (default: ./warped)'
|
|
echo ' --list show available java releases;'
|
|
echo ' takes into consideration other options:'
|
|
echo ' "--java-version", "--no-optimize", "--jvm-impl";'
|
|
echo ' the output may be used to specify concrete'
|
|
echo ' "--java-version"'
|
|
echo ' --no-optimize use JRE instead of optimized JDK;'
|
|
echo ' by default jdeps and jlink are used to create'
|
|
echo ' optimized JDK for the particular jar;'
|
|
echo ' JRE is always used for java 8'
|
|
echo ' --pull check if more recent JDK/JRE distro is available;'
|
|
echo ' by default latest cached version that matches'
|
|
echo ' "--java-version" is used'
|
|
echo ' to get the classpath for jdeps call'
|
|
echo ' --linux create binary for Linux'
|
|
echo ' --macos create binary for macOS'
|
|
echo ' --windows create binary for Windows'
|
|
echo ' if no targets are specified then binaries for'
|
|
echo ' all targets are created'
|
|
echo ' --jvm-options <options>'
|
|
echo ' passed to java like this:'
|
|
echo ' "java <options> -jar <jar file>";'
|
|
echo ' use quotes when passing multiple options'
|
|
echo " example: '-Xms512m -Xmx1024m'"
|
|
echo ' -s, --silent using javaw instead of java for windows'
|
|
echo ' -h, --help show this message'
|
|
exit
|
|
}
|
|
|
|
# exit top level program from subshell
|
|
trap "exit 1" TERM
|
|
export TOP_PID=$$
|
|
function fail() {
|
|
kill -s TERM $TOP_PID
|
|
}
|
|
|
|
# fail with a message
|
|
function fail_with() {
|
|
local message=$1
|
|
echo "Error: $message" >&2
|
|
fail
|
|
}
|
|
|
|
# if error code is not zero fail with a message
|
|
function fail_if() {
|
|
local error_code=$1
|
|
local message=$2
|
|
if [[ $error_code != 0 ]]; then
|
|
fail_with "$message"
|
|
fi
|
|
}
|
|
|
|
# common warning
|
|
function warn() {
|
|
local message=$1
|
|
echo "Warning: $message" >&2
|
|
}
|
|
|
|
# platform IDs
|
|
LIN=linux
|
|
MAC=macos
|
|
WIN=windows
|
|
|
|
# returns this platform ID
|
|
function get_this_platform() {
|
|
local this_platform="$(uname -s)"
|
|
case $this_platform in
|
|
Linux*) echo $LIN ;;
|
|
Darwin*) echo $MAC ;;
|
|
*)
|
|
fail_with "Unsupported platform $this_platform"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# platform Machine
|
|
X64=x64
|
|
AARCH64=aarch64
|
|
|
|
# returns this platform machine
|
|
function get_this_machine() {
|
|
local this_machine="$(uname -m)"
|
|
case $this_machine in
|
|
x86_64) echo $X64 ;;
|
|
aarch64) echo $AARCH64 ;;
|
|
*)
|
|
fail_with "Unsupported machine $this_machine"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# show help if no arguments specified
|
|
if [[ $# -eq 0 ]]; then
|
|
print_help
|
|
exit
|
|
fi
|
|
|
|
# parse arguments
|
|
POSITIONAL=()
|
|
while [[ $# -gt 0 ]]; do
|
|
key="$1"
|
|
case $key in
|
|
-h|--help)
|
|
print_help
|
|
exit
|
|
;;
|
|
-cp|--class-path)
|
|
CLASS_PATH="$2"
|
|
shift 2
|
|
;;
|
|
-j|--java-version)
|
|
JAVA_VERSION="$2"
|
|
JAVA_VERSION_OVERRIDEN=true
|
|
shift 2
|
|
;;
|
|
-o|--output)
|
|
OUTPUT_DIR_PATH="$2"
|
|
shift 2
|
|
;;
|
|
--list)
|
|
LIST_RELEASES=true
|
|
shift
|
|
;;
|
|
--no-optimize)
|
|
NO_OPTIMIZE=true
|
|
shift
|
|
;;
|
|
--pull)
|
|
PULL=true
|
|
shift
|
|
;;
|
|
--linux)
|
|
TARGETS+=($LIN)
|
|
shift
|
|
;;
|
|
--macos)
|
|
TARGETS+=($MAC)
|
|
shift
|
|
;;
|
|
--windows)
|
|
TARGETS+=($WIN)
|
|
shift
|
|
;;
|
|
--jvm-options)
|
|
JVM_OPTIONS="$2"
|
|
shift 2
|
|
;;
|
|
--auto-class-path)
|
|
AUTO_CLASS_PATH=true
|
|
shift
|
|
;;
|
|
-s|--silent)
|
|
SILENT=true
|
|
shift
|
|
;;
|
|
-*|--*) # unsupported options
|
|
fail_with "Unsupported option $1"
|
|
;;
|
|
*)
|
|
POSITIONAL+=("$1") # store positional arguments
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
set -- "${POSITIONAL[@]}" # restore positional arguments
|
|
|
|
THIS_PLATFORM=$(get_this_platform)
|
|
THIS_MACHINE=$(get_this_machine)
|
|
|
|
# checks if all dependencies are available
|
|
function check_deps() {
|
|
local deps=(
|
|
"awk" \
|
|
"curl" \
|
|
"file" \
|
|
"grep" \
|
|
"sed" \
|
|
"sort" \
|
|
"tar" \
|
|
"unzip" \
|
|
"warp-packer" \
|
|
)
|
|
local missing=()
|
|
for d in ${deps[@]}; do
|
|
if ! command -v $d &> /dev/null ; then
|
|
missing+=($d)
|
|
fi
|
|
done
|
|
if [[ $missing ]]; then
|
|
echo -n "Error: Missing dependencies: " >&2
|
|
for d in ${missing[@]}; do
|
|
echo -n "$d " >&2
|
|
done
|
|
echo >&2
|
|
fail
|
|
fi
|
|
}
|
|
|
|
# actually check dependencies
|
|
check_deps
|
|
|
|
# apart from options only one argument is allowed
|
|
if [[ $# -gt 1 ]]; then
|
|
fail_with "Too many arguments: $*; expecting only jar name"
|
|
else
|
|
JAR=$1
|
|
fi
|
|
|
|
# checks if java version specified correctly
|
|
function java_version_is_correct() {
|
|
local pattern="^[0-9]+(\.[0-9]+(\.[0-9]+(\+[0-9]+)?)?)?$"
|
|
local version=$1
|
|
if [[ $version =~ $pattern ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# validate java version
|
|
if [[ $JAVA_VERSION ]] && ! java_version_is_correct $JAVA_VERSION ; then
|
|
fail_with "JDK version \"$JAVA_VERSION\" is not correct"
|
|
fi
|
|
|
|
JVM_IMPL=hotspot
|
|
|
|
LATEST_LTS=17 # latest LTS java branch
|
|
|
|
# default options
|
|
test -z $JAVA_VERSION && JAVA_VERSION=$LATEST_LTS
|
|
test -z $TARGETS && TARGETS=($LIN $MAC $WIN)
|
|
|
|
# returns java branch version
|
|
function get_base_version() {
|
|
local version=$1
|
|
echo `echo $version | cut -d"." -f1`
|
|
}
|
|
|
|
# actually set java branch
|
|
JAVA_VERSION_BASE=$(get_base_version $JAVA_VERSION)
|
|
|
|
DISTRO_TYPE_JRE=jre
|
|
DISTRO_TYPE_JDK=jdk
|
|
|
|
# chooses what to use, JDK or JRE
|
|
function choose_distro_type() {
|
|
if [[ $JAVA_VERSION_BASE == 8 ]] ||
|
|
[[ $NO_OPTIMIZE ]]; then
|
|
echo $DISTRO_TYPE_JRE
|
|
else
|
|
echo $DISTRO_TYPE_JDK
|
|
fi
|
|
}
|
|
|
|
# actually choose distro type
|
|
JAVA_DISTRO_TYPE=$(choose_distro_type)
|
|
|
|
# generates adoptium api url
|
|
function api_url() {
|
|
local platform=$1 # windows/linux/macos
|
|
local architecture=$2
|
|
# adoptium uses "mac" instead of "macos"
|
|
if [[ $platform == "macos" ]]; then
|
|
platform="mac"
|
|
fi
|
|
|
|
echo -n "https://api.adoptium.net/v3/assets/feature_releases/\
|
|
$JAVA_VERSION_BASE/ga?architecture=$architecture&heap_size=normal&image_type=jdk&\
|
|
os=$platform&page=0&page_size=20&project=$JAVA_DISTRO_TYPE&\
|
|
sort_method=DEFAULT&sort_order=DESC&vendor=eclipse"
|
|
|
|
}
|
|
|
|
# requests info about all releases for given platform and java branch
|
|
function fetch_distro_info() {
|
|
local platform=$1 # platform ID
|
|
local architecture=$2
|
|
local branch=$3 # 8/9/10/11...
|
|
curl -s $(api_url $platform $architecture)
|
|
fail_if $? "Failed to fetch java $branch info"
|
|
}
|
|
|
|
# extracts all concrete java versions that match the version specified by user
|
|
# from provided distro info
|
|
function find_matched_versions() {
|
|
local info=$1
|
|
local user_version=$2
|
|
# turning something like "11.0.1+13" into regexp like "^11\.0\.1\+13"
|
|
local pattern="^"$(echo $user_version \
|
|
| sed -e 's/\./\\\./g' -e 's/\+/\\\+/g')
|
|
local versions=$(echo "$info" \
|
|
| grep '"semver"' \
|
|
| sort --reverse --version-sort \
|
|
| awk '{print $2}' \
|
|
| sed -e 's/"//g' -e 's/,//')
|
|
for v in ${versions[@]}; do
|
|
if [[ $v =~ $pattern ]]; then
|
|
echo $v
|
|
fi
|
|
done
|
|
}
|
|
|
|
# prints all concrete java versions that match the version specified by user
|
|
function list_releases() {
|
|
local info
|
|
local matched
|
|
local printed
|
|
local platform="linux" # just picked any
|
|
info=$(fetch_distro_info $platform $X64 $JAVA_VERSION_BASE)
|
|
matched=$(find_matched_versions "$info" $JAVA_VERSION)
|
|
if [[ $matched ]]; then
|
|
echo "Releases that match $JAVA_VERSION:"
|
|
for m in ${matched[@]}; do
|
|
if [[ ${printed[@]} != *"$m"* ]]; then
|
|
echo $m
|
|
printed+=($m)
|
|
fi
|
|
done
|
|
else
|
|
echo "No releases that match $JAVA_VERSION"
|
|
fi
|
|
}
|
|
|
|
# actually show matched releases
|
|
if [[ $LIST_RELEASES ]]; then
|
|
list_releases
|
|
exit
|
|
fi
|
|
|
|
JAR_FILE_BASE_NAME=$(basename -- "$JAR") # "my-app.jar"
|
|
JAR_EXTENSION="${JAR_FILE_BASE_NAME##*.}" # "jar"
|
|
JAR_EXTENSION_LOWERCASE=$(printf "%s" "$JAR_EXTENSION" | tr '[:upper:]' '[:lower:]') # "jar"
|
|
JAR_NAME="${JAR_FILE_BASE_NAME%.*}" # "my-app"
|
|
|
|
APP_NAME=$JAR_NAME # final binary name
|
|
LAUNCHER_NAME=$JAR_NAME # launcher name inside bundle
|
|
|
|
# checking jar file exists
|
|
if [[ ! -e $JAR ]]; then
|
|
fail_with "File \"$JAR\" does not exist"
|
|
fi
|
|
|
|
# checking file is actually java archive
|
|
if ([[ $(file $JAR) != *"Java"* ]] && # it could be "Java archive data" or "Java Jar file data (zip)"
|
|
[[ $(file $JAR) != *"Zip"* ]]) || # or "Zip archive data"
|
|
[[ $JAR_EXTENSION_LOWERCASE != "jar" ]]; then
|
|
fail_with "File \"$JAR\" is not a java archive"
|
|
fi
|
|
|
|
# even if this platform is not targeted, we still need
|
|
# a JDK for this platform to optimize JDKs for other platforms
|
|
TARGETS_TO_CACHE=${TARGETS[@]}
|
|
if [[ $THIS_MACHINE == $X64 ]] && # if architecture is x86
|
|
[[ $JAVA_DISTRO_TYPE == $DISTRO_TYPE_JDK ]] && # and if using JDK (not JRE)
|
|
[[ ${TARGETS[@]} != *"$THIS_PLATFORM"* ]]; then # and this platform is not targeted
|
|
TARGETS_TO_CACHE+=($THIS_PLATFORM)
|
|
fi
|
|
|
|
# choose cache path for this platform
|
|
case $THIS_PLATFORM in
|
|
$MAC) CACHE_PATH="$HOME/Library/Application Support/warp4j" ;;
|
|
*) CACHE_PATH="$HOME/.local/share/warp4j" ;;
|
|
esac
|
|
|
|
# cache path can be overriden with environment variable
|
|
if [[ $WARP4J_CACHE ]]; then
|
|
CACHE_PATH=$WARP4J_CACHE
|
|
fi
|
|
|
|
# this is not full path, platform name and full version will be added
|
|
JAVA_DOWNLOAD_PATH=$CACHE_PATH/$JAVA_DISTRO_TYPE/$JVM_IMPL
|
|
BUNDLES_PATH=$CACHE_PATH/bundle # prepare bundles here
|
|
|
|
# path for extracted jar files
|
|
EXTRACTED_JAR_PATH=$CACHE_PATH/app-jar # prepare bundles here
|
|
mkdir -p ${EXTRACTED_JAR_PATH}
|
|
trap 'rm -rf ${EXTRACTED_JAR_PATH}' EXIT
|
|
|
|
DIR="$(pwd -P)" # execution directory path
|
|
|
|
# final binaries created in WARPED_TEMP_PATH and then moved to WARPED_PATH
|
|
WARPED_TEMP_PATH=$CACHE_PATH/out-temp
|
|
if [[ -z $OUTPUT_DIR_PATH ]]; then
|
|
WARPED_PATH=$DIR/warped
|
|
else
|
|
WARPED_PATH=$OUTPUT_DIR_PATH
|
|
fi
|
|
|
|
BUNDLED_DISTRO_SUBDIR="java" # runtime directory inside a bundle
|
|
|
|
# prints a launcher for bash
|
|
function print_launcher_bash() {
|
|
printf "%s" \
|
|
'#!/usr/bin/env bash
|
|
|
|
JAVA_DIST='"$BUNDLED_DISTRO_SUBDIR"'
|
|
JAR='"$JAR_NAME"'.jar
|
|
|
|
DIR="$(cd "$(dirname "$0")" ; pwd -P)"
|
|
JAVA=$DIR/$JAVA_DIST/bin/'"$JAVA_EXEC"'
|
|
JAR_PATH=$DIR/$JAR
|
|
|
|
exec "$JAVA" '"$JVM_OPTIONS"' -jar "$JAR_PATH" "$@"
|
|
'
|
|
}
|
|
|
|
# prints a launcher for windows cmd
|
|
function print_launcher_cmd() {
|
|
printf "%s" \
|
|
'@ECHO OFF
|
|
|
|
SETLOCAL
|
|
|
|
SET "JAVA_DIST='"$BUNDLED_DISTRO_SUBDIR"'"
|
|
SET "JAR='"$JAR_NAME"'.jar"
|
|
|
|
SET "JAVA=%~dp0\%JAVA_DIST%\bin\'"$JAVA_EXEC"'
|
|
SET "JAR_PATH=%~dp0\%JAR%"
|
|
|
|
START %JAVA% '"$JVM_OPTIONS"' -jar %JAR_PATH% %*
|
|
EXIT /B %ERRORLEVEL%
|
|
'
|
|
}
|
|
|
|
# these files are success markers
|
|
MARKER_DOWNLOADED="downloaded" # after runtime download
|
|
MARKER_UNPACKED="unpacked" # after runtime uncompress
|
|
|
|
# returns latest cached version that matches version specified by user
|
|
function find_latest_cached() {
|
|
local platform=$1
|
|
local architecture=$2
|
|
local user_version=$3
|
|
local platform_dir=$JAVA_DOWNLOAD_PATH/$platform/$architecture
|
|
# turning something like "11.0.1+13" into regexp like "^11\.0\.1\+13"
|
|
local pattern="^"$(echo $user_version \
|
|
| sed -e 's/\./\\\./g' -e 's/\+/\\\+/g')
|
|
local versions=$(ls -1 "$platform_dir" 2> /dev/null \
|
|
| sort --reverse --version-sort)
|
|
local version
|
|
for v in ${versions[@]}; do
|
|
if [[ -e $platform_dir/$v/$MARKER_DOWNLOADED ]] &&
|
|
[[ $v =~ $pattern ]]; then
|
|
version=$v
|
|
break
|
|
fi
|
|
done
|
|
if [[ $version ]]; then
|
|
echo $version
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# finds latest concrete distro version that matches version specified by user
|
|
function find_latest_version() {
|
|
local info=$1 # info fetched from Adoptium
|
|
local user_version=$2 # version supplied by user is a template
|
|
local matched_version # latest version that matches the template
|
|
local versions # all versions
|
|
versions=$(echo "$info" \
|
|
| grep '"semver"' \
|
|
| sort --reverse --version-sort \
|
|
| awk '{print $2}' \
|
|
| sed -e 's/"//g' -e 's/,//')
|
|
# turning something like "11.0.1+13" into regexp like "^11\.0\.1\+13"
|
|
# remember that user may provide shorter version like "11", "11.0", "11.0.1"
|
|
local pattern="^"$(echo $user_version | sed -e 's/\./\\\./g' -e 's/\+/\\\+/g')
|
|
for v in ${versions[@]}; do
|
|
if [[ $v =~ $pattern ]]; then
|
|
matched_version=$v
|
|
break
|
|
fi
|
|
done
|
|
if [[ -z $matched_version ]]; then
|
|
fail_with "Can't find distro that matches $user_version"
|
|
fi
|
|
echo $matched_version
|
|
}
|
|
|
|
# finds direct link to download concrete runtime version
|
|
function find_distro_link() {
|
|
local info=$1 # info fetched from Adoptium
|
|
local version=$2 # concrete distro version like "11.0.2+9"
|
|
local link=$(echo "$info" \
|
|
| grep -B14 "\"release_name\": \"jdk-$version\"" \
|
|
| grep "\"link\":" \
|
|
| sort --reverse \
|
|
| head -n 1 \
|
|
| awk '{print $2}' \
|
|
| sed -e 's/"//g' -e 's/,//')
|
|
if [[ -z $link ]]; then
|
|
fail_with "Can't find download link for $version"
|
|
fi
|
|
echo "$link"
|
|
}
|
|
|
|
# downloads runtime distro
|
|
function download_distro() {
|
|
local platform=$1
|
|
local architecture=$2
|
|
local version=$3
|
|
local link=$4
|
|
local download_dir=$JAVA_DOWNLOAD_PATH/$platform/$architecture/$version
|
|
echo "Download link: $link"
|
|
echo "Downloading $JVM_IMPL-$JAVA_DISTRO_TYPE-$version-$platform..."
|
|
rm -rf "$download_dir"
|
|
mkdir -p "$download_dir"
|
|
(cd "$download_dir"
|
|
curl --progress-bar --location --remote-name "$link"
|
|
if [[ $? == 0 ]]; then
|
|
touch $MARKER_DOWNLOADED
|
|
else
|
|
fail_with "Failed to download $JVM_IMPL-$JAVA_DISTRO_TYPE-$version-$platform"
|
|
fi
|
|
)
|
|
}
|
|
|
|
# ensures required distro is in cache
|
|
function ensure_distro_cached() {
|
|
local platform=$1
|
|
local architecture=$2
|
|
local distro_info
|
|
local distro_link
|
|
if [[ -z $PULL ]]; then
|
|
if [[ -z $JAVA_VERSION_OVERRIDEN ]]; then
|
|
if [[ ! $(find_latest_cached $platform $architecture $LATEST_LTS) ]]; then
|
|
distro_info=$(fetch_distro_info $platform $architecture $LATEST_LTS)
|
|
CONCRETE_JAVA_VERSION=$(find_latest_version "$distro_info" $LATEST_LTS)
|
|
distro_link=$(find_distro_link "$distro_info" $CONCRETE_JAVA_VERSION)
|
|
download_distro $platform $architecture $CONCRETE_JAVA_VERSION "$distro_link"
|
|
else
|
|
CONCRETE_JAVA_VERSION=$(find_latest_cached $platform $architecture $LATEST_LTS)
|
|
fi
|
|
else
|
|
if [[ ! $(find_latest_cached $platform $architecture $JAVA_VERSION) ]]; then
|
|
distro_info=$(fetch_distro_info $platform $architecture $JAVA_VERSION_BASE)
|
|
CONCRETE_JAVA_VERSION=$(find_latest_version "$distro_info" $JAVA_VERSION)
|
|
distro_link=$(find_distro_link "$distro_info" $CONCRETE_JAVA_VERSION)
|
|
download_distro $platform $architecture $CONCRETE_JAVA_VERSION "$distro_link"
|
|
else
|
|
CONCRETE_JAVA_VERSION=$(find_latest_cached $architecture $platform $JAVA_VERSION)
|
|
fi
|
|
fi
|
|
else
|
|
if [[ -z $JAVA_VERSION ]]; then
|
|
distro_info=$(fetch_distro_info $platform $architecture $LATEST_LTS)
|
|
CONCRETE_JAVA_VERSION=$(find_latest_version "$distro_info" $LATEST_LTS)
|
|
else
|
|
distro_info=$(fetch_distro_info $platform $architecture $JAVA_VERSION_BASE)
|
|
CONCRETE_JAVA_VERSION=$(find_latest_version "$distro_info" $JAVA_VERSION)
|
|
fi
|
|
if [[ ! $(find_latest_cached $platform $architecture $CONCRETE_JAVA_VERSION) ]]; then
|
|
distro_link=$(find_distro_link "$distro_info" $CONCRETE_JAVA_VERSION)
|
|
download_distro $platform $architecture $CONCRETE_JAVA_VERSION "$distro_link"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# actually ensure required distro is in cache
|
|
for target in ${TARGETS_TO_CACHE[@]}; do
|
|
ensure_distro_cached $target $X64
|
|
done
|
|
|
|
if [[ $THIS_MACHINE == $AARCH64 ]]; then
|
|
ensure_distro_cached $THIS_PLATFORM $AARCH64
|
|
fi
|
|
|
|
UNPACKED_SUBDIR="distro"
|
|
|
|
# ensures required distro uncompressed
|
|
function ensure_distro_unpacked() {
|
|
local platform=$1
|
|
local architecture=$2
|
|
local version=$3
|
|
local download_dir=$JAVA_DOWNLOAD_PATH/$platform/$architecture/$version
|
|
local unpacked_dir=$download_dir/$UNPACKED_SUBDIR
|
|
if [[ ! -e $download_dir/$MARKER_UNPACKED ]]; then
|
|
echo "Uncompressing $JVM_IMPL-$JAVA_DISTRO_TYPE-$version-$platform"
|
|
# removing all leftover directories
|
|
for d in "$download_dir"/* ; do
|
|
if [[ -d $d ]]; then
|
|
rm -rf "$d"
|
|
fi
|
|
done
|
|
case $platform in
|
|
$LIN)
|
|
mkdir -p "$unpacked_dir"
|
|
tar --strip-components=1 -C "$unpacked_dir" -xzf "$download_dir"/*.tar.gz
|
|
;;
|
|
$MAC)
|
|
# to uncompess distro for macOS we need to use wildcards
|
|
# to use wildcards with GNU tar (on Linux) '--wildcard' option is required
|
|
# to use wildcards with BSD tar (on macOS) no options required
|
|
# if invoked with '--wildcards' BSD tar with exit with message:
|
|
# "Option --wildcards is not supported"
|
|
local tar_cmd
|
|
if tar --wildcards 2>&1 | grep "not supported" > /dev/null ; then
|
|
tar_cmd="tar"
|
|
else
|
|
tar_cmd="tar --wildcards"
|
|
fi
|
|
mkdir -p "$unpacked_dir"
|
|
$tar_cmd --strip-components=3 -C "$unpacked_dir" -xzf "$download_dir"/*.tar.gz \
|
|
"jdk*/Contents/Home"
|
|
;;
|
|
$WIN)
|
|
(cd "$download_dir"
|
|
unzip -oq *.zip && mv jdk* $UNPACKED_SUBDIR
|
|
)
|
|
;;
|
|
esac
|
|
if [[ $? == 0 ]]; then
|
|
touch "$download_dir/$MARKER_UNPACKED"
|
|
case $platform in
|
|
$WIN) rm "$download_dir"/*.zip ;;
|
|
*) rm "$download_dir"/*.tar.gz ;;
|
|
esac
|
|
else
|
|
fail_with "Failed to unpack $JVM_IMPL-$JAVA_DISTRO_TYPE-$version-$platform"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# actually ensure required distro uncompressed
|
|
for target in ${TARGETS[@]}; do
|
|
ensure_distro_unpacked $target $X64 $CONCRETE_JAVA_VERSION
|
|
done
|
|
|
|
# actually ensure required distro for build is uncompressed when it is not x64
|
|
if [[ $THIS_MACHINE == $AARCH64 ]]; then
|
|
ensure_distro_unpacked $THIS_PLATFORM $AARCH64 $CONCRETE_JAVA_VERSION
|
|
fi
|
|
|
|
JDK_PATH=$JAVA_DOWNLOAD_PATH/$THIS_PLATFORM/$THIS_MACHINE/$CONCRETE_JAVA_VERSION/$UNPACKED_SUBDIR
|
|
JLINK=$JDK_PATH/bin/jlink
|
|
JDEPS=$JDK_PATH/bin/jdeps
|
|
|
|
# modules are only needed if JDK optimisation is performed
|
|
if [[ $JAVA_DISTRO_TYPE == $DISTRO_TYPE_JDK ]]; then
|
|
echo "Analyzing dependencies..."
|
|
# TODO check for errors
|
|
# TODO If JAVA_VERSION is not an INT it will throw an error
|
|
if [ -n "$CLASS_PATH" ]
|
|
then
|
|
echo "Using given classpaths: $CLASS_PATH"
|
|
MODULES=$($JDEPS --class-path=$CLASS_PATH --print-module-deps --ignore-missing-deps --multi-release $JAVA_VERSION_BASE $JAR | grep -v Warning)
|
|
elif [ "$AUTO_CLASS_PATH" ]
|
|
then
|
|
echo "Extracting jar file to get classpath"
|
|
unzip -q "${JAR}" -d "${EXTRACTED_JAR_PATH}"
|
|
echo "Fetching modules"
|
|
MODULES=$($JDEPS --ignore-missing-deps --print-module-deps --recursive --multi-release $JAVA_VERSION_BASE -quiet --class-path=${EXTRACTED_JAR_PATH}/* --module-path=${EXTRACTED_JAR_PATH}/* $JAR | grep -v Warning)
|
|
else
|
|
echo "Fetch modules with default behavior"
|
|
MODULES=$("$JDEPS" --print-module-deps --ignore-missing-deps --multi-release $JAVA_VERSION_BASE "$JAR" | grep -v Warning)
|
|
fi
|
|
fi
|
|
|
|
# creates minimized runtime for the platform
|
|
function create_optimized_runtime() {
|
|
local platform=$1
|
|
local machine=$2
|
|
local jmods=$JAVA_DOWNLOAD_PATH/$platform/$machine/$CONCRETE_JAVA_VERSION/$UNPACKED_SUBDIR/jmods
|
|
echo "Creating minimal runtime for $platform..."
|
|
"$JLINK" \
|
|
--no-header-files \
|
|
--no-man-pages \
|
|
--strip-debug \
|
|
--module-path "$jmods" \
|
|
--add-modules $MODULES \
|
|
--output "$BUNDLES_PATH/$platform/$machine/$BUNDLED_DISTRO_SUBDIR"
|
|
fail_if $? "Failed to optimize runtime"
|
|
}
|
|
|
|
# creates warp bundle for the platform
|
|
function create_bundle() {
|
|
local platform=$1
|
|
local machine=$2
|
|
|
|
if [[ $SILENT ]] && [[ $platform == $WIN ]]; then
|
|
JAVA_EXEC=javaw
|
|
else
|
|
JAVA_EXEC=java
|
|
fi
|
|
|
|
case $JAVA_DISTRO_TYPE in
|
|
$DISTRO_TYPE_JDK)
|
|
create_optimized_runtime $platform
|
|
;;
|
|
$DISTRO_TYPE_JRE)
|
|
mkdir -p "$BUNDLES_PATH/$platform/$machine/$BUNDLED_DISTRO_SUBDIR"
|
|
cp -r "$JAVA_DOWNLOAD_PATH/$platform/$CONCRETE_JAVA_VERSION/$UNPACKED_SUBDIR"/* \
|
|
"$BUNDLES_PATH/$platform/$BUNDLED_DISTRO_SUBDIR"
|
|
;;
|
|
esac
|
|
case $platform in
|
|
$WIN) print_launcher_cmd > "$BUNDLES_PATH/$platform/$LAUNCHER_NAME.cmd" ;;
|
|
*) print_launcher_bash > "$BUNDLES_PATH/$platform/$LAUNCHER_NAME.sh"
|
|
chmod +x "$BUNDLES_PATH/$platform/$LAUNCHER_NAME.sh"
|
|
;;
|
|
esac
|
|
cp "$JAR" "$BUNDLES_PATH/$platform/"
|
|
}
|
|
|
|
# remove old bundles
|
|
rm -rf "$BUNDLES_PATH"
|
|
# actually create bundles for all targets
|
|
for target in ${TARGETS[@]}; do
|
|
create_bundle $target
|
|
done
|
|
|
|
# creates binaries and archives for all targets
|
|
function warp_targets() {
|
|
mkdir -p "$WARPED_PATH"
|
|
|
|
if [[ ${TARGETS[*]} == *"$LIN"* ]]; then
|
|
echo "Warping for $LIN..."
|
|
mkdir -p "$WARPED_TEMP_PATH/$LIN"
|
|
warp-packer \
|
|
--arch linux-x64 \
|
|
--input_dir "$BUNDLES_PATH/$LIN" \
|
|
--exec "$LAUNCHER_NAME.sh" \
|
|
--output "$WARPED_TEMP_PATH/$LIN/$APP_NAME" \
|
|
>&2
|
|
fail_if $? "Failed to warp for $LIN"
|
|
echo "Archiving for $LIN..."
|
|
tar -C "$WARPED_TEMP_PATH/$LIN" -czf "$WARPED_TEMP_PATH/$APP_NAME-$LIN-x64.tar.gz" "$APP_NAME"
|
|
fail_if $? "Failed to make archive for $LIN"
|
|
mv "$WARPED_TEMP_PATH/$LIN/$APP_NAME" "$WARPED_PATH/$APP_NAME-$LIN-x64"
|
|
mv "$WARPED_TEMP_PATH/$APP_NAME-$LIN-x64.tar.gz" "$WARPED_PATH"
|
|
rmdir "$WARPED_TEMP_PATH/$LIN"
|
|
fi
|
|
|
|
if [[ ${TARGETS[*]} == *"$MAC"* ]]; then
|
|
echo "Warping for $MAC..."
|
|
mkdir -p "$WARPED_TEMP_PATH/$MAC"
|
|
warp-packer \
|
|
--arch macos-x64 \
|
|
--input_dir "$BUNDLES_PATH/$MAC" \
|
|
--exec "$LAUNCHER_NAME.sh" \
|
|
--output "$WARPED_TEMP_PATH/$MAC/$APP_NAME" \
|
|
&> /dev/null
|
|
fail_if $? "Failed to warp for $MAC"
|
|
echo "Archiving for $MAC..."
|
|
tar -C "$WARPED_TEMP_PATH/$MAC" -czf "$WARPED_TEMP_PATH/$APP_NAME-$MAC-x64.tar.gz" "$APP_NAME"
|
|
fail_if $? "Failed to make archive for $MAC"
|
|
mv "$WARPED_TEMP_PATH/$MAC/$APP_NAME" "$WARPED_PATH/$APP_NAME-$MAC-x64"
|
|
mv "$WARPED_TEMP_PATH/$APP_NAME-$MAC-x64.tar.gz" "$WARPED_PATH"
|
|
rmdir "$WARPED_TEMP_PATH/$MAC"
|
|
fi
|
|
|
|
if [[ ${TARGETS[*]} == *"$WIN"* ]]; then
|
|
echo "Warping for $WIN..."
|
|
mkdir -p "$WARPED_TEMP_PATH/$WIN"
|
|
warp-packer \
|
|
--arch windows-x64 \
|
|
--input_dir "$BUNDLES_PATH/$WIN" \
|
|
--exec "$LAUNCHER_NAME.cmd" \
|
|
--output "$WARPED_TEMP_PATH/$WIN/$APP_NAME.exe" \
|
|
&> /dev/null
|
|
fail_if $? "Failed to warp for $WIN"
|
|
if command -v zip &> /dev/null ; then (
|
|
echo "Archiving for $WIN..."
|
|
cd "$WARPED_TEMP_PATH/$WIN"
|
|
zip -r "$WARPED_TEMP_PATH/$APP_NAME-$WIN-x64.zip" "$APP_NAME.exe" &> /dev/null
|
|
fail_if $? "Failed to make archive for $WIN"
|
|
mv "$WARPED_TEMP_PATH/$APP_NAME-$WIN-x64.zip" "$WARPED_PATH"
|
|
) else
|
|
warn "'zip' not found, will skip creation of archive for windows"
|
|
fi
|
|
mv "$WARPED_TEMP_PATH/$WIN/$APP_NAME.exe" "$WARPED_PATH/$APP_NAME-windows-x64.exe"
|
|
rmdir "$WARPED_TEMP_PATH/$WIN"
|
|
fi
|
|
|
|
rmdir "$WARPED_TEMP_PATH"
|
|
}
|
|
|
|
# actually create binaries and archives for all targets
|
|
warp_targets |