#******************************************************************************* # Copyright (c) 1997-2004, Perforce Software, Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #******************************************************************************* use ExtUtils::MakeMaker; use Getopt::Long; use English; use Cwd; use Cwd 'abs_path'; use Config; use strict; #$ExtUtils::MakeMaker::Verbose = 1; our $APIDIR = undef; our $MAX_API_VERSION = undef; # # Check the Perforce API version from the Version file # sub extract_api_version { my $path = shift; my $cwd = getcwd(); my $apiver = undef; foreach my $vfile ( "$path/Version", "$path/sample/Version" ) { next unless ( -e $vfile ); open( VF, $vfile ) or die( "Can't open $vfile" ); while( ) { if( /^RELEASE = (.*) ;/ ) { $apiver = encode_api_version( $1 ); last; } } close( FH ); } my $tries = 3; while( !defined( $apiver ) && --$tries ) { print( "Unable to determine API version string\n" ); print( "Enter API version: " ); $apiver = ; $apiver = encode_api_version( $apiver ); } die( "Aborting: API version not provided" ) unless $apiver; printf( "Found %d.%d Perforce API in %s\n", api_major( $apiver ), api_minor( $apiver ), $path ); return $apiver; } # # Encode an API version string into an integer # sub encode_api_version( $ ) { my $vs = shift; if( defined $vs && $vs =~ /(\d+)(\.|\s)(\d+)/ ) { return (($1 << 8 ) | $3 ); } return undef; } sub api_major( $ ) { my $v = shift; return $v >> 8; } sub api_minor( $ ) { my $v = shift; return $v & 0xff; } sub is_api_dir( $ ) { my $dir = shift; return 0 unless ( -d $dir ); return 1 if( -e "$dir/Version" ); return 1 if( -e "$dir/sample/Version" ); return 0; } # # Check that they're using an API version we can digest. # sub check_api_version( $ ) { my $api_ver = shift; my $max_ver_name = sprintf( "%d.%d", api_major( $MAX_API_VERSION ), api_minor( $MAX_API_VERSION ) ); return 1 if( $api_ver <= $MAX_API_VERSION ); print <; chomp( $answer ); return 0 unless $answer eq "y"; return 1; } sub get_api_dir() { if( defined( $APIDIR ) && is_api_dir( $APIDIR ) ) { return $APIDIR; } # Get the path to the Perforce API my $apipath = undef; my $tries = 3; $apipath = $APIDIR if( defined( $APIDIR ) ); while( !defined( $apipath ) && --$tries ) { print <; $apipath =~ s/\n//; # Filthy support for ~/ type paths ( NOT ~user/ though! ) $apipath =~ s#\~/#$ENV{HOME}/#; $apipath = abs_path( $apipath ); $apipath = undef unless( is_api_dir( $apipath ) ); } die ( "Aborting - no API directory provided" ) unless $apipath; return $apipath; } # # Add the Perforce libraries to the linker configuration # sub add_p4_libs( $$$ ) { my $cfg = shift; # Perl's pre-set config my $flags = shift; # Flags we want to add my $apidir = shift; # Our API directory my $libdir = $apidir; $libdir = "$libdir/lib" if( -d "$libdir/lib" ); $flags->{'LIBS'} = []; if( defined( $cfg->{LIBS} ) ) { my $libs = $cfg->{LIBS}; foreach my $libset (@$libs ) { push( @{$flags->{LIBS}}, "-L$libdir -lclient -lrpc -lsupp $libset" ); } } else { push( @{$flags->{LIBS}}, "-L$libdir -lclient -lrpc -lsupp" ); } } # # Add the Perforce headers to the includes # sub add_p4_hdrs( $$ ) { my $flags = shift; my $apipath = shift; $apipath = "$apipath/include/p4" if( -d "$apipath/include/p4" ); $flags->{ 'INC' } = "-I$apipath -Ilib"; } # # This sub adds the Perforce API path to the header includes and libs # used by the compiler. It's called by WriteMakefile. # sub config_sub { my $class = shift; my $href = shift; # First warn them about potential build problems print <{ 'DEFINE' } .= " -DP4API_VERSION=$apiver"; # # Set the build date # my $now = time(); $href->{ 'DEFINE' } .= " -DBUILD_DATE=$now"; # # Decide how const_char should be handled. If the API is 2006.1 or # later, then const_char should always be 'const char'. If it's # earlier, then go with the hint (if any) or default to 'char' # my $sixone = encode_api_version( "2006.1" ); if( $apiver ge $sixone ) { $href->{ 'DEFINE' } .= qq( -Dconst_char="const char"); } elsif( defined $href->{CONST_CHAR_HINT} ) { $href->{ 'DEFINE' } .= qq( -Dconst_char="$href->{CONST_CHAR_HINT}"); } else { $href->{ 'DEFINE' } .= qq( -Dconst_char="char"); } delete $href->{CONST_CHAR_HINT} if( defined($href->{CONST_CHAR_HINT}) ); add_p4_libs( $href, $flags, $apipath ); add_p4_hdrs( $flags, $apipath ); # # Make sure we're not linking with -debug on Windows - because the # linker chokes. # if( $^O eq "MSWin32" ) { $flags->{ 'LDDLFLAGS' } = $Config{ 'lddlflags' }; $flags->{ 'LDDLFLAGS' } =~ s/ -debug//g; } # # # Last thing to do is to get the address of their perforce # server for the tests print <; $p4port =~ s/\n//; $p4port = "perforce:1666" if ( $p4port =~ /^$/ ); open( IN, "test.pl.skel" ) or die( "Can't open test.pl.skel! "); open( OUT, ">test.pl" ) or die( "Can't create test.pl" ); my $line; while ( $line = ) { $line =~ s/__P4PORT__/$p4port/g; print( OUT $line ); } close( IN ); close( OUT ); return $flags; } # Ensure that the clientuserperl interface gets built. sub MY::postamble { ' $(MYEXTLIB): lib/Makefile cd lib && $(MAKE) $(PASSTHRU) '; } #******************************************************************************* #* START OF MAIN SCRIPT #******************************************************************************* # # This is the version of the API that was current when this build of # P4Perl was produced. It may build with later releases, but it may # not. # $MAX_API_VERSION = encode_api_version( "2007.2" ); my %flags = ( 'NAME' => 'P4', 'VERSION_FROM' => 'P4.pm', # finds $VERSION 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 'MYEXTLIB' => 'lib/libp4$(LIB_EXT)', 'XSOPT' => '-C++ -prototypes', 'CONFIGURE' => \&config_sub, 'clean' => { FILES => 'test.pl' }, ); our $APIDIR = undef; my $result = GetOptions ( "apidir=s" => \$APIDIR ); WriteMakefile( %flags );