module Rmk

Constants

DEBUG_TRUE
DEFAULT_MOC
DEFAULT_RCC
PACKAGE_ATTRIBUTES

#check_package_attributes recognizes these :nodoc:

PRIV_FILE_NAME
PROJ_FILE_NAME
SLOTS

mapping of slot symbols to integers: slots define order of evaluation

Public Instance Methods

ar() click to toggle source

get instance of archive tool AR

# File tools/ar.rb, line 3
def ar
  @@tools[AR] ||= AR.new
end
available_packages() click to toggle source

available library packages

# File lib/dsl.rb, line 101
def available_packages
  @@available_packages
end
cc() click to toggle source

get instance of C compiler tool CC

# File tools/cc.rb, line 3
def cc
  @@tools[CC] ||= CC.new
end
ccache() click to toggle source

get instance of Ccache tool

# File tools/ccache.rb, line 3
def ccache
  @@tools[Ccache] ||= Ccache.new
end
check_configuration(cfg) click to toggle source

Test if cfg is a valid configuration, raise error or return cfg.

# File lib/rmk.rb, line 32
def check_configuration(cfg)
  unless @@configurations.include?(cfg)
    raise "undefined configuration '#{cfg}' "\
          "(not in #{@@configurations.inspect})"
  end
  cfg
end
check_package_attributes(name) click to toggle source

check if name is a known attribute (avoid mistakes from typos) :nodoc:

# File lib/dsl.rb, line 365
def check_package_attributes(name)
  p = available_packages[name.to_s]
  raise "undefined package '#{name}'" unless p
  p.each_key do |k|
    unless k.is_a?(Symbol)
      logger.warn "attribute key '#{k}' should be symbol in package '#{name}'"
    end

    next if PACKAGE_ATTRIBUTES.include?(k)
    next if Array(p[:extra_attributes]).include?(k)

    logger.warn "unknown attribute '#{k}' in package '#{name}'"
    logger.warn " at  #{p[:update_at].inspect}" if p[:update_at]
  end
end
compdb() click to toggle source

get instance of CompDB tool

# File tools/compdb.rb, line 3
def compdb
  @@tools[CompDB] ||= CompDB.new
end
configurations() click to toggle source

available #configurations

# File lib/rmk.rb, line 22
def configurations
  @@configurations
end
create_generator(options) click to toggle source
# File lib/generator.rb, line 21
def create_generator(options)
  Generator.new(options)
end
cxx() click to toggle source

get instance of C++ compiler tool CC

# File tools/cxx.rb, line 5
def cxx
  @@tools[CXX] ||= CXX.new
end
default_configuration() click to toggle source

default configuration (symbol)

# File lib/rmk.rb, line 27
def default_configuration
  :default
end
define_all_tool_params(tool) { |params, cfg| ... } click to toggle source

define tool parameters for all #configurations (in block + { |params,cfg| … }+)

# File lib/dsl.rb, line 54
def define_all_tool_params(tool)
  expect_symbol(tool)

  @@tools_params[tool] ||= {}

  configurations.each do |cfg|
    @@tools_params[tool][cfg] ||= {}

    params = @@tools_params[tool][cfg]

    yield params, cfg
  end
end
define_package(name) { |p| ... } click to toggle source

Define a new package (which may or may not exist).

Recognized options

:description

String

:url

String (details description)

:comment

String (details description)

:requires

package name or array of package names

:requires_tools

Symbol for class or array of symbols

:lib

library name w/o prefix or extension or array of libs

:path

library search path or aray of paths

:include

include path as for cc.include or array of paths

:define

definition(s) as for cc.define and cxx.define

:cflags

flag(s) as for cc.flags

:cxxflags

flag(s) as for cc.flags

:hooks

evaluated on #use_package

:extra_attributes

define new user attributes

:main_patterns

additional Regexp patterns defining executable

("with main()")

See also #use_package.

# File lib/dsl.rb, line 344
def define_package(name)
  logger.debug "define_package '#{name}'"
  p = (available_packages[name.to_s] ||= {})
  (p[:update_at] ||= []) << caller(1..1).first
  yield p
  check_package_attributes(name)
