Affix
view release on metacpan or search on metacpan
t/017_affix_build.t view on Meta::CPAN
use v5.40;
use blib;
use Affix qw[wrap Int32];
use Affix::Build;
use Test2::Tools::Affix qw[:all];
use Test2::V0 -no_srand => 1;
use Test2::Require::AuthorTesting;
use Path::Tiny qw[path tempfile tempdir];
use DynaLoader;
use Config;
use File::Spec;
#
my $TMP_DIR = Path::Tiny->tempdir( CLEANUP => 0 );
#
subtest 'Inline Source' => sub {
skip_all 'No CC' unless bin_path( $Config{cc} );
my $c = Affix::Build->new( build_dir => $TMP_DIR, name => 'inline_lib' );
$c->add( \<<~'', lang => 'c' );
#include <stdio.h>
#ifdef _WIN32
__declspec(dllexport)
#endif
int inline_add(int a, int b) { return a + b; }
ok lives { $c->compile_and_link() }, 'Linked inline source';
ok my $fn = wrap( $c->link, 'inline_add', [ Int32, Int32 ], Int32 ), 'wrap';
is $fn->( 65, 43 ), 108, 'call';
};
#
sub bin_path ($bin) {
return $bin if -x $bin && !-d $bin; # Check absolute
for my $dir ( File::Spec->path ) { # Check PATH
my $full = File::Spec->catfile( $dir, $bin );
return $full if -x $full && !-d $full;
if ( $^O eq 'MSWin32' ) {
return "$full.exe" if -x "$full.exe";
return "$full.cmd" if -x "$full.cmd";
return "$full.bat" if -x "$full.bat";
}
}
return undef;
}
sub check_dotnet () {
return 0 unless bin_path('dotnet');
my $out = `dotnet --list-sdks 2>&1`;
return ( $out =~ /^8\./m );
}
sub check_rust_gnu () {
return 0 unless bin_path('rustc');
# If not windows, standard rustc is fine
return 1 if $^O ne 'MSWin32';
# On Windows, we need to prove the GNU target works
my $tmp = Path::Tiny->tempfile( SUFFIX => '.rs' );
$tmp->spew('fn main() {}');
my $cmd = "rustc --target x86_64-pc-windows-gnu \"$tmp\" -o \"$tmp.exe\" 2>&1";
my $out = `$cmd`;
return ( $? == 0 );
}
sub enjoin( $lib, @symbols ) {
my $path = $lib->stringify;
my $dll = DynaLoader::dl_load_file( $path, 0 );
unless ($dll) {
fail( "Failed to load library '$path': " . DynaLoader::dl_error() );
return;
}
for my $sym (@symbols) {
if ( DynaLoader::dl_find_symbol( $dll, $sym ) ) {
pass( "Symbol '$sym' found in " . $lib->basename );
}
else {
fail( "Symbol '$sym' NOT found in " . $lib->basename );
}
}
DynaLoader::dl_unload_file($dll) if $^O eq 'MSWin32' && defined &DynaLoader::dl_unload_file;
}
sub run_test ( $lang, $name, $code, $sym, $bin_req, $validator //= () ) {
subtest "$name compilation" => sub {
my $bin = ( $lang eq 'c' ) ? $Config{cc} : $bin_req;
unless ( bin_path($bin) ) {
skip_all "No $name compiler found ($bin)";
return;
}
if ($validator) {
unless ( $validator->() ) {
skip_all "$name toolchain unmet";
return;
}
}
#
my $ext
= $lang eq 'rust' ? 'rs' :
$lang eq 'csharp' ? 'cs' :
$lang eq 'fsharp' ? 'fs' :
$lang eq 'fortran' ? 'f90' :
$lang eq 'pascal' ? 'pas' :
( run in 1.985 second using v1.01-cache-2.11-cpan-d80b1682f3f )