File Coverage

blib/lib/Module/Build/FFI/Rust.pm
Criterion Covered Total %
statement 24 94 25.5
branch 0 28 0.0
condition 0 3 0.0
subroutine 8 12 66.6
pod 2 4 50.0
total 34 141 24.1


line stmt bran cond sub pod time code
1             package Module::Build::FFI::Rust;
2              
3 1     1   190346 use strict;
  1         7  
  1         22  
4 1     1   5 use warnings;
  1         1  
  1         19  
5 1     1   4 use Config;
  1         2  
  1         32  
6 1     1   5 use File::Glob qw( bsd_glob );
  1         1  
  1         76  
7 1     1   377 use File::Which qw( which );
  1         809  
  1         42  
8 1     1   367 use File::chdir;
  1         2934  
  1         101  
9 1     1   392 use File::Copy qw( copy );
  1         1905  
  1         48  
10 1     1   6 use base qw( Module::Build::FFI );
  1         2  
  1         413  
11              
12             # ABSTRACT: (Deprecated) Build Perl extensions in Rust with FFI
13             our $VERSION = '0.52'; # VERSION
14              
15              
16             __PACKAGE__->add_property( ffi_rust_extra_compiler_flags =>
17             default => [],
18             );
19              
20             __PACKAGE__->add_property( ffi_rust_extra_linker_flags =>
21             default => [],
22             );
23              
24              
25             sub ffi_have_compiler
26             {
27 0     0 1   my($self) = @_;
28              
29 0           my $rustc = which('rustc');
30 0           my $cargo = which('cargo');
31              
32 0   0       return (!!$rustc) && (!!$cargo);
33             }
34              
35              
36             sub ffi_build_dynamic_lib
37             {
38 0     0 1   my($self, $src_dir, $name, $target_dir) = @_;
39              
40 0 0         if(@$src_dir > 1)
41             {
42 0           print STDERR "Module::Build::FFI::Rust only supports one ffi directory";
43 0           exit 2;
44             }
45              
46 0           $src_dir = $src_dir->[0];
47              
48 0 0         $target_dir = $src_dir unless defined $target_dir;
49              
50 0           my $dll = File::Spec->catfile($target_dir, "$name.$Config{dlext}");
51              
52 0 0         if(-e File::Spec->catfile($src_dir, 'Cargo.toml'))
53             {
54 0           $self->add_to_cleanup("$src_dir/target");
55              
56 0           do {
57 0           local $CWD = $src_dir;
58 0           my @cmd = ('cargo', 'build', '--release');
59 0           print "@cmd\n";
60 0           system @cmd;
61 0 0         exit 2 if $?;
62             };
63              
64             # Note: $Config{dlext} is frequently the right extension to look for,
65             # some platforms however have exceptions.
66 0           my $dlext = $Config{dlext};
67             # On OS X rust produces a dynamic library, but Perl extensions are
68             # built as bundles. Platypus can work with either and doesn't care
69             # about the extension, so we install the dylib as a bundle.
70 0 0         if($^O eq 'darwin')
    0          
71 0           { $dlext = 'dylib' }
72             # On Strawberry Perl of recent vintage they use .xs.dll as the dynamic
73             # library extension.
74             elsif($^O eq 'MSWin32')
75 0           { $dlext = 'dll' }
76              
77 0           my($build_dll) = bsd_glob("$src_dir/target/release/*.$dlext");
78 0 0         copy($build_dll, $dll) || do {
79 0           print STDERR "copy failed for\n";
80 0           print STDERR " $build_dll => $dll\n";
81 0           print STDERR "reason: $!\n";
82 0           exit 2;
83             };
84              
85 0           my $test_dirs = $self->notes('ffi_rust_dirs');
86 0 0         my %test_dirs = $test_dirs ? map { $_ => 1 } @$test_dirs : ();
  0            
87 0           $test_dirs{$src_dir} = 1;
88 0           $self->notes('ffi_rust_dirs' => [keys %test_dirs]);
89             }
90              
91             else
92             {
93 0           print STDERR "== WARNING WARNING WARNING ==\n";
94 0           print STDERR "\n";
95 0           print STDERR "building rust project without cargo is deprecated and will be removed\n";
96 0           print STDERR "from a future version of Module::Build::FFI::Rust! But not before\n";
97 0           print STDERR "31 December 2015.\n";
98 0           print STDERR "\n";
99 0           print STDERR "== WARNING WARNING WARNING ==\n";
100              
101 0           my @sources = bsd_glob("$src_dir/*.rs");
102              
103 0 0         return unless @sources;
104              
105 0 0         if(@sources != 1)
106             {
107 0           print STDERR "Only one Rust source file at a time please.\n";
108 0           print STDERR "You appear to have more than one in $src_dir.\n";
109 0           exit 2;
110             }
111              
112 0           my $rustc = which('rustc');
113              
114             my @cmd = (
115             $rustc,
116 0           @{ $self->ffi_rust_extra_compiler_flags },
117 0           @{ $self->ffi_rust_extra_linker_flags },
  0            
118             '--crate-type' => 'dylib',
119             @sources,
120             '-o', => $dll,
121             );
122              
123 0           print "@cmd\n";
124 0           system @cmd;
125 0 0         exit 2 if $?;
126             }
127              
128 0           $dll;
129             }
130              
131             sub ACTION_testrust
132             {
133 0     0 0   my($self) = @_;
134              
135 0           $self->notes('ffi_rust_test_fail' => 0);
136              
137 0           my $test_dirs = $self->notes('ffi_rust_dirs');
138 0 0         return unless $test_dirs;
139              
140 0           foreach my $dir (@$test_dirs)
141             {
142 0           local $CWD = $dir;
143 0           my @cmd = ('cargo', 'test');
144 0           print "@cmd\n";
145 0           system @cmd;
146 0 0         $self->notes('ffi_rust_test_fail' => 1) if $?;
147             }
148             }
149              
150             sub ACTION_test
151             {
152 0     0 0   my($self) = @_;
153 0           $self->depends_on('testrust');
154 0           $self->SUPER::ACTION_test;
155 0 0         if($self->notes('ffi_rust_test_fail'))
156             {
157 0           exit 2;
158             }
159             }
160              
161             1;
162              
163             __END__