xref: /OK3568_Linux_fs/buildroot/docs/manual/adding-packages-cargo.txt (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun// -*- mode:doc; -*-
2*4882a593Smuzhiyun// vim: set syntax=asciidoc:
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun=== Integration of Cargo-based packages
5*4882a593Smuzhiyun
6*4882a593SmuzhiyunCargo is the package manager for the Rust programming language. It allows the
7*4882a593Smuzhiyunuser to build programs or libraries written in Rust, but it also downloads and
8*4882a593Smuzhiyunmanages their dependencies, to ensure repeatable builds. Cargo packages are
9*4882a593Smuzhiyuncalled "crates".
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun[[cargo-package-tutorial]]
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun==== Cargo-based package's +Config.in+ file
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunThe +Config.in+ file of Cargo-based package 'foo' should contain:
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun---------------------------
18*4882a593Smuzhiyun01: config BR2_PACKAGE_FOO
19*4882a593Smuzhiyun02: 	bool "foo"
20*4882a593Smuzhiyun03: 	depends on BR2_PACKAGE_HOST_RUSTC_TARGET_ARCH_SUPPORTS
21*4882a593Smuzhiyun04: 	select BR2_PACKAGE_HOST_RUSTC
22*4882a593Smuzhiyun05: 	help
23*4882a593Smuzhiyun06: 	  This is a comment that explains what foo is.
24*4882a593Smuzhiyun07:
25*4882a593Smuzhiyun08: 	  http://foosoftware.org/foo/
26*4882a593Smuzhiyun---------------------------
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun==== Cargo-based package's +.mk+ file
29*4882a593Smuzhiyun
30*4882a593SmuzhiyunBuildroot does not (yet) provide a dedicated package infrastructure for
31*4882a593SmuzhiyunCargo-based packages. So, we will explain how to write a +.mk+ file for such a
32*4882a593Smuzhiyunpackage. Let's start with an example:
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun------------------------------
35*4882a593Smuzhiyun01: ################################################################################
36*4882a593Smuzhiyun02: #
37*4882a593Smuzhiyun03: # foo
38*4882a593Smuzhiyun04: #
39*4882a593Smuzhiyun05: ################################################################################
40*4882a593Smuzhiyun06:
41*4882a593Smuzhiyun07: FOO_VERSION = 1.0
42*4882a593Smuzhiyun08: FOO_SOURCE = foo-$(FOO_VERSION).tar.gz
43*4882a593Smuzhiyun09: FOO_SITE = http://www.foosoftware.org/download
44*4882a593Smuzhiyun10: FOO_LICENSE = GPL-3.0+
45*4882a593Smuzhiyun11: FOO_LICENSE_FILES = COPYING
46*4882a593Smuzhiyun12:
47*4882a593Smuzhiyun13: FOO_DEPENDENCIES = host-rustc
48*4882a593Smuzhiyun14:
49*4882a593Smuzhiyun15: FOO_CARGO_ENV = CARGO_HOME=$(HOST_DIR)/share/cargo
50*4882a593Smuzhiyun16:
51*4882a593Smuzhiyun17: FOO_BIN_DIR = target/$(RUSTC_TARGET_NAME)/$(FOO_CARGO_MODE)
52*4882a593Smuzhiyun18:
53*4882a593Smuzhiyun19: FOO_CARGO_OPTS = \
54*4882a593Smuzhiyun20: 	$(if $(BR2_ENABLE_DEBUG),,--release) \
55*4882a593Smuzhiyun21: 	--target=$(RUSTC_TARGET_NAME) \
56*4882a593Smuzhiyun22: 	--manifest-path=$(@D)/Cargo.toml
57*4882a593Smuzhiyun23:
58*4882a593Smuzhiyun24: define FOO_BUILD_CMDS
59*4882a593Smuzhiyun25: 	$(TARGET_MAKE_ENV) $(FOO_CARGO_ENV) \
60*4882a593Smuzhiyun26: 		cargo build $(FOO_CARGO_OPTS)
61*4882a593Smuzhiyun27: endef
62*4882a593Smuzhiyun28:
63*4882a593Smuzhiyun29: define FOO_INSTALL_TARGET_CMDS
64*4882a593Smuzhiyun30: 	$(INSTALL) -D -m 0755 $(@D)/$(FOO_BIN_DIR)/foo \
65*4882a593Smuzhiyun31: 		$(TARGET_DIR)/usr/bin/foo
66*4882a593Smuzhiyun32: endef
67*4882a593Smuzhiyun33:
68*4882a593Smuzhiyun34: $(eval $(generic-package))
69*4882a593Smuzhiyun--------------------------------
70*4882a593Smuzhiyun
71*4882a593SmuzhiyunThe Makefile starts with the definition of the standard variables for package
72*4882a593Smuzhiyundeclaration (lines 7 to 11).
73*4882a593Smuzhiyun
74*4882a593SmuzhiyunAs seen in line 34, it is based on the
75*4882a593Smuzhiyunxref:generic-package-tutorial[+generic-package+ infrastructure]. So, it defines
76*4882a593Smuzhiyunthe variables required by this particular infrastructure, where Cargo is
77*4882a593Smuzhiyuninvoked:
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun* +FOO_BUILD_CMDS+: Cargo is invoked to perform the build. The options required
80*4882a593Smuzhiyun  to configure the cross-compilation of the package are passed via
81*4882a593Smuzhiyun  +FOO_CONF_OPTS+.
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun* +FOO_INSTALL_TARGET_CMDS+: The binary executable generated is installed on
84*4882a593Smuzhiyun  the target.
85*4882a593Smuzhiyun
86*4882a593SmuzhiyunIn order to have Cargo available for the build, +FOO_DEPENDENCIES+ needs to
87*4882a593Smuzhiyuncontain +host-cargo+.
88*4882a593Smuzhiyun
89*4882a593SmuzhiyunTo sum it up, to add a new Cargo-based package, the Makefile example can be
90*4882a593Smuzhiyuncopied verbatim then edited to replace all occurences of +FOO+ with the
91*4882a593Smuzhiyunuppercase name of the new package and update the values of the standard
92*4882a593Smuzhiyunvariables.
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun==== About Dependencies Management
95*4882a593Smuzhiyun
96*4882a593SmuzhiyunA crate can depend on other libraries from crates.io or git repositories, listed
97*4882a593Smuzhiyunin its Cargo.toml file. Before starting a build, Cargo usually downloads
98*4882a593Smuzhiyunautomatically them. This step can also be performed independently, via the
99*4882a593Smuzhiyun+cargo fetch+ command.
100*4882a593Smuzhiyun
101*4882a593SmuzhiyunCargo maintains a local cache of the registry index and of git checkouts of the
102*4882a593Smuzhiyuncrates, whose location is given by +$CARGO_HOME+. As seen in the package
103*4882a593SmuzhiyunMakefile example at line 15, this environment variable is set to
104*4882a593Smuzhiyun+$(HOST_DIR)/share/cargo+.
105*4882a593Smuzhiyun
106*4882a593SmuzhiyunThis dependency download mechanism is not convenient when performing an offline
107*4882a593Smuzhiyunbuild, as Cargo will fail to fetch the dependencies. In that case, it is advised
108*4882a593Smuzhiyunto generate a tarball of the dependencies using the +cargo vendor+ and add it to
109*4882a593Smuzhiyun+FOO_EXTRA_DOWNLOADS+.
110