Affix
view release on metacpan or search on metacpan
lib/Affix/Build.pod view on Meta::CPAN
=pod
=encoding utf-8
=head1 NAME
Affix::Build - Robust, Polyglot Build System for FFI Extensions
=head1 SYNOPSIS
use v5.40;
use Affix::Build;
use Affix;
# Example 1: Single Language (Rust)
my $rust = Affix::Build->new( name => 'my_rust_lib' );
$rust->add( \<<~'RUST', lang => 'rust' );
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 { a + b }
RUST
my $rust_dll = $rust->link();
# Example 2: Polyglot (C and Go)
my $mix = Affix::Build->new(
name => 'hybrid_lib',
flags => { cflags => '-O3', ldflags => '-L/opt/lib' },
debug => 1
);
# Add file with per-file compiler overrides
$mix->add('src/wrapper.c', flags => '-DDEBUG');
$mix->add('src/core.go');
my $poly_dll = $mix->link();
=head1 DESCRIPTION
C<Affix::Build> is a cross-platform compilation utility designed to generate shared libraries (C<.dll>, C<.so>,
C<.dylib>) from source code in over 20 different programming languages.
While originally developed to compile test fixtures for the Affix suite, it has evolved into a robust tool for creating
polyglot extensions. It abstracts away the complexity of invoking various compilers, normalizing object file
extensions, handling platform-specific linker flags (such as MinGW vs. MSVC on Windows), and ensuring that language
runtimes (like the Go GC or .NET Runtime) are correctly initialized.
It serves as a powerful, polyglot alternative to C<Inline::*> modulesâallowing you to write native code in your
language of choice and instantly bind to it from Perl using L<Affix>.
=head2 Build Strategies
The builder automatically selects the optimal strategy based on the input sources:
=over
=item 1. B<Native Toolchain Strategy> (Single Language)
If you provide source files for only B<one> language, C<Affix::Build> delegates the entire build process to that
language's native toolchain (e.g., C<go build -buildmode=c-shared>, C<rustc --crate-type cdylib>, C<dotnet publish>).
This ensures that the language's standard library and runtime environment are configured exactly as intended by its
maintainers.
=item 2. B<Polyglot Aggregation Strategy> (Mixed Languages)
If you provide source files from B<multiple> languages (e.g., C code calling into a Rust library), the builder switches
to an aggregation strategy:
=over
=item 1. It instructs each language's compiler to output a B<Static Library> (C<.a> / C<.lib>) or B<Object File> (C<.o> / C<.obj>).
=item 2. It aggregates these intermediate artifacts into a unified build context.
=item 3. It invokes the system C/C++ linker (usually C<cc> or C<g++>) to securely link them into a final shared library, bridging their differing ABIs.
=back
=back
=head1 CONSTRUCTOR
my $builder = Affix::Build->new( %params );
Creates a new compiler instance.
=over
=item * B<C<name>>: The base name of the resulting library (default: C<'affix_lib'>). The compiler will automatically append the OS-specific extension (C<.dll> on Windows, C<.dylib> on macOS, C<.so> on Linux).
=item * B<C<version>>: Optional version string to append to the library name.
=item * B<C<build_dir>>: The directory where intermediate artifacts and the final library will be written. If not provided, a temporary directory is created via L<Path::Tiny>.
=item * B<C<clean>>: If true, the generated C<build_dir> and all its contents will be deleted when the object is destroyed (default: C<0>).
=item * B<C<debug>>: If true, the exact system commands executed by the compiler will be printed to C<STDERR> (default: C<0>).
=item * B<C<flags>>: A HashRef of global flags applied across all files. Keys can be C<cflags>, C<cxxflags>, and C<ldflags>.
=item * B<C<os>>: Override the detected operating system (defaults to C<$^O>).
=back
=head1 METHODS
=head2 C<add( $input, %args )>
Adds a source file to the build manifest.
$builder->add( 'path/to/file.c' );
$builder->add( 'file.c', flags => ['-DDEBUG', '-Wall'] );
$builder->add( \"int main(){}", lang => 'c' );
=over
=item * B<File Path:> If C<$input> is a string, it is treated as a file path. The compiler auto-detects the language based on the extension.
=item * B<Inline Code:> If C<$input> is a SCALAR reference, you B<must> provide the C<lang> argument (e.g., C<'c'>, C<'rust'>) so the compiler knows how to handle it.
=item * B<C<flags>>: An ArrayRef or space-separated string of compiler flags specific to this source file.
=back
=head2 C<compile_and_link( )>
Performs the build process:
=over
=item 1. Inspects added sources to determine the Build Strategy.
=item 2. Compiles all sources to their appropriate intermediate or final formats.
=item 3. Links the artifacts (if necessary) into a shared library.
=back
Returns a L<Path::Tiny> object pointing to the generated shared library. Dies with a detailed error message (including
STDOUT/STDERR of the failed command) if compilation fails.
=head2 C<link( )>
An alias for C<compile_and_link()>. Safe to call multiple times; it will return the cached library handle if the build
has already completed.
=head1 SUPPORTED LANGUAGES
C<Affix::Build> attempts to locate the necessary binaries in your system C<PATH>.
=head3 C / C++
Automatically handles C<-fPIC> on non-Windows platforms.
=over
=item * B<Extensions:> C<.c>, C<.cpp>, C<.cxx>, C<.cc>
( run in 0.904 second using v1.01-cache-2.11-cpan-39bf76dae61 )