A Nix library for creating offline and reproducible Julia builds.
Julia uses an Ahead-Of-Time compilation system. This means Julia generates native code for functions that it can compile, while it still needs access to the source code in order to compile just-in-time. Manifest2Nix.jl is designed to take advantage of this system by precompiling as much code as possible.
nix flake new --template git+https://codeberg.org/aniva/Manifest2Nix.jl.git ./minimalBefore building any Julia library, there first has to be a Julia toolchain. Generate a toolchain via one of 4 methods (in decreasing order of preference):
- Use the
self.fromManifest pathoverlay, which reads the version from aManifest.tomlfile. - Use the
self.fromVersion versionoverlay, e.g.manifest2nix.fromVersion "1.11.7". - Use the provided
self.fromJuliaBinoverlay, which uses thejulia-binpackage. (julia = julia-bin) pkgscomes with a defaultjuliapackage. It may work or it may not work. This build of Julia could have problems on Darwin systems.
Once there is a fixed Julia version available as pkgs.julia, create the
manifest2nix library by calling the mkLib function:
m2nlib = manifest2nix.mkLib pkgsIn m2nlib, some functions are available for building Julia packages:
manifest2nix: Tool for creating theLock.toml. To create aLock.tomlfile, execute at the root of a Julia project: (use--upto also update the manifest)
manifest2nix lock [--up] --project .-
buildJuliaPackage { src, depots, deps, pre-exec ? "", env ? {} }: Builds a Julia package with explicit dependencies. A Julia package in Nix is a special attrset generated by this function.If
pre-execis not null, it will run in Julia after precompilation to force Julia to generate more compiled code. Setenvfor environment variables. -
buildJuliaPackageWithDeps { src, lockFile ? "${src}/Lock.toml", pre-exec ? "", override ? {}, env ? {} }: Build a Julia package along with dependencies. If there are any path-tracking dependencies, they must be fed in as overrides. e.g.override = { Artefact = ./artefact; }. The targets of overrides can be either paths to sources or built Julia packages. Setenvto provide environment variables. -
stdlib-depot: A Julia depot containing a precompiled version of Julia standard libraries. -
mkDepsDepot { name, deps }: Given a list of Julia packages, create a depot containing all of them. This depot can be cached to speed up compilation. -
createEnv { package, workingDepot ? "" }: Given a Julia package, create an environment (i.e. set of variables) in which Julia can run and see the precompiled version of the given package. By default, the working depot here is the default path to the system depot. However, if this environment is then used in a Nix build, thenworkingDepotmust be set to a writable path e.g..julia. Not doing so can cause compilation failures.
A Julia package has these attributes:
.compiled: Precompiled binary code. Cache this in Nix to shorten the compilation of downstream packages..load-path: A special derivation for making load paths. Each package$PACKAGE'sload-pathis a derivation containing a single directory$PACKAGEwhich includes the project's source code. In most cases this is a direct link to the project's source directory. For legacy packages without aProject.toml, there will be a syntheticProject.tomlfile so Julia can find the package..artifacts: An attribute set of all downloaded artifacts.
If the SSL certificate in nixpkgs is too old, it may cause registry fetch
failures during package updates. This will manifest as "the identity of the
server ... could not be verified." In which case, update using Julia itself, or
update nixpkgs.
Use the provided flake devShell, and install pre-commit hooks:
pre-commit install --install-hooksWhen there is a new Julia version, execute nix run .#toolchain-fetch $VERSION
to generate Nix attributes. Add these attributes to sources.nix. For minor
version updates, add a new Manifest/Lock pair to version/.