This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge branch 'release-5.35.2' into blead
[perl5.git] / t / porting / extrefs.t
1 #!./perl -w
2
3 # What does this test?
4 # Test that changes to perl header files don't cause external
5 # references by simplying #including them.  This breaks library probe
6 # code on CPAN, and can break cflags.SH.
7 #
8 # Why do we test this?
9 # See https://github.com/Perl/perl5/issues/12824
10 #
11 # It's broken - how do I fix it?
12 # You added an initializer or static function to a header file that
13 # references some symbol you didn't define, you need to remove it.
14
15 BEGIN {
16   require "./test.pl";
17   unshift @INC, ".." if -f "../TestInit.pm";
18 }
19
20 use TestInit qw(T A); # T is chdir to the top level, A makes paths absolute
21 use strict;
22 use warnings;
23 use Config;
24 use File::Path 'rmtree';
25 use Cwd;
26 use IPC::Cmd qw(can_run);
27
28 if ($Config{'usecrosscompile'} && !can_run($Config{'cc'})) {
29     skip_all("compiler not available (cross-compiling)");
30 } else {
31     plan(tests => 1);
32 }
33
34 my $VERBOSE = grep {$_ eq '-v'} @ARGV;
35
36 ok(try_compile_and_link(<<'CODE'));
37 #include "EXTERN.h"
38 #include "perl.h"
39 #include "XSUB.h"
40
41 int main(int argc, char **argv) {
42   return 0;
43 }
44 CODE
45
46
47 # from Time::HiRes's Makefile.PL with minor modifications
48 sub try_compile_and_link {
49     my ($c, %args) = @_;
50
51     my $ld_exeext = ($^O eq 'cygwin' || $^O eq 'MSWin32' ||
52                  $^O eq 'os2' && $Config{ldflags} =~ /-Zexe\b/) ? '.exe' :
53                 (($^O eq 'vos') ? $Config{exe_ext} : '');
54
55     my ($ok) = 0;
56     my $tempdir = tempfile();
57     my $cwd = getcwd();
58     mkdir $tempdir;
59     chdir $tempdir;
60     my ($tmp) = "temp";
61
62     my $obj_ext = $Config{obj_ext} || ".o";
63
64     if (open(my $tmpc, ">$tmp.c")) {
65         print $tmpc $c;
66         unless (close($tmpc)) {
67             chdir($cwd);
68             rmtree($tempdir);
69             warn "Failing closing code file: $!\n" if $VERBOSE;
70             return 0;
71         }
72
73         my $COREincdir =
74             File::Spec->catdir(File::Spec->updir, File::Spec->updir);
75
76         my $ccflags = $Config{'ccflags'} . ' ' . "-I$COREincdir"
77          . ' -DPERL_NO_INLINE_FUNCTIONS';
78
79         if ($^O eq "MSWin32") {
80             $ccflags .= " -I../../win32 -I../../win32/include";
81         }
82
83         my $libs = '';
84
85         # Include libs to be sure of linking against bufferoverflowU.lib for
86         # the SDK2003 compiler on Windows. See win32/Makefile for more details.
87         if ($^O eq "MSWin32" && $Config{cc} =~ /\bcl\b/i) {
88             $libs = " /link $Config{'libs'}";
89         }
90
91         my $null = File::Spec->devnull;
92
93         my $errornull = $VERBOSE ? '' : ">$null 2>$null";
94
95         # Darwin g++ 4.2.1 is fussy and demands a space.
96         # FreeBSD g++ 4.2.1 does not.
97         # We do not know the reaction of either to the presence of brown M&Ms.
98         my $out_opt = "-o ";
99         if ($^O eq "MSWin32" && $Config{cc} =~ /\bcl\b/i) {
100             $out_opt = "/Fe";
101         }
102
103         my $tmp_exe = "$tmp$ld_exeext";
104
105         my $cccmd = "$Config{'cc'} $out_opt$tmp_exe $ccflags $tmp.c $libs $errornull";
106
107         if ($^O eq 'VMS') {
108             $cccmd = "$Config{'cc'} /include=($COREincdir) $tmp.c";
109         }
110
111        if ($^O eq 'VMS') {
112             open( my $cmdfile, ">$tmp.com" );
113             print $cmdfile "\$ SET MESSAGE/NOFACILITY/NOSEVERITY/NOIDENT/NOTEXT\n";
114             print $cmdfile "\$ $cccmd\n";
115             print $cmdfile "\$ IF \$SEVERITY .NE. 1 THEN EXIT 44\n"; # escalate
116             close $cmdfile;
117             system("\@ $tmp.com");
118             $ok = $?==0;
119             chdir($cwd);
120             rmtree($tempdir);
121         }
122         else
123         {
124             printf "cccmd = $cccmd\n" if $VERBOSE;
125             my $res = system($cccmd);
126             $ok = defined($res) && $res == 0 && -s $tmp_exe && -x _;
127
128             chdir($cwd);
129             rmtree($tempdir);
130         }
131     }
132
133     return $ok;
134 }