class Object

Constants

P4API_VERSION_DIR

Set this to the main version directory we look up in ftp.perforce.com for the P4API This is ignored if you specify the version on the command line.

Public Instance Methods

calculate_p4osname() click to toggle source
# File ext/P4/extconf.rb, line 47
def calculate_p4osname
  osname = RbConfig::CONFIG['arch'].split(/-/)[1].upcase
  osname = osname.gsub(/MSWIN32(_\d+)?/, "NT")
  osname = osname.split('-').shift

  case osname
    when /FREEBSD/
      osname = 'FREEBSD'
    when /DARWIN/
      osname = 'DARWIN'
    when /AIX/
      osname = 'AIX'
    when /SOLARIS/
      osname = 'SOLARIS'
  end

  return osname
end
calculate_p4osplat() click to toggle source
# File ext/P4/extconf.rb, line 21
def calculate_p4osplat
  plat = RbConfig::CONFIG['arch'].split(/-/)[0].upcase

  # On Mac OSX, fix the build to 64 bit arch
  if p4osname == 'DARWIN'
    plat = 'X86_64'
  end

  # Translate Ruby's arch names into Perforce's. Mostly the same so
  # only the exceptions are handled here.
  case plat
    when /^I.86$/
      plat = 'X86'
    when /^AMD64$/
      plat = 'X86_64'
    when 'POWERPC'
      plat = 'PPC'
  end

  return plat
end
calculate_p4osver() click to toggle source
# File ext/P4/extconf.rb, line 70
def calculate_p4osver
  ver = ''

  case p4osname
    when 'NT'
      # do nothing
    when /MINGW/
      # do nothing
    when /FREEBSD([0-9]+)/
      ver = $1
    when /DARWIN/
      ver = CONFIG['arch'].upcase.gsub(/.*DARWIN(\d+).*/, '\1')
    when /AIX(5)\.(\d)/
      ver = $1 + $2
    when /SOLARIS2\.(\d+)/
      ver = $1
    else
      # use uname -r to see if it works
      begin
        ver=%x`uname -r`.chomp
        ver_re = /^(\d+)\.(\d+)/
        md = ver_re.match(ver)
        if (md)
          maj = md[1].to_i
          min = md[2].to_i
          ver = maj.to_s + min.to_s
        end
      rescue
        # Nothing - if it failed, it failed.
      end
  end

  return ver
end
calculate_uname_platform() click to toggle source
# File ext/P4/extconf.rb, line 109
def calculate_uname_platform
  plat = "UNKNOWN"
  begin
    plat = %x`uname -p`
    plat = plat.chomp.upcase
  rescue
    # Nothing - if it failed, it failed.
  end
  plat
end
create_p4rubyconf_header(p4api_version, libs) click to toggle source
# File ext/P4/extconf.rb, line 325
def create_p4rubyconf_header(p4api_version, libs)
  File.open("p4rubyconf.h", "w") do
  |ch|
    ch.puts(macro_def("P4APIVER_STRING", p4api_version.to_s))
    ch.puts(macro_def("P4APIVER_ID", p4api_version.to_i, false))
    ch.puts(macro_def("P4API_PATCHLEVEL", p4api_version.patchlevel, false))
    ch.puts(macro_def("P4API_PATCHLEVEL_STRING", p4api_version.patchlevel.to_s))
    ch.puts(macro_def("P4RUBY_VERSION", P4::VERSION))
    ch.puts(macro_def("WITH_LIBS", libs, true))
  end
end
download_api_via_ftp() click to toggle source

Downloads the C++ P4API via FTP to the local directory, then 'initializes' it by unpacking it.

# File ext/P4/extconf.rb, line 480
def download_api_via_ftp
  ftp = Net::FTP.new('ftp.perforce.com')
  ftp.passive=true
  ftp.login

  # At one point, we allowed the gem build to just find the most recent p4api build.
  # P4Ruby probably shouldn't do that by default.
  #version_dir = find_latest_version_dir(ftp)
  version_dir = P4API_VERSION_DIR

  dir = ftp_download_dir(version_dir)
  ftp.chdir(dir)

  puts "downloading #{filename} from #{dir} on ftp.perforce.com"
  ftp.getbinaryfile(filename)

ensure
  ftp.close if ftp and !ftp.closed?
end
downloaded_p4api_dir() click to toggle source
# File ext/P4/extconf.rb, line 508
def downloaded_p4api_dir
  File.expand_path(Dir.entries('.').select { |x| x =~ /^p4api/ and File.directory?(x) }.first)
end
filename() click to toggle source
# File ext/P4/extconf.rb, line 433
def filename
  if RbConfig::CONFIG['target_os'].downcase =~ /nt|mswin|mingw/
    'p4api.zip'
  else
    'p4api.tgz'
  end
