Skip to content

User-installable BEAST.base / BEAST.app packages (off the boot module path)#95

Merged
walterxie merged 6 commits into
masterfrom
installable-core-packages
Jun 16, 2026
Merged

User-installable BEAST.base / BEAST.app packages (off the boot module path)#95
walterxie merged 6 commits into
masterfrom
installable-core-packages

Conversation

@alexeid

@alexeid alexeid commented Jun 15, 2026

Copy link
Copy Markdown
Member

Makes BEAST.base and BEAST.app user-installable packages and loads them from the user package directory, so the package manager can upgrade them in place. Builds on master's #94 fix (BEAST.app is registered as a core package there).

Changes

Packaging

  • Splits root version.xml into a clean BEAST.base descriptor and a new beast-fx/version.xml (BEAST.app), moving the FX service blocks + packageapp entries out of BEAST.base. beast-fx.jar embeds its version.xml.
  • maven-assembly descriptors produce BEAST.base.package.v*.zip (beast-base.jar + its third-party deps, no beast-pkgmgmt) and BEAST.app.package.v*.zip (beast-fx.jar + version.xml only; beast-base, beast-pkgmgmt and JavaFX are provided at runtime).

Module-layer resolution

  • createAndRegisterModuleLayer() parents each package layer on boot + all previously-registered plugin layers (was boot only), so a package can read modules from another package's layer (e.g. beast.fxbeast.base). Backward-compatible — boot remains a parent. Covered by ModuleLayerCrossDependencyTest.

Core loaded from the user dir (Mac)

  • BeastLauncher.seedBundledPackage() extracts a bundled <app>/packages/<pkg>.package*.zip into the user package dir, version-aware (a same-or-newer user copy is preserved). getPath() seeds both core packages, with the legacy single-jar copy as the dev/IDE fallback.
  • build-sign-dmg.sh keeps beast-base/beast-fx off the boot module path and bundles both package zips in the app image; on first launch they seed into the user dir and load as plugin module layers, so the package manager can upgrade them in place. beast-pkgmgmt and third-party deps stay on boot. JavaFX + jdk.jsobject are named in the runtime --add-modules so the bundled JRE+FX modules resolve into the boot layer, where the beast.fx plugin layer reads them (needed because beast.fx, which used to pull them in, is no longer on boot).

Startup loading

  • loadExternalJars no longer network-auto-installs BEAST.app or hard-fails when it is missing (both unreachable given the synthetic registration, and they put a network call and a hard crash on the universal startup path). checkInstalledDependencies runs after all packages load, so dependencies resolved via plugin layers are not flagged as missing.

Tests: CorePackagesInstalledTest, SeedBundledPackageTest, ModuleLayerCrossDependencyTest (full beast-pkgmgmt suite green, 43 tests).

Testing plan for @walterxie

#94 regression./bin/packagemanager -list shows BEAST.app installed; -add SSM / BDMM-Prime resolve and install.

Package zipsmvn -DskipTests packageBEAST.app zip is beast-fx.jar + version.xml; BEAST.base zip is beast-base.jar + third-party deps with no beast-pkgmgmt/JavaFX.

Runtime gate (needs a DMG build + launch)release/Mac/build-sign-dmg.sh, then ./bin/beast -validate <xml> and launch BEAUti. Confirm beast.fx loads from a plugin layer (reading JavaFX from the boot layer), and ~/Library/Application Support/BEAST/2.8/{BEAST.base,BEAST.app} are seeded. Upgrade check: bump a user-dir version.xml/jar and confirm it is picked up after restart.

Remaining (not in this PR)

  • CBAN + standalone JavaFX: add BEAST.base/BEAST.app entries to packages2.8.xml and host the zips. The BEAST.app zip carries no JavaFX (the app image provides it via the JRE+FX), so a standalone/CBAN install on a plain JRE needs JavaFX provided separately, per platform.
  • Linux/Windows: apply the same boot-path + --add-modules change to those release scripts.

alexeid added 4 commits June 16, 2026 10:33
Split the entangled root version.xml into a clean BEAST.base descriptor
and a new BEAST.app descriptor (beast-fx/version.xml), moving the FX
service blocks and packageapp entries out of BEAST.base. Embed the
BEAST.app descriptor in beast-fx.jar (mirroring beast-base), and add
maven-assembly descriptors producing BEAST.base.package.v*.zip and
BEAST.app.package.v*.zip with a correct lib/ split: BEAST.base carries
its third-party deps but not beast-pkgmgmt; BEAST.app carries beast-fx
plus JavaFX only, relying on BEAST.base for the rest.

