use strict;
use warnings;
use Module::Build 0.25;
use Module::Build::ConfigData;
use Carp;
#############################################################################
my $moduleName = 'Sys::CpuLoadX';
my $pmFileName = 'lib/Sys/CpuLoadX.pm';
my $builderclass = Module::Build->subclass(
class => 'Sys::CpuLoadX::Custom::Builder',
code => <<'__CUSTOM_BUILD_CODE__,',
my $xsFileName = 'lib/Sys/CpuLoadX.xs';
sub ACTION_build {
use File::Copy;
my $self = shift;
foreach my $required_dir (qw(lib/xs contrib/ok contrib/fail)) {
mkdir $required_dir unless -d $required_dir;
}
### STEP 1: Try to compile each .xs file in ./contrib/ ###
if (!glob("contrib/fail/*.xs") && ! -f $xsFileName) {
foreach my $contrib_file (glob("contrib/*.xs")) {
my $xs_file = $contrib_file;
$xs_file =~ s!contrib!lib/xs!;
File::Copy::copy($contrib_file, $xs_file);
local $@ = undef;
eval { $self->ACTION_code() };
if ($@) {
print "\n\nFailed to compile $xs_file\n\n";
print $@ if $ENV{BUILD_DEBUG};
File::Copy::move($xs_file, "contrib/fail/");
} else {
print "\n\nSuccessfully compiled $xs_file\n\n";
File::Copy::move($xs_file, "contrib/ok/");
}
unlink <lib/xs/*>;
}
}
### STEP 2: Combine contrib/ok/.xs files ###
if (glob("contrib/ok/*.xs")) {
my (@INCLUDE,%INCLUDE,$MODULE,@PREMOD,@POSTMOD);
foreach my $xs (glob("contrib/ok/*.xs")) {
open my $xs_fh, '<', $xs;
while (<$xs_fh>) {
if (m"#include") {
next if $INCLUDE{$_}++;
push @INCLUDE, $_;
} elsif (/^MODULE/) {
$MODULE = $_;
push @POSTMOD, <$xs_fh>;
} else {
push @PREMOD, $_;
}
}
close $xs_fh;
print "Incorporating $xs into $xsFileName\n";
}
unlink <contrib/ok/*.xs>,<contrib/fail/*.xs>,$xsFileName;
if (@POSTMOD) {
open my $xs_fh, '>', $xsFileName or croak $!;
print $xs_fh @INCLUDE, @PREMOD, $MODULE, @POSTMOD, "\n\n\n";
close $xs_fh;
}
}
unlink glob("lib/xs/*.xs"), glob("lib/xs/*.o"), glob("lib/xs/*.c");
$self->ACTION_code();
return $self->SUPER::ACTION_build(@_);
}
__CUSTOM_BUILD_CODE__,
);
#############################################################################
mkdir 'lib/xs' unless -d 'lib/xs';
open(FOO, '>>', 'lib/xs/foo') && close FOO unless -f 'lib/xs/foo';
my $bugtracker_url
= 'http://rt.cpan.org/NoAuth/Bugs.html?Dist=Sys-CpuLoadX';
my $builder = $builderclass->new(
module_name => 'Sys::CpuLoadX',
license => 'perl',
dist_author => q[Marty O'Brien <mob@cpan.org>],
dist_version_from => $pmFileName,
build_requires => {
'Module::Build' => 0.25,
'Test::More' => 0,
},
recommends => {
'ExtUtils::CBuilder' => 0.15,
},
meta_merge => {
resources => { bugtracker => $bugtracker_url },
keywords => [ qw/cpu load/ ],
},
add_to_cleanup => [ 'Sys-CpuLoadX-*', '_build',
'*.xs.o', 'lib/xs/*', 'blib',
'lib/Sys/CpuLoadX.c',
'lib/Sys/CpuLoadX.o',
'lib/Sys/CpuLoadX.xs',
'contrib/ok/*.*', 'contrib/fail/*.*',
'pod2htm*.*',
],
create_makefile_pl => 'passthrough',
include_dirs => ['include'],
sign => 0,
);
# if $^O =~ /irix/, then we want to compile with -lcpuset
$builder->create_build_script();
__END__
The Sys::CpuLoadX module contains several small XS/C functions
that target features on many different operating systems. On any
particular system, most of the XS files won't compile.
So we use a pretty radical build process to find the largest
subset of valid XS files for each installation. This file
overloads the Module::Build::ACTION_build method with a procedure
that:
1) Copies all .xs files from the ./contrib directory
into the ./lib/xs/ directory.
2) Calls the Module::Build::ACTION_code method. This will
invoke the ExtUtils::CBuilder module to attempt to
compile all the .xs files under the lib/ directory.
3) When ACTION_code fails, parse the error message (in $@)
to determine which .xs file could not be compiled.
Erase that file and repeat step 2.
4) Combine all the remaining valid .xs files into a single
.xs file (lib/Sys/CpuLoadX.xs). Erase all traces of
the individual .xs units.
5) Call ACTION_code one more time to compile the
installation-specific .xs file and continue the build.