1# $Id: Makefile.PL,v 1.48 2012/10/26 19:11:54 mpeppler Exp $ 2 3use ExtUtils::MakeMaker; 4 5require 5.004; 6 7use strict; 8 9# If either of these aren't available on your system then you need to 10# get them! 11use DBI; 12use DBI::DBD; 13use Config; 14use Getopt::Long; 15 16use vars qw($SYBASE $inc_string $lib_string $LINKTYPE $written_pwd_file 17 $newlibnames $libdir); 18 19$LINKTYPE = 'dynamic'; 20$written_pwd_file = 'PWD'; 21$libdir = 'lib'; 22 23my $file; 24my $chained; 25my $threaded_libs; 26my $accept_test_defaults; 27GetOptions( 28 '--file' => \$file, 29 '--chained:s' => \$chained, 30 '--threaded_libs:s' => \$threaded_libs, 31 '--accept_test_defaults' => \$accept_test_defaults 32); 33 34select(STDOUT); 35$| = 1; 36 37configure(); 38 39configPwd(); 40 41my $lddlflags = $Config{lddlflags}; 42$lddlflags = "-L$SYBASE/$libdir $lddlflags" unless $^O eq 'VMS'; 43my $ldflags = $Config{ldflags}; 44$ldflags = "-L$SYBASE/$libdir $ldflags" unless $^O eq 'VMS'; 45 46WriteMakefile( 47 'NAME' => 'DBD::Sybase', 48 LIBS => [$lib_string], 49 INC => $inc_string, 50 clean => { FILES => "Sybase.xsi $written_pwd_file" }, 51 OBJECT => '$(O_FILES)', 52 'VERSION_FROM' => 'Sybase.pm', 53 'LDDLFLAGS' => $lddlflags, 54 55 # 'LDFLAGS' => $ldflags, 56 LINKTYPE => $LINKTYPE, 57 ( 58 $^O eq 'VMS' 59 ? ( MAN3PODS => { 'Sybase.pm' => 'blib/man3/DBD_Sybase.3' } ) 60 : ( MAN3PODS => { 'Sybase.pm' => 'blib/man3/DBD::Sybase.3' } ) 61 ), 62 ( 63 $] >= 5.005 64 ? ( 65 ABSTRACT => 'DBI driver for Sybase datasources', 66 AUTHOR => 'Michael Peppler (mpeppler@peppler.org)' 67 ) 68 : () 69 ), 70 ( 71 $] >= 5.005 72 && $^O eq 'MSWin32' 73 && $Config{archname} =~ /-object\b/i ? ( CAPI => 'TRUE' ) : () 74 ), 75 'dist' => { 'TARFLAGS' => 'cvf', 'COMPRESS' => 'gzip' }, 76 ( $^O eq 'VMS' ? ( PM => 'Sybase.pm' ) : () ) 77); 78 79sub MY::postamble { 80 return dbd_postamble(); 81} 82 83sub configure { 84 my %attr; 85 my ( $key, $val ); 86 87 my $sybase_dir = $ENV{SYBASE}; 88 89 if ( !$sybase_dir ) { 90 91 # PR 517 - getpwnam() isn't portable. 92 eval q{ 93 $sybase_dir = (getpwnam('sybase'))[7]; 94 }; 95 } 96 97 open( IN, "CONFIG" ) || die "Can't open CONFIG: $!"; 98 while (<IN>) { 99 chomp; 100 next if /^\s*\#/; 101 next if /^\s*$/; 102 103 ( $key, $val ) = split( /\s*=\s*/, $_ ); 104 $key =~ s/\s//g; 105 $val =~ s/\s*$//; 106 107 $attr{$key} = $val; 108 } 109 110 if ( -d $sybase_dir ) { 111 $SYBASE = $sybase_dir; 112 } 113 else { 114 if ( $attr{SYBASE} && -d $attr{SYBASE} ) { 115 $SYBASE = $attr{SYBASE}; 116 } 117 } 118 119 if ( !$SYBASE || $SYBASE =~ /^\s*$/ ) { 120 die 121"Please set SYBASE in CONFIG, or set the \$SYBASE environment variable"; 122 } 123 124 $SYBASE = VMS::Filespec::unixify($SYBASE) if $^O eq 'VMS'; 125 if ( $^O eq 'darwin' ) { 126 my $osxdir = 'Applications/Sybase/System'; 127 $SYBASE = $osxdir if -d $SYBASE && -d $osxdir; 128 } 129 130 # System 12.0 has a different directory structure... 131 if ( defined( $ENV{SYBASE_OCS} ) ) { 132 # if $SYBASE_OCS is an absolute path, then use that 133 if ($ENV{SYBASE_OCS} =~ m!^/!) { 134 $SYBASE = $ENV{SYBASE_OCS}; 135 } else { 136 $SYBASE .= "/$ENV{SYBASE_OCS}"; 137 } 138 } 139 140 my $libfound = 0; 141 my $libsub = ''; 142 my @libdir = ( 'lib', 'lib64' ); 143 if ($^O =~ /win/i) { 144 @libdir = ( 'dll' ); 145 } 146 foreach $libdir ( @libdir ) { 147 if ( -d "$SYBASE/$libdir" ) { 148 if ( checkLib($SYBASE) ) { 149 $libfound = 1; 150 $libsub = $libdir; 151 } 152 } 153 } 154 155 die "Can't find any Sybase libraries in $SYBASE/lib or $SYBASE/lib64" 156 unless $libfound; 157 158 my $inc_found = 0; 159 if ( -d "$SYBASE/include" && -f "$SYBASE/include/cspublic.h" ) { 160 ++$inc_found; 161 $inc_string = "-I$SYBASE/include"; 162 } 163 164 # In some freetds installations the include files have been moved 165 # into /usr/include/freetds. 166 if ( -d "$SYBASE/include/freetds" && "$SYBASE/include/freetds/cspublic.h" ) 167 { 168 ++$inc_found; 169 $inc_string = "-I$SYBASE/include/freetds"; 170 } 171 die "Can't find the Client Library include files under $SYBASE" 172 unless ($inc_found); 173 174 my $version = getLibVersion("$SYBASE/$libsub"); 175 176 # if(!$version || $version lt '12') { 177 #print "FreeTDS or older Client Library. Enabling CS-Lib Callbacks\n"; 178 #$inc_string .= " -DUSE_CSLIB_CB=1"; 179 # } 180 181 checkChainedAutoCommit(); 182 183 # print "OS = $^O\n"; 184 185 if ( $^O eq 'MSWin32' ) { 186 if ($version ge '15') { 187 $lib_string = 188 "-L$SYBASE/lib -llibsybct.lib -llibsybcs.lib -llibsybtcl.lib -llibsybcomn.lib -llibsybintl.lib -llibsybblk.lib $attr{EXTRA_LIBS} -lm"; 189 } 190 else { 191 $lib_string = 192 "-L$SYBASE/lib -llibct.lib -llibcs.lib -llibtcl.lib -llibcomn.lib -llibintl.lib -llibblk.lib $attr{EXTRA_LIBS} -lm"; 193 } 194 } 195 elsif ( $^O eq 'VMS' ) { 196 $lib_string = 197"-L$SYBASE/lib -llibct.olb -llibcs.olb -llibtcl.olb -llibcomn.olb -llibintl.olb -llibblk.olb $attr{EXTRA_LIBS}"; 198 } 199 elsif ( $^O =~ /cygwin/ ) { 200 $lib_string = "-L$SYBASE/lib -lct -lcs -lblk"; 201 $inc_string .= " -D_MSC_VER=800"; 202 } 203 else { 204 205 # Supplied by Erick Calder. I'm not sure why libsybsrv is needed... 206 $attr{EXTRA_LIBS} .= " -lsybsrv" if $^O eq 'darwin'; 207 208 my $extra = getExtraLibs( $SYBASE, $attr{EXTRA_LIBS}, $version ); 209 if ($file) { 210 $lib_string = 211"-L$SYBASE/$libdir -lct -lcs -ltcl -lcomn -lintl -lblk $attr{EXTRA_LIBS} -ldl -lm"; 212 } 213 else { 214 $lib_string = 215"-L$SYBASE/$libdir -lct -lcs -ltcl -lcomn -lintl -lblk $extra -ldl -lm"; 216 } 217 if ($newlibnames) { 218 foreach (qw(ct cs tcl comn intl blk)) { 219 $lib_string =~ s/-l$_/-lsyb$_/; 220 } 221 } 222 elsif ( $^O =~ /linux|freebsd/i ) { 223 $lib_string =~ s/-ltcl/-lsybtcl/; 224 } 225 226 my %libname; 227 228 %libname = loadSybLibs("$SYBASE/$libdir"); 229 230 my $libtype = ''; 231 232 # Logic to replace normal libs with _r (re-entrant) libs if 233 # usethreads is defined provided by W. Phillip Moore (wpm@ms.com) 234 # I have no idea if this works on Win32 systems (probably not!) 235 if ( $Config{usethreads} ) { 236 print "Running in threaded mode - looking for _r libraries...\n"; 237 238 if ( checkForThreadedLibs() ) { 239 my $found = 0; 240 foreach ( split( /\s+/, $lib_string ) ) { 241 next unless /^-l(\S+)/; 242 my $oldname = $1; 243 my $newname = $1 . "_r"; 244 next unless exists $libname{$newname}; 245 print "Found -l$newname for -l$oldname\n"; 246 ++$found; 247 $lib_string =~ s/-l$oldname\b/-l$newname/; 248 } 249 if ( !$found ) { 250 print "No thread-safe Sybase libraries found\n"; 251 $inc_string .= ' -DNO_THREADS '; 252 } 253 else { 254 $libtype .= '_r'; 255 } 256 } 257 else { 258 print "OK - I'll use the normal libs\n\n"; 259 } 260 } 261 262 # If we are building for a 64 bit platform that also supports 32 bit 263 # (i.e. Solaris 8, HP-UX11, etc) then we need to make some adjustments 264 if ( $Config{use64bitall} ) { 265 266 # Tru64/DEC OSF does NOT use the SYB_LP64 define 267 # as it is ALWAYS in 64 bit mode. 268 $inc_string .= ' -DSYB_LP64' unless $^O eq 'dec_osf'; 269 270 print "Running in 64bit mode - looking for '64' libraries...\n"; 271 272 my $found = 0; 273 foreach ( split( /\s+/, $lib_string ) ) { 274 next unless /^-l(\S+)/; 275 my $oldname = $1; 276 my $newname = $1 . '64'; 277 next unless exists $libname{$newname}; 278 print "Found -l$newname for -l$oldname\n"; 279 $lib_string =~ s/-l$oldname\b/-l$newname/; 280 ++$found; 281 } 282 if ($found) { 283 $libtype .= '64'; 284 } 285 } 286 287 # Is the blk library available? 288 #my @k = keys(%libname); 289 #print "@k\n"; 290 #print "libtype = $libtype\n"; 291 if ( my @l = grep( /(syb)?blk$libtype/, keys(%libname) ) ) { 292 print "BLK api available - found: @l\n"; 293 } 294 else { 295 print "BLK api NOT available.\n"; 296 $inc_string .= ' -DNO_BLK=1'; 297 } 298 } 299 300 my $config_sitearch = $Config{sitearchexp}; 301 my $attr_dbi_include = $attr{DBI_INCLUDE}; 302 if ( $^O eq 'VMS' ) { 303 $config_sitearch = VMS::Filespec::unixify($config_sitearch); 304 $attr_dbi_include = VMS::Filespec::unixify($attr_dbi_include); 305 } 306 my @try = ( @INC, $Config{sitearchexp} ); 307 unshift @try, $attr{DBI_INCLUDE} if $attr{DBI_INCLUDE}; 308 my $dbidir; 309 for my $trydir (@try) { 310 if ( -e "$trydir/auto/DBI/DBIXS.h" ) { 311 $dbidir = "$trydir/auto/DBI"; 312 last; 313 } 314 } 315 die "Can't find the DBI include files. Please set DBI_INCLUDE in CONFIG" 316 if !$dbidir; 317 $inc_string .= " -I$dbidir"; 318 if ( $attr{LINKTYPE} ) { 319 $LINKTYPE = $attr{LINKTYPE}; 320 } 321} 322 323sub loadSybLibs { 324 my $dir = shift; 325 326 my %libname = (); 327 328 opendir( SYBLIB, $dir ) 329 or die "Unable to opendir $dir: $!\n"; 330 foreach ( readdir(SYBLIB) ) { 331 next unless -f "$dir/$_"; 332 next unless /^lib(\S+)\.(so|a|sl)/; 333 $libname{$1} = 1; 334 } 335 336 closedir(SYBLIB); 337 338 return %libname; 339} 340 341sub getLibVersion { 342 my $lib = shift; 343 344 opendir( DIR, $lib ); 345 346 # reverse to pick up libsybct before libct... 347 my @files = reverse( grep( /lib(syb)?ct(64)?\./, readdir(DIR) ) ); 348 closedir(DIR); 349 my $file; 350 foreach (@files) { 351 $file = "$lib/$_"; 352 last if -e $file; 353 } 354 355 open( IN, $file ) || die "Can't open $file: $!"; 356 binmode(IN); 357 my $version; 358 while (<IN>) { 359 if (/Sybase Client-Library\/([^\/]+)\//) { 360 $version = $1; 361 last; 362 } 363 } 364 close(IN); 365 366 if ( !$version ) { 367 print "Unknown Client Library version - assuming FreeTDS.\n"; 368 } 369 else { 370 print "Sybase OpenClient $version found.\n"; 371 } 372 373 return $version; 374} 375 376sub getExtraLibs { 377 my $dir = shift; 378 my $cfg = shift; 379 my $version = shift; 380 381 opendir( DIR, "$dir/$libdir" ) || die "Can't access $dir/$libdir: $!"; 382 my %files = 383 map { $_ =~ s/lib([^\.]+)\..*/$1/; $_ => 1 } 384 grep( /lib/ && -f "$dir/$libdir/$_", readdir(DIR) ); 385 closedir(DIR); 386 387 my %x = map { $_ => 1 } split( ' ', $cfg ); 388 my $dlext = $Config{dlext} || 'so'; 389 foreach my $f ( keys(%x) ) { 390 my $file = $f; 391 $file =~ s/-l//; 392 next if ( $file =~ /^-/ ); 393 delete( $x{$f} ) unless exists( $files{$file} ); 394 } 395 396 foreach my $f (qw(insck tli sdna dnet_stub tds skrb gss)) { 397 $x{"-l$f"} = 1 if exists $files{$f} && -f "$dir/$libdir/lib$f.$dlext"; 398 } 399 if ( $version gt '11' ) { 400 delete( $x{-linsck} ); 401 delete( $x{-ltli} ); 402 } 403 404 # if($version ge '12.5.1') { 405 # delete($x{-lskrb}); 406 # } 407 408 join( ' ', keys(%x) ); 409} 410 411sub checkLib { 412 my $dir = shift; 413 414 opendir( DIR, "$dir/$libdir" ) || die "Can't access $dir/$libdir: $!"; 415 my @files = grep( /libct|libsybct/i, readdir(DIR) ); 416 closedir(DIR); 417 if ( grep( /libsybct/, @files ) ) { 418 $newlibnames = 1; 419 } 420 else { 421 $newlibnames = 0; 422 } 423 424 scalar(@files); 425} 426 427sub configPwd { 428 open( IN, "PWD.factory" ) || die "Can't open PWD.factory: $!"; 429 my %pwd; 430 while (<IN>) { 431 chomp; 432 next if (/^\s*\#/); 433 next if (/^\s*$/); 434 my ( $key, $val ) = split( /=/, $_ ); 435 $pwd{$key} = $val || "undef"; 436 } 437 close(IN); 438 439 if ($accept_test_defaults) { 440 $pwd{SRV} = $pwd{SRV}; 441 $pwd{UID} = $pwd{UID}; 442 $pwd{PWD} = $pwd{PWD}; 443 $pwd{DB} = $pwd{DB}; 444 } 445 else { 446 print 447"The DBD::Sybase module need access to a Sybase server to run the tests.\n"; 448 print "To clear an entry please enter 'undef'\n"; 449 print "Sybase server to use (default: $pwd{SRV}): "; 450 $pwd{SRV} = getAns(0) || $pwd{SRV}; 451 print "User ID to log in to Sybase (default: $pwd{UID}): "; 452 $pwd{UID} = getAns(0) || $pwd{UID}; 453 print "Password (default: $pwd{PWD}): "; 454 $pwd{PWD} = getAns(1) || $pwd{PWD}; 455 print "Sybase database to use on $pwd{SRV} (default: $pwd{DB}): "; 456 $pwd{DB} = getAns(0) || $pwd{DB}; 457 } 458 459 warn 460"\n* Writing login information, including password, to file $written_pwd_file.\n\n"; 461 462 # Create the file non-readable by anyone else. 463 my $old_umask; 464 unless ( $^O =~ /MSWin32/ ) { 465 $old_umask = umask(077); 466 warn "cannot umask(): $!" unless defined($old_umask); 467 } 468 open( OUT, ">$written_pwd_file" ) || die "Can't open $written_pwd_file: $!"; 469 unless ( $^O =~ /MSWin32/ ) { 470 umask($old_umask) != 077 && warn "strange return from umask()"; 471 } 472 print OUT <<EOF; 473# This file contains optional login id, passwd and server info for the test 474# programs: 475# You probably don't want to have it lying around after you've made 476# sure that everything works OK. 477 478EOF 479 foreach ( keys %pwd ) { 480 $pwd{$_} = '' if $pwd{$_} eq 'undef'; 481 print OUT "$_=$pwd{$_}\n"; 482 } 483 close(OUT); 484} 485 486sub checkChainedAutoCommit { 487 print <<EOF; 488 489By default DBD::Sybase 1.05 and later use the 'CHAINED' mode (where available) 490when 'AutoCommit' is turned off. Versions 1.04 and older instead managed 491the transactions explicitly with a 'BEGIN TRAN' before the first DML 492statement. Using the 'CHAINED' mode is preferable as it is the way that 493Sybase implements AutoCommit handling for both its ODBC and JDBC drivers. 494 495EOF 496 print "Use 'CHAINED' mode by default (Y/N) [Y]: "; 497 my $ans; 498 if ( defined($chained) ) { 499 $ans = $chained; 500 } 501 else { 502 $ans = getAns(0); 503 } 504 if ( $ans and $ans !~ /^y/i ) { 505 $inc_string .= " -DNO_CHAINED_TRAN=1"; 506 } 507 print "\n"; 508} 509 510sub checkForThreadedLibs { 511 my $ret = 1; 512 if ( $] >= 5.008 ) { 513 $ret = 0; 514 515 print <<EOF; 516 517***NOTE*** 518There is an incompatibility between perl (5.8.x or later) built in threaded 519mode and Sybase's threaded libraries, which means that signals delivered to 520the perl process result in a segment violation. 521 522I suggest building DBD::Sybase with the normal libraries in this case to get 523reasonable behavior for signal handling. 524 525EOF 526 print "Use the threaded (lib..._r) libraries [N]: "; 527 my $ans; 528 529 if ( defined($threaded_libs) ) { 530 $ans = $threaded_libs; 531 } 532 else { 533 $ans = getAns(0); 534 } 535 if ( $ans and $ans =~ /^y/i ) { 536 $ret = 1; 537 } 538 print "\n"; 539 } 540 541 return $ret; 542} 543 544sub getAns { 545 my $flag = shift; 546 547 if ( $flag && -t ) { 548 eval { 549 require Term::ReadKey; 550 Term::ReadKey::ReadMode('noecho'); 551 }; 552 } 553 my $ans = <STDIN>; 554 if ( $flag && -t ) { 555 eval { Term::ReadKey::ReadMode('normal'); }; 556 print "\n"; # because newline from user wasn't echo'd 557 } 558 $ans =~ s/^\s+//; 559 $ans =~ s/\s+$//; 560 561 return $ans; 562} 563