end
define_tool_params(tool, cfg) { |params| ... } click to toggle source

define tool parameters (in block + { |params| … }+)

# File lib/dsl.rb, line 40
def define_tool_params(tool, cfg)
  expect_symbol(tool)
  check_configuration(cfg)

  @@tools_params[tool] ||= {}
  @@tools_params[tool][cfg] ||= {}

  params = @@tools_params[tool][cfg]

  yield params
end
define_use_project_hook(hook) click to toggle source

define hook that is executed as +hook(project,options)+ on use_project.

# File lib/dsl.rb, line 232
def define_use_project_hook(hook)
  @@use_project_hooks << hook
end
doxygen() click to toggle source

get instance of Doxygen tool

# File tools/doxygen.rb, line 20
def doxygen
  @@tools[Doxygen] ||= Doxygen.new
end
dump(filename, what) click to toggle source

Dump data to YAML file. Place, e.g., in `RMakefile` for debugging, e.g., as +dump('/tmp/packages.yaml',available_packages)

# File lib/dsl.rb, line 473
def dump(filename, what)
  logger.warn "dump data to '#{filename}'"
  File.open(filename, 'w+b') do |f|
    f.write(YAML.dump(what))
  end
end
empty_library() click to toggle source

same as #emptylib

# File tools/emptylib.rb, line 11
def empty_library
  emptylib
end
emptylib() click to toggle source

get instance of Emptylib tool

# File tools/emptylib.rb, line 6
def emptylib
  @@tools[Emptylib] ||= Emptylib.new
end
exclude_subprojects_matching(pattern) click to toggle source

#subproject has no effect for mathing paths (use, e.g., in RMakefile.priv)

# File lib/dsl.rb, line 407
def exclude_subprojects_matching(pattern)
  p = if pattern.is_a?(Regexp)
        pattern
      else
        /^#{pattern}$/
      end
  generator.exclude_subproject_patterns << p
end
expect_symbol(s) click to toggle source
# File lib/dsl.rb, line 5
def expect_symbol(s)
  return if s.is_a?(Symbol)
  raise "expect symbol instead of '#{s}' of type '#{s.class}'"
end
explicitly_used_packages() click to toggle source

used library packages w/o those from dependencies

# File lib/dsl.rb, line 96
def explicitly_used_packages
  @@explicitly_used_packages
end
extra_ninja(&block) click to toggle source

get instance of ExtraNinja tool

# File tools/extraninja.rb, line 3
def extra_ninja(&block)
  (@@tools[AddExtraNinjaCode] ||= AddExtraNinjaCode.new).add(&block)
end
for_all_configurations_except(*configs) { |configuration| ... } click to toggle source

block +{ |cfg| … }+ is evaluated for all but configs

# File lib/dsl.rb, line 208
def for_all_configurations_except(*configs)
  configs.each { |cfg| check_configuration(cfg) }
  yield(generator.configuration) unless configs.include?(generator.configuration)
end
gcov() click to toggle source

get instance of GCov tool

# File tools/gcov.rb, line 3
def gcov
  @@tools[GCov] ||= GCov.new
end
generator() click to toggle source
# File lib/generator.rb, line 16
def generator
  raise 'require Generator.new' unless @@generator
  @@generator
end
has_package?(name) click to toggle source

Test if package name is available.

# File lib/dsl.rb, line 320
def has_package?(name)
  !available_packages[name.to_s].nil?
end
import_files(pattern, exclude_pattern = nil) click to toggle source

Read and evaluate Ruby files. Evaluates pattern to list files, filtered by exclude_pattern. Then calls require for .rb files or load otherwise. Returns list of imported files.

  • pattern path as for Dir.glob

  • exclude_pattern exclude matching files

# File lib/dsl.rb, line 453
def import_files(pattern, exclude_pattern = nil)
  logger.debug "import files '#{pattern}' (exclude='#{exclude_pattern}')"
  Dir.glob(pattern).find_all do |f|
    exclude_pattern.nil? || (f =~ exclude_pattern).nil
  end.map do |f|
    path = File.expand_path(f)
    if f =~ /\.rb$/
      logger.debug "- require '#{path}' "
      require(File.expand_path(path))
    else
      logger.debug "- load '#{path}' "
      load(File.expand_path(path))
    end
    f
  end
