class Autobuild::CMake

Handler class to build CMake-based packages

Constants

CMAKE_EQVS
DOXYGEN_ACCEPTED_VARIABLES

Attributes

always_use_doc_target[W]

Flag controlling whether autobuild should run doxygen itself or use the “doc” target generated by CMake

This is experimental and OFF by default. See #run_doxygen for more details

See also #always_use_doc_target and #always_use_doc_target? for a per-package control of that feature

full_reconfigures[W]
generator[RW]

Global default for the CMake generator to use. If nil (the default), the -G option will not be given at all. Will work only if the generator creates makefiles

It can be overriden on a per-package basis with CMake.generator=

module_path[R]
always_reconfigure[RW]

If true, always run cmake before make during the build

always_use_doc_target[R]

Flag controlling whether autobuild should run doxygen itself or use the “doc” target generated by CMake

This is experimental and OFF by default. See #run_doxygen for more details

See also CMake.always_use_doc_target= and ::always_use_doc_target? for a global control of that feature

defines[R]

a key => value association of defines for CMake

full_reconfigures[W]

If true, we always remove the CMake cache before reconfiguring.

See full_reconfigures? for more details

generator[W]

Sets a generator explicitely for this component. See generator and #generator

Public Class Methods

always_use_doc_target?() click to toggle source

Flag controlling whether autobuild should run doxygen itself or use the “doc” target generated by CMake

This is experimental and OFF by default. See #run_doxygen for more details

See also #always_use_doc_target and #always_use_doc_target? for a per-package control of that feature

# File lib/autobuild/packages/cmake.rb, line 115
def always_use_doc_target?
    @always_use_doc_target
end
builddir() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 12
def builddir; @builddir || Configurable.builddir end
builddir=(new) click to toggle source
# File lib/autobuild/packages/cmake.rb, line 13
def builddir=(new)
    raise ConfigException, "absolute builddirs are not supported" if (Pathname.new(new).absolute?)
    raise ConfigException, "builddir must be non-nil and non-empty" if (new.nil? || new.empty?)
    @builddir = new
end
full_reconfigures?() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 20
def full_reconfigures?
    @full_reconfigures
end
new(options) click to toggle source
Calls superclass method
# File lib/autobuild/packages/cmake.rb, line 73
def initialize(options)
    @defines = Hash.new
    super
end
show_make_messages=(value) click to toggle source
# File lib/autobuild/packages/cmake.rb, line 344
def self.show_make_messages=(value)
    @show_make_messages = value
end
show_make_messages?() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 340
def self.show_make_messages?
    @show_make_messages
end

Public Instance Methods

always_use_doc_target?() click to toggle source

Flag controlling whether autobuild should run doxygen itself or use the “doc” target generated by CMake

This is experimental and OFF by default. See #run_doxygen for more details

See also CMake.always_use_doc_target= and ::always_use_doc_target? for a global control of that feature

# File lib/autobuild/packages/cmake.rb, line 139
def always_use_doc_target?
    if @always_use_doc_target.nil?
        return CMake.always_use_doc_target?
    else
        @always_use_doc_target
    end
end
build() click to toggle source

Do the build in builddir

# File lib/autobuild/packages/cmake.rb, line 349
    def build
        in_dir(builddir) do
            progress_start "building %s", :done_message => "built %s" do
                if always_reconfigure || !File.file?('Makefile')
                    Subprocess.run(self, 'build', Autobuild.tool(:cmake), '.')
                end

                Autobuild.make_subcommand(self, 'build') do |line|
                    if line =~ /\[\s+(\d+)%\]/
                        progress "building %s (#{Integer($1)}%)"
                    end
                end

                if show_make_messages?
                    warning = String.new
                    Autobuild.make_subcommand(self, 'build') do |line|
                        iswarning = false
                        if line =~ /\[\s*(\d+)%\]/
                            progress "building %s (#{Integer($1)}%)"
                        elsif (line =~
/^(Linking)|^(Scanning)|^(Building)|^(Built)/) == nil
                            warning += line
                            iswarning = true
                        end
                        if(!iswarning && !warning.empty?)
                            warning.split("\n").each do |l|
                                message "%s: #{l}", :magenta
                            end
                            warning = ""
                        end
                    end
                end
            end
        end
        Autobuild.touch_stamp(buildstamp)
    end
