]> git.proxmox.com Git - dh-cargo.git/blob - cargo.pm
Run `cargo build` during dh_auto_test
[dh-cargo.git] / cargo.pm
1 # debhelper buildsystem for Rust crates using Cargo
2 #
3 # Josh Triplett <josh@joshtriplett.org>
4
5 package Debian::Debhelper::Buildsystem::cargo;
6
7 use strict;
8 use warnings;
9 use Cwd;
10 use Debian::Debhelper::Dh_Lib;
11 use Dpkg::Changelog::Debian;
12 use Dpkg::Control::Info;
13 use Dpkg::Version;
14 use base 'Debian::Debhelper::Buildsystem';
15
16 sub DESCRIPTION {
17 "Rust Cargo"
18 }
19
20 sub check_auto_buildable {
21 my $this = shift;
22 if (-f $this->get_sourcepath("Cargo.toml")) {
23 return 1;
24 }
25 return 0;
26 }
27
28 sub new {
29 my $class = shift;
30 my $this = $class->SUPER::new(@_);
31 $this->enforce_in_source_building();
32 return $this;
33 }
34
35 sub pre_building_step {
36 my $this = shift;
37 my $step = shift;
38
39 $this->{cargo_home} = Cwd::abs_path($this->get_sourcepath("debian/cargo_home"));
40 $this->{cargo_registry} = Cwd::abs_path($this->get_sourcepath("debian/cargo_registry"));
41
42 my $control = Dpkg::Control::Info->new();
43
44 my $source = $control->get_source();
45 my $crate = $source->{'X-Cargo-Crate'};
46 if (!$crate) {
47 $crate = $source->{Source};
48 $crate =~ s/^rust-//;
49 $crate =~ s/-[0-9]+(\.[0-9]+)*$//;
50 }
51 $this->{crate} = $crate;
52 my $changelog = Dpkg::Changelog::Debian->new(range => { count => 1 });
53 $changelog->load($this->get_sourcepath("debian/changelog"));
54 $this->{version} = Dpkg::Version->new(@{$changelog}[0]->get_version())->version();
55
56 my @packages = $control->get_packages();
57 $this->{libpkg} = 0;
58 $this->{binpkg} = 0;
59 $this->{featurepkg} = [];
60 foreach my $package (@packages) {
61 if ($package->{Package} =~ /^librust-.*-dev$/ && $package->{Architecture} eq 'all') {
62 if ($package->{Package} =~ /\+/) {
63 push(@{$this->{featurepkg}}, $package->{Package});
64 next;
65 }
66 if ($this->{libpkg}) {
67 error("Multiple Cargo lib packages found: " . $this->{libpkg} . " and " . $package->{Package});
68 }
69 $this->{libpkg} = $package->{Package};
70 } elsif ($package->{Architecture} ne 'all') {
71 $this->{binpkg} = $package->{Package};
72 }
73 }
74 if (!$this->{libpkg} && !$this->{binpkg}) {
75 error("Could not find any Cargo lib or bin packages to build.");
76 }
77 if (@{$this->{featurepkg}} && !$this->{libpkg}) {
78 error("Found feature packages but no lib package.");
79 }
80
81 my $parallel = $this->get_parallel();
82 $this->{j} = $parallel > 0 ? ["-j$parallel"] : [];
83
84 $this->SUPER::pre_building_step($step);
85 }
86
87 sub get_sources {
88 my $this=shift;
89 opendir(my $dirhandle, $this->get_sourcedir());
90 my @sources = grep { $_ ne '.' && $_ ne '..' && $_ ne '.git' && $_ ne 'debian' } readdir($dirhandle);
91 closedir($dirhandle);
92 @sources
93 }
94
95 sub configure {
96 my $this=shift;
97 # Create a fake local registry $this->{cargo_registry} with only our dependencies
98 my $crate = $this->{crate} . '-' . $this->{version};
99 my $registry = $this->{cargo_registry};
100 doit("mkdir", "-p", $this->{cargo_home}, $registry);
101 opendir(my $dirhandle, '/usr/share/cargo/registry');
102 my @crates = map { "/usr/share/cargo/registry/$_" } grep { $_ ne '.' && $_ ne '..' } readdir($dirhandle);
103 closedir($dirhandle);
104 if (@crates) {
105 doit("ln", "-st", "$registry", @crates);
106 }
107 # Handle the case of building the package with the same version of the
108 # package installed.
109 if (-l "$registry/$crate") {
110 unlink("$registry/$crate");
111 }
112 mkdir("$registry/$crate");
113 my @sources = $this->get_sources();
114 doit("cp", "-at", "$registry/$crate", @sources);
115 doit("cp", $this->get_sourcepath("debian/cargo-checksum.json"), "$registry/$crate/.cargo-checksum.json");
116
117 open(CONFIG, ">" . $this->{cargo_home} . "/config");
118 print(CONFIG qq{
119 [source.crates-io]
120 replace-with = "dh-cargo-registry"
121
122 [source.dh-cargo-registry]
123 directory = "$registry"
124 });
125 close(CONFIG);
126 }
127
128 sub test {
129 my $this=shift;
130 $ENV{'CARGO_HOME'} = $this->{cargo_home};
131 # Check that the thing compiles. This might fail if e.g. the package
132 # requires non-rust system dependencies and the maintainer didn't provide
133 # this additional information to debcargo.
134 doit("cargo", "build", "--verbose", "--avoid-dev-deps");
135 }
136
137 sub install {
138 my $this=shift;
139 $ENV{'CARGO_HOME'} = $this->{cargo_home};
140 my $crate = $this->{crate} . '-' . $this->{version};
141 if ($this->{libpkg}) {
142 my $target = $this->get_sourcepath("debian/" . $this->{libpkg} . "/usr/share/cargo/registry/$crate");
143 my @sources = $this->get_sources();
144 doit("mkdir", "-p", $target);
145 doit("cp", "-at", $target, @sources);
146 doit("rm", "-rf", "$target/target");
147 doit("cp", $this->get_sourcepath("debian/cargo-checksum.json"), "$target/.cargo-checksum.json");
148 }
149 foreach my $pkg (@{$this->{featurepkg}}) {
150 my $target = $this->get_sourcepath("debian/$pkg/usr/share/doc");
151 doit("mkdir", "-p", $target);
152 doit("ln", "-s", $this->{libpkg}, "$target/$pkg");
153 }
154 if ($this->{binpkg}) {
155 my $target = $this->get_sourcepath("debian/" . $this->{binpkg} . "/usr");
156 doit("cargo", "install", $this->{crate}, "--verbose", "--vers", $this->{version}, "--root", $target, @{$this->{j}});
157 doit("rm", "$target/.crates.toml");
158 }
159 }
160
161 sub clean {
162 my $this=shift;
163 doit("rm", "-rf", $this->{cargo_home}, $this->{cargo_registry});
164 }
165
166 1