Skip to content

Commit eac8a43

Browse files
committed
Doc, test, implement XSBUILD: control XSMULTI
1 parent 432ec25 commit eac8a43

File tree

3 files changed

+103
-14
lines changed

3 files changed

+103
-14
lines changed

lib/ExtUtils/MM_Unix.pm

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -940,9 +940,12 @@ sub dynamic_lib {
940940
shift @d if $d[0] eq 'lib';
941941
my $instdir = File::Spec->catdir('$(INST_ARCHLIB)', 'auto', @d, $f);
942942
my $instfile = File::Spec->catfile($instdir, "$f.\$(DLEXT)");
943-
my $objfile = "$ext\$(OBJ_EXT)";
943+
my $objfile = $self->_xsbuild_value('xs', $ext, 'OBJECT');
944+
$objfile = "$ext\$(OBJ_EXT)" unless defined $objfile;
945+
my $ldfrom = $self->_xsbuild_value('xs', $ext, 'LDFROM');
946+
$ldfrom = $objfile unless defined $ldfrom;
944947
my $exportlist = "$ext.def";
945-
push @libs, [ $objfile, $instfile, $instdir, $objfile, $exportlist ];
948+
push @libs, [ $objfile, $instfile, $instdir, $ldfrom, $exportlist ];
946949
}
947950
} else {
948951
@libs = ([ qw($(OBJECT) $(INST_DYNAMIC) $(INST_ARCHAUTODIR) $(LDFROM) $(EXPORT_LIST)) ]);
@@ -1012,7 +1015,6 @@ sub xs_make_dynamic_lib {
10121015
push(@m," \$(RM_F) \$\@\n");
10131016

10141017
my $libs = '$(LDLOADLIBS)';
1015-
10161018
if (($Is{NetBSD} || $Is{Interix} || $Is{Android}) && $Config{'useshrplib'} eq 'true') {
10171019
# Use nothing on static perl platforms, and to the flags needed
10181020
# to link against the shared libperl library on shared perl
@@ -3928,19 +3930,38 @@ EOF
39283930
$cccmd =~ s/^\s*CCCMD\s*=\s*//;
39293931
$cccmd =~ s/\$\(DEFINE_VERSION\)/-DVERSION=\\"$version\\"/;
39303932
$cccmd =~ s/\$\(XS_DEFINE_VERSION\)/-DXS_VERSION=\\"$version\\"/;
3931-
# 1 2 3
3932-
$frag .= _sprintf562 <<'EOF', $ext, $cccmd, $minus_o;
3933+
$self->_xsbuild_replace_macro($cccmd, 'xs', $ext, 'INC');
3934+
my $define = '$(DEFINE)';
3935+
$self->_xsbuild_replace_macro($define, 'xs', $ext, 'DEFINE');
3936+
# 1 2 3 4
3937+
$frag .= _sprintf562 <<'EOF', $ext, $cccmd, $minus_o, $define;
39333938
39343939
%1$s$(OBJ_EXT): %1$s.xs
39353940
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc
39363941
$(MV) $*.xsc $*.c
3937-
%2$s $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c %3$s
3942+
%2$s $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) %4$s $*.c %3$s
39383943
EOF
39393944
}
39403945
}
39413946
$frag;
39423947
}
39433948

3949+
# param gets modified
3950+
sub _xsbuild_replace_macro {
3951+
my ($self, undef, $xstype, $ext, $varname) = @_;
3952+
my $value = $self->_xsbuild_value($xstype, $ext, $varname);
3953+
return unless defined $value;
3954+
$_[1] =~ s/\$\($varname\)/$value/;
3955+
}
3956+
3957+
sub _xsbuild_value {
3958+
my ($self, $xstype, $ext, $varname) = @_;
3959+
return $self->{XSBUILD}{$xstype}{$ext}{$varname}
3960+
if $self->{XSBUILD}{$xstype}{$ext}{$varname};
3961+
return $self->{XSBUILD}{$xstype}{all}{$varname}
3962+
if $self->{XSBUILD}{$xstype}{all}{$varname};
3963+
();
3964+
}
39443965

39453966
1;
39463967

