Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2cb1225
Preliminary support for C++ (while for Unix systems)
vovkasm Feb 16, 2013
0f6ee3e
Documentation for XSTARGET_EXT
vovkasm Feb 16, 2013
ff88943
Now C++ support should be done.
vovkasm Feb 16, 2013
b37b875
Merge remote-tracking branch 'upstream/master'
vovkasm Feb 24, 2013
bbe1783
Merge remote-tracking branch 'upstream/master'
vovkasm Mar 16, 2013
b40be0b
Fix warning: "XSTARGET_EXT" is not a known parameter
vovkasm Mar 16, 2013
84d3590
Fix formatting (tabs -> spaces).
vovkasm Mar 16, 2013
87931ea
Add some documentation to FAQ about building XS with C++ compiler, al…
vovkasm Mar 17, 2013
9cb5b00
Fix grammar as pointed by schwern
vovkasm Mar 18, 2013
9755bf4
Grammar check
vovkasm Mar 24, 2013
31e9402
Merge remote-tracking branch 'upstream/master'
vovkasm Apr 7, 2013
41d56d7
Improve tests
vovkasm Apr 7, 2013
c0aa37c
Improve xscpp.t
vovkasm Apr 7, 2013
a2d15ba
Fix xs.t and xscpp.t
vovkasm Apr 7, 2013
ae6cd96
Merge commit '8f393bd6ed756d74a3b6467729099d1a8467462a'
vovkasm Aug 12, 2014
406586e
Merge commit 'feefb1ac245091959c809939665431fef938ec10'
vovkasm Aug 12, 2014
b1728d3
Fix tests after sync with upstream.
vovkasm Aug 12, 2014
9f430d7
Modernize t/xscpp.t test, make it look more like t/xs.t
vovkasm Aug 16, 2014
e1a363e
whitespace fixes
vovkasm Aug 16, 2014
905ac57
Disable full compilation test of XS with C++. Only check that generat…
vovkasm Aug 16, 2014
6d982a0
Add note that this is not full solution to FAQ
vovkasm Aug 16, 2014
0e9bede
Add references to useful modules that can help configure project to u…
vovkasm Aug 16, 2014
dc29097
Merge commit '05ee4308963d40a68dcc3dd7aa5ddd2ead826806'
vovkasm Aug 19, 2014
b41d841
Merge commit '3f38c3a0136464f543c714a10d3fba557afc0d2e'
vovkasm Aug 22, 2014
0808056
Merge commit 'c6a4f151db5bd2b6a820c32e2d9cf1fc8788c3d2'
vovkasm Aug 25, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions lib/ExtUtils/MM_Unix.pm
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ sub constants {
PERLRUNINST FULLPERLRUNINST ABSPERLRUNINST
PERL_CORE
PERM_DIR PERM_RW PERM_RWX
XSTARGET_EXT

) )
{
Expand Down Expand Up @@ -1300,7 +1301,7 @@ sub init_dirscan { # --- File and Directory Lists (.xs .pm .pod etc)
next if $self->{NORECURS};
$dir{$name} = $name if (-f $self->catfile($name,"Makefile.PL"));
} elsif ($name =~ /\.xs\z/){
my($c); ($c = $name) =~ s/\.xs\z/.c/;
my($c); ($c = $name) =~ s/\.xs\z/$self->{XSTARGET_EXT}/;
$xs{$name} = $c;
$c{$c} = 1;
} elsif ($name =~ /\.c(pp|xx|c)?\z/i){ # .c .C .cpp .cxx .cc
Expand Down Expand Up @@ -1755,6 +1756,9 @@ EOP

$self->{LIBPERL_A} ||= "libperl$self->{LIB_EXT}";

# Default extension for target produced from xs file
$self->{XSTARGET_EXT} ||= '.c';

# make a simple check if we find strict
warn "Warning: PERL_LIB ($self->{PERL_LIB}) seems not to be a perl library directory
(strict.pm not found)"
Expand Down Expand Up @@ -3644,16 +3648,17 @@ sub writedoc {

=item xs_c (o)

Defines the suffix rules to compile XS files to C.
Defines the suffix rules to compile XS files to C (or to C++
if XSTARGET_EXT set to ".cpp").

=cut

sub xs_c {
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs.c:
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c
.xs$(XSTARGET_EXT):
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*$(XSTARGET_EXT)
';
}

Expand Down Expand Up @@ -3684,8 +3689,8 @@ sub xs_o { # many makes are too dumb to use xs_c then c_o
return '' unless $self->needs_linking();
'
.xs$(OBJ_EXT):
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c
$(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(PASTHRU_DEFINE) $(DEFINE) $*.c
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*$(XSTARGET_EXT)
$(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(PASTHRU_DEFINE) $(DEFINE) $*$(XSTARGET_EXT)
';
}

Expand Down
8 changes: 4 additions & 4 deletions lib/ExtUtils/MM_VMS.pm
Original file line number Diff line number Diff line change
Expand Up @@ -905,8 +905,8 @@ sub xs_c {
my($self) = @_;
return '' unless $self->needs_linking();
'
.xs.c :
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
.xs$(XSTARGET_EXT) :
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME)$(XSTARGET_EXT)
';
}

Expand All @@ -921,8 +921,8 @@ sub xs_o { # many makes are too dumb to use xs_c then c_o
return '' unless $self->needs_linking();
'
.xs$(OBJ_EXT) :
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
$(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME)$(XSTARGET_EXT)
$(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME)$(XSTARGET_EXT)
';
}

Expand Down
7 changes: 6 additions & 1 deletion lib/ExtUtils/MakeMaker.pm
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ sub full_setup {
PL_FILES PM PM_FILTER PMLIBDIRS PMLIBPARENTDIRS POLLUTE
PREREQ_FATAL PREREQ_PM PREREQ_PRINT PRINT_PREREQ
SIGN SKIP TEST_REQUIRES TYPEMAPS UNINST VERSION VERSION_FROM XS XSOPT XSPROTOARG
XS_VERSION clean depend dist dynamic_lib linkext macro realclean
XSTARGET_EXT XS_VERSION clean depend dist dynamic_lib linkext macro realclean
tool_autosplit

MAN1EXT MAN3EXT
Expand Down Expand Up @@ -2800,6 +2800,11 @@ empty string is equivalent to the xsubpp default, or C<-noprototypes>.
See the xsubpp documentation for details. MakeMaker
defaults to the empty string.

=item XSTARGET_EXT

Suffix for files produced from F<.xs> files. It is F<.c> by default, but can be
set to F<.cpp> if you xs code contains C++.

=item XS_VERSION

Your version number for the .xs file of this package. This defaults
Expand Down
36 changes: 36 additions & 0 deletions lib/ExtUtils/MakeMaker/FAQ.pod
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,42 @@ And of course a very basic test:

This tip has been brought to you by Nick Ing-Simmons and Stas Bekman.

=item How can I build my xs files as C++

Traditionally the language of source files is determined by suffix
(e.g. F<.c>- C, F<.cpp> or F<.cc> is C++),
so you need to tell MakeMaker that it should make files with an appropriate
suffix from your F<.xs> files. It can be done by using
C<XSTARGET_EXT> option. For example:

Makefile.PL:
--------
use ExtUtils::MakeMaker;

WriteMakefile(
NAME => 'Foo',
VERSION_FROM => 'Foo.pm',
OBJECT => q/$(O_FILES)/,
XSTARGET_EXT => '.cpp',
XSOPT => '-C++ -nolinenumbers',
# ... other attrs ...
);

B<CAUTION>: This solution is not crossplatform. Should work with gcc and clang,
but probably will require more tuning (e.g. will need linking with libstdc++).
Other modules that you may find helpful to configure your project to work
across a range of C++ compilers and platforms include: L<ExtUtils::CppGuess>,
L<ExtUtils::CBuilder> and L<ExtUtils::CChecker>.

B<CAUTION>: If you have already generated F<.c> files before switching
the suffix, you need to remove these files manually, otherwise MakeMaker will
detect them and add to build. That will lead to strange errors from linker.

B<CAUTION>: You will probably need to disable file/line numbers info placed in
the generated file because C<xsubpp> knows nothing about the generated file
suffix and uses F<.c> unconditionally. To do this, add C<-nolinenumbers> to
C<XSOPT> option.

=back

=head1 PATCHING
Expand Down
131 changes: 131 additions & 0 deletions t/lib/MakeMaker/Test/Setup/XSCPP.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package MakeMaker::Test::Setup::XSCPP;

@ISA = qw(Exporter);
require Exporter;
@EXPORT = qw(setup_xs teardown_xs);

use strict;
use File::Path;
use File::Basename;
use MakeMaker::Test::Utils;

my $Is_VMS = $^O eq 'VMS';

my %Files = (
'XSCPP-Test/lib/XSCPP/Test.pm' => <<'END',
package XSCPP::Test;

require Exporter;
require DynaLoader;

$VERSION = 1.01;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw(is_even);

bootstrap XSCPP::Test $VERSION;

1;
END

'XSCPP-Test/Makefile.PL' => <<'END',
use ExtUtils::MakeMaker;

WriteMakefile(
NAME => 'XSCPP::Test',
VERSION_FROM => 'lib/XSCPP/Test.pm',
XSTARGET_EXT => '.cpp',
LIBS => ['-lstdc++'],
);
END

'XSCPP-Test/Test.xs' => <<'END',
extern "C" {
#include "EXTERN.h"
#include "perl.h"
}

#include "XSUB.h"

class CPPTest {
public:
CPPTest() { }
~CPPTest() { }
int is_even(int num) { return (num % 2) == 0; }
};

MODULE = XSCPP::Test PACKAGE = XSCPP::Test

PROTOTYPES: DISABLE

CPPTest*
CPPTest::new();

int
CPPTest::is_even(int input);

void
CPPTest::DESTROY();

END

'XSCPP-Test/typemap' => <<'END',
TYPEMAP
CPPTest * O_OBJECT

OUTPUT

O_OBJECT
sv_setref_pv( $arg, CLASS, (void*)$var );

INPUT

O_OBJECT
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
$var = ($type)SvIV((SV*)SvRV( $arg ));
else{
warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
XSRETURN_UNDEF;
}

END

'XSCPP-Test/t/is_even.t' => <<'END',
#!/usr/bin/perl -w

use Test::More tests => 3;

use_ok "XSCPP::Test";
my $o = XSCPP::Test->new;
ok !$o->is_even(1);
ok $o->is_even(2);
END
);


sub setup_xs {

while(my($file, $text) = each %Files) {
# Convert to a relative, native file path.
$file = File::Spec->catfile(File::Spec->curdir, split m{\/}, $file);

my $dir = dirname($file);
mkpath $dir;
open(FILE, ">$file") || die "Can't create $file: $!";
print FILE $text;
close FILE;
}

return 1;
}

sub teardown_xs {
foreach my $file (keys %Files) {
my $dir = dirname($file);
if( -e $dir ) {
rmtree($dir) || return;
}
}
return 1;
}

1;
36 changes: 24 additions & 12 deletions t/lib/MakeMaker/Test/Utils.pm
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ our $Is_FreeBSD = $^O eq 'freebsd';

our @EXPORT = qw(which_perl perl_lib makefile_name makefile_backup
make make_run run make_macro calibrate_mtime
have_compiler slurp
have_compiler have_cplusplus slurp
$Is_VMS $Is_MacOS
run_ok
);
Expand Down Expand Up @@ -348,23 +348,35 @@ Returns true if there is a compiler available for XS builds.
sub have_compiler {
my $have_compiler = 0;

# ExtUtils::CBuilder prints its compilation lines to the screen.
# Shut it up.
use TieOut;
local *STDOUT = *STDOUT;
local *STDERR = *STDERR;
eval {
require ExtUtils::CBuilder;
my $cb = ExtUtils::CBuilder->new(quiet=>1);

$have_compiler = $cb->have_compiler;
};

return $have_compiler;
}

tie *STDOUT, 'TieOut';
tie *STDERR, 'TieOut';
=item have_cplusplus

$have_compiler = have_cplusplus;

Returns true if there is a C++ compiler available for XS builds.

=cut

sub have_cplusplus {
my $have_cplusplus = 0;

eval {
require ExtUtils::CBuilder;
my $cb = ExtUtils::CBuilder->new;
require ExtUtils::CBuilder;
my $cb = ExtUtils::CBuilder->new(quiet=>1);

$have_compiler = $cb->have_compiler;
$have_cplusplus = $cb->have_cplusplus;
};

return $have_compiler;
return $have_cplusplus;
}

=item slurp
Expand Down
60 changes: 60 additions & 0 deletions t/xscpp.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/perl -w

BEGIN {
unshift @INC, 't/lib/';
}
chdir 't';

use strict;

use MakeMaker::Test::Utils;
use MakeMaker::Test::Setup::XSCPP;

# Disable full compilation test for now.
# TODO: Until some consensus in community will reached.
# use Test::More
# have_cplusplus()
# ? (tests => 5)
# : (skip_all => "ExtUtils::CBuilder not installed or couldn't find a C++ compiler");
use Test::More tests => 5;
use File::Find;
use File::Spec;
use File::Path;

my $Is_VMS = $^O eq 'VMS';
my $perl = which_perl();

chdir 't';

perl_lib;

$| = 1;

ok( setup_xs(), 'setup' );
END {
chdir File::Spec->updir or die;
teardown_xs(), 'teardown' or die;
}

ok( chdir('XSCPP-Test'), "chdir'd to XSCPP-Test" ) ||
diag("chdir failed: $!");

my @mpl_out = run(qq{$perl Makefile.PL});

cmp_ok( $?, '==', 0, 'Makefile.PL exited with zero' ) ||
diag(@mpl_out);

my $mf_content = slurp(makefile_name());
like( $mf_content, qr/\bXSTARGET_EXT\b\s*=\s*\.cpp\b/, 'Makefile: XSTARGET_EXT has right value' );
like( $mf_content, qr/\bXSUBPPRUN\b.+\bXSTARGET_EXT\b/, 'Makefile: seems xsubpp generate file with .cpp suffix' );

# Disable full compilation test for now.
# TODO: Until some consensus in community will reached.
# my $make = make_run();
# my $make_out = run("$make");
# is( $?, 0, ' make exited normally' ) ||
# diag $make_out;
#
# my $test_out = run("$make test");
# is( $?, 0, ' make test exited normally' ) ||
# diag $test_out;