class RMagick::Extconf

Constants

MIN_RUBY_VERS
RMAGICK_VERS

Attributes

headers[R]

Public Class Methods

new() click to toggle source
# File ext/RMagick/extconf.rb, line 15
def initialize
  @stdout = $stdout.dup

  setup_pkg_config_path
  configure_compile_options
  assert_can_compile!
  configure_headers
end

Public Instance Methods

assert_can_compile!() click to toggle source
# File ext/RMagick/extconf.rb, line 284
def assert_can_compile!
  assert_minimum_ruby_version!
  assert_has_dev_libs!
end
assert_has_dev_libs!() click to toggle source
# File ext/RMagick/extconf.rb, line 297
def assert_has_dev_libs!
  return unless RUBY_PLATFORM !~ /mswin|mingw/

  unless `pkg-config --libs MagickCore`[/\bl\s*(MagickCore|Magick)6?\b/]
    exit_failure "Can't install RMagick #{RMAGICK_VERS}. " \
               "Can't find the ImageMagick library or one of the dependent libraries. " \
               "Check the mkmf.log file for more detailed information.\n"
  end
end
assert_minimum_ruby_version!() click to toggle source
# File ext/RMagick/extconf.rb, line 289
def assert_minimum_ruby_version!
  unless checking_for("Ruby version >= #{MIN_RUBY_VERS}") do
    Gem::Version.new(RUBY_VERSION) >= Gem::Version.new(MIN_RUBY_VERS)
  end
    exit_failure "Can't install RMagick #{RMAGICK_VERS}. Ruby #{MIN_RUBY_VERS} or later required.\n"
  end
end
check_multiple_imagemagick_versions() click to toggle source

Seems like lots of people have multiple versions of ImageMagick installed.

# File ext/RMagick/extconf.rb, line 190
def check_multiple_imagemagick_versions
  versions = []
  path = ENV['PATH'].split(File::PATH_SEPARATOR)
  path.each do |dir|
    file = File.join(dir, 'Magick-config')
    next unless File.executable? file

    vers = `#{file} --version`.chomp.strip
    prefix = `#{file} --prefix`.chomp.strip
    versions << [vers, prefix, dir]
  end
  versions.uniq!
  return unless versions.size > 1

  msg = "\nWarning: Found more than one ImageMagick installation. This could cause problems at runtime.\n"
  versions.each do |vers, prefix, dir|
    msg << "         #{dir}/Magick-config reports version #{vers} is installed in #{prefix}\n"
  end
  msg << "Using #{versions[0][0]} from #{versions[0][1]}.\n\n"
  Logging.message msg
  message msg
end
check_partial_imagemagick_versions() click to toggle source

Ubuntu (maybe other systems) comes with a partial installation of ImageMagick in the prefix /usr (some libraries, no includes, and no binaries). This causes problems when /usr/lib is in the path (e.g., using the default Ruby installation).

# File ext/RMagick/extconf.rb, line 217
def check_partial_imagemagick_versions
  prefix = config_string('prefix') || ''
  matches = [
    prefix + '/lib/lib?agick*',
    prefix + '/include/ImageMagick',
    prefix + '/bin/Magick-config'
  ].map do |file_glob|
    Dir.glob(file_glob)
  end
  matches.delete_if(&:empty?)
  return unless !matches.empty? && matches.length < 3

  msg = "\nWarning: Found a partial ImageMagick installation. Your operating system likely has some built-in ImageMagick libraries but not all of ImageMagick. This will most likely cause problems at both compile and runtime.\nFound partial installation at: " + prefix + "\n"
  Logging.message msg
  message msg