end
lazy_update_package(name, &block) click to toggle source

block +{ |package| … }+ will be passed to #update_package on #use_package. Must not update :requires list!

# File lib/dsl.rb, line 394
def lazy_update_package(name, &block)
  logger.debug ":lazy_update_package '#{name}'"
  p = available_packages[name.to_s]
  raise "undefined package '#{name}'" unless p
  (p[:lazy_updates] ||= []) << block
end
ld() click to toggle source

get instance of linker tool LD

# File tools/ld.rb, line 3
def ld
  @@tools[LD] ||= LD.new
end
logger() click to toggle source
# File lib/rmk.rb, line 15
def logger
  @@log
end
mex() click to toggle source

get instance of linker tool Mex

# File tools/mex.rb, line 3
def mex
  unless @@tools[Mex]
    use_package('mex')
    @@tools[Mex] ||= Mex.new
  end
  @@tools[Mex]
end
moc() click to toggle source

get instance of Moc tool

# File tools/moc.rb, line 5
def moc
  @@tools[Moc] ||= Moc.new
end
only_for_configuration(*configs) { |configuration| ... } click to toggle source

block +{ |cfg| … }+ is evaluated only for configs

# File lib/dsl.rb, line 202
def only_for_configuration(*configs)
  configs.each { |cfg| check_configuration(cfg) }
  yield(generator.configuration) if configs.include?(generator.configuration)
end
phony(target, other) click to toggle source

define #phony target from other

# File lib/dsl.rb, line 433
def phony(target, other)
  extra_ninja do |writer|
    writer.comment 'user defined phony target'
    writer.phony(target, other)
    writer.newline
  end
end
phony_sub(sub, target, newname = nil) click to toggle source

promote target of sub project (same name or newname)

# File lib/dsl.rb, line 442
def phony_sub(sub, target, newname = nil)
  # TODO: test if sub exists
  phony(project_target(newname || target), subproject_target(sub, target))
end
project_target(target) click to toggle source

get “wrapped” target name

# File lib/dsl.rb, line 422
def project_target(target)
  "${project}_#{target}" # #{generator.lib_base_name}
end
project_used?(proj) click to toggle source

Is proj used (so far)?

# File lib/dsl.rb, line 244
def project_used?(proj)
  !used_project_options(proj).nil?
end
rcc() click to toggle source

get instance of Rcc tool

# File tools/rcc.rb, line 5
def rcc
  @@tools[Rcc] ||= Rcc.new
end
recreate_generator(options) click to toggle source
# File lib/generator.rb, line 25
def recreate_generator(options)
  @@generator = nil
  create_generator(options)
end
rtags() click to toggle source

get instance of RTags tool

# File tools/rtags.rb, line 3
def rtags
  @@tools[RTags] ||= RTags.new
end
subproject(*paths) click to toggle source

request recursive generation

# File lib/dsl.rb, line 402
def subproject(*paths)
  generator.define_subproject(*paths)
end
subproject_target(sub, target) click to toggle source

get “wrapped” sub-project target

# File lib/dsl.rb, line 427
def subproject_target(sub, target)
  p = "#{generator.proj_base}/#{sub}"
  "#{generator.proj_library_base_name(p)}_#{target}"
end
subproject_without_library(*paths) click to toggle source

request recursive generation

# File lib/dsl.rb, line 417
def subproject_without_library(*paths)
  generator.define_subproject_without_library(*paths)
end
symbol(tool) click to toggle source

Get #symbol for a tool, e.g., +symbol(cxx)+ yields :CXX. Don't call in configuration code, because, e.g., cxx will create a new CXX instance and implicitly use_tool!

# File lib/dsl.rb, line 13
def symbol(tool)
  if tool.is_a?(Symbol)
    tool
  elsif tool.is_a?(Class)
    tool.to_s.sub('Rmk::', '').to_sym
  else
    symbol(tool.class)
  end
