123456789_123456789_123456789_123456789_123456789_

Class: Gem::Ext::CmakeBuilder

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Builder
Instance Chain:
Inherits: Gem::Ext::Builder
Defined in: lib/rubygems/ext/cmake_builder.rb

Overview

This builder creates extensions defined using CMake. Its is invoked if a Gem’s spec file sets the extension property to a string that contains CMakeLists.txt.

In general, CMake projects are built in two steps:

* configure
* build

The builder follow this convention. First it runs a configuration step and then it runs a build step.

CMake projects can be quite configurable - it is likely you will want to specify options when installing a gem. To pass options to CMake specify them after in the gem install command. For example:

gem install <gem_name> -- --preset <preset_name>

Note that options are ONLY sent to the configure step - it is not currently possible to specify options for the build step. If this becomes and issue then the CMake builder can be updated to support build options.

Useful options to know are:

-G to specify a generator (-G Ninja is recommended)
-D<CMAKE_VARIABLE> to set a CMake variable (for example -DCMAKE_BUILD_TYPE=Release)
--preset <preset_name> to use a preset

If the ::Gem author provides presets, via CMakePresets.json file, you will likely want to use one of them. If not, you may wish to specify a generator. Ninja is recommended because it can build projects in parallel and thus much faster than building them serially like Make does.

Class Method Summary

Builder - Inherited

.class_name, .make,
.new

Creates a new extension builder for spec.

.ruby, .run, .shelljoin, .shellsplit

Instance Attribute Summary

Instance Method Summary

Builder - Inherited

#build_extensions

Builds extensions.

#build_error

Logs the build output, then raises BuildError.

#build_extension,
#builder_for

Chooses the extension builder class for extension

#write_gem_make_out

Writes output to gem_make.out in the extension install directory.

::Gem::UserInteraction - Included

#alert

Displays an alert statement.

#alert_error

Displays an error statement to the error output location.

#alert_warning

Displays a warning statement to the warning output location.

#ask

Asks a question and returns the answer.

#ask_for_password

Asks for a password with a prompt

#ask_yes_no

Asks a yes or no question.

#choose_from_list

Asks the user to answer question with an answer from the given list.

#say

Displays the given statement on the standard output (or equivalent).

#terminate_interaction

Terminates the RubyGems process with the given exit_code

#verbose

Calls say with msg or the results of the block if really_verbose is true.

::Gem::DefaultUserInteraction - Included

::Gem::Text - Included

#clean_text

Remove any non-printable characters and make the text suitable for printing.

#format_text

Wraps text to wrap characters and optionally indents by indent characters.

#levenshtein_distance

Returns a value representing the “cost” of transforming str1 into str2 Vendored version of DidYouMean::Levenshtein.distance from the ruby/did_you_mean gem @ 1.4.0 github.com/ruby/did_you_mean/blob/2ddf39b874808685965dbc47d344cf6c7651807c/lib/did_you_mean/levenshtein.rb#L7-L37.

#truncate_text, #min3

Constructor Details

.newCmakeBuilder

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 34

def initialize
  @runner = self.class.method(:run)
  @profile = :release
end

Instance Attribute Details

#profile (rw)

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 33

attr_accessor :runner, :profile

#runner (rw)

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 33

attr_accessor :runner, :profile

Instance Method Details

#build(extension, dest_path, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd, target_rbconfig = Gem.target_rbconfig)

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 39

def build(extension, dest_path, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd,
  target_rbconfig = Gem.target_rbconfig)
  if target_rbconfig.path
    warn "--target-rbconfig is not yet supported for CMake extensions. Ignoring"
  end

  # Figure the build dir
  build_dir = File.join(cmake_dir, "build")

  # Check if the gem defined presets
  check_presets(cmake_dir, args, results)

  # Configure
  configure(cmake_dir, build_dir, dest_path, args, results)

  # Compile
  compile(cmake_dir, build_dir, args, results)

  results
end

#check_presets(cmake_dir, args, results) (private)

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 85

def check_presets(cmake_dir, args, results)
  # Return if the user specified a preset
  return unless args.grep(/--preset/i).empty?

  cmd = ["cmake",
         "--list-presets"]

  presets = Array.new
  begin
    runner.call(cmd, presets, "cmake_presets", cmake_dir)

    # Remove the first two lines of the array which is the current_directory and the command
    # that was run
    presets = presets[2..].join
    results << <<~EOS
      The gem author provided a list of presets that can be used to build the gem. To use a preset specify it on the command line:

        gem install <gem_name> -- --preset <preset_name>

      #{presets}
    EOS
  rescue Gem::InstallError
    # Do nothing, CMakePresets.json was not included in the Gem
  end
end

#compile(cmake_dir, build_dir, args, results)

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 73

def compile(cmake_dir, build_dir, args, results)
  cmd = ["cmake",
         "--build",
         build_dir.to_s,
         "--config",
         @profile.to_s]

  runner.call(cmd, results, "cmake_compile", cmake_dir)
end

#configure(cmake_dir, build_dir, install_dir, args, results)

[ GitHub ]

  
# File 'lib/rubygems/ext/cmake_builder.rb', line 60

def configure(cmake_dir, build_dir, install_dir, args, results)
  cmd = ["cmake",
         cmake_dir,
         "-B",
         build_dir,
         "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=#{install_dir}", # Windows
         "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=#{install_dir}", # Not Windows
         *Gem::Command.build_args,
         *args]

  runner.call(cmd, results, "cmake_configure", cmake_dir)
end