#!/usr/local/bin/perl -w # # $Id: Makefile.PL 545 2004-10-29 13:44:06Z jurl $ # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the Perl README file. # BEGIN { require 5.004 } # 5.004 is required for Win32 use Config; use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); use File::Basename; use Getopt::Long; use File::Spec; use DBI 1.21; # must be installed first ... use DBI::DBD; use strict; my %opts = ( NAME => 'DBD::ODBC', VERSION_FROM => 'ODBC.pm', PREREQ_PM => { "Test::Simple" => 0.40 }, # actually Test::More pkg in T::S dist clean => { FILES=> 'ODBC.xsi dbdodbc.h' }, dist => { #DIST_DEFAULT=> 'clean distcheck disttest ci tardist', DIST_DEFAULT=> 'clean distcheck tardist', PREOP => '$(MAKE) -f Makefile.old distdir', COMPRESS => 'gzip -v9', SUFFIX => 'gz' }, OBJECT => '$(O_FILES)', ); if ($ExtUtils::MakeMaker::VERSION >= 5.43) { $opts{AUTHOR} = 'Tim Bunce and Jeff Urlwin mailto:dbi-users@perl.org'; $opts{ABSTRACT} = 'ODBC driver for the DBI module.'; $opts{PREREQ_PM} = { DBI => 1.21 }; $opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; } our $opt_g = 0; our $opt_o = ''; Getopt::Long::GetOptions("g!" => \$opt_g, "o=s" => \$opt_o) or die "Invalid arguments"; print "Overriding ODBC Directory with command line option: $opt_o\n" if $opt_o ; if ($opt_g) { print "Setting debug options!\n"; if ($^O eq 'MSWin32') { $opts{OPTIMIZE} = '/Zi'; } else { $opts{OPTIMIZE} = '-g -O0'; } } print "\nConfiguring DBD::ODBC ...\n >>>\tRemember to actually *READ* the README file! \tAnd re-read it if you have any problems.\n "; my $dbi_dir = dbd_dbi_dir(); my $dbi_arch_dir = dbd_dbi_arch_dir(); open(SQLH, ">dbdodbc.h") || die "Can't open dbdodbc.h: $!\n"; print SQLH "/* Do not edit this file. It is automatically written by Makefile.PL.\n"; print SQLH " Any changes made here will be lost. \n*/\n\n"; print SQLH "#undef WORD /* from perly.y */\n"; my (@known_drivers) = sort { $a cmp $b } ( 'Microsoft ODBC', 'unixodbc', 'iodbc', 'esodbc', 'empress', 'intersolve', 'sapdb', 'adabas', 'udbc', 'easysoft', 'solid', 'informix', ); if ($^O eq 'MSWin32') { my $extrainc = ""; $extrainc = ";$Config{incpath}\\mfc" if $Config{cc} eq 'bcc32'; $opts{SKIP} = ['processPL']; $opts{DEFINE} = ""; $opts{INC} = "-I$dbi_arch_dir" . $extrainc; $opts{LIBS} = ["ODBC32.LIB"]; $opts{macro}->{EXTRALIB} = 'ODBC32.LIB'; print SQLH "#include \n"; print SQLH "#include \n#include \n#include \n"; } else { # for Adabas $ENV{ODBCHOME} = $ENV{DBROOT} if $ENV{DBROOT} && -f "$ENV{DBROOT}/lib/odbclib.a"; print "Overriding ODBC Directory with command line option: $opt_o\n" if $opt_o ; my $odbchome= $opt_o || $ENV{ODBCHOME}; $odbchome = VMS::Filespec::unixify($odbchome) if $^O eq 'VMS'; # per patches from Teun Burgers if (!$odbchome && $ENV{WINDIR} && $^O eq 'cygwin') { my $tmp_odbchome = $ENV{WINDIR}; $tmp_odbchome =~ s/^([A-Za-z]):*$/\/\/$1/; $tmp_odbchome =~ s/\\/\//g; $odbchome = $tmp_odbchome if (-e "$tmp_odbchome/odbc.ini") } if (!$odbchome && -f '/opt/sapdb/interfaces/odbc/lib/libsqlod.a') { $odbchome = '/opt/sapdb/interfaces/odbc/'; } unless ($odbchome) { print "\n"; print "The DBD::ODBC module needs to link with an ODBC 'Driver Manager'.\n"; print "(The Driver Manager, in turn, needs one or more database specific ODBC drivers.\n"; print "The DBD::ODBC module does _not_ include any ODBC drivers!)\n\n"; print "You need to indicate where your ODBC Driver Manager is installed.\n"; print "You can do this ether by setting the ODBCHOME environment variable\n"; print "or by runing 'perl Makefile.PL -o odbcdir'.\n\n"; print "If you do not have an ODBC Driver Manager you can try building\n"; print "the free iODBC Driver Manager in the iodbcsrc directory.\n\n"; die "Makefile.PL aborted.\n"; } die "ODBCHOME environment variable ($odbchome) does not refer to a directory.\n" unless -d $odbchome; warn "Using ODBC in $odbchome\n"; $opts{INC} = "-I. -I$dbi_arch_dir"; # cygwin patch $opts{INC} .= " -I/usr/include/w32api" if $^O eq 'cygwin'; # Try to work out which driver manager is being used. # Feel free to come up with neat (or un-neat) hacks to get your's to build! my $lib_d1 = "$odbchome/lib"; my $lib_d2 = "$odbchome/dlls"; my $libs = "odbc"; $opts{LIBS} = " -L$lib_d1 -R$lib_d1 -L$lib_d2 -R$lib_d2 -l$libs"; my $myodbc =''; # edit and hack to suit! $myodbc = 'Microsoft ODBC' if ( -e "$odbchome/system/odbc32.dll" or -e "$odbchome/system32/odbc32.dll" or -e "$odbchome/odbc32.dll"); my $dlext = $Config{dlext}; my $arext = $Config{lib_ext}; # fix to avoid foo..ext on many systems. $arext =~ s/^\.//; # per patches from Nick Gorham $myodbc = 'unixodbc' if !$myodbc && <$odbchome/lib/libodbc.*>; $myodbc = 'iodbc' if !$myodbc && (<$odbchome/*iodbc*> || <$odbchome/lib/*iodbc*>); $myodbc = 'esodbc' if !$myodbc && <$odbchome/*esoobclient*>; $myodbc = 'empress' if !$myodbc && <$odbchome/lib/libempodbc.*>; $myodbc = 'intersolve' if !$myodbc && -f "$odbchome/include/qeodbc.h"; $myodbc = 'sapdb' if !$myodbc && -f "$odbchome/lib/libsqlod.$arext"; $myodbc = 'adabas' if !$myodbc && $ENV{DBROOT} && $odbchome eq $ENV{DBROOT} && -f "$odbchome/lib/odbclib.$arext"; $myodbc = 'udbc' if !$myodbc && -f "$odbchome/lib/libudbc.$arext"; $myodbc = 'easysoft' if !$myodbc && -f "$odbchome/lib/libesoobclient.$dlext"; $myodbc = 'solid' if !$myodbc && -f "$odbchome/lib/libsolcli.$dlext"; # JL 2002-12-16: This test is accurate on Unix (Solaris 7) with IBM # Informix ClientSDK 2.80.UC1, which includes IBM Informix CLI # v3.81.000, an ODBC 3.x driver. # NB: The correct value for $ODBCHOME is $INFORMIXDIR. $myodbc = 'informix' if !$myodbc && -f "$odbchome/lib/cli/libifcli.$dlext"; if (!$myodbc) { local($") = ", "; my($list) = "@known_drivers"; $list =~ s%^(.{30,70})\s%$1\n\t%gmo; die qq% Hmm...I cannot find an ODBC driver manager that I recognize. ...And I know about these drivers: $list %; } warn "\nUmm, this looks like a $myodbc type of driver manager.\n"; if ($myodbc eq 'Microsoft ODBC') { print "\nBuilding for Microsoft under Cygwin\n"; $opts{LIBS} = "-L/usr/lib/w32api -lodbc32"; print SQLH "#include \n"; print SQLH "#include \n"; print SQLH "#include \n"; print SQLH "#include \n"; print SQLH "#undef WIN32\n"; $opts{dynamic_lib} = {OTHERLDFLAGS => "-lodbc32"}; } elsif ($myodbc eq 'iodbc') { my $ilibdir = "$odbchome/lib"; my @ilibs = <$ilibdir/*iodbc*.*>; @ilibs = grep { /\.($Config{so}|$Config{dlext}|a)$/ } @ilibs; die "That's odd, I can't see any iodbc libs in $ilibdir" unless @ilibs; # This is a hack using Intersolve's free Solaris ODBC manager # Since it doesn't come with the sql header files (!) we get them from iODBC! # Note: we use DEFINE not INC for iODBC so we don't get its config.h print "\n"; print "We expect to find the isql.h, isqlext.h and iodbc.h files (which were\n"; print "supplied with iODBC) in \$ODBCHOME/include directory alongside\n"; print "the @ilibs library.\n\n"; my $ilibpath = $ilibs[0]; # XXX if both .so and .a, pick based on LINKTYPE? my $ilibname = basename($ilibpath); $opts{DEFINE} = "-I$odbchome/include"; if ($ilibname =~ /^iodbc/) { # no "lib" prefix $opts{LIBS} = ""; $opts{dynamic_lib} = { OTHERLDFLAGS => "$ilibpath" }; } else { # remove lib prefix and .so suffix so "-l" style link can be used $ilibname =~ s/^lib(iodbc.*?)\.\w+$/$1/; $opts{LIBS} = "-L$ilibdir -l$ilibname"; # changed /\Q$ilibpath/ to /\Q$ilibdir/ per recommendation # by Ron Savage warn "Warning: LD_LIBRARY_PATH doesn't include $odbchome/lib\n" unless $ENV{LD_LIBRARY_PATH} =~ /\Q$ilibdir/; } #print SQLH qq{#define FAR \n#define EXPORT \n#define CALLBACK \n}; #print SQLH qq{#include \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; #print SQLH qq{#include "fixup_t.h"\n}; } elsif ($myodbc eq 'unixodbc') { my @ilibs = <$odbchome/lib/libodbc.*>; @ilibs = grep { /\.($Config{so}|$Config{dlext}|a)$/ } @ilibs; die "That's odd, I can't see any unixodbc libs in $odbchome" unless @ilibs; print "We expect to find the sql.h, sqlext.h and (which were\n"; print "supplied with unixODBC) in \$ODBCHOME/include directory alongside\n"; print "the @ilibs library. in \$ODBCHOME/lib\n\n"; my $ilibpath = $ilibs[0]; # XXX if both .so and .a, pick based on LINKTYPE? my $ilibname = basename($ilibpath); $opts{DEFINE} = "-I$odbchome/include"; if ($ilibname =~ /^odbc/) { # no "lib" prefix $opts{LIBS} = ""; $opts{dynamic_lib} = { OTHERLDFLAGS => "$ilibpath" }; } else { # remove lib prefix and .so suffix so "-l" style link can be used $ilibname =~ s/^lib(odbc.*?)\.\w+$/$1/; $opts{LIBS} = "-L$odbchome/lib -l$ilibname"; warn "Warning: LD_LIBRARY_PATH doesn't include $odbchome\n" unless $ENV{LD_LIBRARY_PATH} =~ /\Q$odbchome\/lib/; } print SQLH qq{#include \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; } elsif ($myodbc eq 'esodbc') { my @ilibs = <$odbchome/*esoobclient.*>; print "Located library @ilibs\n"; # omit . prefix in next grep as some $Config types have . and some don't @ilibs = grep { /($Config{so}|$Config{dlext}|$Config{lib_ext})$/ } @ilibs; die "That's odd, I can't see any esoobclient libs in $odbchome" unless @ilibs; print "We expect to find the sql.h and sqlext.h files (which were\n"; print "supplied with esoobclient) in \$ODBCHOME/include directory alongside\n"; print "the @ilibs library.\n\n"; my $ilibpath = $ilibs[0]; # XXX if both .so and .a, pick based on LINKTYPE? my $ilibname = basename($ilibpath); print "Using library $ilibname\n"; $opts{INC} .= " -I$odbchome/include"; # # ptrmismatch avoids the char/unsigned problems in DBD # outtyplen is one incorrect fprintf in dbiimp.c(200) # promotmatchw - old prototypes problem # $opts{CCFLAGS} .= "/warnings=informational=(outtypelen,ptrmismatch,promotmatchw)" if ($Config{cc} =~ /DECC/ && $^O eq 'VMS' ); if ($ilibname =~ /^esoobclient/) { # no "lib" prefix $opts{LIBS} = ""; $opts{dynamic_lib} = { OTHERLDFLAGS => "$ilibpath" }; } else { my $extralibs=""; if (($^O eq 'VMS') && ($ilibname =~ /$Config{lib_ext}$/)) { $extralibs = " -lcs_share -lsupport -leasyrpc"; print "Adding libraries $extralibs\n"; } # remove lib prefix and so suffix so "-l" style link can be used $ilibname =~ s/^lib(esoobclient.*?)\.\w+$/$1/; $opts{LIBS} = "-L$odbchome -l$ilibname $extralibs"; if ($^O ne "VMS") { warn "Warning: LD_LIBRARY_PATH doesn't include $odbchome\n" unless $ENV{LD_LIBRARY_PATH} =~ /\Q$odbchome/; } } print SQLH qq{#define FAR \n#define EXPORT \n#define CALLBACK \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; print SQLH qq{#include \n}; } elsif ($myodbc eq 'intersolve') { $opts{DEFINE} = ""; print SQLH qq{#include \n}; if (-f "$odbchome/include/sql.h") { print "You seem to have the official header files.\n"; $opts{INC} .= " -I$odbchome/include"; print SQLH qq{#include \n#include \n#include \n}; } else { # This is common on Solaris print "You don't seem to have the official header files,\n"; print "so I'll use the iODBC ones instead.\n"; $opts{INC} .= " -I$odbchome/include -Iiodbcsrc"; print SQLH qq{#include \n#include \n}; } } elsif ($myodbc eq 'empress') { $opts{INC} .= " -I$odbchome/include"; $opts{DEFINE} = ""; print SQLH qq{#include \n}; print SQLH qq{#include \n#include \n}; $opts{LIBS} = "-L$odbchome/lib -R$odbchome/lib -lempodbc"; } elsif ($myodbc eq 'sapdb') { print SQLH "#include \n"; print SQLH "#include \n"; print SQLH "#include \n"; print SQLH "#define HENV SQLHENV\n"; print SQLH "#define HDBC SQLHDBC\n"; print SQLH "#define HSTMT SQLHSTMT\n"; print SQLH "#define DBD_ODBC_NO_SQLDRIVERCONNECT\n"; print SQLH qq{#define DBD_ODBC_NO_DATASOURCES\n}; # unless ($^O eq 'MSWin32'); $opts{INC} .= " -I$odbchome/incl"; $opts{LDFROM} = "\$(OBJECT) $odbchome/lib/libsqlod.a"; } elsif ($myodbc eq 'adabas') { print SQLH "#define FAR \n#define EXPORT \n#define CALLBACK \n"; print SQLH "#include \n"; print SQLH "#include \n"; print SQLH "#include \n"; $opts{INC} .= " -I$odbchome/incl"; $opts{LIBS} = "-L$odbchome/lib -lsqlrte -lsqlptc"; $opts{LDFROM} = "\$(OBJECT) $odbchome/lib/odbclib.a"; } elsif ($myodbc eq 'udbc') { print SQLH qq{#include \n}; $opts{INC} .= " -I$odbchome/include"; $opts{DEFINE} = ""; $opts{LIBS} = "-L$odbchome/lib -R$odbchome/lib -ludbc"; } elsif ($myodbc eq 'easysoft') { $opts{INC} .= " -I$odbchome/include"; $opts{LIBS} = "-L$odbchome/lib -lesoobclient"; print SQLH qq{#include \n#include \n}; } elsif ($myodbc eq 'solid') { $opts{INC} .= " -I$odbchome/include"; $opts{LIBS} = "-L$odbchome/lib -lsolcli"; # Solid does not support DataSources print SQLH qq{#define DBD_ODBC_NO_DATASOURCES\n}; # Solid does not support DataSources print SQLH qq{#define DBD_ODBC_NO_SQLDRIVERCONNECT\n}; print SQLH qq{#include \n}; } elsif ($myodbc eq 'informix') { # JL 2002-12-16: See comments above for environment details. $opts{INC} = "-I$odbchome/incl/cli $opts{INC}"; $opts{LIBS} = "-L$odbchome/lib/cli -lifcli -lifdmr"; $opts{DEFINE} .= "-DNO_WIN32"; # Applies to Unix only, of course print SQLH qq{#include \n}; print SQLH qq{#include \n}; } else { print "\n*** WARNING ***\a\n"; print "Unknown driver manager. Using default build process.\n"; print "This will almost certainly fail at some point.\n"; print "In which case you will need to edit/hack the Makefile.PL\n"; print "to suit your needs. (Specifically to locate your odbc\n"; print "library and header files.)\n\n"; $opts{DEFINE} = ""; print SQLH qq{#include \n#include \n}; } } print SQLH qq{\n}; print SQLH qq{#include "fixup_c.h"\n}; print SQLH qq{\n}; close(SQLH); print "\n"; my $rv = WriteMakefile(%opts); local($^W)=0; print qq{ The DBD::ODBC tests will use these values for the database connection: DBI_DSN=$ENV{DBI_DSN} e.g. dbi:ODBC:demo DBI_USER=$ENV{DBI_USER} DBI_PASS=$ENV{DBI_PASS} }; print "Warning: not all required environment variables are set.\n" unless ($ENV{DBI_DSN} && $ENV{DBI_USER} && $ENV{DBI_PASS}); print "Warning: DBI_DSN ($ENV{DBI_DSN}) doesn't start with 'dbi:ODBC:'\n" if ($ENV{DBI_DSN} && $ENV{DBI_DSN} !~ m/^dbi:ODBC:/); print "\n"; warn "See README.RH9 if you have problems with a bad Makefile generated here\a\a\a\n" if ($ENV{LANG} && $ENV{LANG} =~ /utf8/); $rv; sub MY::post_constants { my ($self) = shift; ' # make Changes file available as installed pod docs "perldoc DBI::Changes" inst_libdbdodbc = ' . File::Spec->catdir($self->{INST_LIB}, 'DBD/ODBC') . ' changes_pm = ' . File::Spec->catfile($self->{INST_LIB}, 'DBD/ODBC', 'Changes.pm') . ' config :: $(changes_pm) @$(NOOP) $(changes_pm): Changes $(NOECHO) $(MKPATH) $(inst_libdbdodbc) $(NOECHO) $(RM_F) $(changes_pm) $(CP) Changes $(changes_pm) '; } # ==================================================================== { package MY; # SUPER needs package context, $self is not sufficient use strict; use Config; sub postamble { return main::dbd_postamble(@_); } sub const_cccmd { my $self = shift; local($_) = $self->SUPER::const_cccmd(@_); # inject the defined local ODBC before default include to ensure # the ODBC driver we want is first if ($^O ne 'MSWin32') { s/-c/-c \$\(DEFINE\)/; print "Injecting selected odbc driver into cc command\n"; } $_; } } __END__