end
tool_params(tool, cfg) click to toggle source

Get preset parameters for tool in configuration cfg. Note that tool must be a Symbol (of the class name), because parametrization should not create instances of tools!

# File lib/dsl.rb, line 26
def tool_params(tool, cfg)
  expect_symbol(tool)
  check_configuration(cfg)

  data = @@tools_params[tool]
  raise "no entry for tool '#{tool}'" unless data

  data = data[cfg]
  raise "no entry for '#{cfg}' tool '#{tool}'" unless data

  data
end
touch() click to toggle source

get instance of Touch tool

# File tools/touch.rb, line 3
def touch
  @@tools[Touch] ||= Touch.new
end
update_all_tool_params(tool, _cfg) { |tool_params(tool, cfg), cfg| ... } click to toggle source

update existing set of parameters for all #configurations (in block + { |params,cfg| … }+)

# File lib/dsl.rb, line 75
def update_all_tool_params(tool, _cfg)
  configurations.each do |cfg|
    yield tool_params(tool, cfg), cfg
  end
end
update_package(name) { |p| ... } click to toggle source

update an existing package (in block +{ |package| … }+)

# File lib/dsl.rb, line 382
def update_package(name)
  logger.debug "update_package '#{name}'"
  p = available_packages[name.to_s]
  raise "undefined package '#{name}'" unless p
  (p[:update_at] ||= []) << caller(1..1).first
  yield p
  check_package_attributes(name)
end
update_tool_params(tool, cfg) { |tool_params(tool, cfg)| ... } click to toggle source

update existing set of parameters (in block + { |params,cfg| … }+)

# File lib/dsl.rb, line 69
def update_tool_params(tool, cfg)
  yield tool_params(tool, cfg)
end
use_package(*libs) click to toggle source

specify that libs should be used

# File lib/dsl.rb, line 106
def use_package(*libs)
  libs.map(&:to_s).each do |name|
    lib = @@available_packages[name]
    raise "unknown package '#{name}'" unless lib

    next if @@used_packages[name]

    if @@using_required_package_count.zero?
      @@log.debug "use package '#{name}'"
    else
      @@log.debug "use package '#{name}' (required by other)"
    end

    # NOTE: Currently all options are applied to cxx, cc, ld.
    #       Should be able to differentiate processors!

    if lib[:hooks]
      [lib[:hooks]].flatten.each do |hook|
        unless hook.respond_to? :call
          raise "hook must be callable (package '#{name}')"
        end
        hook.call(lib)
      end
    end

    if lib[:main_patterns]
      patterns = Array(lib[:main_patterns])
      @@log.debug "Add patterns #{patterns.inspect} for specifying executable."
      Rmk.cxx.add_main_pattern(patterns)
      Rmk.cc.add_main_pattern(patterns)
    end

    if lib[:requires]
      @@using_required_package_count += 1
      use_package(*lib[:requires])
      @@using_required_package_count -= 1
    end

    if lib[:lazy_updates]
      lib[:lazy_updates].each do |block|
        update_package(name, &block)
      end
      lib[:lazy_updates] = nil # remove after use
    end

    Rmk.ld.add_path(*lib[:path]) if lib[:path]
    Rmk.ld.add_library(*lib[:lib]) if lib[:lib]

    if lib[:include]
      Rmk.cxx.include_path(*lib[:include])
      Rmk.cc.include_path(*lib[:include])
    end

    if lib[:define]
      Rmk.cxx.define(lib[:define])
      Rmk.cc.define(lib[:define])
    end

    Rmk.cxx.flags.add(lib[:cxxflags]) if lib[:cxxflags]
    Rmk.cc.flags.add(lib[:cflags]) if lib[:cflags]

    if lib[:requires_tools]
      Array(lib[:requires_tools]).each do |tool|
        begin
          klass = Kernel.const_get(tool.to_s)
        rescue StandardError
          unless klass.is_a?(Class)
            raise "expected class name for '#{klass.inspect}'"
          end
        end

        @@log.debug "#{name} requires tool #{klass}"
        @@tools[klass] ||= klass.new
      end
    end

    @@used_packages[name] = lib
    @@explicitly_used_packages[name] = lib if @@using_required_package_count.zero?
  end.compact
