class MxxRu::Cpp::Target
Base class for all targets of C/C++ projects.
Expand class Target
to store source and actual manifest descriptions.
Constants
- Global_obj_placement_info
Description of
obj_placement
object installed. Used to store global obj_placement.- OPT_LOCAL
Attribute that the option should be local.
- OPT_UPSPREAD
Attribute that the option should be upspreadable.
Attributes
The list of source C-files. Array of MxxRu::Cpp::CppSourceFile
objects.
The list of source C++-files. Array of MxxRu::Cpp::CppSourceFile
objects.
Default encoding source files.
Import library folder. May contain nil value.
Name of mswin resource file. Should be object of MxxRu::Cpp::MswinRcFile
type. May contain nil value, if resources are not used.
The name of compiled mswin resource file. Should be a string. May contain nil value, if resources are not used.
Object
files list.
Optimization mode. By default, speed optimization is used.
Screen mode. Console by default.
Path, the names of source files are related to.
Custom extension for target. NIL, if custom extension not defined.
The name to get target result. Should not contain file extension.
Custom prefix for target. NIL, if custom prefix not defined.
Since v.1.4.2
Path, the name of result of a target is related to. If contains an empty value, target should be defined using a full path. Otherwise the value of mxx_target_root
is concatenated with a given target name.
Public Class Methods
Generator for methods to manipulation of options those can be 'global', 'local' and 'upspread'.
For each option generates following stuff:
# Global values container. @@mxx_global_<option> = [] # Local and opspread values container. @mxx_<option> = SpreadableOption.new(...) # Setter for global values. def global_<option>( value ); ...; end # Setter for local values. def <option>( value, mode ); ...; end # Getter for all values (including global, local and upspread). def mxx_all_<option>s; ...; end # Getter for upspread values only. def mxx_all_upspread_<option>s; ...; end
# File lib/mxx_ru/cpp/target.rb, line 559 def self.define_spreadable_option_methods( option ) global_container_name = "@@mxx_globals_#{option}" local_container_name = "@mxx_#{option}" global_setter_name = "global_#{option}" local_setter_name = "#{option}" all_getter_name = "mxx_all_#{option}s" upspread_getter_name = "mxx_all_upspread_#{option}s" metaprogram = %Q{ #{global_container_name} = [] def #{global_setter_name}( value ) #{global_container_name} << value SpreadableOption::refresh_option_change_time( :'#{option}' ) end def #{local_setter_name}( value, mode = Target::OPT_LOCAL ) #{local_container_name}.add( value, mode ) end def #{all_getter_name}() return #{local_container_name}.all( #{global_container_name}, mxx_required_prjs, :'#{upspread_getter_name}' ) end def #{upspread_getter_name}() return #{local_container_name}.all_upspreads( mxx_required_prjs, :'#{upspread_getter_name}' ) end } class_eval metaprogram end
Generator for methods to manipulation with 'runtime_mode', 'rtti_mode', 'rtl_mode', 'threading_mode' and so on.
By default generates 3 methods:
# Setter def <option>( value ); ...; end # Setter for default value. def default_<option>( value ); ...; end # Getter def mxx_<option>; ...; end
If no_getter == :nogetter then getter method not generated.
# File lib/mxx_ru/cpp/target.rb, line 526 def self.global_option_methods( option, getter = :withgetter ) class_eval %Q{ def #{option}( value ) @@mxx_#{option}.change( value, prj_alias ) end def default_#{option}( value ) @@mxx_#{option}.change_default( value, prj_alias ) end } class_eval %Q{ def mxx_#{option} @@mxx_#{option}.value end } unless getter == :nogetter end
Initializator for all instance variables created by self.define_spreadable_option_methods().
Must be called in constructor.
# File lib/mxx_ru/cpp/target.rb, line 604 def self.initialize_spreadable_option_instance_variables( target ) class_variables.grep( /^@@mxx_globals_/ ) do |g| option = /^@@mxx_globals_(.+)$/.match(g)[ 1 ] name = "@mxx_#{option}" target.instance_variable_set( name, SpreadableOption.new( option ) ) end end
Constructor
- a_prj_alias
-
Project identifier.
MxxRu::BinaryTarget::new
# File lib/mxx_ru/cpp/target.rb, line 626 def initialize( a_prj_alias ) super( a_prj_alias ) @mxx_target_root = "" @mxx_target_exe = nil @mxx_sources_root = File.dirname( a_prj_alias ) @mxx_screen_mode = SCREEN_CONSOLE @mxx_c_files = Array.new @mxx_cpp_files = Array.new @mxx_mswin_rc_file = nil @mxx_mswin_res_file = nil @mxx_obj_files = Array.new # The storage of local options. # The key is a String, the value is SpreadableOption. @mxx_locals = Hash.new @mxx_implib_path = nil # Object, which defines accommodation of object files. @mxx_obj_placement = nil @mxx_target_name = nil @mxx_optimization = OPTIM_SPEED # Result of work of the previous reference to a build method. # During a repeted calls of build method target build is not performed, # and this value is returned. @mxx_last_build_result = nil # True if toolset has completely defined all compiler and linker options required. @mxx_all_options_defined = false @mxx_encoding = Encoding.find("Binary") Target::initialize_spreadable_option_instance_variables( self ) end
Public Instance Methods
Perform build of the target.
# File lib/mxx_ru/cpp/target.rb, line 906 def build if nil == @mxx_last_build_result builder = self.method( :normal_mode_builder ) builder = self.method( :option_extraction_mode_builder ) \ if MxxRu::Cpp::Mode.instance.is_option_extraction @mxx_last_build_result = builder.call end return @mxx_last_build_result end
Add one C-file to the target.
Note: if a_file_name contains prefix equal to current sources_root
than mxx_ru does not add sources_root
to name of file. For example:
MxxRu::Cpp::exe_target( 'some/module/prj.rb' ) { ... c_source 'f1.c' # become 'some/module/f1.c' c_source 'some/module/impl/f2.c' # remains 'some/module/impl/f2.c
This approach will be useful with Dir.glob:
MxxRu::Cpp::exe_target( 'some/module/prj.rb' ) { ... c_sources Dir.glob( 'some/module/**/*.c' ) }
- a_file_name
-
The name of a file added.
- a_options
-
Optional list of a compiler options for that file. When command line would be created, this options would be concatenated with others.
# File lib/mxx_ru/cpp/target.rb, line 829 def c_source( a_file_name, a_options = nil ) @mxx_c_files.push( CppSourceFile.new( create_full_src_file_name( a_file_name ), a_options ) ) end
Perform target's cleanup.
# File lib/mxx_ru/cpp/target.rb, line 920 def clean if nil == @mxx_last_build_result cleaner = self.method( :normal_mode_cleaner ) cleaner = self.method( :option_extraction_mode_cleaner ) \ if MxxRu::Cpp::Mode.instance.is_option_extraction cleaner.call @mxx_last_build_result = MxxRu::TargetState.new( MxxRu::TargetState::ABSENT ) end end
Add one C++-file to the target.
Note: if a_file_name contains prefix equal to current sources_root
than mxx_ru does not add sources_root
to name of file. For example:
MxxRu::Cpp::exe_target( 'some/module/prj.rb' ) { ... cpp_source 'f1.cpp' # become 'some/module/f1.cpp' cpp_source 'some/module/impl/f2.cpp' # remains 'some/module/impl/f2.cpp
This approach will be useful with Dir.glob:
MxxRu::Cpp::exe_target( 'some/module/prj.rb' ) { ... cpp_sources Dir.glob( 'some/module/**/*.cpp' ) }
- a_file_name
-
The name of a file added.
- a_options
-
Optional list of a compiler options for that file. When command line would be created, this options would be concatenated with others.
# File lib/mxx_ru/cpp/target.rb, line 852 def cpp_source( a_file_name, a_options = nil ) @mxx_cpp_files.push( CppSourceFile.new( create_full_src_file_name( a_file_name ), a_options ) ) end
Creation of complete result target file name.
Result target file name depends on ObjPlacement
and Toolset
.
# File lib/mxx_ru/cpp/target.rb, line 980 def create_full_result_target_file_name do_target_type_depending_actions( :lib => lambda { |toolset| toolset.full_lib_name( self ) }, :dll => lambda { |toolset| toolset.full_dll_name( self ) }, :macos_bundle => lambda { |toolset| toolset.full_dll_name( self ) }, :exe => lambda { |toolset| toolset.full_exe_name( self ) } ) end
Creation of a complete name of a source file taking the value of mxx_sources_root
into account
If a_file_name starts with current value of mxx_sources_root
than a_file_name remains unchanged.
# File lib/mxx_ru/cpp/target.rb, line 964 def create_full_src_file_name( a_file_name ) if "" == mxx_sources_root return a_file_name else if a_file_name[ 0..mxx_sources_root.size ] == mxx_sources_root + '/' return a_file_name else return File.join( [ mxx_sources_root, a_file_name ] ) end end end
Creation of a complete name of a resulting file taking the value of mxx_target_root
into account
# File lib/mxx_ru/cpp/target.rb, line 951 def create_full_target_file_name( a_file_name ) if "" == mxx_target_root return a_file_name else return File.join( [ mxx_target_root, a_file_name ] ) end end
Set global obj_placement. If gloval obj_placement
was already set before, exception is thrown.
# File lib/mxx_ru/cpp/target.rb, line 712 def global_obj_placement( a_placement ) @@mxx_global_obj_placement.change( a_placement, prj_alias ) end
Set import library location.
# File lib/mxx_ru/cpp/target.rb, line 886 def implib_path( name ) @mxx_implib_path = name.clone end
Set mswin resource file name.
- a_rc_file
-
The name of rc-file.
- a_depends
-
Optional dependencies list. Should be Array of String.
# File lib/mxx_ru/cpp/target.rb, line 866 def mswin_rc_file( a_rc_file, a_depends =nil ) @mxx_mswin_rc_file = MswinRcFile.new( create_full_src_file_name( a_rc_file ), a_depends ) end
Set compiled mswin resource file name.
# File lib/mxx_ru/cpp/target.rb, line 876 def mswin_res_file( a_res_file ) @mxx_mswin_res_file = String.new( a_res_file ) end
Get obj_placement
object, which should be used.
If both global and local obj_placement
are set, exception is thrown.
If global or local obj_placement
is defined, it is returned.
If nor global nor local obj_placement
is set, local obj_placement
is created with a help of MxxRu::Cpp::default_obj_placement
function and it's returned.
# File lib/mxx_ru/cpp/target.rb, line 731 def mxx_obj_placement if nil != @mxx_obj_placement && nil != @@mxx_global_obj_placement.placement raise MxxRu::InvalidValueEx.new( "Global and local obj_placement object exists! " + "Global created by: #{@@mxx_global_obj_placement.who}. " + "Local created by: #{prj_alias}" ) end if nil != @@mxx_global_obj_placement.placement return @@mxx_global_obj_placement.placement end if nil == @mxx_obj_placement @mxx_obj_placement = MxxRu::Cpp::default_obj_placement end return @mxx_obj_placement end
runtime_mode accessor (custom implementation).
# File lib/mxx_ru/cpp/target.rb, line 683 def mxx_runtime_mode # If runtime_mode is set to RUNTIME_DEFAULT (i.e. # wasn't changed in a projects), then check of command line options # is required (--mxx-cpp-release, --mxx-cpp-debug). result = @@mxx_runtime_mode.value if @@mxx_runtime_mode.default_value == result if MxxRu::Cpp::Mode.instance.is_release && MxxRu::Cpp::Mode.instance.is_debug # This is an invalid combination of flags. raise MxxRu::InvalidValueEx.new( "#{MxxRu::Cpp::MXXCPPARG_RELEASE} and " + "#{MxxRu::Cpp::MXXCPPARG_DEBUG} cannot be used " + "together" ) elsif MxxRu::Cpp::Mode.instance.is_release result = RUNTIME_RELEASE elsif MxxRu::Cpp::Mode.instance.is_debug result = RUNTIME_DEBUG end end return result end
Add object file to the target.
# File lib/mxx_ru/cpp/target.rb, line 881 def obj_file( file_name ) @mxx_obj_files.push( String.new( file_name ) ) end
Set local obj_placement. It's impossible to simultaneously set global and local obj_placement.
# File lib/mxx_ru/cpp/target.rb, line 718 def obj_placement( a_placement ) @mxx_obj_placement = a_placement end
Set optimization mode required.
# File lib/mxx_ru/cpp/target.rb, line 891 def optimization( a_mode ) if OPTIM_SIZE != a_mode && OPTIM_SPEED != a_mode raise MxxRu::InvalidValueEx.new( "Unknown optimization mode: '#{a_mode}'" ) else @mxx_optimization = a_mode.clone end end
Reset build status to enable rebuild.
# File lib/mxx_ru/cpp/target.rb, line 935 def reset if @mxx_last_build_result reset_required_projects @mxx_last_build_result = nil end end
Set screen mode.
# File lib/mxx_ru/cpp/target.rb, line 802 def screen_mode( a_mode ) if SCREEN_CONSOLE == a_mode || SCREEN_WINDOW == a_mode @mxx_screen_mode = a_mode else raise MxxRu::UnsupportedModeEx.new( "Unsupported screen mode: #{a_mode}" ) end end
Set encoding source files.
# File lib/mxx_ru/cpp/target.rb, line 901 def source_encoding( a_encoding ) @mxx_encoding = Encoding.find("#{a_encoding}") end
Change source files path. If empty string is set, then full file names are required. If block is defined, then path is changed only during a block execution, then old path value is restored.
Returns previous mxx_sources_root
value. Is actual for a case, when method is called without block parameter.
# File lib/mxx_ru/cpp/target.rb, line 788 def sources_root( a_root ) old_root = @mxx_sources_root.clone if block_given? @mxx_sources_root = File.join( [ @mxx_sources_root, a_root ] ) yield @mxx_sources_root = old_root else @mxx_sources_root = a_root end return old_root end
Set a name from which target name would be created.
# File lib/mxx_ru/cpp/target.rb, line 766 def target( a_target ) @mxx_target_name = create_full_target_file_name( a_target ) end
Set a custom extension for target.
# File lib/mxx_ru/cpp/target.rb, line 776 def target_ext( ext ) @mxx_target_ext = ext end
Set a custom prefix for target.
# File lib/mxx_ru/cpp/target.rb, line 771 def target_prefix( ext ) @mxx_target_prefix = ext end
Change path, the names of target results are related to.
NOTE: This method should be called BEFORE target method!
If target_root
is called after target method, then a_root given is added to the name already was set.
# File lib/mxx_ru/cpp/target.rb, line 757 def target_root( a_root ) @mxx_target_root = a_root if @mxx_target_name @mxx_target_name = File.join( [ @mxx_target_root, @mxx_target_name ] ) end end
Get the target type. Should be overloaded in child classes. Object
, inherited from MxxRu::Cpp::TargetType
is returned.
# File lib/mxx_ru/cpp/target.rb, line 945 def target_type raise AbstractMethodEx.new( "MxxRu::Cpp::Target::target_type" ) end
A simple way to get access to the toolset. In a class, inherited from MxxRu::Cpp::Target
is more convinient to call toolset method, instead of MxxRu::Cpp::toolset
function. Just calling MxxRu::Cpp::toolset
function.
# File lib/mxx_ru/cpp/target.rb, line 676 def toolset() return MxxRu::Cpp::toolset() end
Get source manifest description. If target has no manifest then default manifest will be returned.
# File lib/mxx_ru/cpp/toolsets/vc8_family.rb, line 42 def vc8_source_manifest if nil != @vc8_source_manifest @vc8_source_manifest else MxxRu::Cpp::Toolsets::Vc8Family::default_manifest end end
Setter for source manifest description.
# File lib/mxx_ru/cpp/toolsets/vc8_family.rb, line 51 def vc8_source_manifest=( manifest ) @vc8_source_manifest = manifest end
Protected Instance Methods
# File lib/mxx_ru/cpp/target.rb, line 1220 def add_unique_to( what, to ) if !to.include?( what ) to.push( what ) end end
Checks value of @mxx_all_options_defined and initiate options setup if it is nil.
# File lib/mxx_ru/cpp/target.rb, line 991 def check_all_options_definition if !@mxx_all_options_defined # It's necessary, that toolset has defined all the options # taking all current modes into account. MxxRu::Cpp::toolset.setup_mandatory_options( self ) @mxx_all_options_defined = true end end
# File lib/mxx_ru/cpp/target.rb, line 1164 def clean_generators mxx_generators.each { |g| g.clean( self ) } end
# File lib/mxx_ru/cpp/target.rb, line 1168 def clean_objs MxxRu::Cpp::toolset().clean_objs( self ) end
# File lib/mxx_ru/cpp/target.rb, line 1172 def clean_resources if @mxx_mswin_rc_file MxxRu::Cpp::toolset().clean_mswin_res( self ) end end
# File lib/mxx_ru/cpp/target.rb, line 1178 def clean_target do_target_type_depending_actions( :lib => lambda { |toolset| toolset.clean_lib( self ) }, :dll => lambda { |toolset| toolset.clean_dll( self ) }, :macos_bundle => lambda { |toolset| toolset.clean_dll( self ) }, :exe => lambda { |toolset| toolset.clean_exe( self ) } ) end
Start of resource files compiler. Returns nothing.
# File lib/mxx_ru/cpp/target.rb, line 1123 def compile_resources # We proceed from the assumption, that on one platform # some different types of resource files simultaneously can not be used. if @mxx_mswin_rc_file return MxxRu::Cpp::toolset().make_mswin_res( self ) end return MxxRu::TargetState.new( TargetState::EXISTS ) end
Start of source files compiler. Returns MxxRu::TargetState
.
# File lib/mxx_ru/cpp/target.rb, line 1117 def compile_sources return MxxRu::Cpp::toolset().make_objs( self ) end
Do action with toolset depending on target type.
Since v.1.4.7
- a_type_actions
-
Hash with keys :lib, :dll and :exe. Values should be Proc instances.
Usage:
do_target_type_depending_actions( :lib => lambda { |toolset| toolset.clean_lib(self) }, :dll => lambda { |toolset| toolset.clean_dll(self) }, :macos_bundle => lambda { |toolset| toolset.clean_dll(self) }, :exe => lambda { |toolset| toolset.clean_exe(self) } )
# File lib/mxx_ru/cpp/target.rb, line 1201 def do_target_type_depending_actions( a_type_actions ) toolset = MxxRu::Cpp::toolset if nil == target_type raise MxxRu::UnsupportedTargetTypeEx.new( self.class.name, "nil" ) elsif target_type.name == LibTargetType::TYPE a_type_actions[ :lib ].call( toolset ) elsif target_type.name == DllTargetType::TYPE a_type_actions[ :dll ].call( toolset ) elsif target_type.name == MacOSBundleTargetType::TYPE a_type_actions[ :macos_bundle ].call( toolset ) elsif target_type.name == ExeTargetType::TYPE a_type_actions[ :exe ].call( toolset ) else raise MxxRu::UnsupportedTargetTypeEx.new( self.class.name, target_type.name ) end end
Start of target linking.
- required_prjs_state
-
Build results of all subprojects required.
Object
ofMxxRu::TargetState
type. - objs_state
-
Compilation results of all object files
Object
ofMxxRu::TargetState
type. - res_state
-
Compilation results of all resource files.
Object
ofMxxRu::TargetState
type.
# File lib/mxx_ru/cpp/target.rb, line 1141 def link_target( required_prjs_state, objs_state, res_state ) rebuilding_needed = TargetState.rebuilding_needed?( required_prjs_state, objs_state, res_state ) state = do_target_type_depending_actions( :lib => lambda { |toolset| toolset.make_lib( self, rebuilding_needed ) }, :dll => lambda { |toolset| toolset.make_dll( self, rebuilding_needed ) }, :macos_bundle => lambda { |toolset| toolset.make_dll( self, rebuilding_needed ) }, :exe => lambda { |toolset| toolset.make_exe( self, rebuilding_needed ) } ) state end
Performs 'build' in normal mode.
# File lib/mxx_ru/cpp/target.rb, line 1001 def normal_mode_builder MxxRu::Cpp::Mode.instance.before_subprj_processing # The build of subordinated projects performed automatically # taking dry-run mode into account. required_prjs_state = build_required_projects MxxRu::Cpp::Mode.instance.after_subprj_processing # Since v.1.6.11 options are set only after building # of required projects. check_all_options_definition run_generators if !MxxRu::Cpp::Mode.instance.is_no_depends_analyzer run_depends_analyzer end objs_state = compile_sources res_state = compile_resources link_state = link_target( required_prjs_state, objs_state, res_state ) # The status of the target is determined by result of target linking. link_state end
Performs 'clean' in normal mode
# File lib/mxx_ru/cpp/target.rb, line 1029 def normal_mode_cleaner MxxRu::Cpp::Mode.instance.before_subprj_processing # The cleanup of subordinated projects performed automatically # taking dry-run mode into account. clean_required_prjs MxxRu::Cpp::Mode.instance.after_subprj_processing # Since v.1.6.11 options are set only after processing # of required projects. check_all_options_definition clean_generators clean_objs clean_resources clean_target end
Performs 'build' in 'option extraction mode'
# File lib/mxx_ru/cpp/target.rb, line 1047 def option_extraction_mode_builder options = { 'Compiler options' => :mxx_all_compiler_options, 'C++ Compiler Options' => :mxx_all_cpp_compiler_options, 'C Compiler Options' => :mxx_all_c_compiler_options, 'Linker Options' => :mxx_all_linker_options, 'Librarian Options' => :mxx_all_librarian_options, 'Defines' => :mxx_all_defines, 'Include Paths' => :mxx_all_include_paths } if 'mswin' == toolset.tag( 'target_os' ) options.merge!( 'MSWindows Resource Compiler Options' => :mxx_all_mswin_rc_options, 'MSWindows Resource Compiler Include Paths' => :mxx_all_mswin_rc_include_paths, 'MSWindows Resource Compiler Defines' => :mxx_all_mswin_rc_defines, 'MSWindows Resource Linker Options' => :mxx_all_mswin_rlink_options ) end options.keys.sort.each do |k| opts = self.send( options[ k ] ) puts "#{k}:\n\t#{opts.join("\n\t")}\n" end return TargetState.new( TargetState::EXISTS ) end
Performs 'clean' in 'option extraction mode'
# File lib/mxx_ru/cpp/target.rb, line 1077 def option_extraction_mode_cleaner # Nothing to do! end
Start of C++ dependencies analyzer.
# File lib/mxx_ru/cpp/target.rb, line 1087 def run_depends_analyzer analyzer = Analyzer::CppAnalyzer.instance # We prepare the analyzer to start. sources = Array.new mxx_c_files.each { |s| sources << s.name } mxx_cpp_files.each { |s| sources << s.name } analyzer.add_sources( sources ) analyzer.add_include_paths( mxx_all_include_paths ) # Performing analisys. analyzer.analyze mxx_encoding # Getting results of analysis. mxx_c_files.each { |s| depends = analyzer.get_depends_for( s.name ) s.depends << depends s.depends.flatten! } mxx_cpp_files.each { |s| depends = analyzer.get_depends_for( s.name ) s.depends << depends s.depends.flatten! } end
Start of all generators of source files.
# File lib/mxx_ru/cpp/target.rb, line 1082 def run_generators mxx_generators.each { |g| g.build( self ) } end