summaryrefslogtreecommitdiff
path: root/t/porting/extrefs.t
blob: 2e911e7a0b88b7b1406cb04af235c352249dcc1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!./perl -w

# What does this test?
# Test that changes to perl header files don't cause external
# references by simplying #including them.  This breaks library probe
# code on CPAN, and can break cflags.SH.
#
# Why do we test this?
# See https://rt.perl.org/rt3/Ticket/Display.html?id=116989
#
# It's broken - how do I fix it?
# You added an initializer or static function to a header file that
# references some symbol you didn't define, you need to remove it.

BEGIN {
  require "./test.pl";
  unshift @INC, ".." if -f "../TestInit.pm";
}

use TestInit qw(T A); # T is chdir to the top level, A makes paths absolute
use strict;
use warnings;
use Config;
use File::Path 'rmtree';
use Cwd;
use IPC::Cmd qw(can_run);

if ($Config{'usecrosscompile'} && !can_run($Config{'cc'})) {
    skip_all("compiler not available (cross-compiling)");
} else {
    plan(tests => 1);
}

my $VERBOSE = grep {$_ eq '-v'} @ARGV;

ok(try_compile_and_link(<<'CODE'));
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

int main(int argc, char **argv) {
  return 0;
}
CODE


# from Time::HiRes's Makefile.PL with minor modifications
sub try_compile_and_link {
    my ($c, %args) = @_;

    my $ld_exeext = ($^O eq 'cygwin' || $^O eq 'MSWin32' ||
                 $^O eq 'os2' && $Config{ldflags} =~ /-Zexe\b/) ? '.exe' :
                (($^O eq 'vos') ? $Config{exe_ext} : '');

    my ($ok) = 0;
    my $tempdir = tempfile();
    my $cwd = getcwd();
    mkdir $tempdir;
    chdir $tempdir;
    my ($tmp) = "temp";

    my $obj_ext = $Config{obj_ext} || ".o";

    if (open(my $tmpc, ">$tmp.c")) {
	print $tmpc $c;
	unless (close($tmpc)) {
	    chdir($cwd);
	    rmtree($tempdir);
	    warn "Failing closing code file: $!\n" if $VERBOSE;
	    return 0;
	}

	my $COREincdir = File::Spec->catdir(File::Spec->updir);

	my $ccflags = $Config{'ccflags'} . ' ' . "-I$COREincdir"
	 . ' -DPERL_NO_INLINE_FUNCTIONS';

	if ($^O eq "MSWin32") {
	    $ccflags .= " -I../win32 -I../win32/include";
	}

	my $libs = '';

	# Include libs to be sure of linking against bufferoverflowU.lib for
	# the SDK2003 compiler on Windows. See win32/Makefile for more details.
	if ($^O eq "MSWin32" && $Config{cc} =~ /\bcl\b/i) {
	    $libs = " /link $Config{'libs'}";
	}

	my $null = File::Spec->devnull;

	my $errornull = $VERBOSE ? '' : ">$null 2>$null";

	# Darwin g++ 4.2.1 is fussy and demands a space.
	# FreeBSD g++ 4.2.1 does not.
	# We do not know the reaction of either to the presence of brown M&Ms.
	my $out_opt = "-o ";
	if ($^O eq "MSWin32" && $Config{cc} =~ /\bcl\b/i) {
	    $out_opt = "/Fe";
	}

	my $tmp_exe = "$tmp$ld_exeext";

        my $cccmd = "$Config{'cc'} $out_opt$tmp_exe $ccflags $tmp.c $libs $errornull";

	if ($^O eq 'VMS') {
            $cccmd = "$Config{'cc'} /include=($COREincdir) $tmp.c";
        }

       if ($^O eq 'VMS') {
	    open( my $cmdfile, ">$tmp.com" );
	    print $cmdfile "\$ SET MESSAGE/NOFACILITY/NOSEVERITY/NOIDENT/NOTEXT\n";
	    print $cmdfile "\$ $cccmd\n";
	    print $cmdfile "\$ IF \$SEVERITY .NE. 1 THEN EXIT 44\n"; # escalate
	    close $cmdfile;
	    system("\@ $tmp.com");
	    $ok = $?==0;
	    chdir($cwd);
	    rmtree($tempdir);
        }
        else
        {
	    printf "cccmd = $cccmd\n" if $VERBOSE;
	    my $res = system($cccmd);
	    $ok = defined($res) && $res == 0 && -s $tmp_exe && -x _;

	    chdir($cwd);
	    rmtree($tempdir);
        }
    }

    return $ok;
}