This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
[perl5.git] / win32 / buildext.pl
1 =head1 NAME
2
3 buildext.pl - build extensions
4
5 =head1 SYNOPSIS
6
7     buildext.pl make [-make_opts] dep directory [target] [--static|--dynamic] !ext1 !ext2
8
9 E.g.
10
11     buildext.pl nmake -nologo perldll.def ..\ext
12
13     buildext.pl nmake -nologo perldll.def ..\ext clean
14
15     buildext.pl dmake perldll.def ..\ext
16
17     buildext.pl dmake perldll.def ..\ext clean
18
19 Will skip building extensions which are marked with an '!' char.
20 Mostly because they still not ported to specified platform.
21
22 If '--static' specified, only static extensions will be built.
23 If '--dynamic' specified, only dynamic extensions will be built.
24
25 --create-perllibst-h
26     creates perllibst.h file for inclusion from perllib.c
27 --list-static-libs:
28     prints libraries for static linking and exits
29
30 =cut
31
32 use File::Basename;
33 use Cwd;
34 use FindExt;
35 use Config;
36
37 # @ARGV with '!' at first position are exclusions
38 my %excl = map {$_=>1} map {/^!(.*)$/} @ARGV;
39 @ARGV = grep {!/^!/} @ARGV;
40
41 # --static/--dynamic
42 my %opts = map {$_=>1} map {/^--([\w\-]+)$/} @ARGV;
43 @ARGV = grep {!/^--([\w\-]+)$/} @ARGV;
44 my ($static,$dynamic) = ((exists $opts{static}?1:0),(exists $opts{dynamic}?1:0));
45 if ("$static,$dynamic" eq "0,0") {
46   ($static,$dynamic) = (1,1);
47 }
48 if ($opts{'list-static-libs'} || $opts{'create-perllibst-h'}) {
49   my @statics = grep{!/^DynaLoader$/} split /\s+/, $Config{static_ext};
50   if ($opts{'create-perllibst-h'}) {
51     # at moment of creation of perllibst.h no luck consulting Config.pm,
52     # so list of static extensions passed with @ARGV
53     @statics = grep{!/^DynaLoader$/} @ARGV;
54     open my $fh, ">perllibst.h";
55     my @statics1 = map {local $_=$_;s/\//__/g;$_} @statics;
56     my @statics2 = map {local $_=$_;s/\//::/g;$_} @statics;
57     print $fh "/*DO NOT EDIT\n  this file is included from perllib.c to init static extensions */\n";
58     print $fh "#ifdef STATIC1\n",(map {"    \"$_\",\n"} @statics),"#undef STATIC1\n#endif\n";
59     print $fh "#ifdef STATIC2\n",(map {"    EXTERN_C void boot_$_ (pTHX_ CV* cv);\n"} @statics1),"#undef STATIC2\n#endif\n";
60     print $fh "#ifdef STATIC3\n",(map {"    newXS(\"$statics2[$_]::bootstrap\", boot_$statics1[$_], file);\n"} 0 .. $#statics),"#undef STATIC3\n#endif\n";
61   }
62   else {
63     my %extralibs;
64     for (@statics) {
65       open my $fh, "<..\\lib\\auto\\$_\\extralibs.ld" or die "can't open <..\\lib\\auto\\$_\\extralibs.ld: $!";
66       $extralibs{$_}++ for grep {/\S/} split /\s+/, join '', <$fh>;
67     }
68     print map {/([^\/]+)$/;"..\\lib\\auto\\$_/$1.lib "} @statics;
69     print map {"$_ "} sort keys %extralibs;
70   }
71   exit;
72 }
73
74 my $here = getcwd();
75 my $perl = $^X;
76 $here =~ s,/,\\,g;
77 if ($perl =~ m#^\.\.#)
78  {
79   $perl = "$here\\$perl";
80  }
81 (my $topdir = $perl) =~ s/\\[^\\]+$//;
82 # miniperl needs to find perlglob and pl2bat
83 $ENV{PATH} = "$topdir;$topdir\\win32\\bin;$ENV{PATH}";
84 #print "PATH=$ENV{PATH}\n";
85 my $pl2bat = "$topdir\\win32\\bin\\pl2bat";
86 unless (-f "$pl2bat.bat") {
87     my @args = ($perl, ("$pl2bat.pl") x 2);
88     print "@args\n";
89     system(@args) unless defined $::Cross::platform;
90 }
91 my $make = shift;
92 $make .= " ".shift while $ARGV[0]=~/^-/;
93 my $dep  = shift;
94 my $dmod = -M $dep;
95 my $dir  = shift;
96 chdir($dir) || die "Cannot cd to $dir\n";
97 my $targ  = shift;
98 (my $ext = getcwd()) =~ s,/,\\,g;
99 my $code;
100 FindExt::scan_ext($ext);
101
102 my @ext = FindExt::extensions();
103 my %static_exts = map {$_=>1} split /\s+/, $Config{static_ext};
104
105 if ("$static$dynamic" eq "01") {@ext = grep {!exists $static_exts{$_}} @ext}
106 elsif ("$static$dynamic" eq "10") {@ext = grep {exists $static_exts{$_}} @ext}
107
108 foreach $dir (sort @ext)
109  {
110   if (exists $excl{$dir}) {
111     warn "Skipping extension $ext\\$dir, not ported to current platform";
112     next;
113   }
114   if (chdir("$ext\\$dir"))
115    {
116     my $mmod = -M 'Makefile';
117     if (!(-f 'Makefile') || $mmod > $dmod)
118      {
119       print "\nRunning Makefile.PL in $dir\n";
120       my @perl = ($perl, "-I$here\\..\\lib", 'Makefile.PL',
121                   'INSTALLDIRS=perl', 'PERL_CORE=1',
122                   ($static_exts{$dir}?('LINKTYPE=static'):()), # if ext is static
123                 );
124       if (defined $::Cross::platform) {
125         @perl = (@perl[0,1],"-MCross=$::Cross::platform",@perl[2..$#perl]);
126       }
127       print join(' ', @perl), "\n";
128       $code = system(@perl);
129       warn "$code from $dir\'s Makefile.PL" if $code;
130       $mmod = -M 'Makefile';
131       if ($mmod > $dmod)
132        {
133         warn "Makefile $mmod > $dmod ($dep)\n";
134        }
135      }  
136     if ($targ)
137      {
138       print "Making $targ in $dir\n$make $targ\n";
139       $code = system("$make $targ");
140       die "Unsuccessful make($dir): code=$code" if $code!=0;
141      }
142     else
143      {
144       print "Making $dir\n$make\n";
145       $code = system($make);
146       die "Unsuccessful make($dir): code=$code" if $code!=0;
147      }
148     chdir($here) || die "Cannot cd to $here:$!";
149    }
150   else
151    {
152     warn "Cannot cd to $ext\\$dir:$!";
153    }
154  }
155