The package id is kept as BEAST.app (not BEAST.fx) for backward
compatibility with existing <depends on="BEAST.app"> declarations.
createAndRegisterModuleLayer built each package's layer with the boot
layer as its only parent, so a package's module dependency could be
resolved only when that dependency was on the boot module path. Build
each layer with boot plus all previously-registered plugin layers as
parents, so a package can read modules provided by other packages
(e.g. beast.fx requires beast.base once the core modules are no longer
on the boot path). Backward-compatible: boot remains a parent. Covered
by ModuleLayerCrossDependencyTest.
Add BeastLauncher.seedBundledPackage(), which extracts a bundled
<app>/packages/<pkg>.package*.zip into the user package dir, version-aware
(a same-or-newer user copy is preserved). getPath() seeds both core
packages, falling back to the legacy single-jar copy in dev/IDE runs.
build-sign-dmg.sh removes beast-base/beast-fx from the boot module path
and bundles both package zips in the app image; on first launch they are
seeded into the user dir and load as plugin module layers, so the package
manager can upgrade them in place. beast.fx requires beast.base, so both
move together; beast-pkgmgmt and third-party deps stay on boot, JavaFX is
provided by the bundled JRE+FX. package.path is already invalidated on
install/uninstall.

Runtime-unverified: needs a DMG build + BEAUti launch to confirm beast.fx
works from a plugin layer reading boot JavaFX. Covered by
SeedBundledPackageTest and CorePackagesInstalledTest.
The synthetic BEAST.app registration in addInstalledPackages() always
marks it installed, so the follow-up network auto-install and the
RuntimeException hard-fail in loadExternalJars were unreachable in every
normal path while wiring a network call and a hard crash into the
universal startup sequence (and conceptually requiring the GUI layer for
headless runs). Remove both; keep the genuinely useful part -- deferring
checkInstalledDependencies until after all packages are loaded so deps
resolved via plugin layers are not flagged as missing.

A real BEAST.app load failure now surfaces naturally (e.g. main class not
found) rather than being masked by a synthetic-installed flag.
@alexeid alexeid force-pushed the installable-core-packages branch from 7acf9f3 to dda2d83 Compare June 15, 2026 22:36
@alexeid alexeid changed the title Installable BEAST.base / BEAST.app packages + fix #94 (unknown package BEAST.app) User-installable BEAST.base / BEAST.app packages (off the boot module path) Jun 15, 2026
@walterxie

walterxie commented Jun 16, 2026

Copy link
Copy Markdown
Member

The developer version works, but the Mac release is broken. I think you need to keep core jars,  and when I commented out rm -f "$STAGING"/beast-base-*.jar "$STAGING"/beast-fx-*.jar , everything in Mac release works again, but if I uncommeted it, Mac release is broken.

To replicate:

cd $beast3/release/Mac/
# rm dmg-staging
rm -rf dmg-staging
./build-sign-dmg.sh

# clean the lib path
rm -rf  ~/Library/Application\ Support/BEAST/2.8

# go to release version
cd dmg-staging/BEAST 2.8.0
# use released script to test
./bin/beast -validate ~/WorkSpace/beast3/beast-base/src/test/resources/beast.base/examples/testHKY.xml

alexeid added 2 commits June 16, 2026 12:46
…t-fx.jar

Removing beast-fx from the boot module path also removed JavaFX from the
boot layer -- JavaFX was only resolved there because beast.fx (on boot)
required it and pulled it out of the bundled JRE+FX. With beast.fx gone the
BEAST.app plugin layer could not find JavaFX, so beast.fx failed to load
(ClassNotFoundException: beastfx.app.beast.BeastMain).

- Add javafx.controls/fxml/swing/web + jdk.jsobject to the runtime
  --add-modules so the JRE+FX modules resolve into the boot layer, where the
  beast.fx plugin layer reads them (transitive graphics/base/media follow).
- Drop JavaFX from the BEAST.app package zip: it carried both the empty
  automatic-module jars and the platform jars, and the empty ones fail
  resolution ('javafx.graphics not found'); JavaFX comes from the JRE+FX
  anyway. The zip is now beast-fx.jar + version.xml.
The wrapper .app/.bat/shell launchers and the Windows .cfg patch launched
with `--add-modules ALL-MODULE-PATH` only. Since the bundled JRE+FX provides
JavaFX as platform modules and the javafx jars were dropped from the module
path, ALL-MODULE-PATH no longer pulls JavaFX into the module graph, so the
beast.fx plugin layer (which requires javafx.*) fails to resolve and the GUI
tools die silently on launch — BEAUti/TreeAnnotator/LogCombiner/AppLauncher on
all platforms, plus BEAST itself on Windows.

Name javafx.controls/fxml/swing/web + jdk.jsobject explicitly in --add-modules,
matching what BEAST.cfg already does for the jpackage launcher.
@walterxie walterxie merged commit a9072d1 into master Jun 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants