module MxxRu::Cpp

Constants

CPP_STD03

C++03 standard.

Since v.1.6.3

CPP_STD11

C++11 standard.

Since v.1.6.3

CPP_STD14

C++14 standard.

Since v.1.6.3

CPP_STD17

C++17 standard.

Since v.1.6.14.3

CPP_STD_DEFAULT

Default C++ standard variant. The compiler defaults must be used.

Since v.1.6.3

Composite_target

Composition of subprojects target

Composite_target_type

Target type is a composition of subprojects

Cpp_source_file

Class, describing one C/C++ source file.

Custom_subdir_obj_placement

Analog of RuntimeSubdirObjPlacement, but allow to specify paths for final results (EXE, LIB, DLL) and intermediate files (OBJ, RES). Unlike RuntimeSubdirObjPlacement these paths are independent of runtime_mode.

Example:

MxxRu::Cpp::composite_target {
  global_obj_placement MxxRu::Cpp::CustomSubdirObjPlacement.new(
    # Final resuls going here.
    'bin32',
    # All intermediate files going here.
    'tmp/output32' )

  required_prj ...
}

If this composite project will be applied for project structure:

prj_1/
`- src/
prj_2/
`- module_1/
`- module_2/

Then after build project structructure will be:

prj_1/
`- src/
prj_2/
`- module_1/
`- module_2/
bin32/
tmp/
`- output32/
   `- prj_1/
   |  `- src/
   `- prj_2/
      `- module_1/
      `- module_2/
Dll_info

Class, describing a shared library.

Dll_requirements

Class, incapsulating DLL dependencies.

When someone is linking to the DLL on mswin platform, then it depends only from import library of that DLL. But when someone is linking to the DLL on unix platform, then it depends from all libraries DLL depends to. Exact details knows concrete toolset implementation only. Therefore, after DLL building base toolset class addresses to it's derivative with requirement to build all dependencies lists. These lists are returned as an object of DllRequirements type.

Dll_target

Dll is a target type.

Dll_target_type

Target type is shared library (dll).

ENV_VAR
Exe_info

Class, describing EXE-file.

Exe_target

Exe is a target type.

Exe_target_type

Target type is application.

Global_single_value_option

Auxiliary class, intended to store objects like runtime_mode, rtl_mode, etc, with information about who has set this or that mode.

Lib_info

Class, describing a library.

Lib_or_dll_target

Base class for targets that may be lib or dll, or MacOS bundle.

In that cases for a project should be defined special target class. The class constructor should define two blocks:

  • one of them is called if developer wants to build target as a static library. Block is run during as_lib method call;

  • second is called if developer wants to build target as a shared library. Block is run during as_dll method call;

Starting from version 1.4.10 this approach could also be used for bulding MacOS bundles.

For example:

class Prj < MxxRu::Cpp::LibOrDllTarget
  TAG = "threads_1/prj.rb"
  def initialize( a_alias = TAG )
    super( a_alias, TAG )

    target( "threads.1.3" )

    threading_mode( MxxRu::Cpp::THREADING_MULTI )

    init_dll_block(
      Proc.new {
        rtl_mode( MxxRu::Cpp::RTL_SHARED )
        implib_path( "lib" )
        define( "THREADS_1__DLL", OPT_UPSPREAD )
      })
    # This is avaliable from v.1.4.10
    init_macos_bundle_block(
      Proc.new {
        rtl_mode( MxxRu::Cpp::RTL_SHARED )
      }
    )

    cpp_source( "threads.cpp" )
    cpp_source( "micro_time.cpp" )

    if toolset.tag( "target_os" ) == "mswin"
      define( "__WIN32__" )
      cpp_source( "win32/os_thread.cpp" )
    elsif toolset.tag( "target_os" ) == "unix"
      cpp_source( "posix/os_thread.cpp" )
    end

    define( "THREADS_1__PRJ" )
  end
end

After definition of such class for the target, project may allow to use itself by the other projects using two methods.

Manual execution of as_lib, as_dll, as_macos_bundle methods

If project defines one class only, inherited from LibOrDllTarget, then all clients of that project should explicitly call as_lib or as_dll, or as_macos_bundle method during a reference to required_prj:

class MyPrj < MxxRu::Cpp::ExeTarget
  def initialize( a_alias = "my_prj.rb" )
    super( a_alias )
    required_prj( "threads_1/prj.rb" ).as_dll( self )
  end
end

Such approach is not good because if in composite project several projects at the same time uses threads_1/prj.rb, then in one of them it's easy to forget to call as_dll. And it wouldn't be incorrect, because as_dll may be called by other projects in composite project.

Definition of auxiliary target classes

To make usage of target that may be lib or dll easier, project may define two auxiliary classes, which would call methods as_lib, as_dll and as_macos_bundle inside their constructors:

class Prj < MxxRu::Cpp::LibOrDllTarget
  def initialize( a_alias = "threads_1/prj.rb" )
    super( a_alias, "threads_1" )
    ...
  end
end
class Lib < Prj
  def super( a_alias = "threads_1/lib.rb" )
    super( a_alias )
    as_lib
  end
end
class Dll < Prj
  def super( a_alias = "threads_1/dll.rb" )
    super( a_alias )
    as_dll
  end
end
class MacOSBundle < Prj
  def super( a_alias = "threads_1/macos_bundle.rb" )
    super( a_alias )
    as_macos_bundle
  end
end

Then for using the target it would be enough to do that:

class MyPrj < MxxRu::Cpp::ExeTarget
  def initialize( a_alias = "my_prj.rb" )
    super( a_alias )
    required_prj( "threads_1/dll.rb" )
  end
end
Lib_target

Lib is a target type.

Lib_target_type

Target type is static library (lib).

Linker_lists

Class, incapsulating all lists required for linker.

MXXCPPARG_DEBUG
MXXCPPARG_EXTRACT_OPTIONS
MXXCPPARG_NO_DEPENDS_ANALYZER
MXXCPPARG_ONLY_ONE
MXXCPPARG_RELEASE

Arguments passed into Ruby interpreter, intended to control MxxRu::Cpp.

Macos_bundle_target

MacOS bundle is a target type.

Macos_bundle_target_type

Target type is MacOS bundle (.bundle is a kind of dll on MacOS).

Since v.1.4.10

Mswin_rc_file

Class, describing one mswin resource file.

Mswin_res_info

Class, describing mswin-res-info.

OPTIM_SIZE

Optimization by size.

OPTIM_SPEED

Optimization by speed.

Obj_info

Class, describing object file.

Obj_placement

Base class for a folder name generator. Results of compilation and linking would be located in that folder.

Qt_gen

Files generator for Qt class.

Main features:

  • building of moc-files using moc tool. Generation from source and header files is supported.

  • building source files from ui-files using uic-compiler. For all files generated this way moc tool executed automatically.

Generated source files automatically added into cpp_source list of target.

Local list defines is supported.

If only pointer to the target passed into contructor, default list of defines is used. If it's required to change default list, new list should be passed through a second argument:

generator( MxxRu::Cpp::QtGen.new( self, [ "QT_THREAD_SUPPORT" ] ) )
RTL_DEFAULT

Default compiler libraries are used.

RTL_SHARED

Use shared runtime library.

RTL_STATIC

Use static runtime library.

RTTI_DEFAULT

Default RTTI mode. No RTTI options are passed to compiler.

RTTI_DISABLED

RTTI mode should be disabled.

RTTI_ENABLED

RTTI mode should be enabled.

RUNTIME_DEBUG

Debug mode. Debug information is generated.

RUNTIME_DEFAULT

Default mode. Nor debug information nor optimization options are set.

RUNTIME_RELEASE

Release mode. Optimization is turned on.

Runtime_subdir_obj_placement

The generator of folder name for compilation results, building a hierarchy of subfolders in a special folder, which name is choosen based on runtime mode.

For example, let src/lib/l.cpp and src/main/m.cpp files would be the sources of lib/l.lib library and m.exe application. If project is compiled in RELEASE mode, then following files would be created: release/src/lib/l.obj, release/src/main/m.obj, release/lib/l.lib and release/m.exe. Thus the presence of subfolders required will be supervised (for example, release/src/lib, release/src/main,…). If some subfolder doesn't exist, it will be created.

An example of usage:

class  Build < MxxRu::Cpp::Composite_target
  def initialize( a_alias = MxxRu::BUILD_ROOT )
    global_obj_placement(
      MxxRu::Cpp::RuntimeSubdirObjPlacement.new(
        "output" ) )

    required_prj( "src/lib/prj.rb" )
    required_prj( "src/main/prj.rb" )
  end
end
SCREEN_CONSOLE

Console application.

SCREEN_WINDOW

Windowed application.

Source_subdir_obj_placement

The generator of folder name for an object file, using a subfolder with a fixed name in a folder with source file. Folder for lib, dll and exe files are not modified. get_obj and get_mswin_res methods are checking if result folder exists. If it's not, they are trying to create it.

Spreadable_option

Auxiliary class for a storage of options, which can be broken on 3 groups: global, local and upspread. Examples of such options are: defines, include_paths, compiler_options, linker_options, …

THREADING_DEFAULT

Default compiler threading mode.

THREADING_MULTI

Multithreading is used.

THREADING_SINGLE

Multithreading is not used.

Target_type

Target type (exe, lib, dll, unittest, composite etc.). The real type of the target is defined by a derivative class.

Target_with_full_path

Base class for any target for which full path must be calculated.

Public Class Methods

composite_target( prj_alias = nil, &block ) click to toggle source

Simple method to define composite target.

Example:

MxxRu::Cpp::composite_target( MxxRu::BUILD_ROOT ) {
  required_prj 'some_project.rb'
  required_prj 'some_another_project.rb'
}
# File lib/mxx_ru/cpp/composite.rb, line 100
def Cpp.composite_target( prj_alias = nil, &block )
  prj_alias = MxxRu::Util::prj_alias_form_caller( caller ) unless prj_alias
  MxxRu::setup_target CompositeTarget.new( prj_alias, &block )
end
default_obj_placement() click to toggle source

Creation of obj_placement object, which should be used by default.

# File lib/mxx_ru/cpp/obj_placement.rb, line 391
def Cpp.default_obj_placement
  return SourceSubdirObjPlacement.new
end
detect_toolset() click to toggle source

Detect current toolset based on values of environment variables

Following algorithm is used: Getting the value of MXX_RU_CPP_TOOLSET envonment variable. It should be in a following format:

