TheInfiniteKind/appbundler

How do I create a Universal Build with embedded jres

Opened this issue · 4 comments

ijabz commented

HI, I am using the latest version of appbundler and building on a Mac M1 with an embedded cut down jre using the jlink option. Its works on my Mac M1 but unsuprisngly not on my Intel Mac because im not embedding an intel jre as well, but how do I do that, is it possible, there are no examples to show this.

Also have a question open on Stackoverflow if that is a better place for this question https://stackoverflow.com/questions/71664933/building-a-universal-appbunder-build-for-java-on-macos-m1-machine

This is a fantastic question, and I'd love to hear the answer so have upvoted the question on stack overflow. I suspect that it would involve combining each intel and arm dylib to make them all universal, but I'd bet there's a lot more to it than that. If you find out, please to post here with the result!

@ijabz Did you ever get this to work? I think the suggestion in the Stack Overflow post is reasonable, just have 2 embedded JDKs live side-by-side in the Plugins directory. However, I would imagine we also need to change

NSString *runtimePath = [[mainBundle builtInPlugInsPath] stringByAppendingPathComponent:runtime];
so that it loads from the correct plugin location depending on whether you're running on x86 or ARM.

I kind of sidestepped this by building a universal JRE from the two architecture-specific ones from Adoptium using the bash Script from https://incenp.org/notes/2023/universal-java-app-on-macos.html . Cuts down on download size too, since the binaries are combined and also the non-native-code parts are shared.

I did something similar, but adapted the script a bit. Now when I build the embedded JREs with jlink, I combine an amd64 and aarch64 JRE using the following script:

#!/bin/bash

# Script to combine an intel and arm64 JDK into a single universal JDK
# originally sourced from https://incenp.org/notes/2023/universal-java-app-on-macos.html

source build_settings

[ -f jvm-mac/Contents/Home/lib/libjava.dylib ] || die "Missing intel JRE"
[ -f jvm-macarm/Contents/Home/lib/libjava.dylib ] || die "Missing arm64 JRE"

echo "Creating universal JRE..."
rm -rf jvm-macuniversal
mkdir jvm-macuniversal
find jvm-macarm -type f | while read arm_file ; do
    noarch_file=${arm_file#jvm-macarm/}
    mkdir -p jvm-macuniversal/${noarch_file%/*}
    if file $arm_file | grep "Mach-O.\+arm64" ; then
        # Create universal binary from both x86_64 and arm64
        lipo -create -output jvm-macuniversal/$noarch_file jvm-mac/$noarch_file $arm_file
        if file $arm_file | grep executable ; then
            chmod 755 jvm-macuniversal/$noarch_file
        fi
    else
        # Not a file with binary code, copy it as it is
        cp $arm_file jvm-macuniversal/$noarch_file
    fi
done

echo "Packaging the JRE..."
(cd jvm-macuniversal/Contents
 rm -rf MacOS _CodeSignature)

I'd be happy to include it with appbundler, but it seems sensible for it to be invoked separately as part of the JRE building process. Feel free to copy it though.