User:Arthurzam/OpenJDK Bootstrap

From Gentoo Wiki
Jump to:navigation Jump to:search

Bootstrapping dev-java/openjdk is a lengthy process. Each OpenJDK version X needs existing version X or X-1. For our users on some arches, where we can't provide dev-java/openjdk-bin, it means the users need to have some sort of bootstrap binary provided by us. We have a special process for creating those bootstrap binaries.

Finding bootstrap origin

We need to find a source for initial bootstrap itself:

  1. Use binary from other distributions. Collect all parts of openjdk from another distribution and unpack into some place (preferably inside /usr/lib). Extract all parts just so we don't need to find what is needed or missing - this is used just as a part of process, so no need to be minimalist. Try to run bin/java from that directory, and check that no missing shared libraries are requested. You may want to preinstall all dependencies of dev-java/openjdk. Then edit manually the ebuild. You will need to remove the dependencies on slotted openjdk, edit the pkg_setup function, so it will look something like (note that ${JDK_HOME}/bin/java should exist)ː
    pkg_setup() {
    	openjdk_check_requirements
    	java-vm-2_pkg_setup
    	export JDK_HOME="/usr/lib/jvm/openjdk-11"
    }
    
    And hope that everything works (it most definitely can fail).
  2. Bootstrap from previously built openjdk or dev-java/icedtea or dev-java/icedtea-bin. In this case we will need to traverse across major versions, one by one (8 to 9 to ... to 17 for example). We should use the gentoo-bootstrap overlay, which holds ebuilds for all those intermediate openjdk versions. You can enable it usingː
root #emerge -1a -j4 app-eselect/eselect-repository dev-vcs/git
root #eselect repository enable gentoo-bootstrap
root #emerge --sync
  1. Bootstrap from nothing. In case you don't have anything to base on, and you must support this arch (are you really sure?), here is a theoretical possibility to use bootstrap from nearly nothing, shown in gentoo-bootstrap overlay. I have tried it once for ppc64-musl, it failed, and I never tried it again. It might work for you (please update me).

Bootstrapping

I recommend to use a new container with clean stage3.

Important
Try to use the oldest glibc version you can. It is impossible to safely downgrade glibc (at least for the time when this was written), so you are now setting the minimal glibc version for the bootstrap tarball users.

Prepare the profile & dependencies' USE flagsː

root #mkdir -p /etc/portage/profile
root #echo "dev-java/openjdk ~${ARCH}" >>/etc/portage/package.accept_keywords/openjdk
root #echo 'media-libs/libglvnd X' >> /etc/portage/package.use/bootstrap
root #echo 'app-text/ghostscript-gpl cups' >> /etc/portage/package.use/bootstrap
root #echo 'x11-libs/cairo X' >> /etc/portage/package.use/bootstrap

Install all dependencies of openjdk needed (if it complains about cyclic dependency between same slot openjdk, edit the ebuild to remove those).

Prepare the binary package for openjdk (edit the wanted slot)ː

user $XPAK_BOOTSTRAP="bundled" USE="jbootstrap" emerge -1a --buildpkg=y dev-java/openjdk:11

Now you should have a built binary package, which we can convert into bootstrap tarball, using the following scriptː

CODE /usr/local/bin/prepare-openjdk-bootstrap.sh
#!/bin/bash -e

OLD_PWD=${PWD}
source /lib/gentoo/functions.sh || true

if [ -z "$1" ]; then
    echo "usage: $0 /var/cache/binpkgs/dev-java/openjdk-X.X.X.X.tbz2 [-rX]"
    exit 1
fi

TBZ2=$(realpath -e "$1")

ebegin "Reading package environment"
eval "$(qtbz2 -O -x "${TBZ2}" | qxpak -O -x /dev/stdin environment.bz2 | bunzip2)"
eend $?

ebegin "Creating temporary directory"
TMP=$(mktemp --tmpdir -d icedtea.XXXXXXXXXX)
trap 'rm -rf "${TMP}"' EXIT
cd "${TMP}"
eend $?

ebegin "Extracting package files"
qtbz2 -O -t "${TBZ2}" | tar -x --zstd
eend $?

LIB=usr/$(get_libdir)/${PN}-${SLOT}

case "${CHOST%%-*}" in
    powerpc*le) abi=${ABI}le ;;
    *) abi=${ABI} ;;
esac

use() {
    local re="\b${1}\b"
    [[ ${USE} =~ ${re} ]]
}

do_tar() {
    local DIR=${PN}-bootstrap-${PV}
    [[ $1 = *-${abi} ]] && DIR+=-${ABI}

    TARBALL=${PN}-bootstrap-$1-${abi}.tar.xz
    shift

    ebegin "Creating ${TARBALL}"

    tar Jcf "${OLD_PWD}/${TARBALL}" \
        --owner=root --group=root \
        --transform="s:^${LIB}:${DIR}:x" \
        --remove-files \
        "${@}"

    eend $?
}

do_tar "${PV}${2}" "${LIB}"


And then run this script over the generated tarball (fix the version values)ː

user $prepare-openjdk-bootstrap.sh /var/cache/binpkgs/dev-java/openjdk-X.X.X.X.tbz2
Important
If you used a binary from another distribution, rerun the bootstrap process again with newly build bootstrap tarball, so we minimize the potential effects of that binary.

Uploading and Enabling

  1. Upload the tarball. Currently the ebuild code is planned to download from arthurzam's devspace, but maybe we can improve it in future.
  2. You should add an global variable for your new tarball version. You should use ${ARCH^^}_XPAK format for it.
  3. Insert the tarball to SRC_URI using a call to the bootstrap_uri function (which is a nice exercise in bash environment conditional expansion).


Now is the hard part, keywording and masking. You want to keyword the ebuild for the arch, but mask it for all profiles under the arch which aren't supported. Then unmask for supported profiles and unforce system-bootstrap USE flag. Look at existing examples in tree to see examples for it. I very recommend to create a separate branch and open a PR, and call for another dev to review it, and also run CI over it. It is very easy to breakǃ