From 5222363936e343150ed74df660a90d30714fe931 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Fri, 31 Dec 2021 22:58:04 +0100 Subject: [PATCH 01/13] cups-drv-rastertosag-gdi (cups driver): fix simple comment typo --- pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix index d491436554593..683b1b64bca9f 100644 --- a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix +++ b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix @@ -22,7 +22,7 @@ python3Packages.buildPythonApplication rec { format = "other"; nativeBuildInputs = [ (lib.getBin cups) ]; # The source image also brings pre-built ppd files, - # be we prefer to generate from source where possible, so + # but we prefer to generate from source where possible, so # the following line generates ppd files from the drv file. postBuild = '' ppdc -v -d . -I "${cups}/share/cups/ppdc" rastertosag-gdi.drv From 6f622e91c5daefe73b4c988d375a854a37bf92a7 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 20:25:06 +0200 Subject: [PATCH 02/13] cups-drv-rastertosag-gdi (cups driver): gzip ppd files ppd files are gzipped to save some space. The `gzip` "-n" option prevents gzip from storing a timestamp, thus facilitating reproducibility. --- .../doc/manual/from_md/release-notes/rl-2211.section.xml | 9 +++++++++ nixos/doc/manual/release-notes/rl-2211.section.md | 2 ++ .../cups/drivers/cups-drv-rastertosag-gdi/default.nix | 3 +++ 3 files changed, 14 insertions(+) diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml index b731b8b72a3d0..02cb2dd9ccd1c 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml @@ -643,6 +643,15 @@ maintainer to update the package. + + + ppd files in pkgs.cups-drv-rastertosag-gdi + are now gzipped. If you refer to such a ppd file with its path + (e.g. via + hardware.printers.ensurePrinters) + you will need to append .gz to the path. + + xow package removed along with the diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md index 0f0e3c7a2e55d..43abb40b8a04f 100644 --- a/nixos/doc/manual/release-notes/rl-2211.section.md +++ b/nixos/doc/manual/release-notes/rl-2211.section.md @@ -210,6 +210,8 @@ Available as [services.patroni](options.html#opt-services.patroni.enable). - riak package removed along with `services.riak` module, due to lack of maintainer to update the package. +- ppd files in `pkgs.cups-drv-rastertosag-gdi` are now gzipped. If you refer to such a ppd file with its path (e.g. via [hardware.printers.ensurePrinters](options.html#opt-hardware.printers.ensurePrinters)) you will need to append `.gz` to the path. + - xow package removed along with the `hardware.xow` module, due to the project being deprecated in favor of `xone`, which is available via the `hardware.xone` module. - dd-agent package removed along with the `services.dd-agent` module, due to the project being deprecated in favor of `datadog-agent`, which is available via the `services.datadog-agent` module. diff --git a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix index 683b1b64bca9f..2032fa8457d46 100644 --- a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix +++ b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix @@ -35,6 +35,9 @@ python3Packages.buildPythonApplication rec { ln -vst "${placeholder "out"}/lib/cups/filter/" "${placeholder "out"}/bin/rastertosag-gdi" runHook postInstall ''; + postFixup = '' + gzip -9nv "${placeholder "out"}/share/cups/model/rastertosag-gdi"/*.ppd + ''; meta = { description = "CUPS driver for Ricoh Aficio SP 1000S and SP 1100S printers"; downloadPage = "https://www.openprinting.org/download/printing/rastertosag-gdi/"; From 335a9083b02d2a7034dd98c8641f019e85e50426 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 17:38:55 +0200 Subject: [PATCH 03/13] patchPpdFilesHook: new setup hook for absolute executable paths PostScript Printer Description (ppd) files describe printer features and capabilities. They are usually evaluated by CUPS to convert print jobs into a format suitable for a printer. The conversion is often accomplished by commands or even short shell scripts inside the ppd files. ppd files are included in many printer driver packages. Their scripts sometimes refer to other executables; some of them are more common (like `perl`), others are more exotic (like `rastertohp`). If an executable is called with its name alone, the effects of the ppd file depend on whether the executable is in the PATH of CUPS, and on the executable's version. If an executable is called with an absolut path (like `/usr/bin/perl`), it won't work at all in NixOS. The commit at hand adds a setup hook that uses the `fixupPhase` to substitute certain executable's invocations in pdd files with absolute paths. To use it, add the hook to `nativeBuildInputs` and provide a list of executable names in `ppdFileCommands`. Each executable must be available in the package that is being built, or in `buildInputs`. The setup hook's script then looks for ppd files in `share/cups/model` and `share/ppds` in each output, and replaces executable names with their absolute paths. If ppd files need to be patched in unorthodox locations or the setup hook needs to be invoked manually for other reasons, one may leave the list `ppdFileCommands` empty to avoid automatic processing of ppd files, then call the shell function `patchPpdFileCommands` directly. Details are described in the file `patch-ppd-hook.sh`. Notes on the motivation for this setup hook: Most packages in nixpkgs that provide ppd files do not patch those ppd files at all. This is not fatal when the executables are just called with their names since the user can add packages with the executables to `services.printing.drivers`. E.g. if the user adds `pkgs.perl`, then all ppd files that invoke `perl` will work as expected. Nevertheless, to make these ppd files independent of their execution environment, command invocations should be substituted with absolut paths into the nix store. This is similar to patching shebang lines so scripts can be called independently of having the interpreter in the PATH. The hook script in this commit is meant to support new packages `foomatic-db*` which will generate several thousands of ppd files referencing a plethora of different executables. During development of these packages, I realized that it's quite hard to patch ppd files in a robust way. While binary names like `rastertokpsl` seem to be sufficiently unique to be patched with `sed`, names like `date` or `gs` are hard to patch without producing "false positives", i.e., coincidental occurences of the executable's name that do *not* refer to the executable and should not be patched at all. As this problem also affects other packages, it seems reasonable to put a robust implementation in its own setup hook so that other packages can use it without much effort. Notes on the implementation: The ppd file format is far from trivial. The basic structure are key-value pairs; keys may occur multiple times. Only a small subset of keys may contain executable names or shell scripts in their values. Some values may span multiple lines; a linebreak might even occur in the middle of a token. Some executable names also occur in other keys by accident where they must not be substituted (e.g. `gs` or `date`). It is necessary to provide the list of command names that will be patched for two reasons: ppd files often contain "tokens" that might look like commands (e.g. "file" or "host") but aren't; these would erroneously get patched. Also, looking for everything that might be a command would slow down the patching process considerably. The implementation uses `awk` to detect keys that might contain executable names; only their values are treated for substitution. This avoids most cases of "overzealous" substitutions. Since values may span multiple lines, `sed` alone (while faster than `awk`) cannot focus its substitution capabilities on relevant keys. An elaborate set of regular expressions further helps to minimize the probability of "false positives". Several tricks are employed to speed up `awk`. Notably, relevant files are identified with `grep` before `awk` is applied to those files only. Note that the script probably cannot handle fancy command names (like spaces or backslashes as part of the name). Also, there are still edge cases that the script would mistakenly skip, e.g. if a shell script contains a line break in the middle of an executable's name; although ppd files permit such constellations, I have yet to see one. ppd files may be gzipped. The setup hook accepts gzipped ppd files: It decompresses them, substitutes paths, then recompresses them. However, Nix cannot detect substituted paths as runtime dependencies in compressed ppd files. To ensure substituted paths are propagated as runtime dependencies, the script adds each substituted path to the variable `propagatedBuildInputs`. Since this might not be enough for multi-output packages, those paths are also written directly to `nix-support/propagated-build-inputs`. See the comment in `patch-ppd-hook.sh` for details. Finally, the setup hook comes with a small test that probes some edge cases with an artificial ppd file. References: * https://www.cups.org/doc/spec-ppd.html * general ppd file specification * lists some keys that may contain executable names or shell scripts * https://refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Printing/LSB-Printing/ppdext.html * lists some keys that may contain executable names or shell scripts * https://en.wikipedia.org/wiki/PostScript_Printer_Description#CUPS * lists the usual locations of ppd files --- .../setup-hooks/patch-ppd-files/default.nix | 25 +++ .../patch-ppd-files/patch-ppd-hook.sh | 183 ++++++++++++++++++ .../patch-ppd-files/patch-ppd-lines.awk | 50 +++++ .../setup-hooks/patch-ppd-files/test.nix | 40 ++++ .../setup-hooks/patch-ppd-files/test.ppd | 22 +++ pkgs/top-level/all-packages.nix | 2 + 6 files changed, 322 insertions(+) create mode 100644 pkgs/build-support/setup-hooks/patch-ppd-files/default.nix create mode 100644 pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh create mode 100644 pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk create mode 100644 pkgs/build-support/setup-hooks/patch-ppd-files/test.nix create mode 100644 pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/default.nix b/pkgs/build-support/setup-hooks/patch-ppd-files/default.nix new file mode 100644 index 0000000000000..b3c7b19f37325 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-ppd-files/default.nix @@ -0,0 +1,25 @@ +{ lib +, makeSetupHook +, which +, callPackage +}: + +let + patchPpdFilesHook = makeSetupHook + { + name = "patch-ppd-files"; + substitutions.which = lib.attrsets.getBin which; + substitutions.awkscript = ./patch-ppd-lines.awk; + } + ./patch-ppd-hook.sh; +in + +patchPpdFilesHook.overrideAttrs ( + lib.trivial.flip + lib.attrsets.recursiveUpdate + { + passthru.tests.test = callPackage ./test.nix {}; + meta.description = "setup hook to patch executable paths in ppd files"; + meta.maintainers = [ lib.maintainers.yarny ]; + } +) diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh new file mode 100644 index 0000000000000..a450ecd7f963a --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh @@ -0,0 +1,183 @@ +fixupOutputHooks+=(_patchPpdFileCommands4fixupOutputHooks) + + + +# Install a hook for the `fixupPhase`: +# If the variable `ppdFileCommands` contains a list of +# executable names, the hook calls `patchPpdFileCommands` +# on each output's `/share/cups/model` and `/share/ppds` +# directories in order to replace calls to those executables. + +_patchPpdFileCommands4fixupOutputHooks () { + [[ -n $ppdFileCommands ]] || return 0 + if [[ -d $prefix/share/cups/model ]]; then + patchPpdFileCommands "$prefix/share/cups/model" $ppdFileCommands + fi + if [[ -d $prefix/share/ppds ]]; then + patchPpdFileCommands "$prefix/share/ppds" $ppdFileCommands + fi +} + + + +# patchPpdFileCommands PPD-ROOT PROGNAME... +# +# Look for ppd files in the directory PPD-ROOT. +# Descend into subdirectories, even if they are symlinks. +# However, ignore ppd files that don't belong to the same +# prefix ($NIX_STORE/$package_name) as PPD-ROOT-DIR does, +# to avoid stepping into other package's directories. +# ppd files may be gzipped; if the are, +# uncompress them, later recompress them. +# Skip symlinks to ppd files. +# PPD-ROOT may also be a single ppd file. +# +# Look for the PROGNAME executable in outputs and `buildInputs`, +# then look for PROGNAME invocations in the ppd files, +# without path or with common paths like `/usr/bin/$PROGNAME`. +# Replace those invocations with an absolute path to the +# corresponding executable from the outputs or `buildInputs`. +# Executables are searched where CUPS would search them, +# i.e., in `/bin` and `/lib/cups/filter`. +# +# As soon as an executable's path is replaced as +# described above, the package containing the binary +# is added to the list of propagated build inputs. +# This ensures the executable's package is still +# recognized as runtime dependency of the ppd file +# even if the ppd file is compressed lateron. +# +# PROGNAME may not contain spaces or tabs. +# The function will also likely fail or produce +# broken results if PROGNAME contains characters that +# require shell or regex escaping (e.g. a backslash). + +patchPpdFileCommands () { + + local bin binnew binold binoldgrep cupspath path ppdroot ppdrootprefix + + # we will store some temporary data here + pushd "$(mktemp -d --tmpdir patch-ppd-file-commands.XXXX)" + + # remember the ppd root path + [[ "$1" == $NIX_STORE/* ]] # ensure it's a store directory + ppdroot=$1 + shift # now "$@" is the list of binaries + ppdrootprefix=${ppdroot%"/${ppdroot#"$NIX_STORE"/*/}"} + + # create `cupspath` (where we should look for binaries), + # with these priorities + # * outputs of current build before buildInputs + # * `/lib/cups/filter' before `/bin` + # * add HOST_PATH at end, so we don't miss anything + for path in $outputs; do + addToSearchPath cupspath "${!path}/lib/cups/filter" + addToSearchPath cupspath "${!path}/bin" + done + for path in ${pkgsHostTarget+"${pkgsHostTarget[@]}"}; do + addToSearchPath cupspath "$path/lib/cups/filter" + addToSearchPath cupspath "$path/bin" + done + while read -r -d : path; do + addToSearchPath cupspath "$path" + done <<< "${HOST_PATH:+"${HOST_PATH}:"}" + + # create list of compressed ppd files + # so we can recompress them later + find -L "$ppdroot" -type f -iname '*.ppd.gz' '!' -xtype l -print0 > gzipped + + # decompress gzipped ppd files + echo "patchPpdFileCommands: decompressing $(grep -cz '^' < gzipped) gzipped ppd file(s) in $ppdroot" + xargs -0r -n 64 -P "$NIX_BUILD_CORES" gunzip < gzipped + + # create list of all ppd files to be checked + find -L "$ppdroot" -type f -iname '*.ppd' '!' -xtype l -print0 > ppds + + for bin in "$@"; do + + # discover new path + binnew=$(PATH=$cupspath '@which@/bin/which' "$bin") + echo "patchPpdFileCommands: located binary $binnew" + + # for each binary, we look for the name itself, but + # also for a couple of common paths that might be used + for binold in {/usr,}/{lib/cups/filter,sbin,bin}/"$bin" "$bin"; do + + # escape regex characters in the old command string + binoldgrep=$(sed 's,[]$.*[\^],\\&,g' <<< "$binold") + # ...and surround old command with some regex + # that singles out shell command invocations + # to avoid replacing other strings that might contain the + # command name by accident (like "perl" in "perl-script") + binoldgrep='\(^\|[;&| '$'\t''"`(]\)'"$binoldgrep"'\($\|[);&| '$'\t''"`<>]\)' + # this string is used to *quickly* filter out + # unaffected files before the (slower) awk script runs; + # note that a similar regex is build in the awk script; + # if `binoldgrep` is changed, the awk script should also be checked + + # create list of likely affected files + # (might yield exit status != 0 if there are no matches) + xargs -0r grep -lZ "$binoldgrep" < ppds > ppds-to-patch || true + + echo "patchPpdFileCommands: $(grep -cz '^' < ppds-to-patch) ppd file(s) contain $binold" + + # actually patch affected ppd files with awk; + # this takes some time but can be parallelized; + # speed up with LC_ALL=C, https://stackoverflow.com/a/33850386 + LC_ALL=C xargs -0r -n 64 -P "$NIX_BUILD_CORES" \ + awk -i inplace -v old="${binold//\\/\\\\}" -v new="${binnew//\\/\\\\}" -f "@awkscript@" \ + < ppds-to-patch + + done + + # create list of affected files + xargs -0r grep -lZF "$binnew" < ppds > patched-ppds || true + + echo "patchPpdFileCommands: $(grep -cz '^' < patched-ppds) ppd file(s) patched with $binnew" + + # if the new command is contained in a file, + # remember the new path so we can add it to + # the list of propagated dependencies later + if [[ -s patched-ppds ]]; then + printf '%s\0' "${binnew%"/${binnew#"${NIX_STORE}"/*/}"}" >> dependencies + fi + + done + + # recompress ppd files that have been decompressed before + echo "patchPpdFileCommands: recompressing $(grep -cz '^' < gzipped) gzipped ppd file(s)" + # we can't just hand over the paths of the uncompressed files + # to gzip as it would add the lower-cased extension ".gz" + # even for files where the original was named ".GZ" + xargs -0r -n 1 -P "$NIX_BUILD_CORES" \ + "$SHELL" -c 'gzip -9nS ".${0##*.}" "${0%.*}"' \ + < gzipped + + # enlist dependencies for propagation; + # this is needed in case ppd files are compressed later + # (Nix won't find dependency paths in compressed files) + if [[ -s dependencies ]]; then + + # weed out duplicates from the dependency list first + sort -zu dependencies > sorted-dependencies + + mkdir -p "$ppdrootprefix/nix-support" + while IFS= read -r -d '' path; do + printWords "$path" >> "$ppdrootprefix/nix-support/propagated-build-inputs" + # stdenv writes it's own `propagated-build-inputs`, + # based on the variable `propagatedBuildInputs`, + # but only to one output (`outputDev`). + # So we also add our dependencies to that variable. + # If our file survives as written above, great! + # If stdenv overwrits it, + # our dependencies will still be added to the file. + # The end result might contain too many + # propagated dependencies for multi-output packages, + # but never a broken package. + propagatedBuildInputs+=("$path") + done < sorted-dependencies + fi + + popd + +} diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk new file mode 100644 index 0000000000000..ddb9171fff32e --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk @@ -0,0 +1,50 @@ +BEGIN { + + # ppd file keys are separated from their values by a colon, + # but "options" may reside between the key name and the colon; + # options are separated from the key by spaces + # (we also permit tabs to be on the safe side) + FS = "[: \t]"; + + # escape regex characters in the old and new command strings + gsub(/[]\\.^$(){}|*+?[]/, "\\\\&", old); + gsub(/\\/, "\\\\&", new); + # ...and surround old command with some regex + # that singles out shell command invocations + # to avoid replacing other strings that might contain the + # command name by accident (like "perl" in "perl-script") + new = "\\1" new "\\2"; + old = "(^|[;&| \\t\"`(])" old "($|[);&| \\t\"`<>])"; + # note that a similar regex is build in the shell script to + # filter out unaffected files before this awk script is called; + # if the regex here is changed, the shell script should also be checked + + # list of PPD keys that contain executable names or scripts, see + # https://refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Printing/LSB-Printing/ppdext.html + # https://www.cups.org/doc/spec-ppd.html + cmds["*APAutoSetupTool"] = ""; + cmds["*APPrinterLowInkTool"] = ""; + cmds["*FoomaticRIPCommandLine"] = ""; + cmds["*FoomaticRIPPostPipe"] = ""; + cmds["*cupsFilter"] = ""; + cmds["*cupsFilter2"] = ""; + cmds["*cupsPreFilter"] = ""; + +} + +# since comments always start with "*%", +# this mechanism also properly recognizes (and ignores) them + +{ + + # if the current line starts a new key, + # check if it is a command-containing key; + # also reset the `isCmd` flag if a new file begins + if ($0 ~ /^\*/ || FNR == 1) { isCmd = ($1 in cmds) } + + # replace commands if the current keys might contain commands + if (isCmd) { $0 = gensub(old, new, "g") } + + print + +} diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/test.nix b/pkgs/build-support/setup-hooks/patch-ppd-files/test.nix new file mode 100644 index 0000000000000..4f2996b235105 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-ppd-files/test.nix @@ -0,0 +1,40 @@ +{ substituteAll +, diffutils +, stdenv +, patchPpdFilesHook +}: + +let + input = substituteAll { + src = ./test.ppd; + keep = "cmp"; + patch = "cmp"; + pathkeep = "/bin/cmp"; + pathpatch = "/bin/cmp"; + }; + + output = substituteAll { + src = ./test.ppd; + keep = "cmp"; + patch = "${diffutils}/bin/cmp"; + pathkeep = "/bin/cmp"; + pathpatch = "${diffutils}/bin/cmp"; + }; +in + +stdenv.mkDerivation { + name = "${patchPpdFilesHook.name}-test"; + buildInputs = [ diffutils ]; + nativeBuildInputs = [ diffutils patchPpdFilesHook ]; + dontUnpack = true; + dontInstall = true; + ppdFileCommands = [ "cmp" ]; + preFixup = '' + install -D "${input}" "${placeholder "out"}/share/cups/model/test.ppd" + install -D "${input}" "${placeholder "out"}/share/ppds/test.ppd" + ''; + postFixup = '' + diff --color --report-identical-files "${output}" "${placeholder "out"}/share/cups/model/test.ppd" + diff --color --report-identical-files "${output}" "${placeholder "out"}/share/ppds/test.ppd" + ''; +} diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd b/pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd new file mode 100644 index 0000000000000..d0ca11ccfe6dd --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd @@ -0,0 +1,22 @@ +*% This comment: might look like a command @keep@ +*% but it should be left untouched +*SomeKey: do not replace this @keep@ +*APAutoSetupTool: do replace this @patch@ +*FoomaticRIPCommandLine: "patch also @patch@ +in a multi-line command @patch@ +and another line @patch@ +*SomeKey: "stop patching on new non-command key @keep@ +and remember the key in the next line @keep@" +*cupsFilter option: recognize keys with options @patch@ +*cupsFilter : handle strange spacing;@patch@ +*cupsFilter : handle tabulator @patch@ +*cupsFilter: patch common paths @pathpatch@ +*cupsFilter: patch quoted commands "@patch@" +*cupsFilter: patch commands in subshell (@patch@) +*cupsFilter: patch commands in subshell `@pathpatch@` +*cupsFilter: keep uncommon paths /fancy/@pathkeep@ +*cupsFilter: keep entangled commands-@keep@ +*cupsFilter: keep entangled commands\@keep@ +*cupsFilter: keep entangled commands @keep@() +*cupsFilter: keep entangled commands @pathkeep@-cmd +*%cupsFilter: This comment should also be left as is @pathkeep@ diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 9456fdfe6487c..5b1faf8d586b4 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -1076,6 +1076,8 @@ with pkgs; { name = "validate-pkg-config"; deps = [ findutils pkg-config ]; } ../build-support/setup-hooks/validate-pkg-config.sh; + patchPpdFilesHook = callPackage ../build-support/setup-hooks/patch-ppd-files {}; + #package writers writers = callPackage ../build-support/writers {}; From ef8566f38b422f92759cdbaa5510c06fdb49106e Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 20:25:53 +0200 Subject: [PATCH 04/13] cups-drv-rastertosag-gdi (cups driver): patch ppd bin paths The `cups-drv-rastertosag-gdi` CUPS printer driver package provides a filter executable `rastertosag-gdi` and two ppd files that reference the filter file. The commit at hand uses `patchPpdFilesHook` to replace calls to the filter executable with absolute paths to increase package purity. --- pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix index 2032fa8457d46..4f1ad6c9911e5 100644 --- a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix +++ b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix @@ -3,6 +3,7 @@ , fetchpatch , cups , python3Packages +, patchPpdFilesHook }: python3Packages.buildPythonApplication rec { @@ -20,7 +21,7 @@ python3Packages.buildPythonApplication rec { }) ]; format = "other"; - nativeBuildInputs = [ (lib.getBin cups) ]; + nativeBuildInputs = [ (lib.getBin cups) patchPpdFilesHook ]; # The source image also brings pre-built ppd files, # but we prefer to generate from source where possible, so # the following line generates ppd files from the drv file. @@ -35,6 +36,7 @@ python3Packages.buildPythonApplication rec { ln -vst "${placeholder "out"}/lib/cups/filter/" "${placeholder "out"}/bin/rastertosag-gdi" runHook postInstall ''; + ppdFileCommands = [ "rastertosag-gdi" ]; postFixup = '' gzip -9nv "${placeholder "out"}/share/cups/model/rastertosag-gdi"/*.ppd ''; From bf30b53817652cc0bdaca8fbf8891165e273e332 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 21:27:21 +0200 Subject: [PATCH 05/13] cups-kyocera (cups driver): use patchPpdFilesHook The `sed` script in the `installPhase` is removed. Instead, the setup hook `patchPpdFilesHook` is used to patch the path to `rastertokpsl`. The result should essentially be the same. Comparing the generated ppd files showed no difference (short of the package's hash in the absolute paths). The new package also contains a `propagated-build-inputs` file which propagates the package itself. This ensures the package is available whenever a ppd file is singled out by another package. --- pkgs/misc/cups/drivers/kyocera/default.nix | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pkgs/misc/cups/drivers/kyocera/default.nix b/pkgs/misc/cups/drivers/kyocera/default.nix index 28b2a1281761e..12e6f5bb4baee 100644 --- a/pkgs/misc/cups/drivers/kyocera/default.nix +++ b/pkgs/misc/cups/drivers/kyocera/default.nix @@ -1,4 +1,9 @@ -{ stdenv, lib, fetchzip, cups }: +{ lib +, stdenv +, cups +, fetchzip +, patchPpdFilesHook +}: let platform = @@ -23,6 +28,8 @@ stdenv.mkDerivation { sha256 = "0z1pbgidkibv4j21z0ys8cq1lafc6687syqa07qij2qd8zp15wiz"; }; + nativeBuildInputs = [ patchPpdFilesHook ]; + installPhase = '' tar -xvf ${platform}/Global/English.tar.gz install -Dm755 English/rastertokpsl $out/lib/cups/filter/rastertokpsl @@ -33,13 +40,11 @@ stdenv.mkDerivation { mkdir -p $out/share/cups/model/Kyocera cd English - for i in *.ppd; do - sed -i $i -e \ - "s,/usr/lib/cups/filter/rastertokpsl,$out/lib/cups/filter/rastertokpsl,g" - cp $i $out/share/cups/model/Kyocera - done; + cp *.ppd $out/share/cups/model/Kyocera ''; + ppdFileCommands = [ "rastertokpsl" ]; + meta = with lib; { description = "CUPS drivers for several Kyocera FS-{1020,1025,1040,1060,1120,1125} printers"; homepage = "https://www.kyoceradocumentsolutions.ru/index/service_support/download_center.false.driver.FS1040._.EN.html#"; From bfe3271fc0cc6d0a471f8ef4ebe466cd8cf4c949 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 21:41:32 +0200 Subject: [PATCH 06/13] samsung-unified-linux-driver (cups driver): use patchPpdFilesHook The `sed` script in the `installPhase` is removed. Instead, the setup hook `patchPpdFilesHook` is used to patch the path to the filter executables. The result should essentially be the same. Comparing the generated ppd files showed no difference, short of the package's hash in the absolute paths and added newline characters at the end of some ppd files. Missing newline characters at the end of the last line are apparently added by `awk`; this shouldn't affect functionality. The new package also contains a `propagated-build-inputs` file which propagates the package itself. This ensures the package is available whenever a ppd file is singled out by another package. --- pkgs/misc/cups/drivers/samsung/4.01.17.nix | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pkgs/misc/cups/drivers/samsung/4.01.17.nix b/pkgs/misc/cups/drivers/samsung/4.01.17.nix index 12cfcde82f76a..dc9cb8f0515bb 100644 --- a/pkgs/misc/cups/drivers/samsung/4.01.17.nix +++ b/pkgs/misc/cups/drivers/samsung/4.01.17.nix @@ -11,7 +11,13 @@ # } # (This advice was tested on the 1st November 2016.) -{ lib, stdenv, fetchurl, cups, libusb-compat-0_1 }: +{ lib +, stdenv +, cups +, libusb-compat-0_1 +, fetchurl +, patchPpdFilesHook +}: # Do not bump lightly! Visit # to see what will break when upgrading. Consider a new versioned attribute. @@ -28,6 +34,8 @@ in stdenv.mkDerivation rec { sha256 = "1vv3pzvqpg1dq3xjr8161x2yp3v7ca75vil56ranhw5pkjwq66x0"; }; + nativeBuildInputs = [ patchPpdFilesHook ]; + dontPatchELF = true; dontStrip = true; @@ -63,15 +71,11 @@ in stdenv.mkDerivation rec { mkdir -p $out/share/cups/model/samsung cd - cd ../noarch/at_opt/share/ppd - for i in *.ppd; do - sed -i $i -e \ - "s,pstosecps,$out/lib/cups/filter/pstosecps,g; \ - s,pstospl,$out/lib/cups/filter/pstospl,g; \ - s,rastertospl,$out/lib/cups/filter/rastertospl,g" - done; cp -r ./* $out/share/cups/model/samsung ''; + ppdFileCommands = [ "pstosecps" "pstospl" "rastertospl" ]; + meta = with lib; { description = "Samsung's Linux printing drivers; includes binaries without source code"; homepage = "http://www.samsung.com/"; From bafefd7ae237ce6f82300a3093574c1c697bb8ce Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Thu, 8 Jul 2021 20:54:30 +0200 Subject: [PATCH 07/13] samsung-unified-linux-driver (cups driver): patch all filters ppd files in the `samsung-unified-linux-driver` package invoke these filter commands: * pstosecps * pstospl * rastertospl * pstosplc The paths to all of those commands excluding the last one got patched with their absolute paths during the build process. This commit adds the last one to the list of commands to be patched. --- pkgs/misc/cups/drivers/samsung/4.01.17.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/misc/cups/drivers/samsung/4.01.17.nix b/pkgs/misc/cups/drivers/samsung/4.01.17.nix index dc9cb8f0515bb..e03dbe458abaf 100644 --- a/pkgs/misc/cups/drivers/samsung/4.01.17.nix +++ b/pkgs/misc/cups/drivers/samsung/4.01.17.nix @@ -74,7 +74,12 @@ in stdenv.mkDerivation rec { cp -r ./* $out/share/cups/model/samsung ''; - ppdFileCommands = [ "pstosecps" "pstospl" "rastertospl" ]; + ppdFileCommands = [ + "pstosecps" + "pstospl" + "pstosplc" + "rastertospl" + ]; meta = with lib; { description = "Samsung's Linux printing drivers; includes binaries without source code"; From cd4c8d63f5698d86960086c3d0e3c94c08efd285 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 20:52:43 +0200 Subject: [PATCH 08/13] foomatic-db-engine: init at unstable-2022-05-03 `foomatic-db-engine` contains several perl scripts to parse and process XML files from the Foomatic database packages. It can be used to extract ppd files, which will be accomplished in a follow-up commit. The package also contains scripts to handle print queues and jobs. It can -- optionally -- talk to the local cups server, to network printers and to SMB print servers. The build recipe contains switches to enable these features; however, they are not needed when generating ppd files. There is a daily snapshot of a source archive available at https://www.openprinting.org/download/foomatic/ . However, these files rotate daily and cannot be used as a stable download source. So we rely on OpenPrinting's Github repository instead and pinpoint a fresh commit. --- .../drivers/foomatic-db-engine/default.nix | 94 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 + 2 files changed, 96 insertions(+) create mode 100644 pkgs/misc/cups/drivers/foomatic-db-engine/default.nix diff --git a/pkgs/misc/cups/drivers/foomatic-db-engine/default.nix b/pkgs/misc/cups/drivers/foomatic-db-engine/default.nix new file mode 100644 index 0000000000000..b5e107ebf37f4 --- /dev/null +++ b/pkgs/misc/cups/drivers/foomatic-db-engine/default.nix @@ -0,0 +1,94 @@ +{ lib +, perlPackages +, fetchFromGitHub +, withCupsAccess ? false # needed to access local cups server +, cups +, cups-filters +, curl +, withSocketAccess ? false # needed to access network printers +, netcat-gnu +, withSMBAccess ? false # needed to access SMB-connected printers +, samba +, autoconf +, automake +, file +, makeWrapper +}: + +perlPackages.buildPerlPackage { + pname = "foomatic-db-engine"; + version = "unstable-2022-05-03"; + + src = fetchFromGitHub { + # there is also a daily snapshot at the `downloadPage`, + # but it gets deleted quickly and would provoke 404 errors + owner = "OpenPrinting"; + repo = "foomatic-db-engine"; + rev = "2e6f14b54748fa121a4d2e3d480010e10b070c5a"; + hash = "sha256-m7FQTxWmawbtm24h8UqznGKXgX41JhOtyyFMRwEhm5k="; + }; + + outputs = [ "out" ]; + + propagatedBuildInputs = [ + perlPackages.Clone + perlPackages.DBI + perlPackages.XMLLibXML + ]; + + buildInputs = + # provide some "cups-*" commands to `foomatic-{configure,printjob}` + # so that they can manage a local cups server (add queues, add jobs...) + lib.optionals withCupsAccess [ cups cups-filters curl ] + # the commands `foomatic-{configure,getpjloptions}` need + # netcat if they are used to query or alter a network + # printer via AppSocket/HP JetDirect protocol + ++ lib.optional withSocketAccess netcat-gnu + # `foomatic-configure` can be used to access printers that are + # shared via the SMB protocol, but it needs the `smbclient` binary + ++ lib.optional withSMBAccess samba + ; + + nativeBuildInputs = [ autoconf automake file makeWrapper ]; + + # sed-substitute indirection is more robust against + # characters in paths that might need escaping + prePatch = '' + sed -Ei 's|^(S?BINSEARCHPATH=).+$|\1"@PATH@"|g' configure.ac + substituteInPlace configure.ac --subst-var PATH + touch Makefile.PL # `buildPerlPackage` fails unless this exists + ''; + + preConfigure = '' + ./make_configure + ''; + + configureFlags = [ + "--sysconfdir=${placeholder "out"}/etc" + "LIBDIR=${placeholder "out"}/share/foomatic" + "PERLPREFIX=${placeholder "out"}" + ]; + + postFixup = '' + for bin in "${placeholder "out"}/bin"/*; do + test '!' -L "$bin" || continue # skip symlink + wrapProgram "$bin" --set PERL5LIB "$PERL5LIB" + done + ''; + + doCheck = false; # no tests, would fail + + meta = { + description = "OpenPrinting printer support database engine"; + downloadPage = "https://www.openprinting.org/download/foomatic/"; + homepage = "https://openprinting.github.io/projects/02-foomatic/"; + license = lib.licenses.gpl2Only; + maintainers = [ lib.maintainers.yarny ]; + longDescription = '' + Foomatic's database engine generates PPD files + from the data in Foomatic's XML database. + It also contains scripts to directly + generate print queues and handle jobs. + ''; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 5b1faf8d586b4..088bea97441ab 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -36319,6 +36319,8 @@ with pkgs; epson-workforce-635-nx625-series = callPackage ../misc/drivers/epson-workforce-635-nx625-series { }; + foomatic-db-engine = callPackage ../misc/cups/drivers/foomatic-db-engine {}; + gutenprint = callPackage ../misc/drivers/gutenprint { }; gutenprintBin = callPackage ../misc/drivers/gutenprint/bin.nix { }; From 90a8a78e7c703ec6d9a4e9d5251f09823498bc12 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 20:51:01 +0200 Subject: [PATCH 09/13] foomatic-db (cups ppd files): init at unstable/2022-10-03 `foomatic-db` contains the collected knowledge about printers, drivers, and driver options from OpenPrinting in xml files. It also provides thousands of ppd files. The build process patches those files to reference executables in the nix store and gzips them to reduce storage (from about 670 MiB to 90 MiB installed). In contrast to the sister package `foomatic-db-nonfree` (packaged in a follow-up commit), this package only includes files published under a free license. Most files are published under the GPL, some under the MIT license. For details see https://github.com/OpenPrinting/foomatic-db/blob/master/COPYING . To encompass the different licenses, the package's license is set to "free" as the common denominator. ppd files can be found in `$out/share/cups/model/foomatic-db`. The subdirectory `foomatic-db` is used to avoid conflicts with other packages that might be combined with the package `foomatic-db` in `config.services.printing.drivers`. There is a daily snapshot of a source archive available at https://www.openprinting.org/download/foomatic/ . However, these files rotate daily and cannot be used as a stable download source. So we rely on OpenPrinting's Github repository instead and pinpoint a fresh commit. --- .../misc/cups/drivers/foomatic-db/default.nix | 99 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 1 + 2 files changed, 100 insertions(+) create mode 100644 pkgs/misc/cups/drivers/foomatic-db/default.nix diff --git a/pkgs/misc/cups/drivers/foomatic-db/default.nix b/pkgs/misc/cups/drivers/foomatic-db/default.nix new file mode 100644 index 0000000000000..26cbc29424758 --- /dev/null +++ b/pkgs/misc/cups/drivers/foomatic-db/default.nix @@ -0,0 +1,99 @@ +{ lib +, stdenv +, fetchFromGitHub +, cups +, cups-filters +, ghostscript +, gnused +, perl +, autoconf +, automake +, patchPpdFilesHook +}: + +stdenv.mkDerivation { + pname = "foomatic-db"; + version = "unstable-2022-10-03"; + + src = fetchFromGitHub { + # there is also a daily snapshot at the `downloadPage`, + # but it gets deleted quickly and would provoke 404 errors + owner = "OpenPrinting"; + repo = "foomatic-db"; + rev = "2a3c4d1bf7eadc42f936ce8989c1dd2973ea9669"; + hash = "sha256-in0/j1nAQvM0NowBIBx3jj5WVMPIfZAeAk1SkuA3tjA="; + }; + + buildInputs = [ cups cups-filters ghostscript gnused perl ]; + + nativeBuildInputs = [ autoconf automake patchPpdFilesHook perl ]; + + # sed-substitute indirection is more robust + # against characters in paths that might need escaping + postPatch = '' + sed -Ei -e 's|^(S?BINSEARCHPATH=).+$|\1"@PATH@"|g' \ + -e 's|^(DATASEARCHPATH=).+$|\1"@DATA@"|g' configure.ac + substituteInPlace configure.ac \ + --subst-var PATH \ + --subst-var-by DATA "${placeholder "out"}/share" + ''; + + preConfigure = '' + mkdir -p "${placeholder "out"}/share/foomatic/db/source" + ./make_configure + ''; + + # don't let the intaller gzip ppd files as we would + # have to unzip them later in order to patch them + configureFlags = [ "--disable-gzip-ppds" ]; + + # make ppd files available to cups, + # use a package-specific subdirectory to avoid + # conflicts with other ppd-containing packages + postInstall = '' + if ! [[ -d "${placeholder "out"}/share/foomatic/db/source/PPD" ]]; then + echo "failed to create share/foomatic/db/source/PPD" + exit 1 + fi + mkdir -p "${placeholder "out"}/share/cups/model" + ln -s "${placeholder "out"}/share/foomatic/db/source/PPD" \ + "${placeholder "out"}/share/cups/model/foomatic-db" + ''; + + # Comments indicate the respective + # package the command is contained in. + ppdFileCommands = [ + "cat" "date" "printf" # coreutils + "rastertohp" # cups + "foomatic-rip" # cups-filters or foomatic-filters + "gs" # ghostscript + "sed" # gnused + "perl" # perl + ]; + + # compress ppd files + postFixup = '' + echo 'compressing ppd files' + find -H "${placeholder "out"}/share/cups/model/foomatic-db" -type f -iname '*.ppd' -print0 \ + | xargs -0r -n 64 -P "$NIX_BUILD_CORES" gzip -9n + ''; + + meta = { + description = "OpenPrinting printer support database (free content)"; + downloadPage = "https://www.openprinting.org/download/foomatic/"; + homepage = "https://openprinting.github.io/projects/02-foomatic/"; + license = lib.licenses.free; # mostly GPL and MIT, see README in source dir + maintainers = [ lib.maintainers.yarny ]; + # list printer manufacturers here so people + # searching for ppd files can find this package + longDescription = '' + The collected knowledge about printers, + drivers, and driver options in XML files. + Besides the XML files, this package contains + about 6,600 PPD files, for printers from + Brother, Canon, Epson, Gestetner, HP, InfoPrint, + Infotec, KONICA_MINOLTA, Kyocera, Lanier, Lexmark, NRG, + Oce, Oki, Ricoh, Samsung, Savin, Sharp, Toshiba and Utax. + ''; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 088bea97441ab..ecfd91fd865c0 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -36319,6 +36319,7 @@ with pkgs; epson-workforce-635-nx625-series = callPackage ../misc/drivers/epson-workforce-635-nx625-series { }; + foomatic-db = callPackage ../misc/cups/drivers/foomatic-db {}; foomatic-db-engine = callPackage ../misc/cups/drivers/foomatic-db-engine {}; gutenprint = callPackage ../misc/drivers/gutenprint { }; From 156cc612ff9588cbcdfb858c0086ee250b42c781 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Wed, 7 Jul 2021 20:51:57 +0200 Subject: [PATCH 10/13] foomatic-db-nonfree (cups ppd files): init at unstable/2015-06-05 `foomatic-db-nonfree` contains -- similar to its sister package `foomatic-db` -- knowledge about printers, drivers, and driver options from OpenPrinting in xml files. It needs to be combined with the `foomatic-db` package to yield a working database. It also provides about 100 (gzipped) ppd files. In contrast to `foomatic-db`, this package contains data that is provided under non-free licenses. Quoting https://github.com/OpenPrinting/foomatic-db-nonfree/blob/master/README > This is a repository of PPD and Foomatic XML files that may > have restrictions that keep them from being used on a variety > of machines for licensing and other non-technical reasons. ppd files can be found in `$out/share/cups/model/foomatic-db-nonfree`. The subdirectory `foomatic-db-nofree` is used to avoid conflicts with other packages that might be combined with the package `foomatic-db-nonfree` in `config.services.printing.drivers`. ppd files in this package are *not* patched to call executables from the nix store: The only executable "rastertophaser6100" that is called from ppd files isn't available in nixpkgs. There is a daily snapshot of a source archive available at https://www.openprinting.org/download/foomatic/ . However, these files rotate daily and cannot be used as a stable download source. So we rely on OpenPrinting's Github repository instead and pinpoint a fresh commit. Note that the current version is from 2015, so updates are unlikely. --- .../drivers/foomatic-db-nonfree/default.nix | 82 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 1 + 2 files changed, 83 insertions(+) create mode 100644 pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix diff --git a/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix b/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix new file mode 100644 index 0000000000000..bf569d522aabd --- /dev/null +++ b/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix @@ -0,0 +1,82 @@ +{ lib +, stdenv +, fetchFromGitHub +, autoconf +, automake +, perl +}: + +stdenv.mkDerivation { + pname = "foomatic-db-nonfree"; + version = "unstable-2015-06-05"; + + src = fetchFromGitHub { + # there is also a daily snapshot at the `downloadPage`, + # but it gets deleted quickly and would provoke 404 errors + owner = "OpenPrinting"; + repo = "foomatic-db-nonfree"; + rev = "6ddae02ac89240c019f8b5026cfe70e30fd2b3db"; + hash = "sha256-cRZH0CXg03FEqUJdxaNnPVXjf8+ct86PjhL59WQbw60="; + }; + + nativeBuildInputs = [ autoconf automake perl ]; + + # sed-substitute indirection is more robust against + # characters in paths that might need escaping + postPatch = '' + sed -Ei -e 's|^(S?BINSEARCHPATH=).+$|\1"@PATH@"|g' \ + -e 's|^(DATASEARCHPATH=).+$|\1"@DATA@"|g' configure.ac + substituteInPlace configure.ac \ + --subst-var PATH \ + --subst-var-by DATA "${placeholder "out"}/share" + ''; + + preConfigure = '' + mkdir -p "${placeholder "out"}/share/foomatic/db/source" + ./make_configure + ''; + + # make ppd files available to cups, + # use a package-specific subdirectory to avoid + # conflicts with other ppd-containing packages + postInstall = '' + if ! [[ -d "${placeholder "out"}/share/foomatic/db/source/PPD" ]]; then + echo "failed to create share/foomatic/db/source/PPD" + exit 1 + fi + mkdir -p "${placeholder "out"}/share/cups/model" + ln -s "${placeholder "out"}/share/foomatic/db/source/PPD" \ + "${placeholder "out"}/share/cups/model/foomatic-db-nonfree" + ''; + + # we might patch ppd file commands with `patchPpdFilesHook`, + # but the only command "rastertophaser6100" isn't packaged yet + + # compress ppd files + postFixup = '' + echo 'compressing ppd files' + find -H "${placeholder "out"}/share/cups/model/foomatic-db-nonfree" -type f -iname '*.ppd' -print0 \ + | xargs -0r -n 64 -P "$NIX_BUILD_CORES" gzip -9n + ''; + + meta = { + description = "OpenPrinting printer support database (unfree content)"; + downloadPage = "https://www.openprinting.org/download/foomatic/"; + homepage = "https://openprinting.github.io/projects/02-foomatic/"; + license = lib.licenses.unfree; + maintainers = [ lib.maintainers.yarny ]; + # list printer manufacturers here so people + # searching for ppd files can find this package + longDescription = '' + The collected knowledge about printers, + drivers, and driver options in XML files. + This is a package of PPD and Foomatic XML files + that may have restrictions that keep them + from being used on a variety of machines + for licensing and other non-technical reasons. + Besides the XML files, this package contains + about 130 PPD files, for printers from + Dell, Genicom, Lexmark, Oce and Xerox. + ''; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index ecfd91fd865c0..d8edb369e1d07 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -36321,6 +36321,7 @@ with pkgs; foomatic-db = callPackage ../misc/cups/drivers/foomatic-db {}; foomatic-db-engine = callPackage ../misc/cups/drivers/foomatic-db-engine {}; + foomatic-db-nonfree = callPackage ../misc/cups/drivers/foomatic-db-nonfree {}; gutenprint = callPackage ../misc/drivers/gutenprint { }; From 075d11213142f0f8b96b3213a6714df6ae7395be Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Thu, 8 Jul 2021 20:18:11 +0200 Subject: [PATCH 11/13] foomatic-db-ppds (cups ppd files): init `foomatic-db-ppds` uses the Foomatic database from the packages `foomatic-db` and -- optionally -- `foomatic-db-nonfree` and the perl modules from `foomatic-db-engine` to generate about 8,800 ppd files. The general structure of the build recipe is as follows: * Merge `foomatic-db` and `foomatic-db-nonfree` into one package that represents the Foomatic database. The package `foomatic-db-nonfree` is optional as it taints the result license-wise; it will only be used if `withNonfreeDb` is to to `true` in the `callPackage` call. We create a tiny setup hook script that provides the combined database and sets an environment variable pointing to the database direcotry, which is expected by the foomatic engine. * The final package's license and version are computed from the licenses and versions of the database packages. The license is set to `free` if each database-providing package has a free license, and to `unfree` otherwise. The version is simply the highest version of the database-providing packages. * The final package uses `foomatic-compiledb` from the `foomatic-db-engine` package to extract all ppd files from the database packages. `patchPpdFilesHook` is used to patch most executable invocations in the ppd files so that they point to nix store paths. Finally, ppd files are gzipped to reduce storage (from about 550 MiB to 90 MiB installed). The "nonfree" version of the package, i.e. the version that is based on `foomatic-db-nonfree` in addition to `foomatic-db`, contains about 120 additional ppd files compared to the "free" version. Since the "free" version already produces about 8,700 ppd files and hydra won't build the "nonfree" version, the commit adds two package variables to `all-packages.nix`: * `foomatic-db-ppds` is based on `foomatic-db` only * `foomatic-db-ppds-withNonfreeDb` is also based on `foomaitc-db-nonfree` The package introduced by this commit is the result of combining other packages; it is not the build product of a simple source tarball. While it would also be possible to perform the ppd file generation directly in the build process of the database packages, this would yield further complexity as the `foomatic-db-nonfree` package needs to be combined with the `foomatic-db` package before ppd file extraction is possible. There is no upstream product with a name that could/should be used for the `name` attribute, the variable name, or for the filename in nixpkgs. Similar packages have different names across distributions: * https://repology.org/projects/?search=openprinting * https://repology.org/projects/?search=foomatic The name `foomatic-db-ppds` seems to be most common (albeit not really *that* common): * https://repology.org/project/foomatic-db-ppds/versions At least openSUSE splits their corresponding package into multiple "binary" packages (similar to our multi-output packages): * https://build.opensuse.org/package/binaries/Printing/OpenPrintingPPDs/openSUSE_Tumbleweed I considered something similar. However, after doing some statistics, I concluded that it's not worth the effort: The biggest dependencies (`perl` and `cups-filters`) are already present on most NixOS systems, and they cannot be "split away" easily since it cannot be done along a canonical line (e.g. printer driver). Splitting directly by dependency risks that ppd files unexpectedly "move from output to output" on package updates; disappearing ppd files can be quite annoying for package users. --- .../drivers/foomatic-db-nonfree/default.nix | 6 +- .../cups/drivers/foomatic-db-ppds/default.nix | 122 ++++++++++++++++++ .../misc/cups/drivers/foomatic-db/default.nix | 5 +- pkgs/top-level/all-packages.nix | 2 + 4 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix diff --git a/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix b/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix index bf569d522aabd..1c38ae38b98a8 100644 --- a/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix +++ b/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix @@ -69,11 +69,15 @@ stdenv.mkDerivation { # searching for ppd files can find this package longDescription = '' The collected knowledge about printers, - drivers, and driver options in XML files. + drivers, and driver options in XML files, + used by `foomatic-db-engine` to generate PPD files. This is a package of PPD and Foomatic XML files that may have restrictions that keep them from being used on a variety of machines for licensing and other non-technical reasons. + The XML files in this package enable `foomatic-db-ppds` + to create about 120 additional PPD files, for printer from + Dell, Genicom, Lexmark, Oce, Tektronix and Xerox. Besides the XML files, this package contains about 130 PPD files, for printers from Dell, Genicom, Lexmark, Oce and Xerox. diff --git a/pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix b/pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix new file mode 100644 index 0000000000000..bdc1e0a9b5feb --- /dev/null +++ b/pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix @@ -0,0 +1,122 @@ +{ lib +, foomatic-db +, foomatic-db-nonfree +, buildEnv +, foomatic-db-engine +, stdenv +, cups-filters +, ghostscript +, netpbm +, perl +, psutils +, patchPpdFilesHook +, withNonfreeDb ? false # include foomatic-db-nonfree ppd files +}: + +let + foomatic-db-packages = [ foomatic-db ] ++ + lib.lists.optional withNonfreeDb foomatic-db-nonfree; + + foomatic-db-combined = buildEnv { + name = "foomatic-db-combined"; + paths = foomatic-db-packages; + pathsToLink = [ "/share/foomatic" ]; + # `foomatic-db-combined` is a nativeBuildInput of `foomatic-db-ppds`. + # The setup hook defined here helps scripts in + # `foomatic-db-engine` to find the database. + postBuild = '' + mkdir -p "${placeholder "out"}"/{etc/cups,nix-support} + cat >> "${placeholder "out"}/nix-support/setup-hook" << eof + export FOOMATICDB="${placeholder "out"}/share/foomatic" + eof + ''; + }; + + # the effective license is `free` if all database + # packages have free licenses, `unfree` otherwise + isFree = lib.trivial.pipe foomatic-db-packages [ + (lib.lists.map (lib.attrsets.attrByPath [ "meta" "license" ] lib.licenses.unfree)) + (lib.lists.all (lib.attrsets.attrByPath [ "free" ] true)) + ]; +in + +stdenv.mkDerivation { + pname = "foomatic-db-ppds"; + # the effective version is simply the + # highest version of all database packages + version = lib.trivial.pipe foomatic-db-packages [ + (lib.lists.map (lib.attrsets.getAttr "version")) + (lib.lists.sort lib.strings.versionOlder) + lib.lists.reverseList + lib.lists.head + ]; + + buildInputs = [ + cups-filters + ghostscript + netpbm + perl + psutils + ]; + + nativeBuildInputs = [ + foomatic-db-combined + foomatic-db-engine + patchPpdFilesHook + ]; + + dontUnpack = true; + + installPhase = '' + runHook preInstall + mkdir -p "${placeholder "out"}/share/cups/model" + foomatic-compiledb -j "$NIX_BUILD_CORES" -d "${placeholder "out"}/share/cups/model/foomatic-db-ppds" + runHook postInstall + ''; + + # Comments indicate the respective + # package the command is contained in. + ppdFileCommands = [ + "cat" "echo" # coreutils + "foomatic-rip" # cups-filters or foomatic-filters + "gs" # ghostscript + "pnmflip" "pnmgamma" "pnmnoraw" # netpbm + "perl" # perl + "psresize" # psutils + # These commands aren't packaged yet. + # ppd files using these likely won't work. + #"c2050" "c2070" "cjet" "lm1100" + #"pbm2l2030" "pbm2lwxl" "rastertophaser6100" + ]; + + # compress ppd files + postFixup = '' + echo 'compressing ppd files' + find -H "${placeholder "out"}/share/cups/model/foomatic-db-ppds" -type f -iname '*.ppd' -print0 \ + | xargs -0r -n 64 -P "$NIX_BUILD_CORES" gzip -9n + ''; + + meta = { + description = "OpenPrinting ppd files"; + homepage = "https://openprinting.github.io/projects/02-foomatic/"; + license = if isFree then lib.licenses.free else lib.licenses.unfree; + maintainers = [ lib.maintainers.yarny ]; + # list printer manufacturers here so people + # searching for ppd files can find this package + longDescription = '' + All PPD files available in + OpenPrinting's Foomatic database. + This package contains about 8,800 PPD files, + for printers from + Alps, Anitech, Apollo, Apple, Avery, Brother, Canon, + Citizen, CItoh, Compaq, DEC, Dell, Dymo-CoStar, Epson, + Fujitsu, FujiXerox, Generic, Genicom, Gestetner, + Heidelberg, Hitachi, HP, IBM, Imagen, Imagistics, + InfoPrint, Infotec, Kodak, KONICAMINOLTA, Kyocera, Lanier, + Lexmark, Minolta, MinoltaQMS, Mitsubishi, NEC, NRG, Oce, + Oki, Olivetti, Panasonic, PCPI, Pentax, QMS, Raven, Ricoh, + Samsung, Savin, Seiko, Sharp, SiPix, Sony, Star, Tally, + Tektronix, TexasInstruments, Toshiba, Xante and Xerox. + ''; + }; +} diff --git a/pkgs/misc/cups/drivers/foomatic-db/default.nix b/pkgs/misc/cups/drivers/foomatic-db/default.nix index 26cbc29424758..dd76fb1ee05b4 100644 --- a/pkgs/misc/cups/drivers/foomatic-db/default.nix +++ b/pkgs/misc/cups/drivers/foomatic-db/default.nix @@ -88,7 +88,10 @@ stdenv.mkDerivation { # searching for ppd files can find this package longDescription = '' The collected knowledge about printers, - drivers, and driver options in XML files. + drivers, and driver options in XML files, + used by `foomatic-db-engine` to generate PPD files. + PPD files generated from the XML files in this package + are contained in the package 'foomatic-db-ppds'. Besides the XML files, this package contains about 6,600 PPD files, for printers from Brother, Canon, Epson, Gestetner, HP, InfoPrint, diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index d8edb369e1d07..bce606d56c659 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -36322,6 +36322,8 @@ with pkgs; foomatic-db = callPackage ../misc/cups/drivers/foomatic-db {}; foomatic-db-engine = callPackage ../misc/cups/drivers/foomatic-db-engine {}; foomatic-db-nonfree = callPackage ../misc/cups/drivers/foomatic-db-nonfree {}; + foomatic-db-ppds = callPackage ../misc/cups/drivers/foomatic-db-ppds {}; + foomatic-db-ppds-withNonfreeDb = callPackage ../misc/cups/drivers/foomatic-db-ppds { withNonfreeDb = true; }; gutenprint = callPackage ../misc/drivers/gutenprint { }; From 2c28e0dc18110736437e2a0b760aa933dd475ee0 Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Sun, 22 Aug 2021 19:40:05 +0200 Subject: [PATCH 12/13] cups-kyocera (cups driver): call {pre,post}Install Add `preInstall` and `postInstall` to the `installPhase` to permit package overrides to add commands to the install phase. Suggested by r-rmcgibbo bot in https://github.com/NixOS/nixpkgs/pull/133537#issuecomment-897437621 --- pkgs/misc/cups/drivers/kyocera/default.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/misc/cups/drivers/kyocera/default.nix b/pkgs/misc/cups/drivers/kyocera/default.nix index 12e6f5bb4baee..0a560e3188f63 100644 --- a/pkgs/misc/cups/drivers/kyocera/default.nix +++ b/pkgs/misc/cups/drivers/kyocera/default.nix @@ -31,6 +31,8 @@ stdenv.mkDerivation { nativeBuildInputs = [ patchPpdFilesHook ]; installPhase = '' + runHook preInstall + tar -xvf ${platform}/Global/English.tar.gz install -Dm755 English/rastertokpsl $out/lib/cups/filter/rastertokpsl patchelf \ @@ -41,6 +43,8 @@ stdenv.mkDerivation { mkdir -p $out/share/cups/model/Kyocera cd English cp *.ppd $out/share/cups/model/Kyocera + + runHook postInstall ''; ppdFileCommands = [ "rastertokpsl" ]; From 0d36fdc66bb40f9471e63d41c4f2246da1e8e5ea Mon Sep 17 00:00:00 2001 From: Yarny0 <41838844+Yarny0@users.noreply.github.com> Date: Sun, 22 Aug 2021 19:47:02 +0200 Subject: [PATCH 13/13] samsung-unified-linux-driver (cups driver): call {pre,post}Install Add `preInstall` and `postInstall` to the `installPhase` to permit package overrides to add commands to the install phase. Suggested by r-rmcgibbo bot in https://github.com/NixOS/nixpkgs/pull/133537#issuecomment-897437621 --- pkgs/misc/cups/drivers/samsung/1.00.36/default.nix | 3 +++ pkgs/misc/cups/drivers/samsung/1.00.37.nix | 3 +++ pkgs/misc/cups/drivers/samsung/4.01.17.nix | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix b/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix index fac3dfccba620..47700265231f2 100644 --- a/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix +++ b/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix @@ -23,6 +23,7 @@ in stdenv.mkDerivation rec { ]; installPhase = '' + runHook preInstall mkdir -p $out/bin cp -R ${arch}/{gettext,pstosecps,rastertospl,smfpnetdiscovery,usbresetter} $out/bin @@ -82,6 +83,8 @@ in stdenv.mkDerivation rec { cd $out/share/cups ln -s ../ppd . ln -s ppd model + + runHook postInstall ''; preFixup = '' diff --git a/pkgs/misc/cups/drivers/samsung/1.00.37.nix b/pkgs/misc/cups/drivers/samsung/1.00.37.nix index 0aab52eac5dac..59a210e6f534e 100644 --- a/pkgs/misc/cups/drivers/samsung/1.00.37.nix +++ b/pkgs/misc/cups/drivers/samsung/1.00.37.nix @@ -22,6 +22,7 @@ in stdenv.mkDerivation rec { ]; installPhase = '' + runHook preInstall mkdir -p $out/bin cp -R ${arch}/{gettext,pstosecps,rastertospl,smfpnetdiscovery,usbresetter} $out/bin @@ -65,6 +66,8 @@ in stdenv.mkDerivation rec { cd $out/share/cups ln -s ../ppd . ln -s ppd model + + runHook postInstall ''; preFixup = '' diff --git a/pkgs/misc/cups/drivers/samsung/4.01.17.nix b/pkgs/misc/cups/drivers/samsung/4.01.17.nix index e03dbe458abaf..3347030174783 100644 --- a/pkgs/misc/cups/drivers/samsung/4.01.17.nix +++ b/pkgs/misc/cups/drivers/samsung/4.01.17.nix @@ -40,6 +40,8 @@ in stdenv.mkDerivation rec { dontStrip = true; installPhase = '' + runHook preInstall + cd Linux/${installationPath} mkdir -p $out/lib/cups/{backend,filter} install -Dm755 mfp $out/lib/cups/backend/ @@ -72,6 +74,8 @@ in stdenv.mkDerivation rec { cd - cd ../noarch/at_opt/share/ppd cp -r ./* $out/share/cups/model/samsung + + runHook postInstall ''; ppdFileCommands = [