end
configure_compile_options() click to toggle source
# File ext/RMagick/extconf.rb, line 61
def configure_compile_options
  # Magick-config is not available on Windows
  if RUBY_PLATFORM !~ /mswin|mingw/

    # Check for compiler. Extract first word so ENV['CC'] can be a program name with arguments.
    config = defined?(RbConfig) ? ::RbConfig : ::Config
    cc = (ENV['CC'] || config::CONFIG['CC'] || 'gcc').split(' ').first
    exit_failure "No C compiler found in ${ENV['PATH']}. See mkmf.log for details." unless find_executable(cc)

    magick_package = determine_imagemagick_package

    $magick_version = `pkg-config #{magick_package} --modversion`[/^(\d+\.\d+\.\d+)/]

    check_multiple_imagemagick_versions
    check_partial_imagemagick_versions

    # Ensure minimum ImageMagick version
    # Check minimum ImageMagick version if possible
    checking_for("outdated ImageMagick version (<= #{Magick::MIN_IM_VERSION})") do
      Logging.message("Detected ImageMagick version: #{$magick_version}\n")

      exit_failure "Can't install RMagick #{RMAGICK_VERS}. You must have ImageMagick #{Magick::MIN_IM_VERSION} or later.\n" if Gem::Version.new($magick_version) < Gem::Version.new(Magick::MIN_IM_VERSION)
    end

    # Save flags
    $CFLAGS = ENV['CFLAGS'].to_s + ' ' + `pkg-config --cflags #{magick_package}`.chomp
    $CPPFLAGS = ENV['CPPFLAGS'].to_s + ' ' + `pkg-config --cflags #{magick_package}`.chomp
    $LDFLAGS = ENV['LDFLAGS'].to_s + ' ' + `pkg-config --libs #{magick_package}`.chomp
    $LOCAL_LIBS = ENV['LIBS'].to_s + ' ' + `pkg-config --libs #{magick_package}`.chomp

    set_archflags_for_osx if RUBY_PLATFORM =~ /darwin/ # osx

  elsif RUBY_PLATFORM =~ /mingw/ # mingw

    `identify -version` =~ /Version: ImageMagick (\d+\.\d+\.\d+)-+\d+ /
    abort 'Unable to get ImageMagick version' unless Regexp.last_match(1)
    $magick_version = Regexp.last_match(1)

    dir_paths = search_paths_for_library_for_windows
    $CPPFLAGS = %(-I"#{dir_paths[:include]}")
    $LDFLAGS = %(-L"#{dir_paths[:lib]}")

    have_library('CORE_RL_magick_')

  else # mswin

    `identify -version` =~ /Version: ImageMagick (\d+\.\d+\.\d+)-+\d+ /
    abort 'Unable to get ImageMagick version' unless Regexp.last_match(1)
    $magick_version = Regexp.last_match(1)

    dir_paths = search_paths_for_library_for_windows
    $CPPFLAGS << %( -I"#{dir_paths[:include]}")
    $LDFLAGS << %( -libpath:"#{dir_paths[:lib]}")

    $LOCAL_LIBS = 'CORE_RL_magick_.lib'

  end

  $CFLAGS << (have_macro('__GNUC__') ? ' -std=gnu99' : ' -std=c99')
end
configure_headers() click to toggle source
# File ext/RMagick/extconf.rb, line 51
def configure_headers
  @headers = %w[assert.h ctype.h stdio.h stdlib.h math.h time.h sys/types.h]

  if have_header('magick/MagickCore.h')
    headers << 'magick/MagickCore.h'
  else
    exit_failure "Can't install RMagick #{RMAGICK_VERS}. Can't find magick/MagickCore.h."
  end
end
configured_compile_options() click to toggle source
# File ext/RMagick/extconf.rb, line 39
def configured_compile_options
  {
    magick_version: $magick_version,
    local_libs: $LOCAL_LIBS,
    cflags: $CFLAGS,
    cppflags: $CPPFLAGS,
    ldflags: $LDFLAGS,
    defs: $defs,
    config_h: $config_h
  }
end
create_header_file() click to toggle source
# File ext/RMagick/extconf.rb, line 307
def create_header_file
  [
    'GetImageChannelEntropy', # 6.9.0-0
    'SetImageGray' # 6.9.1-10
  ].each do |func|
    have_func(func, headers)
  end

  # Miscellaneous constants
  $defs.push("-DRUBY_VERSION_STRING=\"ruby #{RUBY_VERSION}\"")
  $defs.push("-DRMAGICK_VERSION_STRING=\"RMagick #{RMAGICK_VERS}\"")

  if Gem::Version.new($magick_version) >= Gem::Version.new('6.8.9')
    $defs.push('-DIMAGEMAGICK_GREATER_THAN_EQUAL_6_8_9=1')
  end
  if Gem::Version.new($magick_version) >= Gem::Version.new('6.9.0')
    $defs.push('-DIMAGEMAGICK_GREATER_THAN_EQUAL_6_9_0=1')
  end

  create_header
end
create_makefile_file() click to toggle source
# File ext/RMagick/extconf.rb, line 329
def create_makefile_file
  create_header_file
  # Prior to 1.8.5 mkmf duplicated the symbols on the command line and in the
  # extconf.h header. Suppress that behavior by removing the symbol array.
  $defs = []

  # Force re-compilation if the generated Makefile changed.
  $config_h = 'Makefile rmagick.h'

  create_makefile('RMagick2')
  print_summary
