C-Blocks
view release on metacpan or search on metacpan
lib/C/Blocks/PerlAPI.xs.PL view on Meta::CPAN
use strict;
use warnings;
use Alien::TinyCCx;
use Capture::Tiny qw(capture_merged);
use Config;
use ExtUtils::CBuilder;
use ExtUtils::Config;
use ExtUtils::Embed;
use File::Basename;
use File::Spec;
use File::Temp ();
use Module::Build;
my $tempdir = File::Temp::tempdir(CLEANUP => 1);
my $xs_counter = 1;
my %prelinking = map { $_ => 1 } qw/MSWin32 VMS aix/;
my @path = File::Spec->path;
# With static libperls, I cannot look up symbol names on the fly.
# In order to work on all Perls, these libperl bindings build a
# cached symbol table for perl.h. They then load all pointers to
# the symbols during the BOOT section. Module::Build knows how to
# build XS modules that have access to these symbols, whether
# libperl is static or shared.
##################################################
# Serialize perl.h and get a list of identifiers #
##################################################
# It turns out that lots of identifiers in the various header files
# are declared but are not actually defined. This command uses TCC
# to get the list of declarations, not definitions. We'll have to
# pare down the results next.
sub serialize_perl_h {
# Put the cache file in the sharedir
my $share_file_location = File::Spec->catfile('share', 'perl.h.cache');
return if -f $share_file_location and -f 'names.txt';
my($perl_h_fh, $perl_h_file) = File::Temp::tempfile(
'perl_h_XXXXXXXX', SUFFIX => '.c', UNLINK => 1
);
my $header_contents = <<HEADER_CONTENTS;
#ifdef PERL_DARWIN
typedef unsigned short __uint16_t, uint16_t;
typedef unsigned int __uint32_t, uint32_t;
typedef unsigned long __uint64_t, uint64_t;
#elif defined WIN32
#define __C89_NAMELESS __extension__
#define __MINGW_EXTENSION __extension__
typedef long uid_t;
typedef long gid_t;
#endif
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
int main() {
return 0;
}
HEADER_CONTENTS
print $perl_h_fh $header_contents;
close $perl_h_fh;
# Construct the compiler arguments
my $compiler_args = ccopts;
$compiler_args =~ s/\n+//g;
# tcc doesn't know how to use quotes in -I paths; remove them if found.
$compiler_args =~ s/-I"([^"]*)"/-I$1/g if $^O =~ /MSWin/;
# Scrub all linker (-Wl,...) options
$compiler_args =~ s/-Wl,[^\s]+//g;
# tcc does not like the -arch compiler option
$compiler_args =~ s/-arch\s+\w+//g;
# GCC Statement Expressions (also called brace groups) give tcc
# trouble. I should be able to turn those off by defining
# $compiler_args .= ' -DPERL_GCC_BRACE_GROUPS_FORBIDDEN'; # doesn't work... why?
# but that doesn't work. So instead I just turn off debugging. It's
# not the greatest solution, but it seems like it gets things to
# work.
$compiler_args =~ s/\s*-DDEBUGGING//;
# System perl on Debian includes the -DDEBIAN, which causes a
# similar issue:
$compiler_args =~ s/\s*-DDEBIAN//;
# Add arguments to produce the identifier list and serialization
mkdir 'share';
$compiler_args = join(' ', '-run', $compiler_args,
'-dump-identifier-names=names.txt',
'-serialize-symtab='.$share_file_location,
$perl_h_file
);
# Build the files! Only croak on errors that are not due to
# undefined symbols, as we don't care about linking here.
my ($output, $exit) = capture_merged { system("tcc $compiler_args") };
print $output;
if ($exit != 0) {
if ($output =~ /undefined symbol/) {
warn "^^^ Ignoring likely erroneous undefined symbol warning/error\n";
}
else {
die "Unable to serialize the header file\n";
}
}
unlink $perl_h_file;
Module::Build->current->add_to_cleanup($share_file_location);
( run in 1.661 second using v1.01-cache-2.11-cpan-5735350b133 )