{ lib }: with builtins; rec { # Derive a file by substituting # "${pkgs.foo}/bin/foo" for each {-pkg-}"foo", and # "${pkgs.bar}/bin/foo" for each {-pkg:bar-}"foo". # If a package doesn't exist, a warning gets printed. substitutePkgs = name: { callsite ? null, pkgs, path }: let sourceDescription = if callsite != null then "${name} in ${toString callsite}" else "${name} from ${toString path}"; f = dependencies: s: let parse = match "(.*)([{]-pkg(:([^}]+))?-[}]\"([^\"]+)\")(.*)" s; prefix = elemAt parse 0; pname = if elemAt parse 3 != null then elemAt parse 3 else exename; exename = elemAt parse 4; suffix = elemAt parse 5; pkg = pkgs.${pname} or null; substitute = if pkg != null then "${pkg}/bin/${exename}" else trace (toString [ "lib.haskell.substitutePkgs:" "warning:" "while deriving ${sourceDescription}:" "no substitute found for ${elemAt parse 1}" ]) exename; in if parse == null then (pkgs.writeText name s).overrideAttrs (old: { dependencies = lib.uniq (lib.sort (lib.on lib.lessThan (lib.getAttr "name")) (filter (lib.ne null) (old.dependencies or [] ++ dependencies))); }) else f (dependencies ++ [pkg]) (prefix + toJSON substitute + suffix); in f [] (readFile path); }