end
determine_imagemagick_package() click to toggle source
# File ext/RMagick/extconf.rb, line 163
def determine_imagemagick_package
  unless find_executable('pkg-config')
    exit_failure "Can't install RMagick #{RMAGICK_VERS}. Can't find pkg-config in #{ENV['PATH']}\n"
  end

  packages = `pkg-config --list-all`.scan(/(ImageMagick\-6[\.A-Z0-9]+) .*/).flatten

  # For ancient version of ImageMagick 6 we need a different regex
  if packages.empty?
    packages = `pkg-config --list-all`.scan(/(ImageMagick) .*/).flatten
  end

  if packages.empty?
    exit_failure "Can't install RMagick #{RMAGICK_VERS}. Can't find ImageMagick with pkg-config\n"
  end

  if packages.length > 1
    package_lines = packages.map { |package| " - #{package}" }.join("\n")
    msg = "\nWarning: Found more than one ImageMagick installation. This could cause problems at runtime.\n#{package_lines}\n\n"
    Logging.message msg
    message msg
  end

  packages.first
end
exit_failure(msg) click to toggle source
# File ext/RMagick/extconf.rb, line 146
def exit_failure(msg)
  msg = "ERROR: #{msg}"

  Logging.message msg

  @stdout.puts "\n\n"
  if ENV['NO_COLOR']
    @stdout.puts msg
  else
    @stdout.print "\e[31m\e[1m#{msg}\e[0m"
  end
  @stdout.puts "\n\n"
  @stdout.flush

  exit(1)
end
have_enum_value(enum, value, headers = nil, &b) click to toggle source

Test for a specific value in an enum type

# File ext/RMagick/extconf.rb, line 123
    def have_enum_value(enum, value, headers = nil, &b)
      checking_for "#{enum}.#{value}" do
        if try_compile(<<"SRC", &b)
#{COMMON_HEADERS}
        #{cpp_include(headers)}
/*top*/
int main() { #{enum} t = #{value}; t = t; return 0; }
SRC
          $defs.push(format('-DHAVE_ENUM_%s', value.upcase))
          true
        else
          false
        end
      end
    end
have_enum_values(enum, values, headers = nil, &b) click to toggle source

Test for multiple values of the same enum type

# File ext/RMagick/extconf.rb, line 140
def have_enum_values(enum, values, headers = nil, &b)
  values.each do |value|
    have_enum_value(enum, value, headers, &b)
  end
end
print_summary() click to toggle source
search_paths_for_library_for_windows() click to toggle source
# File ext/RMagick/extconf.rb, line 251
    def search_paths_for_library_for_windows
      msg = 'searching PATH for the ImageMagick library...'
      Logging.message msg
      message msg + "\n"

      found_lib = false
      dir_paths = {}

      paths = ENV['PATH'].split(File::PATH_SEPARATOR)
      paths.each do |dir|
        lib = File.join(dir, 'lib')
        lib_file = File.join(lib, 'CORE_RL_magick_.lib')
        next unless File.exist?(lib_file)

        dir_paths[:include] = File.join(dir, 'include')
        dir_paths[:lib] = lib

        found_lib = true
        break
      end

      return dir_paths if found_lib

      exit_failure <<END_MINGW
Can't install RMagick #{RMAGICK_VERS}.
Can't find the ImageMagick library.
Retry with '--with-opt-dir' option.
Usage: gem install rmagick -- '--with-opt-dir=\"[path to ImageMagick]\"'
e.g.
  gem install rmagick -- '--with-opt-dir=\"C:\Program Files\ImageMagick-6.9.1-Q16\"'
END_MINGW
    end
set_archflags_for_osx() click to toggle source

issue #169 set ARCHFLAGS appropriately for OSX

# File ext/RMagick/extconf.rb, line 236
def set_archflags_for_osx
  archflags = []
  fullpath = `which convert`
  fileinfo = `file #{fullpath}`

  # default ARCHFLAGS
  archs = $ARCH_FLAG.scan(/-arch\s+(\S+)/).flatten

  archs.each do |arch|
    archflags << "-arch #{arch}" if fileinfo.include?(arch)
  end

  $ARCH_FLAG = archflags.join(' ') unless archflags.empty?
end
setup_pkg_config_path() click to toggle source
# File ext/RMagick/extconf.rb, line 24
def setup_pkg_config_path
  if find_executable('brew')
    pkg_config_path = "#{`brew --prefix imagemagick@6`.strip}/lib/pkgconfig"
  elsif find_executable('pacman')
    pkg_config_path = '/usr/lib/imagemagick6/pkgconfig'
  else
    return
  end

  pkg_config_paths = ENV['PKG_CONFIG_PATH'].to_s.split(':')
  if File.exist?(pkg_config_path) && !pkg_config_paths.include?(pkg_config_path)
    ENV['PKG_CONFIG_PATH'] = [ENV['PKG_CONFIG_PATH'], pkg_config_path].compact.join(':')
  end
end