cmake_cache() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 70
def cmake_cache; File.join(builddir, "CMakeCache.txt") end
configure() click to toggle source

Configure the builddir directory before starting make

Calls superclass method Autobuild::Configurable#configure
# File lib/autobuild/packages/cmake.rb, line 297
def configure
    super do
        in_dir(builddir) do
            if !File.file?(File.join(srcdir, 'CMakeLists.txt'))
                raise ConfigException.new(self, 'configure'), "#{srcdir} contains no CMakeLists.txt file"
            end

            command = [ "cmake", "-DCMAKE_INSTALL_PREFIX=#{prefix}", "-DCMAKE_MODULE_PATH=#{CMake.module_path.join(";")}" ]

                                if(RbConfig::CONFIG["host_os"] =~%r(msdos|mswin|djgpp|mingw|[Ww]indows)!)
                                        command << '-G' 
                                        command << "MSYS Makefiles"
                                end
                                
            defines.each do |name, value|
                command << "-D#{name}=#{value}"
            end
            if generator
                command << "-G#{generator}"
            end
            command << srcdir
            
            progress_start "configuring CMake for %s", :done_message => "configured CMake for %s" do
                if full_reconfigures?
                    FileUtils.rm_f cmake_cache
                end
                Subprocess.run(self, 'configure', *command)
            end
        end
    end
end
configurestamp() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 71
def configurestamp; cmake_cache end
define(name, value) click to toggle source
# File lib/autobuild/packages/cmake.rb, line 78
def define(name, value)
    @defines[name] = value
end
doc_dir() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 82
def doc_dir
    if @doc_dir
        File.expand_path(@doc_dir, builddir)
    end
end
equivalent_option_value?(old, new) click to toggle source
# File lib/autobuild/packages/cmake.rb, line 224
def equivalent_option_value?(old, new)
    if old == new
        true
    else
        old = CMAKE_EQVS[old]
        new = CMAKE_EQVS[new]
        if old && new
            old == new
        else
            false
        end
    end
end
full_reconfigures?() click to toggle source

If true, we always remove the CMake cache before reconfiguring. This is to workaround the aggressive caching behaviour of CMake, and is set to true by default.

See ::full_reconfigures? and CMake.full_reconfigures= for a global setting

# File lib/autobuild/packages/cmake.rb, line 62
def full_reconfigures?
    if @full_reconfigures.nil?
        CMake.full_reconfigures?
    else
        @full_reconfigures
    end
end
generator() click to toggle source

The CMake generator to use. You must choose one that generates Makefiles. If not set for this package explicitely, it is using the global value #generator.

# File lib/autobuild/packages/cmake.rb, line 50
def generator
    if @generator then @generator
    else CMake.generator
    end
end
import() click to toggle source
Calls superclass method
# File lib/autobuild/packages/cmake.rb, line 238
def import
    super

    Dir.glob(File.join(srcdir, "*.pc.in")) do |file|
        file = File.basename(file, ".pc.in")
        provides "pkgconfig/#{file}"
    end
end
install() click to toggle source

Install the result in prefix

Calls superclass method
# File lib/autobuild/packages/cmake.rb, line 387
def install
    in_dir(builddir) do
        progress_start "installing %s", :done_message => 'installed %s' do
            Subprocess.run(self, 'install', Autobuild.tool(:make), "-j#{parallel_build_level}", 'install')
        end
    end
    super
end
internal_doxygen_mode?() click to toggle source

To avoid having to build packages to run the documentation target, we try to autodetect whether (1) the package is using doxygen and (2) whether the cmake variables in the doxyfile can be provided by autobuild itself.

This can be disabled globally by setting Autobuild::CMake.always_use_doc_target= or on a per-package basis with always_use_doc_target=

This method returns true if the package can use the internal doxygen mode and false otherwise

