Affix
view release on metacpan or search on metacpan
lib/Affix/Build.pm view on Meta::CPAN
# Go runtime (and SSE/AVX instructions) on Windows x64. If Perl calls your library with a
# 8-byte aligned stack (which was common in older GCC optimization flags), Go will segfault
# immediately when it tries to access the stack.
push @local, q[-ldflags "-extldflags '-static -static-libgcc -static-libstdc++'"] if $^O eq 'MSWin32';
if ( $mode eq 'dynamic' ) {
$self->_run( 'go', 'build', '-buildmode=c-shared', @local, '-o', "$out", "$file" );
return $out;
}
else {
my $lib = $build_dir->child( $self->_base($file) . $Config{_a} );
$self->_run( 'go', 'build', '-buildmode=c-archive', @local, '-o', "$lib", "$file" );
return { file => $lib, libs => ['pthread'] };
}
}
#~ https://odin-lang.org/news/calling-odin-from-python/
#~ https://odin-lang.org/docs/install/#release-requirements--notes
method _build_odin ( $src, $out, $mode ) {
my $file = $src->{path};
my @local = @{ $src->{flags} };
my $odin = $self->_can_run('odin') // croak "Odin not found";
if ( $mode eq 'dynamic' ) {
$self->_run( $odin, 'build', "$file", '-file', '-build-mode:dll', @local, "-out:$out" );
return $out;
}
else {
my $obj = $build_dir->child( $self->_base($file) . $Config{_o} );
my @cmd = ( $odin, 'build', "$file", '-file', '-build-mode:obj', @local, "-out:$obj" );
push @cmd, '-reloc-mode:pic' unless $os eq 'MSWin32';
$self->_run(@cmd);
unless ( $obj->exists ) { # Attempt to find it if Odin misnamed it (e.g. .obj vs .o)
my $cwd_obj = Path::Tiny::path( $self->_base($file) . $Config{_o} );
$cwd_obj->move($obj) if $cwd_obj->exists;
}
return { file => $obj };
}
}
#~ https://dlang.org/articles/dll-linux.html#dso9
#~ dmd -c dll.d -fPIC
#~ dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is
method _build_d ( $src, $out, $mode ) {
my $file = $src->{path};
my $dmd = $self->_can_run(qw[dmd ldc2 gdc]) // croak "D compiler not found";
if ( $mode eq 'dynamic' ) {
my @cmd = ( $dmd, '-shared', "$file", "-of=$out" );
push @cmd, '-fPIC' unless $os eq 'MSWin32';
$self->_run(@cmd);
return $out;
}
else {
my $lib = $build_dir->child( $self->_base($file) . $Config{_a} );
my @cmd = ( $dmd, '-lib', "$file", "-of=$lib" );
push @cmd, '-fPIC' unless $os eq 'MSWin32';
$self->_run(@cmd);
return { file => $lib };
}
}
method _build_csharp ( $file, $out, $mode ) { $self->_build_dotnet( $file, $out, $mode, 'cs' ); }
#~ https://github.com/secana/Native-FSharp-Library
#~ https://secanablog.wordpress.com/2020/02/01/writing-a-native-library-in-f-which-can-be-called-from-c/
method _build_fsharp ( $file, $out, $mode ) { $self->_build_dotnet( $file, $out, $mode, 'fs' ); }
method _build_dotnet ( $src, $out, $mode, $lang ) {
my $file = $src->{path};
my $dotnet = $self->_can_run('dotnet') // croak "Dotnet not found";
my $proj_dir = $build_dir->child( "dotnet_${lang}_" . $self->_base($file) );
$proj_dir->mkpath;
$file->copy( $proj_dir->child( $file->basename ) );
my $ext = $lang eq 'fs' ? 'fsproj' : 'csproj';
my $proj = $proj_dir->child("Build.$ext");
my $lib_type = ( $mode eq 'dynamic' ) ? 'Shared' : 'Static';
my $items = $lang eq 'fs' ? '<ItemGroup><Compile Include="**/*.fs" /></ItemGroup>' : '';
$proj->spew_utf8(<<"XML");
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<PublishAot>true</PublishAot>
<NativeLib>$lib_type</NativeLib>
<SelfContained>true</SelfContained>
</PropertyGroup>
$items
</Project>
XML
my $out_dir = $proj_dir->child('out');
my $rid = $os eq 'MSWin32' ? 'win-x64' : 'linux-x64';
# Local flags? Dotnet CLI args are tricky, assuming they aremsbuild props?
# Ignoring for now to keep it safe, or pass as raw args if user knows what they do.
my @local = @{ $src->{flags} };
$self->_run( "$dotnet", 'publish', "$proj", '-r', $rid, '-o', "$out_dir", @local );
if ( $mode eq 'dynamic' ) {
my $dll_ext = $Config{so};
$dll_ext = ".$dll_ext" unless $dll_ext =~ /^\./;
my ($artifact) = grep {/\Q$dll_ext\E$/} $out_dir->children;
croak "Dotnet build failed" unless $artifact;
Path::Tiny::path($artifact)->move($out);
return $out;
}
else {
my $lib_ext = $Config{_a};
my ($artifact) = grep {/\Q$lib_ext\E$/} $out_dir->children;
croak "Dotnet build failed" unless $artifact;
return { file => Path::Tiny::path($artifact) };
}
}
#~ https://ziglang.org/documentation/0.13.0/#Exporting-a-C-Library
#~ zig build-lib mathtest.zig -dynamic
method _build_zig ( $src, $out, $mode ) {
my $file = $src->{path};
my @local = @{ $src->{flags} };
my $zig = $self->_can_run('zig') // croak "Zig not found";
if ( $mode eq 'dynamic' ) {
$self->_run( $zig, 'build-lib', '-dynamic', @local, "$file", "-femit-bin=$out" );
return $out;
}
else {
my $lib = $build_dir->child( $self->_base($file) . $Config{_a} );
$self->_run( $zig, 'build-lib', '-static', @local, "$file", "-femit-bin=$lib" );
return { file => $lib, libs => ( $os eq 'MSWin32' ? ['ntdll'] : [] ) };
( run in 0.815 second using v1.01-cache-2.11-cpan-39bf76dae61 )