Dependencies and native libraries¶
Consuming packages this library did not build¶
fromDerivation¶
Wrap an arbitrary Nix derivation — a Quicklisp-packaged library from nixpkgs,
the output of an unrelated project's hand-written flake, anything — as a
lispDependencies-compatible leaf.
cl.fromDerivation {
drv = someForeignPackage;
recursive = false;
nativeLibraries = [ ];
lispImplementation = null;
}
| Argument | Default | Effect |
|---|---|---|
drv |
required | The foreign package |
recursive |
false |
Append // so ASDF searches $out's whole subtree for .asd files, not just $out itself |
nativeLibraries |
[ ] |
Declare that this package itself provides native libraries |
lispDependencies |
[ ] |
Dependencies of the wrapped package, if it has them |
lispImplementation |
null |
Which implementation built any fasls inside |
A generic foreign derivation is an opaque leaf: its output directory joins
CL_SOURCE_REGISTRY, but it contributes no inferred Lisp dependencies,
because it might not be ASDF-based by the time it reaches $out. If its own
$out/lib holds a .so/.dylib that a Lisp consumer will dlopen, say so
with nativeLibraries = [ drv ] — cl-nix-forge cannot detect this for a
package it did not build.
lispImplementation is optional here because fromDerivation
wraps outputs containing no Lisp at all: a C shared library, a
data directory, some foreign flake's binary. Those have no implementation to
name, and demanding one would only teach callers to invent an answer. Two
properties keep the omission from being a hole. Wrapping something
cl-nix-forge built preserves its recorded implementation without the caller
restating it; and contradicting an inherited value is an assertion failure,
not a silent relabel of somebody else's fasls.
fromNixpkgsLisp¶
Shorthand for the common case of pulling in a Quicklisp-packaged nixpkgs library.
lispDependencies = [
(cl.fromNixpkgsLisp {
drv = pkgs.sbcl.pkgs.alexandria;
lispImplementation = "sbcl";
})
];
Both arguments are required, and there is no bare-derivation
shorthand — passing one is an error that says what to write instead, rather
than the opaque "called without required argument" a destructuring pattern
would produce. Everything this function wraps is a precompiled Lisp package
whose fasls belong to exactly one implementation. A shorthand letting the
caller leave that unsaid would be a one-character way to opt out of the
boundary lispDerivation enforces. A consumer built with a different
implementation fails during evaluation
instead of asking ASDF to rewrite fasls inside the immutable store.
It defaults to recursive = true and does not offer the argument: nixpkgs'
own ASDF builder copies a package's whole build tree into $out, and unlike
cl-nix-forge's convention of keeping every system's .asd at the source
root, several real Quicklisp systems (cffi's grovel and toolchain
subsystems, for instance) keep secondary .asd files in subdirectories.
propagatedBuildInputs are wrapped recursively, so a dependency's .asd
stays discoverable to ASDF without any of them entering buildInputs.
Native libraries¶
The gap these close: a Lisp dependency that also builds a native
.so/.dylib has, in prior art, no way to make that fact visible more than
one hop away. Every transitive consumer has to know by name which of its
dependencies-of-dependencies produced the library and hand-copy a search-path
line for it.
lib/core/native.nix does not walk the dependency graph itself.
lib/core/asdf-derivation.nix already walks it once for lispDependencies,
and reuses that exact walk to fold in each dependency's own
already-transitive nativeLibraries. These functions only turn the resulting
flat list of producer derivations into the right form for whichever
consumption point needs it: a build/check environment, an interactive dev
shell, or a delivered executable's wrapper. Explicit data flow instead of
nixpkgs setup-hook chaining, so propagation depth is never a surprise.
Of the five, only markNativeLibrary is normally called by hand. The other
four are the low-level loader helpers lispDerivation, lispWithSystems and
mkExecutable apply for you; they stay public — like
ancestryWalker — for the case where you are
building something this library does not yet cover, and are documented here
so that use is against a stated contract rather than a read of the source.
markNativeLibrary¶
Marks a derivation that itself produces a native library — its $out/lib
holds a .so/.dylib — as a nativeLibraries entry for consumers.
Most producers just need passthru.nativeLibraries = [ finalDrv ], spelled
out at the call site rather than forced through one more layer of
indirection. This helper exists for the common case of wrapping a plain
stdenv.mkDerivation with no other cl-nix-forge involvement — a pure-C
shared library with no Lisp code of its own. It sets the attribute both
directly and in passthru, because consumers read it directly and attrset
extension does not promote passthru the way mkDerivation does.
nativeLibraryPath¶
<drv>/lib directories for a list of producer derivations, :-joined into
one string.
nativeLibraryEnv¶
The same directories as an attrset suitable for a derivation's env, so a
test suite that dlopens a transitively-declared native library finds it
without a hand-copied preBuild hook.
An empty input produces an empty attrset, not an environment variable set to the empty string.
Setting the search-path variable in env yourself while nativeLibraries
are present is refused by lispDerivation, with a message pointing at a
wrapper or at adding the library to nativeLibraries — because the two would
otherwise silently overwrite each other.
nativeLibraryWrapperArgs¶
makeWrapper arguments (--suffix <var> : <path>) that bake the same search
path into a delivered executable, so it keeps resolving its native libraries
after leaving the Nix build sandbox. This is what
mkExecutable and
lispWithSystems apply.
Also empty for an empty input, so an unconditional splice into a
makeWrapper invocation stays correct.
libraryPathVar¶
The runtime-loader search-path variable for the host platform:
DYLD_LIBRARY_PATH on Darwin, LD_LIBRARY_PATH elsewhere. Exported so a
consumer writing its own wrapper spells the platform condition the same way
the library does, instead of a second time.