end
find_latest_version_dir(ftp) click to toggle source
# File ext/P4/extconf.rb, line 465
def find_latest_version_dir(ftp)
  ftp.chdir('perforce')

  # Capture all versions
  versions = remote_files_matching(ftp, '.', /r(1\d\.\d)/) { |m| m.captures.first }.sort

  version = find_latest_with_p4api(ftp, versions)

  ftp.chdir('..')

  "r#{version}"
end
find_latest_with_p4api(ftp, versions) click to toggle source
# File ext/P4/extconf.rb, line 453
def find_latest_with_p4api(ftp, versions)
  versions.reverse_each { |v|
    begin
      remote_files_matching(ftp, "r#{v}/#{platform_dir_name}/", /p4api/) do
        return v
      end
    rescue
      next
    end
  }
end
ftp_download_dir(version) click to toggle source
# File ext/P4/extconf.rb, line 429
def ftp_download_dir(version)
  "perforce/#{version}/#{platform_dir_name}"
end
macro_def(macro, value, string=true) click to toggle source
# File ext/P4/extconf.rb, line 317
def macro_def(macro, value, string=true)
  if (string)
    %Q{#define #{macro}\t"#{value}"}
  else
    %Q{#define #{macro}\t#{value}}
  end
end
p4_cpu(os) click to toggle source

Our 'cpu' label we use as part of the directory name on ftp.perforce.com

# File ext/P4/extconf.rb, line 382
def p4_cpu(os)
  cpu = RbConfig::CONFIG['target_cpu']
  case os
    when :darwin, :linux
      if cpu =~ /i686/
        'x86'
      else
        cpu
      end
    else
      case cpu
        when /ia/i
          'ia64'
        else
          cpu
      end
  end
end
p4_platform_label() click to toggle source

The p4_platform is our label that basically ends up being part of the directory name where we can download files from.

# File ext/P4/extconf.rb, line 403
def p4_platform_label
  case RbConfig::CONFIG["target_os"].downcase
    when /nt|mswin|mingw/
      # Ruby on windows is only MinGW via Rubyinstaller.org, though this may
      # not work on all rubies.
      if RbConfig::CONFIG['MAJOR'].to_i >= 2
        # Note that x64 or x86 needs to be suffixed to this
        'mingw64'
      else
        'mingwx86'
      end
    when /darwin/
      "darwin90#{p4_cpu(:darwin)}"
    when /solaris/
      "solaris10#{p4_cpu(:solaris)}"
    when /linux/
      "linux26#{p4_cpu(:linux)}"
    when /cygwin/
      raise 'cygwin is not supported for the --download-p4api option'
  end
end
p4osname() click to toggle source
# File ext/P4/extconf.rb, line 43
def p4osname
  @p4osname ||= calculate_p4osname
end
p4osplat() click to toggle source
Provide platform variables in P4-specific format
# File ext/P4/extconf.rb, line 17
def p4osplat
  @p4osplat ||= calculate_p4osplat
end
p4osver() click to toggle source
# File ext/P4/extconf.rb, line 66
def p4osver
  @p4osver ||= calculate_p4osver
end
platform_dir_name() click to toggle source
# File ext/P4/extconf.rb, line 425
def platform_dir_name
  "bin.#{p4_platform_label}"
end
remote_files_matching(ftp, dir, regex) { |match| ... } click to toggle source
# File ext/P4/extconf.rb, line 441
def remote_files_matching(ftp, dir, regex)
  ftp.ls(dir.to_s).map { |entry|
    if match = entry.match(regex)
      yield match
    else
      nil
    end
  }.reject { |entry|
    entry.nil?
  }
end
resolve_p4api_dir() click to toggle source

If the user has not specified –with-p4api-dir, check the –enable-p4api-download flag, and download the p4api before proceeding, unless that's disabled.

This may be a little confusing. If people specify –with-p4api-dir, we want use only use that setting. If that setting is wrong, we want to fail.

If they don't set the –with-p4api-dir, we'll proceed as if –enable-p4api-download has been set. Otherwise, they can –disable-p4api-download to ensure we just don't bother doing anything.

# File ext/P4/extconf.rb, line 352
def resolve_p4api_dir
  p4api_dir = nil

  # When running rake compile, use this instead of other options, I'm not sure how
  # gem/bundler options are passed through via rake
  p4api_dir = with_config('p4api-dir')
  dir_config('supp', "#{p4api_dir}/include/perforce", "#{p4api_dir}/lib/perforce")

  p4api_dir
end
resolve_ssl_dirs() click to toggle source
# File ext/P4/extconf.rb, line 363
def resolve_ssl_dirs
  ssl_dir = nil
  # When running rake compile, use this instead of other options, I'm not sure how
  # gem/bundler options are passed through via rake
  if ENV.has_key?('ssl_dir')
    ssl_dir = ENV['ssl_dir']
    dir_config('ssl', "#{ssl_dir}/include", "#{ssl_dir}/lib")
    puts "SSL Path #{ssl_dir}"
  end
  if ENV.has_key?('ssl_include_dir') && ENV.has_key?('ssl_lib_dir')
    ssl_include_dir = ENV['ssl_include_dir']
    ssl_lib_dir = ENV['ssl_lib_dir']
    dir_config('ssl', ssl_include_dir, ssl_lib_dir)
    puts "SSL Includes #{ssl_include_dir} Lib #{ssl_lib_dir}"
  end
  ssl_dir
end
set_platform_cflags() click to toggle source
# File ext/P4/extconf.rb, line 180
def set_platform_cflags
  if (p4osname == 'DARWIN')
    # Only build for 64 bit if we have more than one arch defined in CFLAGS
    $CFLAGS.slice!("-arch i386")
    $CFLAGS.slice!("-arch ppc");
  end
end
set_platform_cppflags() click to toggle source
# File ext/P4/extconf.rb, line 158
def set_platform_cppflags
  $CPPFLAGS += "-DOS_#{p4osname} "
  $CPPFLAGS += "-DOS_#{p4osname}#{p4osver} "
  $CPPFLAGS += "-DOS_#{p4osname}#{p4osver}#{p4osplat} "

  if (p4osname == 'NT')
    $CPPFLAGS += '/DCASE_INSENSITIVE '
  end

  if (p4osname == 'MINGW32')
    $CPPFLAGS += '-DOS_NT -DCASE_INSENSITIVE '
  end

  if (p4osname == 'SOLARIS')
    $CPPFLAGS += '-Dsolaris '
  end

  if (p4osname == 'DARWIN')
    $CPPFLAGS += '-DCASE_INSENSITIVE '
  end
end
set_platform_libs() click to toggle source

Initialize the base sets of platform libraries *before other initializers* to preserve linking order.

# File ext/P4/extconf.rb, line 190
def set_platform_libs

  case p4osname
    when 'SOLARIS'
      osver = %x`uname -r`
      osver.gsub!(/5\./, '2')
      if (osver == '25')
        $LDFLAGS += '/usr/ucblib/libucb.a '
      end
      have_library('nsl')
      have_library('socket')
    when 'NT'
      have_library('advapi32')
      have_library('wsock32')
      have_library('kernel32')
      have_library('oldnames')
    when 'CYGWIN'
      # Clear out 'bogus' libs on cygwin
      CONFIG['LIBS'] = ''
    when 'DARWIN'
      if p4osver.to_i >= 8
        # Only build for 64 bit if we have more than one arch defined in CFLAGS
        $LDFLAGS.slice!('-arch i386')
        $LDFLAGS.slice!('-arch ppc')
        $LDFLAGS += ' -framework CoreFoundation -framework Foundation'
      end
    when 'LINUX', 'MINGW32'
      have_library('supc++')
  end
end
set_platform_opts() click to toggle source
Setup additional compiler and linker options.

We generally need to launch these things before we configure most of the flags.
(See the main script at the end.)
# File ext/P4/extconf.rb, line 126
def set_platform_opts

  # Expand any embedded variables (like '$(CC)')
  CONFIG["CC"] = RbConfig::CONFIG["CC"]
  CONFIG["LDSHARED"] = RbConfig::CONFIG["LDSHARED"]

  # Make sure we have a CXX value (sometimes there isn't one)
  CONFIG["CXX"] = CONFIG["CC"] unless CONFIG.has_key?("CXX")

  # O/S specific oddities

  case p4osname
    when /DARWIN/
      CONFIG['CC'] = 'xcrun c++'
      CONFIG['CXX'] = 'xcrun c++'
      CONFIG['LDSHARED'] = CONFIG['CXX'] + ' -bundle'
    when /FREEBSD/, /LINUX/
      # FreeBSD 6 and some Linuxes use 'cc' for linking by default. The
      # gcc detection patterns above won't catch that, so for these
      # platforms, we specifically convert cc to c++.
      CONFIG['LDSHARED'].sub!(/^cc/, 'c++')
    when /MINGW32/
      # When building with MinGW we need to statically link libgcc
      # and make sure we're linking with gcc and not g++. On older
      # Rubies, they use LDSHARED; newer ones (>=1.9) use LDSHAREDXX
      CONFIG['LDSHARED'].sub!(/g\+\+/, 'gcc')
      CONFIG['LDSHAREDXX'].sub!(/g\+\+/, 'gcc')
      CONFIG['LDSHARED'] = CONFIG['LDSHARED'] + ' -static-libgcc'
      CONFIG['LDSHAREDXX'] = CONFIG['LDSHARED'] + ' -static-libgcc'
  end
end
uname_platform() click to toggle source
# File ext/P4/extconf.rb, line 105
def uname_platform
  @uname_platform ||= calculate_uname_platform
end
unzip_file() click to toggle source
# File ext/P4/extconf.rb, line 500
def unzip_file
  if RbConfig::CONFIG['target_os'].downcase =~ /nt|mswin|mingw/
    %x`unzip #{filename}`
  else
    %x`tar xzf #{filename}`
  end
end