<file> [tag=value [tag=value [...]]

<file> value is used in require directive.

After loading of file defined, toolset method should return a pointer to toolset object.

If toolset object was created, pairs of tag=value are parsed and saved to the toolset created using a setup_tag method.

# File lib/mxx_ru/cpp/detect_toolset.rb, line 50
def Cpp.detect_toolset
  begin
    env = get_or_detect_toolset_variable_content

    # Exctracting file name, responsible for toolset object creation.
    toolset_file_name_regexp = /^(\S+)(.*)$/
    file_name_match = toolset_file_name_regexp.match( env )
    if nil == file_name_match
      raise MxxRu::InvalidValueEx.new(
        "Invalid format of environment variable '#{env_var}'. " +
        "Expected format: #{env_var}=<file>[ <tag>=<value>[ " +
        "<tag>=<value>[ ...]]]" )
    end

    file_name = file_name_match[ 1 ]
    unparsed_tags = file_name_match[ 2 ]

    # Loading the file
    # Try to loading specified file first, if it fails try to
    # loading file with 'mxx_ru/cpp/toolsets' added...
    try_load_toolset_file file_name

    if nil == toolset()
      raise MxxRu::InvalidValueEx.new(
        "C/C++ Toolset is not set by file '#{file_name}'" )
    end

    # Setting up toolset tags
    setup_toolset_tags( toolset(), unparsed_tags )

  rescue MxxRu::Ex => ex
    $stderr.print "<<<[#{ex.class.name}]\t#{ex}>>>\n"
    exit( -1 )
  end
end
ext_cmake_project( prj_alias = nil, &block ) click to toggle source

Simple method to define externals CMake project.

Example:

MxxRu::Cpp::ext_cmake_project {
  where 'deps/some_library'

  with WITH_SSL: 'NO', WITH_THREADS: 'YES'

  install_includedir 'some_library/headers'

  includedir_subfolders 'interface', 'backends', 'statistics'
}

Since v.1.6.11

# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 466
def Cpp.ext_cmake_project( prj_alias = nil, &block )
  prj_alias = MxxRu::Util::prj_alias_form_caller( caller ) unless prj_alias
  MxxRu::setup_target ExtCMakeProjectTarget.new( prj_alias, &block )
end
generate_simple_target_method( target_type ) click to toggle source

Generator for generating method for simple way of describing targets.

# File lib/mxx_ru/cpp/target.rb, line 1548
def Cpp.generate_simple_target_method( target_type )
  target_class_name = target_type.to_s.capitalize
  class_eval %Q{
    def Cpp.#{target_type}( prj_alias = nil, &block )
      prj_alias = MxxRu::Util::prj_alias_form_caller( caller ) unless prj_alias
      MxxRu::setup_target #{target_class_name}.new( prj_alias, &block )
    end
  }
end
get_or_detect_toolset_variable_content() click to toggle source

Gets or detects value for MXX_RU_CPP_TOOLSET.

Since v.1.5.1

# File lib/mxx_ru/cpp/detect_toolset.rb, line 120
def Cpp.get_or_detect_toolset_variable_content
  env = ENV[ ENV_VAR ]
  if env.nil?
    $stderr.puts "Environment variable #{ENV_VAR} not found. " +
        "Try to detect toolset by HOST_OS and/or PATH..."
    env = try_detect_toolset_myself
    if env
      $stderr.puts "Detection successed. Toolset is: #{env}"
    else
      $stderr.puts "Detection failed."
      raise MxxRu::InvalidValueEx.new(
        "Environment variable '#{ENV_VAR}' not found (not set " +
        "or empty" )
    end
  end

  env
end
lib_collection_target( prj_alias = nil, &block ) click to toggle source

Simple method to define libraries collection target.

Example:

MxxRu::Cpp::lib_collection_target {
  required_prj 'some_project.rb'
  required_prj 'some_another_project.rb'
}

Since v.1.4.0

# File lib/mxx_ru/cpp/lib_collection.rb, line 87
def Cpp.lib_collection_target( prj_alias = nil, &block )
  prj_alias = MxxRu::Util::prj_alias_form_caller( caller ) unless prj_alias
  MxxRu::setup_target LibCollectionTarget.new( prj_alias, &block )
end
setup_toolset( toolset ) click to toggle source

Set current toolset.

# File lib/mxx_ru/cpp/toolset.rb, line 1327
def Cpp.setup_toolset( toolset )
  raise MxxRu::InvalidCastEx.new(
    'Expected MxxRu::Cpp::Toolset' ) if
      !( toolset.kind_of?( MxxRu::Cpp::Toolset ) )

  @@current_toolset = toolset
end
setup_toolset_tags( a_toolset, a_unparsed_tags ) click to toggle source
a_toolset

Toolset, tags are set for

a_unparsed_tags

A string, formatted that way: <tag>=<value>[ <tag>=<value> [<tag>=<value> …]]

# File lib/mxx_ru/cpp/detect_toolset.rb, line 89
def Cpp.setup_toolset_tags( a_toolset,
  a_unparsed_tags )

  a_unparsed_tags.scan( /(\S+)=(\S+)/ ) { |t, v|
    a_toolset.setup_tag( t, v )
  }

end
toolset() click to toggle source

Get current toolset.

# File lib/mxx_ru/cpp/toolset.rb, line 1336
def Cpp.toolset
  return @@current_toolset
end
try_detect_toolset_myself() click to toggle source

Try to detect toolset from host_os and PATH.

Since v.1.5.1

Only Windows platform and MS C++, Linux and GCC is detected now.

Returns name of toolset of throw exception if toolset is not detectable.

# File lib/mxx_ru/cpp/detect_toolset.rb, line 146
def Cpp.try_detect_toolset_myself
  if RbConfig::CONFIG['host_os'] =~ /linux/
    # Assume that GCC is default compiler on Linux.
    "gcc_linux"
  elsif RbConfig::CONFIG['host_os'] =~ /^freebsd(9|10|11|12)$/
    "clang_freebsd"
  else
    if ENV[ 'COMP_ENV' ] and ENV[ 'VC_ARCH' ]
      'icc_win'
    elsif ENV[ 'VS160COMNTOOLS' ]
      'vc16'
    elsif ENV[ 'VS140COMNTOOLS' ]
      'vc14'
    elsif ENV[ 'VS120COMNTOOLS' ]
      'vc12'
    elsif ENV[ 'VS110COMNTOOLS' ]
      'vc11'
    elsif ENV[ 'VS100COMNTOOLS' ]
      'vc10'
    elsif ENV[ 'VS90COMNTOOLS' ]
      'vc9'
    elsif ENV[ 'VS80COMNTOOLS' ]
      'vc8'
    elsif ENV[ 'VS71COMNTOOLS' ]
      'vc7'
    end
  end
end
try_load_toolset_file( file_name ) click to toggle source

Try load toolset file (without and with 'mxx_ru/cpp/toolsets' prefix).

Raises LoadError if loading failed

# File lib/mxx_ru/cpp/detect_toolset.rb, line 101
def Cpp.try_load_toolset_file( file_name )
  files_to_load = [ file_name,
      File.join( 'mxx_ru/cpp/toolsets', file_name ) ]
  load_result = files_to_load.detect { |file_to_load|
      begin
        require file_to_load
      rescue LoadError
        false
      end
    }
  raise MxxRu::InvalidValueEx.new(
    "Unable to load Toolset from files: " +
      "'#{files_to_load.join('; ')}'" ) unless load_result
end