Hi Guix, I'd like to raise concerns about Guix's current approach to software configuration management. Configuration schemas are inherently public interfaces of software, valid only for specific package versions. Currently, Guix separates these interfaces from the software they originate from. We place =define-configuration= forms directly within Guix's source code, which presents several drawbacks:
- *Potential breakage upon package updates:* Updating a package version can inadvertently break Guix services that rely on it. For example, a removed run argument could cause the application to error upon startup. - *Duplication of documentation:* The documentation for these records often duplicates information already provided with the software itself, leading to redundancy and potential inconsistencies. An illustrative example is mpv, where each version can introduce changes to dozens of configuration options and run arguments: (see https://github.com/mpv-player/mpv/blob/master/DOCS/interface-changes.rst) Therefore, I propose the following: Define "binding" Guix packages that provide Scheme code encompassing: - Configuration data structures (records, =define-configuration= forms, alists, etc.). - Serializers for converting these structures into the software's native configuration format. - Run arguments specifications, detailing available options and their expected types. - Procedures for generating run commands based on the specified configuration. So, for e.g. =mpv@0.40.0= we can define =mpv-guix-bindings@0.40.0= package that depends either on =mpv= or its source: - in the build phase generate scheme files by parsing the source code or the output of =mpv --list-options= - in the =check= phase verify that no changes happened in the public interfaces (e.g. checksum of the input data used to generate code) Then in Guix: - remove existing configurations and documentation - import configurations from binding modules, e.g. =(use-config-bindings pkg)= would add =pkg-guix-bindings= modules to =%load-path= - use the bindings where necessary, e.g.: --8<---------------cut here---------------start------------->8--- ; generate config (pkg-serialize-config (pkg-configuration (option-foo? #t))) ; prepare run arguments (make-forkexec-constructor '(#$pkg #$@(pkg-run-args (pkg-options (daemon? #t))) #$(pkg-serialize-config cfg))) --8<---------------cut here---------------end--------------->8--- Thoughts?