# File lib/autobuild/packages/cmake.rb, line 158
def internal_doxygen_mode?
    if always_use_doc_target?
        return false
    end

    doxyfile_in = File.join(srcdir, "Doxyfile.in")
    if !File.file?(doxyfile_in)
        return false
    end
    File.readlines(doxyfile_in).each do |line|
        matches = line.scan(/@[^@]+@/)
        if matches.any? { |str| !DOXYGEN_ACCEPTED_VARIABLES.has_key?(str) }
            return false
        end
    end
end
prepare() click to toggle source
Calls superclass method Autobuild::Configurable#prepare
# File lib/autobuild/packages/cmake.rb, line 247
def prepare
    if !internal_doxygen_mode? && has_doc?
        task "#{name}-doc" => configurestamp
    end

    # A failed initial CMake configuration leaves a CMakeCache.txt file,
    # but no Makefile.
    #
    # Delete the CMakeCache to force reconfiguration
    if !File.exists?( File.join(builddir, 'Makefile') )
        FileUtils.rm_f cmake_cache
    end

    if File.exists?(cmake_cache)
        all_defines = defines.dup
        all_defines['CMAKE_INSTALL_PREFIX'] = prefix
        all_defines['CMAKE_MODULE_PATH'] = "#{CMake.module_path.join(";")}"
        cache = File.read(cmake_cache)
        did_change = all_defines.any? do |name, value|
            cache_line = cache.each_line.find do |line|
                line =~ /^#{name}:/
            end

            value = value.to_s
            old_value = cache_line.split("=")[1].chomp if cache_line
            if !old_value || !equivalent_option_value?(old_value, value)
                if Autobuild.debug
                    message "%s: option '#{name}' changed value: '#{old_value}' => '#{value}'"
                end
                if old_value
                    message "%s: changed value of #{name} from #{old_value} to #{value}"
                else
                    message "%s: setting value of #{name} to #{value}"
                end
                
                true
            end
        end
        if did_change
            if Autobuild.debug
                message "%s: CMake configuration changed, forcing a reconfigure"
            end
            FileUtils.rm_f cmake_cache
        end
    end

    super
end
run_doxygen() click to toggle source

To avoid having to build packages to run the documentation target, we try to autodetect whether (1) the package is using doxygen and (2) whether the cmake variables in the doxyfile can be provided by autobuild itself.

This can be disabled globally by setting ::always_use_doc_target or on a per-package basis with always_use_doc_target

This method generates the corresponding doxygen file in <builddir>/Doxygen and runs doxygen. It raises if the internal doxygen support cannot be used on this package

# File lib/autobuild/packages/cmake.rb, line 187
def run_doxygen
    doxyfile_in = File.join(srcdir, "Doxyfile.in")
    if !File.file?(doxyfile_in)
        raise RuntimeError, "no Doxyfile.in in this package, cannot use the internal doxygen support"
    end
    doxyfile_data = File.readlines(doxyfile_in).map do |line|
        line.gsub(/@[^@]+@/) { |match| DOXYGEN_ACCEPTED_VARIABLES[match].call(self) }
    end
    doxyfile = File.join(builddir, "Doxyfile")
    File.open(doxyfile, 'w') do |io|
        io.write(doxyfile_data)
    end
    Subprocess.run(self, 'doc', Autobuild.tool(:doxygen), doxyfile)
end
show_make_messages=(value) click to toggle source
# File lib/autobuild/packages/cmake.rb, line 336
def show_make_messages=(value)
    @show_make_messages = value
end
show_make_messages?() click to toggle source
# File lib/autobuild/packages/cmake.rb, line 329
def show_make_messages?
    if !@show_make_messages.nil?
        @show_make_messages
    else CMake.show_make_messages?
    end
end
with_doc(target = 'doc') { || ... } click to toggle source

Declare that the given target can be used to generate documentation

# File lib/autobuild/packages/cmake.rb, line 203
def with_doc(target = 'doc')
    doc_task do
        in_dir(builddir) do
            progress_start "generating documentation for %s", :done_message => 'generated documentation for %s' do
                if internal_doxygen_mode?
                    run_doxygen
                else
                    Subprocess.run(self, 'doc', Autobuild.tool(:make), "-j#{parallel_build_level}", target)
                end
                yield if block_given?
            end
        end
    end
end