end
use_package_if_available(*libs) { |name| ... } click to toggle source

Use only packages from libs that are available.

For all in libs that satisfy has_package? call #use_package and yield package name (in block +{ |name| …}+).

# File lib/dsl.rb, line 191
def use_package_if_available(*libs)
  libs.each do |p|
    name = p.to_s
    if has_package?(name)
      use_package(name)
      yield(name)
    end
  end
end
use_project(*proj) click to toggle source

Specify that proj should be used.

  • proj can be an array

  • Each item can be a string or a Hash.

  • Hashes p have the project name with key :project the remainder is used as options to Rmk::Processor#add_project.

# File lib/dsl.rb, line 253
def use_project(*proj)
  # TODO: document syntax "use_project name, opt1: val1, opt2: val2"

  if proj.size == 2 && proj.last.is_a?(Hash)
    proj.last[:project] = proj.first
    proj = [proj.last]
  end

  # TODO: check for valid options (similar as for package)
  #       :proj_root -- should be done by use_project

  # TODO: simplify method

  proj.each do |p|
    project, options =
      if p.is_a?(Hash)
        raise "missing project name in Hash '#{p.inspect}'" unless p[:project]
        [p[:project], p]
      else
        [p, {}]
      end

    if project_used?(project)
      logger.warn "use_project '#{project}' specified twice (redundant)."
      if options != used_project_options(project)
        logger.warn "use_project '#{project}' with different options " \
                    '(using initial definition):'
        logger.warn "  using #{used_project_options(project).inspect}, " \
                    "ignoring #{options.inspect}."
      end
      next
    end

    if options[:proj_root]
      root = Pathname.new(options[:proj_root]).expand_path
      if root == Rmk.generator.proj_root
        options.delete(:proj_root)
        logger.warn "use_project '#{project}' with 'proj_root' equal to " \
                    'current root (not required).'
      else
        # TODO: relative paths are w.r.t. cwd!?!
        unless File.directory?(root)
          raise "use_project '#{project}' with nonexistent proj_root '#{root}'."
        end
      end
      options[:proj_root] = root
    end

    options[:config] = generator.configuration if options[:config].nil?

    @@used_projects[project] = options
    @@use_project_hooks.each { |hook| hook.call(project, options) }

    tools = Rmk.generator.tool_chain
    [cc, cxx, ld].each { |tool| tools << tool unless tools.include?(tool) }
    tools.find_all { |tool| tool.respond_to?(:add_project) }
         .each { |tool| tool.add_project(project, options) }

    # TODO: what if tool is "not yet used"
    # TODO: store projects in list

    # TODO: inefficient (filter tool chain)
    # TODO: method+cache above
  end
end
use_tool(*tools) click to toggle source

specify that tools should be used

# File lib/dsl.rb, line 214
def use_tool(*tools)
  tools.each do |tool|
    if tool.is_a?(Class)
      @tools[tool] ||= tool.new
    elsif (tool.is_a?(String) || tool.is_a?(Symbol)) &&
          respond_to?(tool.to_sym)
      send(tool.to_sym)
    elsif tool.is_a?(NinjaGenerator)
      # do nothing
    else
      raise "unknown tool '#{tool}"
    end
  end
end
use_tool?(tool) click to toggle source

Is tool used? The tool argument is the class name as a #symbol or a string.

# File lib/rmk.rb, line 44
def use_tool?(tool)
  klass = Kernel.const_get(tool)
  return false unless klass
  raise 'invalid use of use_tool?' unless klass.is_a?(Class)
  @@tools.key?(klass)
rescue StandardError
  false
end
used_packages() click to toggle source

used library packages (list “instances” for “meta-packages”)

# File lib/dsl.rb, line 91
def used_packages
  @@used_packages
end
used_project_options(proj) click to toggle source

Get options Hash for proj if used, nil otherwise.

# File lib/dsl.rb, line 239
def used_project_options(proj)
  @@used_projects[proj]
end