A means of bootstrapping Java Packages Tools.
In a nutshell, Java Packages Bootstrap (JPB) is a standalone build of all Java software packages that are required for Java Packages Tools (JPT) to work.
JPT provides packagers with numerous RPM macros and tools to make Java
packaging simpler and easier. While it implements some of its simpler
functionality in shell and Python, it relies on external Java packages
for most of heavy lifting work. Notably, %mvn_build and %mvn_install
RPM macros, which are the essence of JPT, are just thin wrappers for
XMvn, which is written in Java.
In order to achieve reliable and reproducible builds of Java packages while meeting Fedora policy that requires everything to be built from source, without using prebuilt binary artifacts, it is necessary to build the packages in a well-defined, acyclic order. Dependency cycles between packages are the biggest obstacle to achieving this goal and JPT is the biggest offender -- it requires more than a hundred of Java packages, all of which in turn build-require JPT.
JPB comes with a solution to this problem -- it builds everything that JPT needs to work, without reliance on any Java software other than OpenJDK. JPT can depend on JPB for everything, without depending on any other Java packages. For example, JPB contains embedded version of XMvn, removing dependency of JPT on XMvn, allowing JPT to be used before one builds XMvn package.
-
mbi- code of MBI, custom build system for javapackages-bootstrap. -
project- project descriptors,*.propertiesare upstream descriptors,*.xmlare build descriptors. -
upstream- cache of pristine upstream sources (git repos or zipballs). -
patches- downstream patches in git format. -
downstream- upstream sources with problematic files removed and downstream patches applied. -
build- results of the build. -
eclipse- holds generated Eclipse projects that can be imported into Eclipse IDE.
Most of Java build systems are complex software projects with numerous external dependencies. For the purpose of bootstrapping Java packages a minimalistic build system was created.
The core part of MBI has no external dependencies. Additional extension tools can have dependencies, but MBI is responsible for building them from sources before particular tool can be used.
MBI has two basic concepts, project and module. Project corresponds to a single upstream project -- typically a single git repository. Module corresponds to a single binary artifact. More than one module can be built from sources of the same project.
For each project there is a properties file in project directory
that links that project with corresponding upstream project. That
file is called project descriptor, or upstream descriptor.
Project descriptor has the following properties defined:
-
version- version of upstream project. -
type- determines the form in which upstream sources are fetched, can be eithergit(default; sources are obtained by cloning a Git repository) orzip(sources are downloaded as a ZIP file). -
url- URL of Git repo or ZIP file to get the sources from. -
ref- Git ref (commit ID, tag or branch) within Git repo to get sources from.
Each module is described by an XML file in project directory that
specifies dependencies between modules and describes how to build
particular module.
For the sake of simplicity MBI doesn't distinguish between different dependency scopes (such as runtime vs build dependencies) and doesn't support transitive dependencies - all dependencies must be listed explicitly.
Each module build is split into build steps. Each build step involves a single invocation of MBI tool on the module. One tool can be invoked more than once on the same module, in different build steps.
MBI provides the following tools that can be used as build steps:
-
compiler- invokes Java compiler to compile Java source files into Java bytecode. -
modello- invokes Modello tool to generate code from data models. -
sisu- JSR-330 indexer, searches compiled classes for JSR-330 components annotated withjavax.inject.Namedand generates Sisu index for them, allowing Sisu to use these components for dependency injection. -
plexus- Plexus component descriptor creator, extracts Plexus component descriptors from Javadoc comments or Java annotations, enabling Plexus to discover and load components implemented by the module. -
pdc- plugin descriptor creator, invokes Maven Plugin Tools to generate plugin descriptors, allowing module to be used as a Maven plugin. -
pom- transforms Maven POM and includes it as output artifact. -
ant- executes arbitrary Ant tasks.
First you need to obtain pristine upstream sources of all projects
that will be built. That can be done with the clone command:
./downstream.sh clone. It may take 10 or more minutes to complete,
depending on your network speed. That command reads upstream
descriptors and fetches upstream sources, either by cloning Git
repositories or downloading appropriate ZIP archives with the sources.
Once the command completes it will create upstream directory.
Once you have the upstream sources, you'll need to generate downstream
sources based on upstream sources. This is done by executing the prep
command: ./downstream.sh prep. This command will create downstream
directory with patched upstream sources that are ready to be built.
Modules are built by executing ./mbi.sh build command. It allows the
environment variable JAVA_HOME to be set and pointed to JDK installation
which will be used (e. g. /usr/lib/jvm/java-21). The minimal required
version of JDK is 21.
The build command accepts a few options:
-
-incrementalor-ito skip building modules that have already been built, -
-parallelor-jto use multiple threads to execute independent build steps in parallel and -
-keepGoingor-kif you want MBI not to stop the build after first failure, but rather continue and build as many projects as possible.
Once the build is done you can create binary distribution with the
dist command, ./mbi.sh dist. That command accepts several options
that allow you to control the shape and the location of binary
distribution:
-
-javaCmdPathpoints tojavaexecutable, for use in launcher shebangs (defaults to/usr/lib/jvm/java-21). -
-installRootspecifies directory into which distribution will be installed (equivalent to$RPM_BUILD_ROOTin RPM build), by default it's system root directory/. -
-mavenHomePathspecifies the directory into which XMvn will be installed (/usr/share/xmvnin Fedora). -
-artifactsPathspecifies where produced binary artifacts should be installed (/usr/share/javain Fedora). -
-basePackageNamespecifies package name to be used as subdirectory of artifact paths. -
-metadataPathpoints to directory for installing accompanying Javapackages metadata files (/usr/share/maven-metadada). -
-launchersPathspecifies where executable binary launches should be installed (/usr/bin). -
-licensesPathspecifies where license files should be installed (/usr/share/licenses).
Additionally there is ./mbi.sh graph command which is used to directly
output the dependency graph of the modules in the .dot format. An .svg
diagram can be obtained by executing the following chain of commands:
./mbi.sh graph | tred | dot -Tsvg > graph.svg
That creates the following diagram:
Java Packages Bootstrap is free software. You can redistribute and/or modify it under the terms specified in the LICENSE file. This software comes with ABSOLUTELY NO WARRANTY.