1package mymm; 2 3use strict; 4use warnings; 5use Config; 6use File::Glob qw( bsd_glob ); 7use ExtUtils::MakeMaker (); 8use IPC::Cmd (); 9use lib 'inc'; 10use File::Spec; 11use My::BuildConfig; 12use My::ShareConfig; 13 14{ 15 my $dh; 16 opendir $dh, 'inc'; 17 my @files = map { File::Spec->catfile('inc', $_) } grep /^bad-.*\.pl$/, readdir $dh; 18 close $dh; 19 20 foreach my $badcheck (@files) 21 { 22 system $^X, $badcheck; 23 if($?) 24 { 25 print "bad check $badcheck failed\n"; 26 exit; 27 } 28 } 29} 30 31sub vcpkg 32{ 33 return unless $Config{ccname} eq 'cl'; 34 require Alien::FFI::Vcpkg; 35 !!eval { Alien::FFI::Vcpkg->vcpkg } 36} 37 38sub myWriteMakefile 39{ 40 my %args = @_; 41 my $build_config = My::BuildConfig->new; 42 my $share_config = My::ShareConfig->new; 43 my %diag; 44 my %alien; 45 46 ExtUtils::MakeMaker->VERSION('7.12'); 47 $build_config->set(version => [ $args{VERSION} =~ /^([0-9]+)\.([0-9]{2})/ ]); 48 49 if(eval { require Alien::FFI; Alien::FFI->VERSION('0.20'); 1 }) 50 { 51 print "using already installed Alien::FFI (version @{[ Alien::FFI->VERSION ]})\n"; 52 $build_config->set(alien => { class => 'Alien::FFI', mode => 'already-installed' }); 53 require Alien::Base::Wrapper; 54 Alien::Base::Wrapper->import( 'Alien::FFI', 'Alien::psapi', '!export' ); 55 %alien = Alien::Base::Wrapper->mm_args; 56 } 57 elsif(vcpkg()) 58 { 59 print "using vcpkg libffi package\n"; 60 $build_config->set(alien => { class => 'Alien::FFI::Vcpkg', mode => 'system' }); 61 require Alien::Base::Wrapper; 62 Alien::Base::Wrapper->import( 'Alien::FFI::Vcpkg', '!export'); 63 %alien = Alien::Base::Wrapper->mm_args; 64 } 65 else 66 { 67 require Alien::FFI::pkgconfig if $^O ne 'MSWin32'; 68 require Alien::FFI::PkgConfigPP if $^O eq 'MSWin32'; 69 70 my $alien_install_type_unset = !defined $ENV{ALIEN_INSTALL_TYPE}; 71 72 if($alien_install_type_unset && $^O eq 'MSWin32' && Alien::FFI::PkgConfigPP->exists) 73 { 74 print "using system libffia via PkgConfigPP\n"; 75 $build_config->set(alien => { class => 'Alien::FFI::PkgConfigPP', mode => 'system' }); 76 require Alien::Base::Wrapper; 77 Alien::Base::Wrapper->import( 'Alien::FFI::PkgConfigPP', 'Alien::psapi', '!export' ); 78 %alien = Alien::Base::Wrapper->mm_args; 79 } 80 elsif($alien_install_type_unset && $^O ne 'MSWin32' && Alien::FFI::pkgconfig->exists) 81 { 82 print "using system libffi via @{[ Alien::FFI::pkgconfig->pkg_config_exe ]}\n"; 83 $build_config->set(alien => { class => 'Alien::FFI::pkgconfig', mode => 'system' }); 84 require Alien::Base::Wrapper; 85 Alien::Base::Wrapper->import( 'Alien::FFI::pkgconfig', 'Alien::psapi', '!export' ); 86 %alien = Alien::Base::Wrapper->mm_args; 87 } 88 else 89 { 90 print "requiring Alien::FFI in fallback mode.\n"; 91 $build_config->set(alien => { class => 'Alien::FFI', mode => 'fallback' }); 92 %alien = ( 93 CC => '$(FULLPERL) -Iinc -MAlien::Base::Wrapper=Alien::FFI,Alien::psapi -e cc --', 94 LD => '$(FULLPERL) -Iinc -MAlien::Base::Wrapper=Alien::FFI,Alien::psapi -e ld --', 95 ); 96 $args{BUILD_REQUIRES}->{'Alien::FFI'} = '0.20'; 97 } 98 } 99 $alien{INC} = defined $alien{INC} ? "-Iinclude $alien{INC}" : "-Iinclude"; 100 101 %args = (%args, %alien); 102 103 if($ENV{FFI_PLATYPUS_DEBUG_FAKE32} || $Config{uvsize} < 8) 104 { 105 $args{BUILD_REQUIRES}->{'Math::Int64'} = '0.34'; 106 } 107 108 if($ENV{FFI_PLATYPUS_DEBUG_FAKE32} && $Config{uvsize} == 8) 109 { 110 print "DEBUG_FAKE32:\n"; 111 print " + making Math::Int64 a prereq\n"; 112 print " + Using Math::Int64's C API to manipulate 64 bit values\n"; 113 $build_config->set(config_debug_fake32 => 1); 114 $diag{config}->{config_debug_fake32} = 1; 115 } 116 if($ENV{FFI_PLATYPUS_NO_ALLOCA}) 117 { 118 print "NO_ALLOCA:\n"; 119 print " + alloca() will not be used, even if your platform supports it.\n"; 120 $build_config->set(config_no_alloca => 1); 121 $diag{config}->{config_no_alloca} = 1; 122 } 123 124 delete $args{PM}; 125 $args{XSMULTI} = 1; 126 $args{XSBUILD} = { 127 xs => { 128 'lib/FFI/Platypus' => { 129 OBJECT => 'lib/FFI/Platypus$(OBJ_EXT) ' . join(' ', map { s/\.c$/\$(OBJ_EXT)/; $_ } bsd_glob "xs/*.c"), 130 %alien, 131 }, 132 }, 133 }; 134 135 $args{PREREQ_PM}->{'Math::Int64'} = '0.34' 136 if $ENV{FFI_PLATYPUS_DEBUG_FAKE32} || $Config{uvsize} < 8; 137 138 # dlext as understood by MB and MM 139 my @dlext = ($Config{dlext}); 140 141 # extra dlext as understood by the OS 142 push @dlext, 'dll' if $^O =~ /^(cygwin|MSWin32|msys)$/; 143 push @dlext, 'xs.dll' if $^O =~ /^(MSWin32)$/; 144 push @dlext, 'so' if $^O =~ /^(cygwin|darwin)$/; 145 push @dlext, 'bundle', 'dylib' if $^O =~ /^(darwin)$/; 146 147 # uniq'ify it 148 @dlext = do { my %seen; grep { !$seen{$_}++ } @dlext }; 149 150 $build_config->set(diag => \%diag); 151 $share_config->set(config_dlext => \@dlext); 152 153 ExtUtils::MakeMaker::WriteMakefile(%args); 154} 155 156#package MM; 157# 158#sub init_tools 159#{ 160# my $self = shift; 161# $self->SUPER::init_tools(@_); 162# 163# return if !!$ENV{V}; 164# 165# my $noecho = $^O eq 'MSWin32' ? 'REM ' : '@'; 166# 167# foreach my $tool (qw( RM_F RM_RF CP MV )) 168# { 169# $self->{$tool} = $noecho . $self->{$tool}; 170# } 171# 172# return; 173#} 174 175package MY; 176 177use Config; 178 179sub dynamic_lib 180{ 181 my($self, @therest) = @_; 182 my $dynamic_lib = $self->SUPER::dynamic_lib(@therest); 183 184 my %h = map { m!include/(.*?)$! && $1 => [$_] } File::Glob::bsd_glob('include/*.h'); 185 push @{ $h{"ffi_platypus.h"} }, map { "include/ffi_platypus_$_.h" } qw( config ); 186 187 my %targets = ( 188 'include/ffi_platypus_config.h' => ['_mm/config'], 189 'lib/FFI/Platypus.c' => [File::Glob::bsd_glob('xs/*.xs'), 'lib/FFI/Platypus.xs', 'lib/FFI/typemap'], 190 ); 191 192 foreach my $cfile (File::Glob::bsd_glob('xs/*.c'), 'lib/FFI/Platypus.c') 193 { 194 my $ofile = $cfile; 195 $ofile =~ s/\.c$/\$(OBJ_EXT)/; 196 197 my @deps = ($cfile, '_mm/config'); 198 199 if(-d ".git") 200 { 201 # for a development build, lets go ahead and compute the .h 202 # dependencies to make it easier to do a partial rebuild. 203 my $source_file = $cfile; 204 $source_file = 'lib/FFI/Platypus.xs' if $source_file =~ /^lib\/FFI/; 205 my $fh; 206 open $fh, '<', $source_file; 207 while(<$fh>) 208 { 209 if(/^#include [<"](.*?)[>"]/ && $h{$1}) 210 { 211 push @deps, @{$h{$1}}; 212 } 213 } 214 close $fh; 215 } 216 217 $targets{$ofile} = \@deps; 218 } 219 220 $dynamic_lib .= "\n"; 221 222 foreach my $target (sort keys %targets) 223 { 224 $dynamic_lib .= "$target : @{$targets{$target}}\n"; 225 } 226 227 $dynamic_lib; 228} 229 230sub postamble { 231 my $postamble = ''; 232 233 my $noecho = !!$ENV{V} ? '' : '$(NOECHO) '; 234 235 my $sep = $^O eq 'MSWin32' && $Config{make} eq 'nmake' 236 ? '\\' 237 : '/'; 238 239 $postamble .= 240 "flags: _mm${sep}flags\n" . 241 "_mm${sep}flags:\n"; 242 243 foreach my $key (qw( cc inc ccflags cccdlflags optimize ld ldflags lddlflags )) 244 { 245 $postamble .= 246 sprintf "\t$noecho\$(FULLPERL) inc${sep}mm-config-set.pl %-20s \$(%s)\n", $key, uc $key; 247 } 248 249 $postamble .= 250 "\t$noecho\$(MKPATH) _mm\n" . 251 "\t$noecho\$(TOUCH) _mm${sep}flags\n\n"; 252 253 $postamble .= 254 "probe-runner-builder prb: _mm${sep}probe-builder\n" . 255 "_mm${sep}probe-builder: _mm${sep}flags\n" . 256 "\t$noecho\$(FULLPERL) inc${sep}mm-config-pb.pl\n" . 257 "\t$noecho\$(MKPATH) _mm\n" . 258 "\t$noecho\$(TOUCH) _mm${sep}probe-builder\n\n"; 259 260 $postamble .= 261 "config :: _mm${sep}config\n" . 262 "_mm${sep}config: _mm${sep}flags _mm${sep}probe-builder\n" . 263 "\t$noecho\$(FULLPERL) inc${sep}mm-config.pl\n" . 264 "\t$noecho\$(MKPATH) _mm\n" . 265 "\t$noecho\$(TOUCH) _mm${sep}config\n\n"; 266 267 $postamble .= 268 "pure_all :: ffi\n" . 269 "ffi: _mm${sep}config\n" . 270 "\t$noecho\$(FULLPERL) inc${sep}mm-build.pl\n\n"; 271 272 $postamble .= 273 "subdirs-test_dynamic subdirs-test_static subdirs-test :: ffi-test\n" . 274 "ffi-test : _mm${sep}config\n" . 275 "\t$noecho\$(FULLPERL) inc${sep}mm-test.pl\n\n"; 276 277 $postamble .= 278 "clean :: mm-clean\n" . 279 "mm-clean :\n" . 280 "\t$noecho\$(FULLPERL) inc${sep}mm-clean.pl\n" . 281 "\t$noecho\$(RM_RF) _mm ffi-probe-*\n" . 282 "\t$noecho\$(RM_RF) .tmp\n" . 283 "\t$noecho\$(RM_RF) corpus${sep}*${sep}*${sep}tmpbuild*\n\n"; 284 285 # Workaround for the tireless testers out there 286 # who want to make -jX a thing. For some reason. 287 # 288 # When bsd make is passed -jX it turns off compat 289 # mode, even if the Makefile itself turns off 290 # parallel build. Unfortunately the Makefile 291 # generated by EUMM does not work without compat 292 # mode. So we: 293 $postamble .= 294 # 1. turn off parallel build using the bsd-only 295 # faux rule `.NO_PARALLEL` rather than the 296 # more portable `.NOTPARALLEL`, because this 297 # will allow parallel build with gmake, which 298 # does work. 299 ".NO_PARALLEL:\n\n"; 300 301 if($^O eq 'MSWin32' && $Config{ccname} eq 'cl') 302 { 303 # nothing. 304 } 305 else 306 { 307 $postamble .= 308 # 2. turn compat mode back on. 309 ".MAKE.MODE=compat\n\n"; 310 } 311 312 $postamble; 313} 314 315sub special_targets { 316 my($self, @therest) = @_; 317 my $st = $self->SUPER::special_targets(@therest); 318 $st .= "\n.PHONY: flags probe-runner-builder prb ffi ffi-test\n"; 319 $st; 320} 321 3221; 323