summaryrefslogtreecommitdiff
path: root/doc/guix-cookbook.texi
diff options
context:
space:
mode:
authorHilton Chain <hako@ultrarare.space>2025-03-18 14:22:55 +0800
committerHilton Chain <hako@ultrarare.space>2025-08-21 19:09:04 +0800
commit3e45fc0f37d027516ac3d112ca7768d698eeac74 (patch)
tree77c7cd59f5b7027ed37e07a1f97522fbab0f132d /doc/guix-cookbook.texi
parent92d130e03594bd2b8e6688c83fc35a3f2c2954da (diff)
doc: Document lockfile importer based Rust packaging workflow.
* doc/guix.texi (Build Systems) [cargo-build-system]: Add cross-reference for the term "Cargo workspaces". * doc/contributing.texi (Packaging Guidelines)[Rust Crates]: Update documentation. * doc/guix-cookbook.texi (Packaging)[Packaging Workflow]: New section. * gnu/packages/rust-crates.scm, * gnu/packages/rust-sources.scm: Stop mentioning guix-rust-registry for now, we may remove the repository if future merges are managed well. Change-Id: Ic0c6378cf5f5df97d6f8bdd040b486be62c7bddc
Diffstat (limited to 'doc/guix-cookbook.texi')
-rw-r--r--doc/guix-cookbook.texi377
1 files changed, 377 insertions, 0 deletions
diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi
index b0567047033..bd2add42856 100644
--- a/doc/guix-cookbook.texi
+++ b/doc/guix-cookbook.texi
@@ -106,6 +106,7 @@ Scheme tutorials
106Packaging 106Packaging
107 107
108* Packaging Tutorial:: A tutorial on how to add packages to Guix. 108* Packaging Tutorial:: A tutorial on how to add packages to Guix.
109* Packaging Workflows:: Real life examples on working with specific build systems.
109 110
110Packaging Tutorial 111Packaging Tutorial
111 112
@@ -130,6 +131,16 @@ Programmable and automated package definition
130* Automatic update:: 131* Automatic update::
131* Inheritance:: 132* Inheritance::
132 133
134Packaging Workflows
135
136* Packaging Rust Crates::
137
138Packaging Rust Crates
139
140* Common Workflow for Rust Packaging::
141* Cargo Workspaces and Development Snapshots::
142* Using Rust Libraries in Other Build Systems::
143
133System Configuration 144System Configuration
134 145
135* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY 146* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY
@@ -519,6 +530,7 @@ them.
519 530
520@menu 531@menu
521* Packaging Tutorial:: A tutorial on how to add packages to Guix. 532* Packaging Tutorial:: A tutorial on how to add packages to Guix.
533* Packaging Workflows:: Real life examples on working with specific build systems.
522@end menu 534@end menu
523 535
524@node Packaging Tutorial 536@node Packaging Tutorial
@@ -1599,6 +1611,371 @@ The @uref{https://guix.gnu.org/manual/en/html_node/Defining-Packages.html, packa
1599@uref{https://guix.gnu.org/guix-ghm-andreas-20130823.pdf, ``GNU Guix: Package without a scheme!''}, by Andreas Enge 1611@uref{https://guix.gnu.org/guix-ghm-andreas-20130823.pdf, ``GNU Guix: Package without a scheme!''}, by Andreas Enge
1600@end itemize 1612@end itemize
1601 1613
1614@node Packaging Workflows
1615@section Packaging Workflows
1616
1617The following sections provide real-life examples on working with specific build
1618systems, serving as extensions to the concise packaging guidelines
1619(@pxref{Packaging Guidelines,,, guix, GNU Guix Reference Manual}).
1620
1621@menu
1622* Packaging Rust Crates::
1623@end menu
1624
1625@node Packaging Rust Crates
1626@subsection Packaging Rust Crates
1627
1628In preparation, add the following packages to our environment:
1629
1630@example
1631$ guix shell rust rust:cargo cargo-audit cargo-license
1632@end example
1633
1634@menu
1635* Common Workflow for Rust Packaging::
1636* Cargo Workspaces and Development Snapshots::
1637* Using Rust Libraries in Other Build Systems::
1638@end menu
1639
1640@node Common Workflow for Rust Packaging
1641@subsubsection Common Workflow for Rust Packaging
1642
1643In this example, we'll package @code{cargo-audit}, which is published on the
1644@uref{https://crates.io, crates.io} Rust package repository. All its
1645dependencies are on crates.io as well.
1646
1647@enumerate
1648@item
1649Since @code{cargo-audit} is available on crates.io, we can generate a template
1650via the crates.io importer (@pxref{Invoking guix import,,, guix, GNU Guix
1651Reference Manual}):
1652
1653@example
1654$ guix import crate cargo-audit
1655@end example
1656
1657After manual editing, we'll have the following definiton:
1658
1659@lisp
1660(define-public cargo-audit
1661 (package
1662 (name "cargo-audit")
1663 (version "0.21.2")
1664 (source
1665 (origin
1666 (method url-fetch)
1667 (uri (crate-uri "cargo-audit" version))
1668 (file-name (string-append name "-" version ".tar.gz"))
1669 (sha256
1670 (base32 "1a00yqpckkw86zh2hg7ra82c5fx0ird5766dyynimbvqiwg2ps0n"))))
1671 (build-system cargo-build-system)
1672 (arguments (list #:install-source? #f))
1673 (inputs (cargo-inputs 'cargo-audit))
1674 (home-page "https://rustsec.org/")
1675 (synopsis "Audit Cargo.lock for crates with security vulnerabilities")
1676 (description
1677 "This package provides a Cargo subcommand, @@command@{cargo audit@}, to
1678audit @@file@{Cargo.lock@} for crates with security vulnerabilities.")
1679 (license (list license:asl2.0 license:expat))))
1680@end lisp
1681
1682The identifier used to invoke @code{cargo-inputs}, in this case
1683@code{'cargo-audit}, must be unique, usually matching the variable name of the
1684package.
1685
1686@item
1687Unpack package source and navigate to the unpacked directory, then run the
1688following commands:
1689
1690@example
1691$ cargo generate-lockfile
1692$ cargo audit
1693$ cargo license
1694@end example
1695
1696@command{cargo generate-lockfile} updates dependencies to compatible versions.
1697Applying it to all Rust applications helps reduce a great number of Rust
1698libraries we need to check later. Although sometimes libraries may fail to
1699follow the @uref{https://semver.org/, semantic versioning} scheme, it's still
1700acceptable.
1701
1702@command{cargo audit} checks known vulnerabilities and @command{cargo license}
1703checks licenses, for all the dependencies. We must have an acceptable output of
1704@command{cargo audit} and ensure all dependencies are licensed with our
1705supported licenses (@pxref{Defining Packages,,, guix, GNU Guix Reference
1706Manual}).
1707
1708@item
1709Import dependencies from the generated lockfile:
1710
1711@example
1712$ guix import --insert=gnu/packages/rust-crates.scm \
1713 crate --lockfile=/path/to/Cargo.lock cargo-audit
1714
1715# Or use short options, in this case the shell processes file names
1716# before passing them to Guix, allowing tilde expansion, for example.
1717$ guix import -i gnu/packages/rust-crates.scm \
1718 crate -f /path/to/Cargo.lock cargo-audit
1719@end example
1720
1721@code{cargo-audit} here must be consistent with the identifier used for
1722@code{cargo-inputs} invocation in the package definition.
1723
1724At this stage, the package @code{cargo-audit} is buildable.
1725
1726@item
1727Finally we'll unbundle the vendored dependencies. The lockfile importer
1728inserts @code{TODO:} comments for libraries with high probability of
1729bundled dependencies. @code{cargo-build-system} also performs
1730additional check for binary files in its
1731@code{check-for-pregenerated-files} phase, which usually indicates
1732bundling:
1733
1734@example
1735$ ./pre-inst-env guix build cargo-audit
1736@dots{}
1737starting phase `check-for-pregenerated-files'
1738Searching for binary files...
1739./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/dictionary-rust
1740./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/dictionary-rust-other
1741./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/lib.rs.zst
1742./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/long-window-size-lib.rs.zst
1743./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_aclui.a
1744./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_activeds.a
1745./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_asycfilt.a
1746./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_amsi.a
1747@dots{}
1748@end example
1749
1750Although Rust libraries are not publicly exported, we can still select them via
1751the Guix command-line interface via a Guile expression:
1752
1753@example
1754$ guix build --expression='(@@@@ (gnu packages rust-crates) rust-ring-0.17.14)'
1755@end example
1756
1757To unbundle most dependencies, a snippet is sufficient:
1758
1759@lisp
1760(define rust-curl-sys-0.4.80+curl-8.12.1
1761 (crate-source "curl-sys" "0.4.80+curl-8.12.1"
1762 "0d7ppx4kq77hc5nyff6jydmfabpgd0i3ppjvn8x0q833mhpdzxsm"
1763 #:snippet '(delete-file-recursively "curl")))
1764@end lisp
1765
1766@lisp
1767(define rust-bzip2-sys-0.1.13+1.0.8
1768 (crate-source "bzip2-sys" "0.1.13+1.0.8"
1769 "056c39pgjh4272bdslv445f5ry64xvb0f7nph3z7860ln8rzynr2"
1770 #:snippet
1771 '(begin
1772 (delete-file-recursively "bzip2-1.0.8")
1773 (delete-file "build.rs")
1774 (with-output-to-file "build.rs"
1775 (lambda _
1776 (format #t "fn main() @{~@@
1777 println!(\"cargo:rustc-link-lib=bz2\");~@@
1778 @}~%"))))))
1779@end lisp
1780
1781In a more complex case, where unbundling one dependency requires a build process
1782that involves other packages, we should make a full package in @code{(gnu
1783packages rust-sources)} first and reference it in the imported definition.
1784
1785For example, we have defined a @code{rust-ring-0.17} in @code{(gnu packages
1786rust-sources)}, then the imported definition in @code{(gnu packages
1787rust-crates)} should be modified to reference it.
1788
1789@lisp
1790(define rust-ring-0.17.14 rust-ring-0.17)
1791@end lisp
1792
1793When one dependency can be safely removed, modify it to @code{#f}.
1794
1795@lisp
1796(define rust-openssl-src-300.4.2+3.4.1 #f)
1797@end lisp
1798
1799To facilitate various tasks in the common workflow, several scripts are provided
1800in the @file{etc/teams/rust} directory of Guix source tree.
1801@end enumerate
1802
1803@node Cargo Workspaces and Development Snapshots
1804@subsubsection Cargo Workspaces and Development Snapshots
1805
1806In this example, we'll package @code{niri}, which depends on development
1807snapshots (also Cargo workspaces here).
1808
1809As we can't ensure compatibility of a development snapshot, before executing
1810@command{cargo generate-lockfile}, we should modify @file{Cargo.toml} to pin it
1811to a known working revision.
1812
1813To use our packaged development snapshots, it's also necessary to modify
1814@file{Cargo.toml} in a build phase, with a package-specific substitution
1815pattern.
1816
1817@lisp
1818(define-public niri
1819 (package
1820 (name "niri")
1821 (version "25.02")
1822 (source (origin
1823 (method git-fetch)
1824 (uri (git-reference
1825 (url "https://github.com/YaLTeR/niri")
1826 (commit (string-append "v" version))))
1827 (file-name (git-file-name name version))
1828 (sha256
1829 (base32
1830 "0vzskaalcz6pcml687n54adjddzgf5r07gggc4fhfsa08h1wfd4r"))))
1831 (build-system cargo-build-system)
1832 (arguments
1833 (list #:install-source? #f
1834 #:phases
1835 #~(modify-phases %standard-phases
1836 (add-after 'unpack 'use-guix-vendored-dependencies
1837 (lambda _
1838 (substitute* "Cargo.toml"
1839 (("# version =.*")
1840 "version = \"*\"")
1841 (("git.*optional")
1842 "version = \"*\", optional")
1843 (("^git = .*")
1844 "")))))))
1845 (native-inputs
1846 (list pkg-config))
1847 (inputs
1848 (cons* clang
1849 libdisplay-info
1850 libinput-minimal
1851 libseat
1852 libxkbcommon
1853 mesa
1854 pango
1855 pipewire
1856 wayland
1857 (cargo-inputs 'niri)))
1858 (home-page "https://github.com/YaLTeR/niri")
1859 (synopsis "Scrollable-tiling Wayland compositor")
1860 (description
1861 "Niri is a scrollable-tiling Wayland compositor which arranges windows in a
1862scrollable format. It is considered stable for daily use and performs most
1863functions expected of a Wayland compositor.")
1864 (license license:gpl3+)))
1865@end lisp
1866
1867@code{niri} has Cargo workspace dependencies. When packaging a Cargo
1868workspace dependency, parameter @code{#:cargo-package-crates} is
1869required.
1870
1871@lisp
1872(define-public rust-pipewire-0.8.0.fd3d8f7
1873 (let ((commit "fd3d8f7861a29c2eeaa4c393402e013578bb36d9")
1874 (revision "0"))
1875 (package
1876 (name "rust-pipewire")
1877 (version (git-version "0.8.0" revision commit))
1878 (source
1879 (origin
1880 (method git-fetch)
1881 (uri (git-reference
1882 (url "https://gitlab.freedesktop.org/pipewire/pipewire-rs.git")
1883 (commit commit)))
1884 (file-name (git-file-name name version))
1885 (sha256
1886 (base32 "1hzyhz7xg0mz8a5y9j6yil513p1m610q3j9pzf6q55vdh5mcn79v"))))
1887 (build-system cargo-build-system)
1888 (arguments
1889 (list #:skip-build? #t
1890 #:cargo-package-crates
1891 ''("libspa-sys" "libspa" "pipewire-sys" "pipewire")))
1892 (inputs (cargo-inputs 'rust-pipewire-0.8.0.fd3d8f7))
1893 (home-page "https://pipewire.org/")
1894 (synopsis "Rust bindings for PipeWire")
1895 (description "This package provides Rust bindings for PipeWire.")
1896 (license license:expat))))
1897@end lisp
1898
1899Don't forget to modify all workspace members in @code{(gnu packages
1900rust-crates)}:
1901
1902@lisp
1903(define rust-pipewire-0.8.0.fd3d8f7 rust-pipewire-0.8.0.fd3d8f7)
1904(define rust-pipewire-sys-0.8.0.fd3d8f7 rust-pipewire-0.8.0.fd3d8f7)
1905@dots{}
1906(define rust-libspa-0.8.0.fd3d8f7 rust-pipewire-0.8.0.fd3d8f7)
1907(define rust-libspa-sys-0.8.0.fd3d8f7 rust-pipewire-0.8.0.fd3d8f7)
1908@end lisp
1909
1910@node Using Rust Libraries in Other Build Systems
1911@subsubsection Using Rust Libraries in Other Build Systems
1912
1913In this example, we'll package @code{libchewing}, which combines two build
1914systems.
1915
1916When building Rust packages in other build systems, we need to add @code{rust},
1917and @code{rust:cargo} to @code{native-inputs}, import and use modules from both
1918build systems, and apply necessary build phases from @code{cargo-build-system}.
1919
1920For cross-compilation support, we'll also add @code{rust-sysroot} created with
1921@code{(make-rust-sysroot (%current-target-system))} to @code{native-inputs}, and
1922set @code{#:cargo-target} for @code{cargo-build-system}'s build phases.
1923
1924@lisp
1925(define-public libchewing
1926 (package
1927 (name "libchewing")
1928 (version "0.9.1")
1929 (source
1930 (origin
1931 (method git-fetch)
1932 (uri (git-reference
1933 (url "https://github.com/chewing/libchewing")
1934 (commit (string-append "v" version))))
1935 (file-name (git-file-name name version))
1936 (sha256
1937 (base32 "0gh64wvrk5pn0fhmpvj1j99d5g7f7697rk96zbkc8l72yjr819z5"))))
1938 (build-system cmake-build-system)
1939 (arguments
1940 (list #:imported-modules
1941 (append %cmake-build-system-modules
1942 %cargo-build-system-modules)
1943 #:modules
1944 '(((guix build cargo-build-system) #:prefix cargo:)
1945 (guix build cmake-build-system)
1946 (guix build utils))
1947 #:phases
1948 #~(modify-phases %standard-phases
1949 (add-after 'unpack 'prepare-cargo-build-system
1950 (lambda args
1951 (for-each
1952 (lambda (phase)
1953 (format #t "Running cargo phase: ~a~%" phase)
1954 (apply (assoc-ref cargo:%standard-phases phase)
1955 ;; For cross-compilation.
1956 #:cargo-target #$(cargo-triplet)
1957 args))
1958 '(unpack-rust-crates
1959 configure
1960 check-for-pregenerated-files
1961 patch-cargo-checksums)))))))
1962 (native-inputs
1963 (append
1964 (list rust `(,rust "cargo") )
1965 ;; For cross-compilation.
1966 (or (and=> (%current-target-system)
1967 (compose list make-rust-sysroot))
1968 '())))
1969 (inputs
1970 (cons* corrosion ncurses sqlite (cargo-inputs 'libchewing)))
1971 (synopsis "Chinese phonetic input method")
1972 (description "Chewing is an intelligent phonetic (Zhuyin/Bopomofo) input
1973method, one of the most popular choices for Traditional Chinese users.")
1974 (home-page "https://chewing.im/")
1975 (license license:lgpl2.1+)))
1976@end lisp
1977
1978
1602@c ********************************************************************* 1979@c *********************************************************************
1603@node System Configuration 1980@node System Configuration
1604@chapter System Configuration 1981@chapter System Configuration