EDIT 2023-10-17: Package specifications in Scheme cannot have versions. IRC Logs
Guix has a notion of a package specification, and it is what Guix defaults to in many cases. From my understanding the reason Guix defaults to using specifications in automatically-generated places is because they are easier to programmatically handle. Using specifications means raw variables are not used, which could be renamed later. It also means that no modules need to be imported, as Guix looks up the packages at run-time.
This post is meant as an introduction to Guix's use of package specifications, and not a comprehensive block of documentation. If something is missing from here or you simply wish to read more, please see the manual. If you need to get cooking with specifications quickly, the cookbook is a good resource.
Package Specifications
Package specifications area convenient way to name packages with specific properties.
For example, the libgccjit
package has multiple versions defined and multiple outputs.
A package output is a way to split up the resulting files for distribution. This is typically done for particularly large packages or for ones that have somewhat independent output components. For example, libgccjit 12.3.0's
out
output is 279.4MiB, but itsdebug
output is 669.0 MiB.
Specifications support two modifiers, the version to use and the package output to select.
You must always provide the package's name, which can be found with guix search
or by reading Guix's package definition's name
field.
NOTE: A package's name does not have to correspond to its variable/symbol name.
So a fully-specified package is written:
package-name@version:output
NOTE: You must follow this ordering! The following will produce an error:
guix shell package-name:output@version # error: package `package-name@<default-version>' lacks output `output@version'
The reason this happens is because the Guix procedure which parses specifications will misunderstand your specification request. Typed incorrectly, it believes "
output@version
" is an output of the default package, which it certainly will not be.
However, you are not forced to always specify everything. You can do something like below:
package-name@version
package-name:output
You are more likely to use the package-name@version
variant than package-name:output
, as what you want is usually in the default out
output.
An Example
If you ask Guix to give you libgccjit
, Guix will give you the default libgccjit
version's out
(the default) output.
guix shell libgccjit
On Guix commit 1328c4c
, libgccjit defaults to 12.3.0.
This may (will probably) be different for different versions of Guix.
libgccjit is both the name of the package and the symbol that refers to the package. On the command-line (and almost everywhere else a specification is used), the package's name is what is used.
If we wanted, we could have manually asked for any other version Guix currently (1328c4c
) supports.
guix shell libgccjit@10.4.0
This will put you in a shell where libgccjit 10.4.0 is available.
You want libgccjit
's debug information for the currently-default libgccjit version?
guix shell libgccjit:debug
Guix strips debug information by default, as a majority of users and uses of a program do not require the debugging information, which consumes a significant amount of space.
But say you wanted the debug information for libgccjit
10.4.0, what would you type?
guix shell libgccjit@10.4.0:debug
Like stated previously, building the specification in the wrong order will produce an error.
guix shell libgccjit:debug@10.4.0 # guix shell: error: package `libgccjit@12.3.0' lacks output `debug@10.4.0'
With that, we have covered all possible ways to use a specification. The next section discusses how to use specifications on both the command-line (like I was just showing) and from within Scheme.
Using Specifications
All of the example above showed how to use specifications on the command-line, but that was only with guix shell
.
Extra information about using specifications on the command-line with other commands Guix has for packages are in the next section.
Then we move on to discussing how to use specifications in Scheme.
On the Command Line
All of the examples from the previous section used the guix shell
command, which allows you to use the full specification syntax on the command-line.
However, not all commands support all of the specification options!
In particular, guix build
only allows version numbers!
This works:
guix build libgccjit@10.4.0
But this fails:
guix build libgccjit@10.4.0:debug # guix build: error: libgccjit: package not found for version 10.4.0:debug
This makes sense as
guix build
builds a package, which necessarily means all outputs need to be built.
As far as I can tell, all other package-operating commands allow the use of the full specification syntax. This includes:
guix shell
guix install
In Scheme
If you want to use an exact specification in Scheme, replace the bare package's variable/symbol name with a list.
;; libgccjit:debug instead of the default
(list libgccjit "debug")
NOTE: You can only specify an output, not a version, and not the full specification.
In Scheme, you can replace a package with its list-specification anywhere a package is expected.
As an example, let us assume there is a package named example
that uses the default libgccjit version Guix sets that we want to replace the default output with the debug
one.
(use-modules (gnu packages)
(gnu packages gcc))
(package
(name "example")
... ;; Unnecessary fields omitted
;; Commented-out portion below is the original definition
;; (native-inputs
;; (list libgccjit))
(native-inputs
;; libgccjit here is the SYMBOL for the package, NOT the package's name.
;; This is the only way a package's name is not used for a specification.
(list (list libgccjit "debug"))))
As stated earlier, this replacement can be done anywhere a package is expected. That includes:
- The
operating-system
package list - The
home-environment
package list packages->manifest
lists
You can also provide the specification as a string, if you use the specification->package
procedure.
This procedure returns the specification's corresponding package
object.
This behaves the exact same way as on the command-line (in fact, the command-line tools use this exact procedure).
A common example you will see is creating a manifest out of specifications, which automates the process of going from specification to package to manifest.
(use-modules (gnu packages)) ;; To access specifications->manifest
;; Manifest with default libgccjit and debug information for libgccjit 10.4.0
(specifications->manifest
;; libgccjit here is the NAME of the package, NOT the symbol!
(list "libgccjit@10.4.0:debug"
"libgccjit"))
Reproducibility
As always, reproducibility is cornerstone of Guix.
To make any Guix package specification reproducible, you need to know the Guix commit to use.
This can be done with the guix describe
command to lock the commits and guix time-machine
to use those commits.
guix describe --format=channels > channels-lock.scm
I do not discuss
guix describe
orguix time-machine
much here because this post is about specifications. Another post will be coming out soon about some Guix commands, or you can read the manual pages aboutguix describe
andguix time-machine
.
Conclusion
Guix uses a custom specification syntax to make specific package selection easier. The complete and correct syntax is:
package-name@version:output
Almost all package-operating commands in Guix accept the full syntax.
The exception is guix build
, which does not accept an output
selection.
Specifications are effectively packages, and as such, they can be used anywhere Guix expects a package
object, in both Scheme and on the command-line; so long as the specification somehow corresponds to a package
object.
Finally, specifications can be made reproducible by locking the channels with guix describe
and guix time-machine
.
This concise syntax makes working with Guix from the command-line simpler to read and type, and makes selecting the right thing easier.
I hope this post helped explain package specifications, as much of this was collected by testing, experience, and trawling the documentation. As always, please refer to the manual for complete documentation.