lib/ExtUtils/MakeMaker.pm

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ my %Special_Sigs = (
116116
SKIP => 'ARRAY',
117117
TYPEMAPS => 'ARRAY',
118118
XS => 'HASH',
119+
XSBUILD => 'HASH',
119120
VERSION => ['version',''],
120121
_KEEP_AFTER_FLUSH => '',
121122

@@ -312,8 +313,8 @@ sub full_setup {
312313
PL_FILES PM PM_FILTER PMLIBDIRS PMLIBPARENTDIRS POLLUTE
313314
PREREQ_FATAL PREREQ_PM PREREQ_PRINT PRINT_PREREQ
314315
SIGN SKIP TEST_REQUIRES TYPEMAPS UNINST VERSION VERSION_FROM XS
315-
XSMULTI XSOPT XSPROTOARG XS_VERSION clean depend dist dynamic_lib
316-
linkext macro realclean tool_autosplit
316+
XSBUILD XSMULTI XSOPT XSPROTOARG XS_VERSION
317+
clean depend dist dynamic_lib linkext macro realclean tool_autosplit
317318
318319
MAN1EXT MAN3EXT
319320
@@ -2795,6 +2796,40 @@ Hashref of .xs files. MakeMaker will default this. e.g.
27952796
The .c files will automatically be included in the list of files
27962797
deleted by a make clean.
27972798
2799+
=item XSBUILD
2800+
2801+
Hashref with options controlling the operation of C<XSMULTI>:
2802+
2803+
{
2804+
xs => {
2805+
all => {
2806+
# options applying to all .xs files for this distribution
2807+
},
2808+
'lib/Class/Name/File' => { # specifically for this file
2809+
DEFINE => '-Dfunktastic', # defines for only this file
2810+
INC => "-I$funkyliblocation", # include flags for only this file
2811+
# OBJECT => 'lib/Class/Name/File$(OBJ_EXT)', # default
2812+
LDFROM => "lib/Class/Name/File\$(OBJ_EXT) $otherfile\$(OBJ_EXT)", # what's linked
2813+
},
2814+
},
2815+
}
2816+
2817+
Note C<xs> is the file-extension. More possibilities may arise in the
2818+
future. Note that object names are specified without their XS extension -
2819+
it is axiomatic that no extension will exist that has more than one type
2820+
of XSUB code.
2821+
2822+
C<LDFROM> defaults to the same as C<OBJECT>. C<OBJECT> defaults to,
2823+
for C<XSMULTI>, just the XS filename with the extension replaced with
2824+
the compiler-specific object-file extension.
2825+
2826+
The distinction between C<OBJECT> and C<LDFROM>: C<OBJECT> is the make
2827+
target, so make will try to build it. However, C<LDFROM> is what will
2828+
actually be linked together to make the shared object or static library
2829+
(SO/SL), so if you override it, make sure it includes what you want to
2830+
make the final SO/SL, almost certainly including the XS basename with
2831+
C<$(OBJ_EXT)> appended.
2832+
27982833
=item XSMULTI
27992834
28002835
When this is set to C<1>, multiple XS files may be placed under F<lib/>

t/lib/MakeMaker/Test/Setup/XS.pm

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,7 @@ $label2files{multi} = +{
169169
'lib/XS/Other.pm' => $PM_OTHER,
170170
'lib/XS/Other.xs' => $XS_MULTI,
171171
't/is_odd.t' => $T_OTHER,
172-
173-
'lib/XS/header.h' => <<'END',
174-
#define INVAR input
175-
END
176-
172+
'lib/XS/header.h' => "#define INVAR input\n",
177173
};
178174
virtual_rename('multi', $typemap, "lib/XS/$typemap");
179175
virtual_rename('multi', 'Test.xs', 'lib/XS/Test.xs');
@@ -194,6 +190,42 @@ $label2files{staticmulti} = +{
194190
),
195191
};
196192

193+
$label2files{xsbuild} = +{
194+
%{ $label2files{'multi'} }, # make copy
195+
'Makefile.PL' => sprintf(
196+
$MAKEFILEPL, 'Test', 'lib/XS/Test.pm', qq{'$typemap'},
197+
q{
198+
XSMULTI => 1,
199+
XSBUILD => {
200+
xs => {
201+
'lib/XS/Other' => {
202+
DEFINE => '-DINVAR=input',
203+
OBJECT => 'lib/XS/Other$(OBJ_EXT) lib/XS/plus1$(OBJ_EXT)'
204+
}
205+
},
206+
},
207+
},
208+
),
209+
'lib/XS/Other.xs' => $XS_OTHER . <<EOF,
210+
\nint
211+
plus1(input)
212+
int input
213+
CODE:
214+
RETVAL = plus1(INVAR);
215+
OUTPUT:
216+
RETVAL
217+
EOF
218+
'lib/XS/plus1.c' => 'int plus1(i) int i; { return i + 1; }',
219+
't/is_odd.t' => <<'END',
220+
#!/usr/bin/perl -w
221+
use Test::More tests => 4;
222+
use_ok "XS::Other";
223+
ok is_odd(1);
224+
ok !is_odd(2);
225+
is XS::Other::plus1(3), 4;
226+
END
227+
};
228+
197229
sub virtual_rename {
198230
my ($label, $oldfile, $newfile) = @_;
199231
$label2files{$label}->{$newfile} = delete $label2files{$label}->{$oldfile};
@@ -235,6 +267,7 @@ sub list_dynamic {
235267
[ 'multi', '', '' ],
236268
[ 'staticmulti', ' LINKTYPE=dynamic', ' LINKTYPE=dynamic' ],
237269
[ 'staticmulti', ' dynamic', '_dynamic' ],
270+
[ 'xsbuild', '', '' ],
238271
);
239272
}
240273

@@ -263,7 +296,7 @@ sub run_tests {
263296

264297
my $test_cmd = "$make test" . (defined $add_testtarget ? $add_testtarget : '');
265298
my $test_out = run($test_cmd);
266-
is( $?, 0, "$test_cmd exited normally" ) || diag $test_out;
299+
is( $?, 0, "$test_cmd exited normally" ) || diag "$make_out\n$test_out";
267300
}
268301

269302
chdir File::Spec->updir or die;

0 commit comments

Comments
 (0)