Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/core.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
config,
...
}: {
imports = [inputs.sops-nix.nixosModules.sops self.nixosModules.patches self.nixosModules.compat];
imports = [inputs.sops-nix.nixosModules.sops self.nixosModules.patches self.nixosModules.compat self.nixosModules.java];

options.stars = {
mainUser = lib.mkOption {
Expand Down
4 changes: 4 additions & 0 deletions modules/hosts/lyra/configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@
efiSupport = true;
device = "nodev"; # "nodev" for UEFI
theme = pkgs.minimal-grub-theme;
# /boot is only 511M; without a limit GRUB keeps every generation's
# kernel+initrd (~100M each) and fills the ESP. Cap the menu so old
# boot files get pruned on each rebuild.
configurationLimit = 10;
};
efi.canTouchEfiVariables = true;
};
Expand Down
120 changes: 120 additions & 0 deletions modules/pkgs/java/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
This directory serves as a testing ground for complete Java bootstrap from
source. I will probably setup an overlay which *will* make me cache miss a lot
of packages in nixpkgs.
Doing this for the love of the game.

BLOB AUDIT (per-package)
------------------------
Packages are checked at the git tag used in the bootstrap build. "blob" means
a precompiled binary in the source tree; "test-only" means it is not on any
production compile classpath.

commons-cli 1.10.0 — clean
commons-io 2.20.0 — test-only .bin fixtures; not touched by our build
commons-lang 2.6 — clean
commons-lang3 3.19.0 — clean
jspecify 0.3.0 — gradle-wrapper.jar (wrapper, never invoked)
jsoup 1.17.2 — gradle-wrapper.jar (wrapper, never invoked)
java-hamcrest 3.0 — gradle-wrapper.jar (wrapper, never invoked)
junit4 4.13.2 — maven-wrapper.jar + lib/hamcrest-core-1.3.jar;
neither is used: our build passes -classpath
explicitly and never invokes the Maven wrapper
plexus-classworlds 2.8.0 — test-data/*.jar (test fixtures only)
plexus-utils 3.5.1 — clean
plexus-containers 2.2.0 — clean
plexus-interpolation 1.27 — clean
plexus-cipher 2.0 — clean
plexus-sec-dispatcher 2.0 — clean
javax.inject 1.0.5 — clean
jsr250-api / common-annotations-api 1.3.5 — clean
cdi-api 2.0.2 — clean
guava 32.1.3 — gradle-wrapper.jar in integration-tests/ subdir
guice 5.1.0 — clean
slf4j 1.7.36 — integration/lib/*.jar; "integration" is a
separate reactor module not needed for
slf4j-api or slf4j-simple
sisu 0.3.2 — test resources only (*.jar / *.class in
src/test/resources)
maven-wagon 3.5.3 — clean
modello 2.4.0 — clean
maven-resolver 1.9.22 — demo.jar in demo-snippets (not a build dep)
Maven 3.3.9 — all blobs are in src/test/resources except one:
maven-ant-tasks-2.1.1.jar at the repo root,
referenced only by build.xml (the Ant-based
build path). The Maven-based bootstrap never
invokes build.xml so this blob is inert.
junit 3.8.2 — no git repo; sourced from Maven Central -sources.jar
(same as aopalliance). No blobs in the sources.jar.
xml-apis 1.3.04 — no git repo; sourced from Maven Central -sources.jar.
No blobs in the sources.jar.
xercesImpl 2.9.1 — clean (2.9.0 had no source tarball; 2.9.1 used instead)
commons-logging 1.1.3 — clean
commons-codec 1.6 — clean
httpcore 4.3.2 — clean
httpclient 4.3.5 — clean

KNOWN BLOB ISSUES
-----------------
ant_1_7: RESOLVED. bootstrap.sh hardcoded lib/xercesImpl.jar, lib/xml-apis.jar,
ant-antunit-1.0.jar, and junit-3.8.2.jar on the javac classpath.
postPatch removes all four blobs. xercesImpl and xml-apis are replaced by
from-source builds (xerces_j 2.9.1 and xml-apis 1.3.04) copied to lib/; dist-lite
then ships them in the output distribution. The junit blob is replaced by junit_3
(built from source) copied to lib/optional/; check_for_optional_packages finds
junit.present=true and compiles JUnitTask against it. ant-antunit is not replaced
(not needed for the bootstrap).
postInstall verifies: JUnitTask present in ant-junit.jar, xercesImpl-*.jar and
xml-apis-*.jar present in $out/share/ant/lib/.

ant 1.10.15: postPatch evicts junit/hamcrest from lib/optional, but
ant-antunit-1.4.1.jar is left behind. build.sh passes -lib lib/optional to
bootstrap ant, so antunit lands on the compile classpath for AntUnit tasks.

SOURCE PROVENANCE ISSUES
------------------------
aopalliance 1.0: No public git repository exists. Fedora's javapackages-
bootstrap sources it directly from Maven Central as a -sources.jar archive.
This is the only package in the graph without a proper VCS origin.

Eclipse Aether 1.0.2: The original source lived at eclipse.org Gerrit (now
retired). The apache/maven-resolver GitHub repo begins at 2.0.0 and does
not contain the 1.0.x history. Building Aether 1.0.2 from source requires
fetching the eclipse.org source tarball (available on Maven Central as
-sources.jar) or switching to a newer maven-resolver release for Maven 3.5+.

BOOTSTRAP CHAIN NOTES
---------------------
wagon-http 2.10: pom lists httpclient:4.3.5, httpcore:4.3.2, and
commons-logging:1.1.3 as direct compile deps. httpclient additionally
requires httpcore, commons-logging, and commons-codec:1.6 (all compile
scope). All four HttpComponents nodes are now in the graph and are leaves
(no compile deps beyond javac itself).

logback-core / logback-classic 1.0.7: all non-core deps (janino, jansi,
groovy, servlet-api, JavaMail, JMS spec) are declared <optional>true</optional>
in pom. A minimal javac build that excludes those source files compiles
cleanly with only SLF4J-API and logback-core — no new nodes needed.

commons-lang 2.6 / commons-io 2.20.0: NOT compile deps of any Maven 3.3.9
core module, but ARE needed by the Wagon 2.10 transport layer:
commons-lang → wagon-file, wagon-http-shared
commons-io → wagon-http-shared
wagon-http-shared in turn feeds wagon-http, which is bundled in the Maven
distribution. So both are necessary for a complete Maven 3.3.9 bootstrap.

jsoup: wagon-http-shared 2.10 pom specifies jsoup:1.7.2 (compile scope);
jsoup 1.7.2 is a pure leaf (no compile deps). Our overlay ships 1.17.2,
which adds jspecify as a provided (annotation-only) compile dep but is
otherwise API-compatible for wagon's use. JSOUP → WAG_HTSH edge is now
in the graph.

MAVEN VERSION NOTES
-------------------
Maven 3.3.9 uses guice:4.0:no_aop (the classifier that strips bytecode
weaving), so ASM and cglib are NOT required for the bootstrap despite being
listed as compile deps in the full guice pom.

Maven 3.3.9 uses plexus-cipher:1.7 and plexus-sec-dispatcher:1.3 under the
org.sonatype.plexus groupId (now moved to codehaus-plexus). The newer
codehaus releases (cipher:2.0, sec-dispatcher:2.0) are API-compatible
drop-in replacements and are what javapackages-bootstrap targets.
77 changes: 77 additions & 0 deletions modules/pkgs/java/ant/_package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
lib,
stdenv,
fetchurl,
jdk,
makeWrapper,
junit_4,
java-hamcrest,
}:
# Built from source (nixpkgs ships ant as a binary distribution). build.sh
# first bootstraps a minimal ant with javac, then drives the full build with
# that bootstrap ant. The JUnit optional tasks and the test jar are compiled
# against JUnit, which the build discovers on the classpath via lib/optional;
# we swap the pre-built binaries shipped there for our from-source junit_4 and
# java-hamcrest. JUnit 5 (junitlauncher) stays absent, so those tasks are
# skipped — junit_4 is enough for a JUnit 4 capable ant.
stdenv.mkDerivation (finalAttrs: {
pname = "ant";
version = "1.10.15";

src = fetchurl {
url = "mirror://apache/ant/source/apache-ant-${finalAttrs.version}-src.tar.bz2";
hash = "sha256-WPU+khKoAFW/FOknicf1BCBqs1uLw5dfo7cocg2A79c=";
};

nativeBuildInputs = [
jdk
makeWrapper
];

postPatch = ''
# Replace the binary JUnit/Hamcrest jars shipped in the source tree with our
# from-source builds. build.sh adds lib/optional to the build classpath, so
# the JUnit tasks and tests compile against these. Our java-hamcrest is a
# single merged jar (vs upstream's split core/library 1.3 jars).
rm -f lib/optional/junit-*.jar lib/optional/hamcrest-*.jar
cp ${junit_4}/share/java/junit-*.jar lib/optional/
cp ${java-hamcrest}/share/java/hamcrest-*.jar lib/optional/
'';

buildPhase = ''
runHook preBuild

# build.sh bootstraps with javac if needed, then runs the bootstrap ant on
# the default `main` target, producing a minimal distribution in ./dist.
sh build.sh

runHook postBuild
'';

installPhase = ''
runHook preInstall

mkdir -p $out/share/ant
cp -r dist/* $out/share/ant/
rm -rf $out/share/ant/bin/*.bat $out/share/ant/bin/*.cmd

makeWrapper $out/share/ant/bin/ant $out/bin/ant \
--set ANT_HOME $out/share/ant \
--set JAVA_HOME ${jdk.home}

runHook postInstall
'';

__structuredAttrs = true;
strictDeps = true;

meta = {
homepage = "https://ant.apache.org/";
description = "Java-based build tool";
sourceProvenance = with lib.sourceTypes; [fromSource];
license = lib.licenses.asl20;
teams = [lib.teams.java];
platforms = lib.platforms.all;
mainProgram = "ant";
};
})
112 changes: 112 additions & 0 deletions modules/pkgs/java/ant_1_7/_package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
lib,
stdenv,
fetchurl,
jdk,
makeWrapper,
junit_3,
xml-apis,
xerces_j,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "ant";
version = "1.7.1";

src = fetchurl {
url = "mirror://apache/ant/source/apache-ant-${finalAttrs.version}-src.tar.bz2";
hash = "sha256-TcSacmDvkKbcZhG36WufBH1QdYlzbUoq1u++Pt/G+6Y=";
};

nativeBuildInputs = [
jdk
makeWrapper
];

depsVersions.junit = "3.8.2";
depsVersions.xercesImpl = "2.9.1";
depsVersions.xmlApis = "1.3.04";

postPatch = ''
# dist-lite depends on test-jar, which has an unconditional
# <fail unless="junit.present"> — drop it; we don't need the test jar.
substituteInPlace build.xml \
--replace-fail 'depends="jars,test-jar"' 'depends="jars"'

# Evict all binary blobs and replace with from-source builds.
# bootstrap.sh hardcodes lib/xercesImpl.jar and lib/xml-apis.jar on the
# classpath; we replace them so the compile classpath is blob-free.
# dist-lite copies lib/*.jar to the output distribution, so replacing the
# blobs also makes the shipped ant blob-free.
# junit_3 replaces the optional junit blob; check_for_optional_packages then
# finds junit.present and compiles JUnitTask.
rm -f lib/xercesImpl.jar lib/xml-apis.jar \
lib/optional/junit-*.jar lib/optional/ant-antunit-*.jar
cp ${xml-apis}/share/java/xml-apis-${finalAttrs.depsVersions.xmlApis}.jar lib/
cp ${xerces_j}/share/java/xercesImpl-${finalAttrs.depsVersions.xercesImpl}.jar lib/
mkdir -p lib/optional
cp ${junit_3}/share/java/junit-${finalAttrs.depsVersions.junit}.jar lib/optional/
'';

postInstall = ''
# Verify JUnitTask compiled and all expected jars are in the distribution.
found=0
for j in $out/share/ant/lib/*.jar; do
if jar tf "$j" 2>/dev/null | grep -q "JUnitTask"; then
found=1; break
fi
done
if [ $found -eq 0 ]; then
echo "ant_1_7: JUnitTask not found — junit_3 was not picked up" >&2; exit 1
fi
if ! ls $out/share/ant/lib/xercesImpl-*.jar &>/dev/null; then
echo "ant_1_7: xercesImpl jar missing from output" >&2; exit 1
fi
if ! ls $out/share/ant/lib/xml-apis-*.jar &>/dev/null; then
echo "ant_1_7: xml-apis jar missing from output" >&2; exit 1
fi
if ! ls $out/share/ant/lib/optional/junit-*.jar &>/dev/null; then
echo "ant_1_7: junit jar missing from lib/optional" >&2; exit 1
fi
'';

buildPhase = ''
runHook preBuild

# build.xml pins javac source/target to 1.2/1.3, which a modern javac
# rejects (minimum is 8). bootstrap.sh forwards its arguments into the ant
# invocation that drives the build, and -D overrides the in-file <property>
# defaults. JDK feature detection in build.xml is class-existence based
# (e.g. java.net.Proxy for jdk1.5+), so every source still compiles here.
sh bootstrap.sh -Djavac.source=8 -Djavac.target=8

runHook postBuild
'';

installPhase = ''
runHook preInstall
mkdir -p $out/share/ant
cp -r bootstrap/* $out/share/ant/
rm -rf $out/share/ant/bin/*.bat
mkdir -p $out/share/ant/lib/optional
cp ${junit_3}/share/java/junit-${finalAttrs.depsVersions.junit}.jar \
$out/share/ant/lib/optional/

makeWrapper $out/share/ant/bin/ant $out/bin/ant \
--set ANT_HOME $out/share/ant \
--set JAVA_HOME ${jdk.home}
runHook postInstall
'';

__structuredAttrs = true;
strictDeps = true;

meta = {
homepage = "https://ant.apache.org/";
description = "Java-based build tool";
sourceProvenance = with lib.sourceTypes; [fromSource];
license = lib.licenses.asl20;
teams = [lib.teams.java];
platforms = lib.platforms.all;
mainProgram = "ant";
};
})
64 changes: 64 additions & 0 deletions modules/pkgs/java/commons-cli/_package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
lib,
stdenvNoCC,
fetchFromGitHub,
jdk,
stripJavaArchivesHook,
}:
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "commons-cli";
version = "1.10.0";

src = fetchFromGitHub {
owner = "apache";
repo = "commons-cli";
rev = "rel/commons-cli-${finalAttrs.version}";
hash = "sha256-xYefS5iict9yspWEZrhgGfWbqT9uzfilj3ehXjgQBOE=";
};

nativeBuildInputs = [
jdk
stripJavaArchivesHook
];

buildPhase = ''
runHook preBuild

mkdir -p build/classes

find src/main/java -name "*.java" > sources.txt

javac \
--release 8 \
-encoding UTF-8 \
-d build/classes \
@sources.txt

jar cf commons-cli-${finalAttrs.version}.jar -C build/classes .

runHook postBuild
'';

installPhase = ''
runHook preInstall

install -Dm644 commons-cli-${finalAttrs.version}.jar \
$out/share/java/commons-cli-${finalAttrs.version}.jar
ln -s $out/share/java/commons-cli-${finalAttrs.version}.jar \
$out/share/java/commons-cli.jar

runHook postInstall
'';

strictDeps = true;
__structuredAttrs = true;

meta = {
homepage = "https://commons.apache.org/proper/commons-cli/";
description = "Apache Commons CLI provides a simple API for presenting, processing and validating a command line interface";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [airone01];
platforms = lib.platforms.all;
sourceProvenance = with lib.sourceTypes; [fromSource];
};
})
Loading
Loading