class MxxRu::Cpp::ExtCMakeProjectTarget
External CMake project.
Since v.1.6.11
Constants
- INSTALL_MANIFEST
Public Class Methods
MxxRu::Cpp::CompositeTarget::new
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 71 def initialize( a_alias, &block ) @mxx_cmake_defs = {} @mxx_includedir_subfolders = [] super( a_alias ) if @mxx_cmakelists_location.nil? raise CMakeProjectLocationNotDefined.new( a_alias ) end end
Public Instance Methods
MxxRu::Cpp::CompositeTarget#build
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 204 def build if nil == @mxx_last_build_result super # Actual result must be set only after CMake-related build steps. @mxx_last_build_result = nil @mxx_last_build_result = do_cmake_specific_build end @mxx_last_build_result end
Set the name of folder in which cmake-controlled build will be performed. If this name is not specified then name of that folder will be generated automatically (it will be based on toolset name and build mode).
Note: this folder is always created in location defined by obj_placement. Because of that is cannot be absolute path.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 125 def build_dir_name( name ) @mxx_cmake_build_dir_name = name end
MxxRu::Cpp::CompositeTarget#clean
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 216 def clean do_cmake_specific_clean super end
Set a name of includedir subfolder to be added to include path of all dependent targets.
Sometimes a project can have several subfolder in its include directory. Something like that:
some_project `- include/ `- subfolder1/ `- subfolder2/ `- subfolder3
When cmake install will be performed all these subfolders will be installed into install_includedir. But only install_includedir
will be added to include path. It means that header files from these subfolders must be included as:
#include <subfolder1/first_header.hpp> #include <subfolder2/second_header.hpp> ...
It could be inappropriate. In that case includedir_subfolder
can be used:
MxxRu::Cpp::ext_cmake_project { where 'soci' install_includedir 'soci_headers' includedir_subfolder 'soci' includedir_subfolder 'soci/postgresql' ... }
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 179 def includedir_subfolder( name ) @mxx_includedir_subfolders << name end
Same as includedir_subfolder
but allow to specify several folder names at once.
For example:
MxxRu::Cpp::ext_cmake_project { where 'soci' install_includedir 'soci_headers' includedir_subfolders 'soci', 'soci/postgresql' ... }
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 196 def includedir_subfolders( *names ) @mxx_includedir_subfolders.push( *names ) end
Set name of folder for header files.
This name will be passed to cmake command via -DINCLUDEDIR option.
Usage example:
MxxRu::Cpp::ext_cmake_project { where 'soci' install_includedir 'soci_headers' ... }
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 142 def install_includedir( dir ) @mxx_cmake_install_includedir = dir end
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 200 def target_type return ExtCMakeProjectTargetType.new end
Set the location of external project's CMakeLists.txt file.
This is mandatory parameter.
NOTE. location must be a relative path.
Usage example:
MxxRu::Cpp::ext_cmake_project { where 'soci' # It means that 'soci' must be subfolder of # the prject's root folder. ... }
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 96 def where( location ) @mxx_cmakelists_location = location end
Set values to be passes to cmake commands via -D option.
Usage example:
MxxRu::Cpp::ext_cmake_project { where 'soci' with WITH_BOOST: :ON, WITH_ORACLE: :OFF with :SOCI_EMPTY => 'OFF' with :SOCI_SHARED => 'ON', :SOCI_STATIC => 'OFF' with SOCI_TESTS: :OFF }
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 113 def with( options ) @mxx_cmake_defs.merge!( options ) end
Private Instance Methods
NOTE. This method must be called when cmake working dir is the current directory.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 336 def clean_installed_files do_with_install_manifest_content do |file_to_remove| if File.exists?( file_to_remove ) FileUtils.rm( file_to_remove, file_utils_options ) end end end
Compares old and new states and returns TargetState::EXISTS or TargetState::REBUILT
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 293 def compare_build_results_states( old_state, new_state ) # Keeps files which are not present in old_state or # files with new modification time. new_state.keep_if do |name, mtime| old_mtime = old_state.fetch( name, nil ) old_mtime.nil? ? true : (old_mtime < mtime) end new_state.empty? ? TargetState::EXISTS : TargetState::REBUILT end
Create local name of cmake working directory. If `cmake_build_dir` is specified then its value will be used. Otherwise a name based on toolset id string and build mode will be created.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 394 def create_cmake_build_dir_value if @mxx_cmake_build_dir_name.nil? v = "cmake_build_#{toolset.make_identification_string}_" v += RUNTIME_RELEASE == mxx_runtime_mode ? "release" : "debug" else @mxx_cmake_build_dir_name end end
Returns hash where key is a file name and value is file modification time.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 280 def detect_build_results_state result = {} do_with_install_manifest_content do |filename| if File.exists?( filename ) result[ filename ] = File.mtime( filename ) end end result end
Returns value for CMAKE_BUILD_TYPE definition.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 411 def detect_cmake_build_type RUNTIME_RELEASE == mxx_runtime_mode ? "Release" : "Debug" end
Make part of cmake command line with CMAKE_C_COMPILER and CMAKE_CXX_COMPILER definitions.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 441 def detect_cmake_compilers "-DCMAKE_C_COMPILER=#{toolset.c_compiler_name} " + "-DCMAKE_CXX_COMPILER=#{toolset.cpp_compiler_name} " end
Make part of cmake command line with '-G' option and appropriate value for it.
NOTE: if there is no known generator name for the toolset then empty string is returned.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 420 def detect_cmake_generator if 'vc' == toolset.name '-G "NMake Makefiles"' elsif 'gcc' == toolset.name k = MxxRu::Cpp::Toolsets::GccFamily if k::GCC_PORT_MINGW == toolset.tag( k::GCC_PORT_TAG, 'unix' ) '-G "MinGW Makefiles"' else '-G "Unix Makefiles"' end elsif 'clang' == toolset.name '-G "Unix Makefiles"' else # Return empty string in hope that CMake can detect a generator # by itself. '' end end
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 224 def do_cmake_specific_build ctx = make_building_context if !MxxRu::Util::Mode.instance.is_dry_run try_run_cmake_build( ctx ) else TargetState.new( TargetState::REBUILT ) end end
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 234 def do_cmake_specific_clean ctx = make_building_context if !MxxRu::Util::Mode.instance.is_dry_run try_run_cmake_clean( ctx ) end end
Open INSTALL_MANIFEST
if it exists and call block for every non-empty name from it.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 355 def do_with_install_manifest_content(&block) if File.exists?( INSTALL_MANIFEST ) File::open( INSTALL_MANIFEST, 'r' ) do |manifest| manifest.each_line do |line| filename = line.chomp block[ line.chomp ] unless filename.empty? end end end end
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 446 def file_utils_options { :verbose => MxxRu::Util::Mode::instance.is_brief_desc } end
Create instance of BuildingContext
with all members initialized with appropriate values.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 368 def make_building_context ctx = BuildingContext.new ctx.cmakelists_location = File.absolute_path( @mxx_cmakelists_location ) ctx.install_prefix = File.absolute_path( mxx_obj_placement.get_lib( '.', toolset, self ) ) includedir = @mxx_cmake_install_includedir includedir = 'include' unless includedir ctx.install_includedir = File.absolute_path( mxx_obj_placement.get_lib( includedir, toolset, self ) ) ctx.install_libdir = File.absolute_path( mxx_obj_placement.get_lib( '.', toolset, self ) ) ctx.cmake_build_dir = File.join( mxx_obj_placement.get_obj( @mxx_cmakelists_location, toolset, self ), create_cmake_build_dir_value ) ctx end
NOTE. This method must be called when cmake working dir is the current directory.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 305 def run_cmake( ctx ) cmd_line = "cmake -DCMAKE_BUILD_TYPE=#{detect_cmake_build_type} " cmd_line += "-DCMAKE_INSTALL_PREFIX=#{ctx.install_prefix} " cmd_line += "-DINCLUDEDIR=#{ctx.install_includedir} " if ctx.install_includedir cmd_line += "-DLIBDIR=#{ctx.install_libdir} " if ctx.install_libdir cmd_line += "-DBINDIR=#{ctx.install_bindir} " if ctx.install_bindir cmd_line += transform_options_to_cmd_line_params cmd_line += detect_cmake_compilers cmd_line += "#{detect_cmake_generator} " cmd_line += ctx.cmakelists_location AbstractTarget::run( [cmd_line], [], "Running CMake for native build files configuration" ) end
NOTE. This method must be called when cmake working dir is the current directory.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 327 def run_native_build AbstractTarget::run( ["cmake --build . --target install"], [], "Launching native build via CMake" ) end
NOTE. This method must be called when cmake working dir is the current directory.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 346 def run_native_clean AbstractTarget::run( ["cmake --build . --target clean"], [], "Launching native clean via CMake" ) end
Make part of cmake command line with definitions from 'with' values.
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 404 def transform_options_to_cmd_line_params r = '' @mxx_cmake_defs.each_pair { |k,v| r += "-D#{k}=#{v} " } r end
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 242 def try_run_cmake_build( ctx ) # Assume that target is rebuilt. # Actual state will be detected later. target_state = TargetState::REBUILT MxxRu::Util::ensure_path_exists( ctx.cmake_build_dir ) FileUtils.cd( ctx.cmake_build_dir ) do pre_build_state = detect_build_results_state run_cmake( ctx ) run_native_build target_state = compare_build_results_states( pre_build_state, detect_build_results_state ) end # If everything is all right then include path and library paths # must be set for all dependent targets. include_path( ctx.install_includedir, OPT_UPSPREAD ) @mxx_includedir_subfolders.each do |folder| include_path( File.join( ctx.install_includedir, folder ), OPT_UPSPREAD ) end lib_path( ctx.install_libdir ) TargetState.new( target_state ) end
# File lib/mxx_ru/cpp/ext_cmake_project.rb, line 269 def try_run_cmake_clean( ctx ) if File.directory?( ctx.cmake_build_dir ) FileUtils.cd( ctx.cmake_build_dir ) do clean_installed_files run_native_clean end FileUtils.rm_r( ctx.cmake_build_dir, file_utils_options ) end end