|
"succinct" is hard to answer. It depends a lot on the upstream package. For most packages the package expression looks like data: (define-public r-valr
(package
(name "r-valr")
(version "0.5.0")
(source
(origin
(method url-fetch)
(uri (cran-uri "valr" version))
(sha256
(base32
"14jhrwkiwmha3vlmm7b50n2xxyizj6ddmy89gb20mpzq7qhz1ika"))))
(build-system r-build-system)
(propagated-inputs
`(("r-broom" ,r-broom)
("r-dplyr" ,r-dplyr)
("r-ggplot2" ,r-ggplot2)
("r-rcpp" ,r-rcpp)
("r-readr" ,r-readr)
("r-rlang" ,r-rlang)
("r-stringr" ,r-stringr)
("r-tibble" ,r-tibble)))
(home-page "https://github.com/rnabioco/valr")
(synopsis "Genome interval arithmetic in R")
(description
"This package enables you to read and manipulate genome intervals and
signals. It provides functionality similar to command-line tool suites within
R, enabling interactive analysis and visualization of genome-scale data.")
(license license:expat)))
This defines the name "r-valr" to be a "package" value with the given fields. The "source" field describes how Guix should obtain the source tarball ("url-fetch" is a procedure that implements a URL downloader, but there are others like "git-fetch", "hg-fetch", etc) and what the hash of that data is supposed to be. The "build-system" field tells Guix how to build the thing. "r-build-system" is a very succinct way to say "do with this package as you do for all other R packages: unpack the tarball, run `R CMD bla`, then run the tests, etc". We've got quite a few such build systems: "gnu-build-system", "cmake-build-system", "python-build-system", "ant-build-system", ... All of these can be further configured via the "arguments" package field, which isn't used here, because this is a boring package.The "propagated-inputs" field is an association list of arbitrary labels to actual package values --- the things on the right hand side are variable names that are bound to package values, which are unquoted here, so this field really contains actual references to these other package values. The result is a lazily constructed graph of package values. Some packages can be really nasty, though, when the developers decided to ignore conventions and implement their very own way to build their very special software. We can usually accommodate those packages by starting out with e.g. the gnu-build-system and then modifying the build phases: deleting the "configure" phase, adding a custom phase before the "build", replacing the "install" phase, etc. The system is flexible enough for all of this, but for really ... special software I would no longer call this "succinct" or "intuitive". That said, most packages are easy. Almost all R packages, for example, look like the one above. But there are some really frustrating ones like Tensorflow (due to the fact that we use CMake instead of Bazel because Bazel hasn't been bootstrapped yet) or the old JDKs (that we use as part of a longer bootstrap chain) that are plain ugly. You just need to know when to give up, I suppose :) |
Oh gosh I relate to this. I tried to package 3DSlicer for NixOS, which uses a cmake superbuild of dozens of dependent projects, which it fetched during compile and required a very special GCC. I had to give up; it was making me too depressed.
Thank you for sharing how Guix derivations work. It seems very similar semantically to Nix, but I like the build-system method. In nix we have e.g. buildDotnetPackage, buildBazelPackage functions which are overridden, but there's not a clean interface for build systems. I like it.
Is the module system similar to Nix's? Nix modules define imports, config schema and config values, which are merged together to produce an expression for the state of the whole system, e.g. configuration.nix. How's that work in GuixSD?