Skip to content

JVM / PHP and other languages

Overview

Beyond the Python / Node / Rust / Go survey, Nixpkgs’ Languages and frameworks chapter covers many other ecosystems—JVM (Java/Gradle), PHP (Composer), Ruby, Perl, OCaml, and more. Each has specialised builders or hooks on top of stdenv.mkDerivation, usually scoped into a matching package set.

This page is a survey hub: entry points and FOD patterns, not a mirror of each manual section. Same rules as Python / Node / Rust / Go: prefer language builders; stay in the matching package set; pin lock/vendor inputs with fixed-output hashes (fetchers and pinning).

Details

Shared packaging rules

Rule Why
Prefer the documented language builder / hooks They wire phases, setup hooks, and dependency FODs you would otherwise reimplement
Depend inside the matching package set Same interpreter/compiler scope (e.g. php.extensions, ruby.gems, perlPackages)
Pin lock / vendor trees with FODs vendorHash, Gradle deps.json / mitmCache, Composer repository hashes — same FOD workflow as cargoHash / npmDepsHash

Explore nested sets in nix repl (the Languages chapter shows tab-completing javaPackages and similar). For shell-oriented toolchain maps, see language toolchains.

JVM / Java

javaPackages groups compiler and related variants (OpenJFX releases, javaPackages.compiler, helpers such as mavenfod). The manual’s Languages intro walks navigating that set with nix repl (Languages and frameworks).

Classic Ant-based packages usually take ant, a jdk, and often stripJavaArchivesHook in nativeBuildInputs, then run ant in buildPhase. Install shared JARs under $out/share/java so JDK setup hooks can put them on CLASSPATH; wrap programs with makeWrapper and a JRE. Details: Java.

Gradle (Java/Kotlin) does not make dependency resolution reproducible by itself. Nixpkgs records Gradle network fetches via a MITM cache:

  1. Put gradle in nativeBuildInputs so the Gradle setup hook runs configure/build/check.
  2. Set mitmCache = gradle.fetchDeps { …; data = ./deps.json; } (and usually pname or pkg) so the build restores pinned deps.
  3. Refresh the lock with the cache’s updateScript when dependencies change.

Optional knobs include gradleFlags, gradleBuildTask (default assemble), and gradleCheckTask (default test). Full API: Gradle / Building a Gradle package.

PHP

PHP interpreters live under versioned attributes (php81, …); php is the release’s preferred default. Extensions and tools hang off that interpreter (php.extensions, php.packages.composer); compose runtimes with php.withExtensions / php.buildEnv (PHP).

For Composer applications, the documented high-level builder is php.buildComposerProject2: a mkDerivation wrapper that builds a fixed-output Composer repository from composer.json / composer.lock, installs vendor, and links bin scripts. Pin deps with vendorHash; if upstream omits the lockfile, pass composerLock. Lower-level composition uses php.mkComposerRepository and php.composerHooks inside a normal derivation. See Building PHP projects.

Ruby

Default interpreter is ruby (versioned MRI as ruby_3_y, plus jruby / mruby). Gems live under ruby.gems (and per-interpreter sets); prefer ruby.withPackages (ps: [ … ]) so the interpreter can require them. Application packaging may use a locked Gemfile workflow or the shared gem set—follow Ruby rather than inventing Bundler helpers.

Perl

CPAN-style libraries use buildPerlPackage and live in perlPackages. The builder runs perl Makefile.PL, adjusts shebangs/PERL5LIB, and propagates Perl deps for nix-env-style installs. Prefer mirror://cpan/ sources and depend on siblings from the same set. See Perl / Packaging Perl programs.

Rest of the Languages chapter

OCaml (ocamlPackages / ocaml-ng.ocamlPackages_*), and many other ecosystems, are documented in the same Languages and frameworks chapter. Treat those sections as the source of truth for builders and package-set names; this hub does not duplicate them. Haskell has its own leaf: Haskell packaging.

Examples

Minimal shapes only—replace placeholder hashes after the first failed build.

Gradle (mitmCache + gradle.fetchDeps):

stdenv.mkDerivation (finalAttrs: {
  pname = "example";
  version = "1.0.0";

  src = fetchFromGitHub {
    owner = "example";
    repo = "example";
    tag = "v${finalAttrs.version}";
    hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
  };

  nativeBuildInputs = [ gradle makeWrapper ];

  mitmCache = gradle.fetchDeps {
    inherit (finalAttrs) pname;
    data = ./deps.json;
  };

  # gradleFlags / gradleBuildTask as needed — see Gradle manual section
  # Refresh deps: $(nix-build -A mitmCache.updateScript) then commit deps.json
})

PHP Composer app (php.buildComposerProject2):

{ php, fetchFromGitHub }:

php.buildComposerProject2 (finalAttrs: {
  pname = "php-app";
  version = "1.0.0";

  src = fetchFromGitHub {
    owner = "example";
    repo = "php-app";
    tag = finalAttrs.version;
    hash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
  };

  vendorHash = "sha256-CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=";
  # composerLock = ./composer.lock;  # if missing from src
})

Ruby environment (withPackages):

# pkgs.ruby.withPackages (ps: with ps; [ nokogiri pry ])

Perl library (buildPerlPackage in perlPackages):

buildPerlPackage rec {
  pname = "Class-C3";
  version = "0.21";
  src = fetchurl {
    url = "mirror://cpan/authors/id/F/FL/FLORA/Class-C3-${version}.tar.gz";
    hash = "sha256-DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD=";
  };
}

References

See also