mirror of
https://git.proxmox.com/git/dh-cargo
synced 2025-08-20 10:56:33 +00:00
206 lines
6.8 KiB
Perl
206 lines
6.8 KiB
Perl
# debhelper buildsystem for Rust crates using Cargo
|
|
#
|
|
# This builds Debian rust crates to be installed into a system-level
|
|
# crate registry in /usr/share/cargo/registry containing crates that
|
|
# can be used and Build-Depended upon by other Debian packages. The
|
|
# debcargo(1) tool will automatically generate Debian source packages
|
|
# that uses this buildsystem and packagers are not expected to use this
|
|
# directly which is why the documentation is poor.
|
|
#
|
|
# If you have a multi-language program such as firefox or librsvg that
|
|
# includes private Rust crates or libraries not exposed to others, you
|
|
# should instead use our cargo wrapper, in /usr/share/cargo/bin/cargo,
|
|
# which this script also uses. That file contains usage instructions.
|
|
# You then should define a Build-Depends on cargo and not dh-cargo.
|
|
# The Debian cargo package itself also uses the wrapper as part of its
|
|
# own build, which you can look at for a real usage example.
|
|
#
|
|
# Josh Triplett <josh@joshtriplett.org>
|
|
# Ximin Luo <infinity0@debian.org>
|
|
|
|
package Debian::Debhelper::Buildsystem::cargo;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Cwd;
|
|
use Debian::Debhelper::Dh_Lib;
|
|
use Dpkg::Changelog::Debian;
|
|
use Dpkg::Control::Info;
|
|
use Dpkg::Version;
|
|
use JSON::PP;
|
|
use base 'Debian::Debhelper::Buildsystem';
|
|
|
|
sub DESCRIPTION {
|
|
"Rust Cargo"
|
|
}
|
|
|
|
sub cargo_version {
|
|
my $src = shift;
|
|
open(F, "cargo metadata --manifest-path $src --no-deps --format-version 1 |");
|
|
local $/;
|
|
my $json = JSON::PP->new;
|
|
my $manifest = $json->decode(<F>);
|
|
return %{@{%{$manifest}{'packages'}}[0]}{'version'} . "";
|
|
}
|
|
|
|
sub deb_host_rust_type {
|
|
open(F, 'printf "include /usr/share/rustc/architecture.mk\n\
|
|
all:\n\
|
|
echo \$(DEB_HOST_RUST_TYPE)\n\
|
|
" | make --no-print-directory -sf - |');
|
|
$_ = <F>;
|
|
chomp;
|
|
return $_;
|
|
}
|
|
|
|
sub check_auto_buildable {
|
|
my $this = shift;
|
|
if (-f $this->get_sourcepath("Cargo.toml")) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $this = $class->SUPER::new(@_);
|
|
$this->enforce_in_source_building();
|
|
return $this;
|
|
}
|
|
|
|
sub pre_building_step {
|
|
my $this = shift;
|
|
my $step = shift;
|
|
|
|
# Many files are coming from crates.io with incorrect timestamp
|
|
# See https://github.com/rust-lang/crates.io/issues/3859
|
|
complex_doit("find . ! -newermt 'jan 01, 2000' -exec touch -d@" . $ENV{SOURCE_DATE_EPOCH} . " {} +");
|
|
|
|
$this->{cargo_home} = Cwd::abs_path("debian/cargo_home");
|
|
$this->{host_rust_type} = deb_host_rust_type;
|
|
|
|
my $control = Dpkg::Control::Info->new();
|
|
|
|
my $source = $control->get_source();
|
|
my $crate = $source->{'X-Cargo-Crate'};
|
|
if (!$crate) {
|
|
$crate = $source->{Source};
|
|
$crate =~ s/^ru[sz]t-//;
|
|
$crate =~ s/-[0-9]+(\.[0-9]+)*$//;
|
|
}
|
|
$this->{crate} = $crate;
|
|
my $changelog = Dpkg::Changelog::Debian->new(range => { count => 1 });
|
|
$changelog->load("debian/changelog");
|
|
$this->{version} = Dpkg::Version->new(@{$changelog}[0]->get_version())->version();
|
|
|
|
my @packages = $control->get_packages();
|
|
$this->{libpkg} = 0;
|
|
$this->{binpkg} = 0;
|
|
$this->{featurepkg} = [];
|
|
foreach my $package (@packages) {
|
|
if ($package->{Package} =~ /^libru[sz]t-.*-dev$/) {
|
|
if ($package->{Package} =~ /\+/) {
|
|
push(@{$this->{featurepkg}}, $package->{Package});
|
|
next;
|
|
}
|
|
if ($this->{libpkg}) {
|
|
error("Multiple Cargo lib packages found: " . $this->{libpkg} . " and " . $package->{Package});
|
|
}
|
|
$this->{libpkg} = $package->{Package};
|
|
} elsif ($package->{Architecture} ne 'all') {
|
|
$this->{binpkg} = $package->{Package};
|
|
}
|
|
}
|
|
if (!$this->{libpkg} && !$this->{binpkg}) {
|
|
error("Could not find any Cargo lib or bin packages to build.");
|
|
}
|
|
if (@{$this->{featurepkg}} && !$this->{libpkg}) {
|
|
error("Found feature packages but no lib package.");
|
|
}
|
|
|
|
my $parallel = $this->get_parallel();
|
|
$this->{j} = $parallel > 0 ? ["-j$parallel"] : [];
|
|
|
|
$ENV{'CARGO_HOME'} = $this->{cargo_home};
|
|
$ENV{'DEB_CARGO_CRATE'} = $crate . '_' . $this->{version};
|
|
$ENV{'DEB_HOST_RUST_TYPE'} = $this->{host_rust_type};
|
|
$ENV{'DEB_HOST_GNU_TYPE'} = dpkg_architecture_value("DEB_HOST_GNU_TYPE");
|
|
|
|
$this->SUPER::pre_building_step($step);
|
|
}
|
|
|
|
sub get_sources {
|
|
my $this=shift;
|
|
opendir(my $dirhandle, '.');
|
|
my @sources = grep { $_ ne '.' && $_ ne '..' && $_ ne '.git' && $_ ne '.pc' && $_ ne 'debian' } readdir($dirhandle);
|
|
push @sources, 'debian/patches' if -d 'debian/patches';
|
|
closedir($dirhandle);
|
|
@sources
|
|
}
|
|
|
|
sub configure {
|
|
my $this=shift;
|
|
doit("cp", "debian/cargo-checksum.json",
|
|
".cargo-checksum.json");
|
|
rm_files("Cargo.lock");
|
|
doit("/usr/share/cargo/bin/cargo", "prepare-debian", "debian/cargo_registry", "--link-from-system");
|
|
}
|
|
|
|
sub test {
|
|
my $this=shift;
|
|
my $cmd="build";
|
|
if (!defined $_[0]) {
|
|
# nop
|
|
} elsif ($_[0] eq "test") {
|
|
$cmd="test";
|
|
shift;
|
|
} elsif ($_[0] eq "build") {
|
|
shift;
|
|
}
|
|
# Check that the thing compiles. This might fail if e.g. the package
|
|
# requires non-rust system dependencies and the maintainer didn't provide
|
|
# this additional information to debcargo.
|
|
doit("/usr/share/cargo/bin/cargo", $cmd, @_);
|
|
# test generating Built-Using fields
|
|
doit("env", "CARGO_CHANNEL=debug", "/usr/share/cargo/bin/dh-cargo-built-using");
|
|
}
|
|
|
|
sub install {
|
|
my $this=shift;
|
|
my $destdir=shift;
|
|
my $crate = $this->{crate} . '-' . ($this->{version} =~ tr/~/-/r);
|
|
if ($this->{libpkg}) {
|
|
my $target = tmpdir($this->{libpkg}) . "/usr/share/cargo/registry/$crate";
|
|
my @sources = $this->get_sources();
|
|
install_dir($target);
|
|
doit("cp", "--parents", "-at", $target, @sources);
|
|
doit("rm", "-rf", "$target/target");
|
|
doit("cp", "debian/cargo-checksum.json", "$target/.cargo-checksum.json");
|
|
# prevent an ftpmaster auto-reject regarding files with old dates.
|
|
doit("touch", "-d@" . $ENV{SOURCE_DATE_EPOCH}, "$target/Cargo.toml");
|
|
}
|
|
foreach my $pkg (@{$this->{featurepkg}}) {
|
|
my $target = tmpdir($pkg) . "/usr/share/doc";
|
|
install_dir($target);
|
|
make_symlink_raw_target($this->{libpkg}, "$target/$pkg");
|
|
}
|
|
if ($this->{binpkg}) {
|
|
# Do the install
|
|
my $destdir = $ENV{'DESTDIR'} || tmpdir($this->{binpkg});
|
|
doit("env", "DESTDIR=$destdir",
|
|
"/usr/share/cargo/bin/cargo", "install", @_);
|
|
# generate Built-Using fields
|
|
doit("env", "/usr/share/cargo/bin/dh-cargo-built-using", $this->{binpkg});
|
|
}
|
|
}
|
|
|
|
sub clean {
|
|
my $this=shift;
|
|
doit("touch", "--no-create", "-d@" . $ENV{SOURCE_DATE_EPOCH}, ".cargo_vcs_info.json");
|
|
doit("/usr/share/cargo/bin/cargo", "clean", @_);
|
|
rm_files(".cargo-checksum.json");
|
|
doit("rm", "-rf", "debian/cargo_registry");
|
|
}
|
|
|
|
1
|