File Coverage

blib/lib/Module/Install/Rust.pm
Criterion Covered Total %
statement 17 55 30.9
branch 0 16 0.0
condition 0 4 0.0
subroutine 6 16 37.5
pod 6 6 100.0
total 29 97 29.9


line stmt bran cond sub pod time code
1             package Module::Install::Rust;
2              
3 1     1   12697 use 5.006;
  1         2  
4 1     1   3 use strict;
  1         1  
  1         15  
5 1     1   2 use warnings;
  1         3  
  1         23  
6              
7 1     1   340 use Module::Install::Base;
  1         2  
  1         22  
8 1     1   423 use TOML 0.97 ();
  1         17789  
  1         19  
9 1     1   5 use Config ();
  1         1  
  1         456  
10              
11             our @ISA = qw( Module::Install::Base );
12              
13             =head1 NAME
14              
15             Module::Install::Rust - Helpers to build Perl extensions written in Rust
16              
17             =head1 VERSION
18              
19             Version 0.02
20              
21             =cut
22              
23             our $VERSION = '0.03';
24              
25              
26             =head1 SYNOPSIS
27              
28             # In Makefile.PL
29             use inc::Module::Install;
30              
31             # ...
32              
33             rust_requires libc => "0.2";
34             rust_write;
35              
36             WriteAll;
37              
38             =head1 DESCRIPTION
39              
40             This package allows L to build Perl extensions written in Rust.
41              
42             =head1 COMMANDS
43              
44             =head2 rust_requires
45              
46             rust_requires libc => "0.2";
47             rust_requires internal_crate => { path => "../internal_crate" };
48              
49             This command is used to specify Rust dependencies. First argument should be a
50             crate name, second - either a version string, or a hashref with keys per Cargo
51             manifest spec.
52              
53             =cut
54              
55             sub rust_requires {
56 0     0 1   my ($self, $name, $spec) = @_;
57 0           $self->{rust_requires}{$name} = $spec;
58             }
59              
60             =head2 rust_feature
61              
62             rust_feature default => [ "some_feature" ];
63             rust_feature some_feature => [ "some-crate/feature" ];
64              
65             This command adds items to C<[features]> section of the generated C.
66              
67             =cut
68              
69             sub rust_feature {
70 0     0 1   my ($self, $name, $spec) = @_;
71 0 0         die "Feature $name is already defined" if $self->{rust_features}{$name};
72 0           $self->{rust_features}{$name} = $spec;
73             }
74              
75             =head2 rust_profile
76              
77             rust_profile debug => { "opt-level" => 1 };
78             rust_profile release => { lto => 1 };
79              
80             This command configures a C<[profile]> section to the generated C.
81              
82             =cut
83              
84             sub rust_profile {
85 0     0 1   my ($self, $name, $spec) = @_;
86 0 0         die "Profile $name is already configured" if $self->{rust_profile}{$name};
87              
88 0           $self->{rust_profile}{$name} = $spec;
89             }
90              
91             =head2 rust_use_perl_xs
92              
93             rust_use_perl_xs;
94              
95             Configure crate to use C bindings.
96              
97             =cut
98              
99             sub rust_use_perl_xs {
100 0     0 1   my ($self, $spec) = @_;
101              
102 0   0       $spec //= { version => "0" };
103              
104 0           $self->rust_requires("perl-xs", $spec);
105 0           $self->rust_clean_on_rebuild("perl-sys");
106             }
107              
108             =head2 rust_clean_on_rebuild
109              
110             rust_clean_on_rebuild;
111             # or
112             rust_clean_on_rebuild qw/crate_name/;
113              
114             If Makefile changed since last build, force C run. If crate names
115             are specified, force clean only for those packages (C).
116              
117             =cut
118              
119             sub rust_clean_on_rebuild {
120 0     0 1   my ($self, @args) = @_;
121              
122 0   0       my $crates = $self->{cargo_clean} //= [];
123 0           push @$crates, @args;
124             }
125              
126             =head2 rust_write
127              
128             rust_write;
129              
130             Writes C and sets up Makefile options as needed.
131              
132             =cut
133              
134             sub rust_write {
135 0     0 1   my $self = shift;
136              
137 0           $self->_rust_write_cargo;
138 0           $self->_rust_setup_makefile;
139             }
140              
141             sub _rust_crate_name {
142             lc shift->name
143 0     0     }
144              
145             sub _rust_target_name {
146 0     0     shift->_rust_crate_name =~ s/-/_/gr
147             }
148              
149             sub _rust_write_cargo {
150 0     0     my $self = shift;
151              
152 0           my $crate_spec = {
153             package => {
154             name => $self->_rust_crate_name,
155             description => $self->abstract,
156             version => "1.0.0", # FIXME
157             },
158              
159             lib => {
160             "crate-type" => [ "cdylib" ],
161             },
162             };
163              
164             $crate_spec->{dependencies} = $self->{rust_requires}
165 0 0         if $self->{rust_requires};
166              
167             $crate_spec->{features} = $self->{rust_features}
168 0 0         if $self->{rust_features};
169              
170             $crate_spec->{profile} = $self->{rust_profile}
171 0 0         if $self->{rust_profile};
172              
173 0 0         open my $f, ">", "Cargo.toml" or die $!;
174 0           $f->print("# This file is autogenerated\n\n");
175 0           $f->print(TOML::to_toml($crate_spec));
176 0 0         close $f or die $!;
177             }
178              
179             sub _rust_setup_makefile {
180 0     0     my $self = shift;
181 0           my $class = ref $self;
182              
183             # FIXME: don't assume libraries have "lib" prefix
184 0           my $libname = "lib" . $self->_rust_target_name;
185              
186 0           $self->postamble(<
187             # --- $class section:
188              
189             INST_RUSTDYLIB = \$(INST_ARCHAUTODIR)/\$(DLBASE).\$(DLEXT)
190             RUST_TARGETDIR = target/release
191             RUST_DYLIB = \$(RUST_TARGETDIR)/$libname.\$(DLEXT)
192             CARGO = cargo
193             CARGO_OPTS = --release
194              
195             dynamic :: \$(INST_RUSTDYLIB)
196              
197             MAKE
198              
199 0 0         if ($self->{cargo_clean}) {
200 0           my @opts = map qq{-p "$_"}, @{$self->{cargo_clean}};
  0            
201              
202 0           $self->postamble(<
203             \$(RUST_DYLIB) ::
204             test \$(FIRST_MAKEFILE) -ot \$@ || \$(CARGO) clean \$(CARGO_OPTS) @opts
205              
206             MAKE
207             }
208              
209 0           $self->postamble(<
210             \$(RUST_DYLIB) ::
211             PERL=\$(FULLPERL) \$(CARGO) build \$(CARGO_OPTS)
212              
213             \$(INST_RUSTDYLIB): \$(RUST_DYLIB)
214             \$(CP) \$< \$@
215              
216             clean ::
217             \$(CARGO) clean
218             \$(RM) Cargo.toml Cargo.lock
219             MAKE
220             }
221              
222             =head1 AUTHOR
223              
224             Vickenty Fesunov, C<< >>
225              
226             =head1 BUGS
227              
228             Please report any bugs or feature requests to L.
229              
230             =head1 LICENSE AND COPYRIGHT
231              
232             Copyright 2015 Vickenty Fesunov.
233              
234             This module may be used, modified, and distributed under the same terms as Perl
235             itself. Please see the license that came with your Perl distribution for
236             details.
237              
238             =cut
239              
240             1;