#******************************************************************************* #* Usage: #* #* ruby p4conf.rb --apidir= \ #* --apilibdir= \ #* --apiincludedir= \ #* --apiver= \ #* --gccver=[23] #* #* --apidir=xx is equivalent to --apilibdir=xx --apiincludedir=xx #* #* --gccver defaults to 3 if not specified. #* #* #******************************************************************************* require 'mkmf' require 'rbconfig' require "getoptlong" #******************************************************************************* # C++ programs should be linked with g++ not with gcc. mkmf doesn't get that # right, so we have to hack it a little here. This particularly affects # gcc 3.x users as older gcc versions didn't mind too much. #******************************************************************************* if ( CONFIG[ 'LDSHARED' ] =~ /gcc/ ) CONFIG[ 'LDSHARED' ].gsub!( /gcc/, "g++" ) end if ( CONFIG[ "CC" ] =~ /gcc/ ) CONFIG[ "CXX" ] = CONFIG[ "CC" ].sub(/gcc/,"g++") unless CONFIG.has_key?( "CXX" ) end #******************************************************************************* # Prompt the user for something #******************************************************************************* def prompt( str, testproc ) while true print( str + ": " ) val = $stdin.gets.chomp break if ( testproc.call( val ) ) end return val end #******************************************************************************* # Set platform specific compile options #******************************************************************************* def set_platform_cflags $CFLAGS += "-DOS_#{$p4osname} " if ( $p4osname == "NT" ) $CFLAGS += "/DCASE_INSENSITIVE " $CFLAGS += "/MT " end if ( $p4osname == "SOLARIS" ) osver = `uname -r` osver.gsub!( /5\./, "2" ) if ( osver == "25" ) $CFLAGS += "-DSOLARIS25 " else $CFLAGS += "-DSOLARIS#{osver} " end # Solaris 2.7 and later require -Dconst_char="const char" if ( osver.to_i >= 27 ) $CFLAGS += "-Dconst_char='const char'" end $CFLAGS += "-Dsolaris " end if( $p4osname == "DARWIN" ) $CFLAGS += "-DCASE_INSENSITIVE " end end #******************************************************************************* # Set platform specific build options #******************************************************************************* def set_platform_opts if ( $p4osname == "CYGWIN" && $p4gccver == 2 ) CONFIG[ "CC" ] = "gcc-2" CONFIG[ "CXX" ] = "g++-2" CONFIG[ "LDSHARED" ].gsub!( /g\+\+/, "g++-2" ) elsif ( $p4osname == "DARWIN" && $p4gccver == 2 ) CONFIG[ "CC" ] = "gcc2" CONFIG[ "CXX" ] = "g++2" CONFIG[ "LDSHARED" ].sub!( /^cc/, "g++2" ) end end #******************************************************************************* # Use platform libs. Call *before* adding the API libs to preserve linking # order. #******************************************************************************* def use_platform_libs if ( $p4osname == "SOLARIS" ) osver = `uname -r` osver.gsub!( /5\./, "2" ) if ( osver == "25" ) $LDFLAGS += "/usr/ucblib/libucb.a " end use_lib( "nsl" ) use_lib( "socket" ) elsif ( $p4osname == "FREEBSD" ) use_lib( "gcc" ) elsif ( $p4osname == "NT" ) use_lib( "advapi32" ) use_lib( "wsock32" ) use_lib( "kernel32" ) use_lib( "oldnames" ) use_lib( "libcmt" ) elsif( $p4osname == "CYGWIN" ) # Clear out the bogus libs on cygwin. CONFIG[ "LIBS" ] = "" end end #******************************************************************************* # Set directory for the Perforce API libraries #******************************************************************************* def set_apilibdir( path ) $LIBPATH = $LIBPATH | [ path ] end #******************************************************************************* # Set directory for the Perforce API header files #******************************************************************************* def set_apiincludedir( path ) $CFLAGS += " -I#{path} " end #******************************************************************************* # function for generating a correctly formatted #define string #******************************************************************************* def define( macro, value ) %Q{#define #{macro}\t"#{value}"} end #******************************************************************************* #* Write the extconf.h file #******************************************************************************* def write_extconf_h File.open( "extconf.h", "w" ) do |ch| ch.puts( define( "P4APIVER", $apiver ) ) ch.puts( define( "P4OSNAME", $p4osname ) ) ch.puts( define( "P4CFLAGS", $CFLAGS ) ) ch.puts( define( "P4LIBPATH",$LIBPATH.join( ":" ) ) ) ch.puts( define( "P4LIBS", $libs ) ) end end #******************************************************************************* # Add a Perforce API library making sure it's properly named on NT #******************************************************************************* def api_lib( lib ) rlib = lib rlib = "lib" + lib if ( $p4osname == "NT" ) use_lib( rlib ) end #******************************************************************************* # Add a library to the link command bypassing lame have_library/find_library # which utterly suck for C++ libs. # NOTE: Add libs in *reverse* order. #******************************************************************************* def use_lib( lib ) $libs = append_library( $libs, lib ) end #******************************************************************************* # Function to write the makefile itself. This is mostly a wrapper around # mkmf's create_makefile(), but due to some deficiencies in mkmf w.r.t C++ # sources, we occasionally have to edit the makefile #******************************************************************************* def write_makefile( name ) create_makefile( name ) if ( CONFIG[ "CC" ] =~ /^gcc/ ) # Then we need to add a definition of CXX to the makefile # or the build will fail on some platforms (Cygwin at least). File.unlink( "Makefile.tmp" ) if File.exists?( "Makefile.tmp" ) File.rename( "Makefile", "Makefile.tmp" ) inmf = File.open( "Makefile.tmp" ) outmf = File.open( "Makefile", "w+" ) seen = false inmf.each do |line| if ( !seen && line =~ /^CC = / ) outmf.puts( "CXX = " + CONFIG[ "CXX" ] ) seen = true end outmf.puts( line ) end inmf.close outmf.close File.unlink( "Makefile.tmp" ) end end #******************************************************************************* # Start of main functionality #******************************************************************************* opts = GetoptLong.new( [ "--apidir", "-d", GetoptLong::REQUIRED_ARGUMENT ], [ "--apilibdir", GetoptLong::REQUIRED_ARGUMENT ], [ "--apiincludedir", GetoptLong::REQUIRED_ARGUMENT ], [ "--apiver", "-v", GetoptLong::REQUIRED_ARGUMENT ], [ "--gccver", GetoptLong::REQUIRED_ARGUMENT ] ) $apilibdir = nil $apiincludedir = nil $apiver = nil $p4gccver = 3 opts.each do |opt,arg| if ( opt == "--apidir" ) $apiincludedir = $apilibdir = File.expand_path( arg ) elsif( opt == "--apilibdir" ) $apilibdir = File.expand_path( arg ) elsif( opt == "--apiincludedir" ) $apiincludedir = File.expand_path( arg ) elsif( opt == "--apiver" ) $apiver = arg elsif( opt == "--gccver" ) $p4gccver = arg[0,1].to_i end end puts( "" ) puts( "Starting to configure P4/Ruby for building" ) puts( "" ) # # If the user has not supplied the api directories or apiver we prompt for them # dirproc = Proc.new { |dir| dir = File.expand_path( dir ) if ( ! File.directory?( dir ) ) puts( "No such directory. Try again" ) false else true end } if ( ! $apilibdir ) $apilibdir = prompt( "Where are the Perforce API Libraries?", dirproc ) $apilibdir = File.expand_path( $apilibdir ) end if ( ! $apiincludedir ) $apiincludedir = prompt( "Where are the Perforce API Headers?", dirproc ) $apiincludedir = File.expand_path( $apiincludedir ) end if ( ! $apiver ) verproc = Proc.new { |ver| if ( ver =~ /^\d{4}\.\d/ ) true else puts( "Invalid version number. Should be like '2002.1'" ) false end } $apiver = prompt( "Enter Perforce API Version", verproc ) end # # Work out the target OS, to guess the right defines to pass to the # Perforce API. Set this globally so we can refer to it elsewhere. # $p4osname = RUBY_PLATFORM.dup $p4osname.gsub!( /.*-(.*)(-.*)?/, '\1' ) $p4osname.gsub!( /(\d+\.?)*/, "" ) $p4osname.upcase! $p4osname.gsub!( /MSWIN/, "NT" ) set_apilibdir( $apilibdir ) set_apiincludedir( $apiincludedir ) set_platform_opts() set_platform_cflags() use_platform_libs() # Perforce API libraries - in reverse order api_lib( "supp" ) api_lib( "rpc" ) api_lib( "client" ) # # OK, now we know what we're going to do, let's tell the user # puts <