diff options
25 files changed, 406 insertions, 122 deletions
diff --git a/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst b/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst index a99c108..34524d1 100644 --- a/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst +++ b/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst @@ -9,5 +9,5 @@ any directories outside the project that are in the linker search path or contain linked library files. The directories are appended after the value of the :prop_tgt:`INSTALL_RPATH` target property. -This varibale is used to initialize the target property +This variable is used to initialize the target property :prop_tgt:`INSTALL_RPATH_USE_LINK_PATH` for all targets. diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index 6132693..018956b 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -191,8 +191,7 @@ Hints ``Python_FIND_STRATEGY`` This variable defines how lookup will be done. - The ``Python_FIND_STRATEGY`` variable can be set to empty or one of the - following: + The ``Python_FIND_STRATEGY`` variable can be set to one of the following: * ``VERSION``: Try to find the most recent version in all specified locations. @@ -205,8 +204,7 @@ Hints ``Python_FIND_REGISTRY`` On Windows the ``Python_FIND_REGISTRY`` variable determine the order of preference between registry and environment variables. - the ``Python_FIND_REGISTRY`` variable can be set to empty or one of the - following: + the ``Python_FIND_REGISTRY`` variable can be set to one of the following: * ``FIRST``: Try to use registry before environment variables. This is the default. @@ -216,8 +214,8 @@ Hints ``Python_FIND_FRAMEWORK`` On macOS the ``Python_FIND_FRAMEWORK`` variable determine the order of preference between Apple-style and unix-style package components. - This variable can be set to empty or take same values as - :variable:`CMAKE_FIND_FRAMEWORK` variable. + This variable can take same values as :variable:`CMAKE_FIND_FRAMEWORK` + variable. .. note:: @@ -231,8 +229,8 @@ Hints ``virtualenv`` or ``conda``. It is meaningful only when a virtual environment is active (i.e. the ``activate`` script has been evaluated). In this case, it takes precedence over ``Python_FIND_REGISTRY`` and ``CMAKE_FIND_FRAMEWORK`` - variables. The ``Python_FIND_VIRTUALENV`` variable can be set to empty or - one of the following: + variables. The ``Python_FIND_VIRTUALENV`` variable can be set to one of the + following: * ``FIRST``: The virtual environment is used before any other standard paths to look-up for the interpreter. This is the default. diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index a40d7f7..0ca1f56 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -939,15 +939,15 @@ endif() # Compute search signature # This signature will be used to check validity of cached variables on new search -set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}") +set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${_${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}") if (NOT WIN32) string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_USE_STATIC_LIBS}:") endif() if (CMAKE_HOST_APPLE) - string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_FIND_FRAMEWORK}") + string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${_${_PYTHON_PREFIX}_FIND_FRAMEWORK}") endif() if (CMAKE_HOST_WIN32) - string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_FIND_REGISTRY}") + string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${_${_PYTHON_PREFIX}_FIND_REGISTRY}") endif() diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake index 10fe211..15e1ce1 100644 --- a/Modules/FindPython2.cmake +++ b/Modules/FindPython2.cmake @@ -140,8 +140,7 @@ Hints ``Python2_FIND_STRATEGY`` This variable defines how lookup will be done. - The ``Python2_FIND_STRATEGY`` variable can be set to empty or one of the - following: + The ``Python2_FIND_STRATEGY`` variable can be set to one of the following: * ``VERSION``: Try to find the most recent version in all specified locations. @@ -154,8 +153,7 @@ Hints ``Python2_FIND_REGISTRY`` On Windows the ``Python2_FIND_REGISTRY`` variable determine the order of preference between registry and environment variables. - the ``Python2_FIND_REGISTRY`` variable can be set to empty or one of the - following: + the ``Python2_FIND_REGISTRY`` variable can be set to one of the following: * ``FIRST``: Try to use registry before environment variables. This is the default. @@ -165,8 +163,8 @@ Hints ``Python2_FIND_FRAMEWORK`` On macOS the ``Python2_FIND_FRAMEWORK`` variable determine the order of preference between Apple-style and unix-style package components. - This variable can be set to empty or take same values as - :variable:`CMAKE_FIND_FRAMEWORK` variable. + This variable can take same values as :variable:`CMAKE_FIND_FRAMEWORK` + variable. .. note:: @@ -180,8 +178,8 @@ Hints ``virtualenv`` or ``conda``. It is meaningful only when a virtual environment is active (i.e. the ``activate`` script has been evaluated). In this case, it takes precedence over ``Python2_FIND_REGISTRY`` and ``CMAKE_FIND_FRAMEWORK`` - variables. The ``Python2_FIND_VIRTUALENV`` variable can be set to empty or - one of the following: + variables. The ``Python2_FIND_VIRTUALENV`` variable can be set to one of the + following: * ``FIRST``: The virtual environment is used before any other standard paths to look-up for the interpreter. This is the default. diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index 211f982..8135a1d 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -188,8 +188,7 @@ Hints ``Python3_FIND_STRATEGY`` This variable defines how lookup will be done. - The ``Python3_FIND_STRATEGY`` variable can be set to empty or one of the - following: + The ``Python3_FIND_STRATEGY`` variable can be set to one of the following: * ``VERSION``: Try to find the most recent version in all specified locations. @@ -202,8 +201,7 @@ Hints ``Python3_FIND_REGISTRY`` On Windows the ``Python3_FIND_REGISTRY`` variable determine the order of preference between registry and environment variables. - The ``Python3_FIND_REGISTRY`` variable can be set to empty or one of the - following: + The ``Python3_FIND_REGISTRY`` variable can be set to one of the following: * ``FIRST``: Try to use registry before environment variables. This is the default. @@ -213,8 +211,8 @@ Hints ``Python3_FIND_FRAMEWORK`` On macOS the ``Python3_FIND_FRAMEWORK`` variable determine the order of preference between Apple-style and unix-style package components. - This variable can be set to empty or take same values as - :variable:`CMAKE_FIND_FRAMEWORK` variable. + This variable can take same values as :variable:`CMAKE_FIND_FRAMEWORK` + variable. .. note:: @@ -228,8 +226,8 @@ Hints ``virtualenv`` or ``conda``. It is meaningful only when a virtual environment is active (i.e. the ``activate`` script has been evaluated). In this case, it takes precedence over ``Python3_FIND_REGISTRY`` and ``CMAKE_FIND_FRAMEWORK`` - variables. The ``Python3_FIND_VIRTUALENV`` variable can be set to empty or - one of the following: + variables. The ``Python3_FIND_VIRTUALENV`` variable can be set to one of the + following: * ``FIRST``: The virtual environment is used before any other standard paths to look-up for the interpreter. This is the default. diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index 1e010bf..1bdee60 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -22,6 +22,9 @@ standard syntax, e.g. It also determines what the name of the library is. +Virtual environments such as RVM are handled as well, by passing +the argument ``Ruby_FIND_VIRTUALENV`` + Result Variables ^^^^^^^^^^^^^^^^ @@ -49,6 +52,28 @@ Also: ``Ruby_INCLUDE_PATH`` same as Ruby_INCLUDE_DIRS, only provided for compatibility reasons, don't use it + +Hints +^^^^^ + +``Ruby_ROOT_DIR`` + Define the root directory of a Ruby installation. + +``Ruby_FIND_VIRTUALENV`` + This variable defines the handling of virtual environments managed by + ``rvm``. It is meaningful only when a virtual environment + is active (i.e. the ``rvm`` script has been evaluated or at least the + ``MY_RUBY_HOME`` environment variable is set). + The ``Ruby_FIND_VIRTUALENV`` variable can be set to empty or + one of the following: + + * ``FIRST``: The virtual environment is used before any other standard + paths to look-up for the interpreter. This is the default. + * ``ONLY``: Only the virtual environment is used to look-up for the + interpreter. + * ``STANDARD``: The virtual environment is not used to look-up for the + interpreter (assuming it isn't still in the PATH...) + #]=======================================================================] # Backwards compatibility @@ -121,14 +146,115 @@ if(NOT Ruby_FIND_VERSION_EXACT) list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES) endif() +# virtual environments handling (eg RVM) +if (DEFINED ENV{MY_RUBY_HOME}) + if(_Ruby_DEBUG_OUTPUT) + message("My ruby home is defined: $ENV{MY_RUBY_HOME}") + endif() + + if (DEFINED Ruby_FIND_VIRTUALENV) + if (NOT Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$") + message (AUTHOR_WARNING "FindRuby: ${Ruby_FIND_VIRTUALENV}: invalid value for 'Ruby_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.") + set (_Ruby_FIND_VIRTUALENV "FIRST") + else() + set (_Ruby_FIND_VIRTUALENV ${Ruby_FIND_VIRTUALENV}) + endif() + else() + set (_Ruby_FIND_VIRTUALENV FIRST) + endif() +else() + if (DEFINED Ruby_FIND_VIRTUALENV) + message("Environment variable MY_RUBY_HOME isn't set, defaulting back to Ruby_FIND_VIRTUALENV=STANDARD") + endif() + set (_Ruby_FIND_VIRTUALENV STANDARD) +endif() + if(_Ruby_DEBUG_OUTPUT) message("_Ruby_POSSIBLE_EXECUTABLE_NAMES=${_Ruby_POSSIBLE_EXECUTABLE_NAMES}") + message("_Ruby_FIND_VIRTUALENV=${_Ruby_FIND_VIRTUALENV}") endif() -find_program (Ruby_EXECUTABLE - NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES} - NAMES_PER_DIR - ) +function (_RUBY_VALIDATE_INTERPRETER) + if (NOT Ruby_EXECUTABLE) + return() + endif() + + cmake_parse_arguments (PARSE_ARGV 0 _RVI "EXACT;CHECK_EXISTS" "" "") + if (_RVI_UNPARSED_ARGUMENTS) + set (expected_version ${_RVI_UNPARSED_ARGUMENTS}) + else() + unset (expected_version) + endif() + + if (_RVI_CHECK_EXISTS AND NOT EXISTS "${Ruby_EXECUTABLE}") + # interpreter does not exist anymore + set (_Ruby_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${Ruby_EXECUTABLE}\"") + set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND") + return() + endif() + + # Check the version it returns + # executable found must have a specific version + execute_process (COMMAND "${Ruby_EXECUTABLE}" -e "puts RUBY_VERSION" + RESULT_VARIABLE result + OUTPUT_VARIABLE version + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (result OR (_RVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) + # interpreter not usable or has wrong major version + if (result) + set (_Ruby_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${Ruby_EXECUTABLE}\"") + else() + set (_Ruby_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${Ruby_EXECUTABLE}\"") + endif() + set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND") + return() + endif() + +endfunction() + +while(1) + # Virtual environments handling + if(_Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") + if(_Ruby_DEBUG_OUTPUT) + message("Inside Matches") + endif() + find_program (Ruby_EXECUTABLE + NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES} + NAMES_PER_DIR + PATHS ENV MY_RUBY_HOME + PATH_SUFFIXES bin Scripts + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + + if(_Ruby_DEBUG_OUTPUT) + message("Ruby_EXECUTABLE=${Ruby_EXECUTABLE}") + endif() + + _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}}) + if(Ruby_EXECUTABLE) + break() + endif() + if(NOT _Ruby_FIND_VIRTUALENV STREQUAL "ONLY") + break() + endif() + elseif(_Ruby_DEBUG_OUTPUT) + message("_Ruby_FIND_VIRTUALENV doesn't match: ${_Ruby_FIND_VIRTUALENV}") + endif() + + # try using standard paths + find_program (Ruby_EXECUTABLE + NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES} + NAMES_PER_DIR) + _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}) + if (Ruby_EXECUTABLE) + break() + endif() + + break() +endwhile() if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR) function(_RUBY_CONFIG_VAR RBVAR OUTVAR) @@ -266,6 +392,8 @@ if(Ruby_VERSION_MAJOR) set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}") endif() +# FIXME: Currently we require both the interpreter and development components to be found +# in order to use either. See issue #20474. find_path(Ruby_INCLUDE_DIR NAMES ruby.h HINTS diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3bf80ea..d85832e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 17) -set(CMake_VERSION_PATCH 20200322) +set(CMake_VERSION_PATCH 20200325) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index eaf50f2..2543215 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -484,7 +484,7 @@ void QCMake::setWarnUnusedMode(bool value) void QCMake::checkOpenPossible() { - auto data = this->BinaryDirectory.toLocal8Bit().data(); + std::string data = this->BinaryDirectory.toLocal8Bit().data(); auto possible = this->CMakeInstance->Open(data, true); emit openPossible(possible); } diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index ee89b0d..8789f6e 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -124,13 +124,13 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } this->CacheMajorVersion = 0; this->CacheMinorVersion = 0; - if (const std::string* cmajor = + if (cmProp cmajor = this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) { unsigned int v = 0; if (sscanf(cmajor->c_str(), "%u", &v) == 1) { this->CacheMajorVersion = v; } - if (const std::string* cminor = + if (cmProp cminor = this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) { if (sscanf(cminor->c_str(), "%u", &v) == 1) { this->CacheMinorVersion = v; @@ -150,8 +150,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } // check to make sure the cache directory has not // been moved - const std::string* oldDir = - this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + cmProp oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); if (internal && oldDir) { std::string currentcwd = path; std::string oldcwd = *oldDir; @@ -159,8 +158,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, currentcwd += "/CMakeCache.txt"; oldcwd += "/CMakeCache.txt"; if (!cmSystemTools::SameFile(oldcwd, currentcwd)) { - const std::string* dir = - this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + cmProp dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); std::ostringstream message; message << "The current CMakeCache.txt directory " << currentcwd << " is different than the directory " << (dir ? *dir : "") @@ -210,7 +208,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, cmMessenger* messenger) { for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) { - if (const char* value = i.GetProperty(*p)) { + if (cmProp value = i.GetProperty(*p)) { std::string helpstring = cmStrCat(*p, " property for variable: ", i.GetName()); cmCacheManager::OutputHelpString(os, helpstring); @@ -218,9 +216,9 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, std::string key = cmStrCat(i.GetName(), '-', *p); cmCacheManager::OutputKey(os, key); os << ":INTERNAL="; - cmCacheManager::OutputValue(os, value); + cmCacheManager::OutputValue(os, *value); os << "\n"; - cmCacheManager::OutputNewlineTruncationWarning(os, key, value, + cmCacheManager::OutputNewlineTruncationWarning(os, key, *value, messenger); } } @@ -305,8 +303,8 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) */ } else if (t != cmStateEnums::INTERNAL) { // Format is key:type=value - if (const char* help = ce.GetProperty("HELPSTRING")) { - cmCacheManager::OutputHelpString(fout, help); + if (cmProp help = ce.GetProperty("HELPSTRING")) { + cmCacheManager::OutputHelpString(fout, *help); } else { cmCacheManager::OutputHelpString(fout, "Missing description"); } @@ -336,8 +334,8 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) this->WritePropertyEntries(fout, i, messenger); if (t == cmStateEnums::INTERNAL) { // Format is key:type=value - if (const char* help = i.GetProperty("HELPSTRING")) { - cmCacheManager::OutputHelpString(fout, help); + if (cmProp help = i.GetProperty("HELPSTRING")) { + cmCacheManager::OutputHelpString(fout, *help); } cmCacheManager::OutputKey(fout, i.GetName()); fout << ":" << cmState::CacheEntryTypeToString(t) << "="; @@ -508,8 +506,7 @@ cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator() return { *this, nullptr }; } -const std::string* cmCacheManager::GetInitializedCacheValue( - const std::string& key) const +cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const { auto i = this->Cache.find(key); if (i != this->Cache.end() && i->second.Initialized) { @@ -619,17 +616,15 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const return this->Properties.GetKeys(); } -const char* cmCacheManager::CacheEntry::GetProperty( - const std::string& prop) const +cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const { if (prop == "TYPE") { - return cmState::CacheEntryTypeToString(this->Type).c_str(); + return &cmState::CacheEntryTypeToString(this->Type); } if (prop == "VALUE") { - return this->Value.c_str(); + return &this->Value; } - cmProp retVal = this->Properties.GetPropertyValue(prop); - return retVal ? retVal->c_str() : nullptr; + return this->Properties.GetPropertyValue(prop); } void cmCacheManager::CacheEntry::SetProperty(const std::string& prop, @@ -663,7 +658,7 @@ void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop, } } -const char* cmCacheManager::CacheIterator::GetProperty( +cmProp cmCacheManager::CacheIterator::GetProperty( const std::string& prop) const { if (!this->IsAtEnd()) { @@ -692,8 +687,8 @@ void cmCacheManager::CacheIterator::AppendProperty(const std::string& p, bool cmCacheManager::CacheIterator::GetPropertyAsBool( const std::string& prop) const { - if (const char* value = this->GetProperty(prop)) { - return cmIsOn(value); + if (cmProp value = this->GetProperty(prop)) { + return cmIsOn(*value); } return false; } diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index d8be991..3db76a9 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -37,7 +37,7 @@ private: cmStateEnums::CacheEntryType Type = cmStateEnums::UNINITIALIZED; cmPropertyMap Properties; std::vector<std::string> GetPropertyList() const; - const char* GetProperty(const std::string&) const; + cmProp GetProperty(const std::string&) const; void SetProperty(const std::string& property, const char* value); void AppendProperty(const std::string& property, const std::string& value, bool asString = false); @@ -54,7 +54,7 @@ public: void Next(); std::string GetName() const { return this->Position->first; } std::vector<std::string> GetPropertyList() const; - const char* GetProperty(const std::string&) const; + cmProp GetProperty(const std::string&) const; bool GetPropertyAsBool(const std::string&) const; bool PropertyExists(const std::string&) const; void SetProperty(const std::string& property, const char* value); @@ -121,19 +121,19 @@ public: int GetSize() { return static_cast<int>(this->Cache.size()); } //! Get a value from the cache given a key - const std::string* GetInitializedCacheValue(const std::string& key) const; + cmProp GetInitializedCacheValue(const std::string& key) const; - const char* GetCacheEntryValue(const std::string& key) + cmProp GetCacheEntryValue(const std::string& key) { cmCacheManager::CacheIterator it = this->GetCacheIterator(key); if (it.IsAtEnd()) { return nullptr; } - return it.GetValue().c_str(); + return &it.GetValue(); } - const char* GetCacheEntryProperty(std::string const& key, - std::string const& propName) + cmProp GetCacheEntryProperty(std::string const& key, + std::string const& propName) { return this->GetCacheIterator(key).GetProperty(propName); } diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index da04396..9c26f61 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -101,29 +101,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->SrcFileSignature = true; cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE; - const char* tt = - this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); - if (!isTryRun && tt && *tt) { - if (strcmp(tt, cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) == - 0) { + const std::string* tt = + this->Makefile->GetDef("CMAKE_TRY_COMPILE_TARGET_TYPE"); + if (!isTryRun && tt && !tt->empty()) { + if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) { targetType = cmStateEnums::EXECUTABLE; - } else if (strcmp(tt, - cmState::GetTargetTypeName( - cmStateEnums::STATIC_LIBRARY)) == 0) { + } else if (*tt == + cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) { targetType = cmStateEnums::STATIC_LIBRARY; } else { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - std::string("Invalid value '") + tt + - "' for " - "CMAKE_TRY_COMPILE_TARGET_TYPE. Only " - "'" + - cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) + - "' and " - "'" + - cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY) + - "' " - "are allowed."); + cmStrCat("Invalid value '", *tt, + "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '", + cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE), + "' and '", + cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY), + "' are allowed.")); return -1; } } @@ -296,12 +290,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, default: this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "Only libraries may be used as try_compile or try_run IMPORTED " - "LINK_LIBRARIES. Got " + - std::string(tgt->GetName()) + - " of " - "type " + - cmState::GetTargetTypeName(tgt->GetType()) + "."); + cmStrCat("Only libraries may be used as try_compile or try_run " + "IMPORTED LINK_LIBRARIES. Got ", + tgt->GetName(), " of type ", + cmState::GetTargetTypeName(tgt->GetType()), ".")); return -1; } if (tgt->IsImported()) { diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 63c6680..53bd1d5 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -974,7 +974,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // Expand rule variables referenced in the given launcher command. cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = target->GetName().c_str(); - vars.CMTargetType = cmState::GetTargetTypeName(target->GetType()); + vars.CMTargetType = + cmState::GetTargetTypeName(target->GetType()).c_str(); std::string output; const std::vector<std::string>& outputs = ccg.GetOutputs(); if (!outputs.empty()) { diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 0471a45..4fe10ad 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -547,7 +547,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); + cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); vars.Language = linkLanguage.c_str(); vars.Objects = buildObjs.c_str(); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index d3f3a4f..4434f1d 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -756,7 +756,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); + cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); vars.Language = linkLanguage.c_str(); vars.AIXExports = aixExports.c_str(); vars.Objects = buildObjs.c_str(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 451f19e..f95d233 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -639,7 +639,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); + cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); vars.Language = lang.c_str(); vars.Target = targetOutPathReal.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 062c46c..9c4ff83 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -156,23 +156,25 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule( const std::string& config) const { - return this->TargetLinkLanguage(config) + "_" + - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + - "_LINKER__" + + return cmStrCat( + this->TargetLinkLanguage(config), "_", + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()), + "_LINKER__", cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()) + - "_" + config; + this->GetGeneratorTarget()->GetName()), + "_", config); } std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( const std::string& config) const { - return this->TargetLinkLanguage(config) + "_" + - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + - "_DEVICE_LINKER__" + + return cmStrCat( + this->TargetLinkLanguage(config), "_", + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()), + "_DEVICE_LINKER__", cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()) + - "_" + config; + this->GetGeneratorTarget()->GetName()), + "_", config); } struct cmNinjaRemoveNoOpCommands @@ -191,7 +193,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()); + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + .c_str(); vars.Language = "CUDA"; @@ -282,7 +285,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, cmNinjaRule rule(std::move(linkRuleName)); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); - vars.CMTargetType = cmState::GetTargetTypeName(targetType); + vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str(); std::string lang = this->TargetLinkLanguage(config); vars.Language = config.c_str(); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0e1136f..8833fa4 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -495,7 +495,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()); + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str(); vars.Language = lang.c_str(); vars.Source = "$in"; vars.Object = "$out"; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index bc08223..6d95c7a 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -34,30 +34,44 @@ cmState::cmState() cmState::~cmState() = default; -const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType) -{ +const std::string& cmState::GetTargetTypeName( + cmStateEnums::TargetType targetType) +{ +#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(STATIC_LIBRARY); + MAKE_STATIC_PROP(MODULE_LIBRARY); + MAKE_STATIC_PROP(SHARED_LIBRARY); + MAKE_STATIC_PROP(OBJECT_LIBRARY); + MAKE_STATIC_PROP(EXECUTABLE); + MAKE_STATIC_PROP(UTILITY); + MAKE_STATIC_PROP(GLOBAL_TARGET); + MAKE_STATIC_PROP(INTERFACE_LIBRARY); + MAKE_STATIC_PROP(UNKNOWN_LIBRARY); + static const std::string propEmpty; +#undef MAKE_STATIC_PROP + switch (targetType) { case cmStateEnums::STATIC_LIBRARY: - return "STATIC_LIBRARY"; + return propSTATIC_LIBRARY; case cmStateEnums::MODULE_LIBRARY: - return "MODULE_LIBRARY"; + return propMODULE_LIBRARY; case cmStateEnums::SHARED_LIBRARY: - return "SHARED_LIBRARY"; + return propSHARED_LIBRARY; case cmStateEnums::OBJECT_LIBRARY: - return "OBJECT_LIBRARY"; + return propOBJECT_LIBRARY; case cmStateEnums::EXECUTABLE: - return "EXECUTABLE"; + return propEXECUTABLE; case cmStateEnums::UTILITY: - return "UTILITY"; + return propUTILITY; case cmStateEnums::GLOBAL_TARGET: - return "GLOBAL_TARGET"; + return propGLOBAL_TARGET; case cmStateEnums::INTERFACE_LIBRARY: - return "INTERFACE_LIBRARY"; + return propINTERFACE_LIBRARY; case cmStateEnums::UNKNOWN_LIBRARY: - return "UNKNOWN_LIBRARY"; + return propUNKNOWN_LIBRARY; } assert(false && "Unexpected target type"); - return nullptr; + return propEmpty; } static const std::array<std::string, 7> cmCacheEntryTypes = { @@ -199,7 +213,8 @@ const char* cmState::GetCacheEntryProperty(std::string const& key, if (!it.PropertyExists(propertyName)) { return nullptr; } - return it.GetProperty(propertyName); + cmProp retVal = it.GetProperty(propertyName); + return retVal ? retVal->c_str() : nullptr; } bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, diff --git a/Source/cmState.h b/Source/cmState.h index b577a72..89400d6 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -53,7 +53,8 @@ public: CPack, }; - static const char* GetTargetTypeName(cmStateEnums::TargetType targetType); + static const std::string& GetTargetTypeName( + cmStateEnums::TargetType targetType); cmStateSnapshot CreateBaseSnapshot(); cmStateSnapshot CreateBuildsystemDirectorySnapshot( diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 03f1525..872f02c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1668,7 +1668,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const } // the type property returns what type the target is if (prop == propTYPE) { - return cmState::GetTargetTypeName(this->GetType()); + return cmState::GetTargetTypeName(this->GetType()).c_str(); } if (prop == propINCLUDE_DIRECTORIES) { if (impl->IncludeDirectoriesEntries.empty()) { diff --git a/Tests/FindRuby/CMakeLists.txt b/Tests/FindRuby/CMakeLists.txt index 193cb4f..3f4807c 100644 --- a/Tests/FindRuby/CMakeLists.txt +++ b/Tests/FindRuby/CMakeLists.txt @@ -24,7 +24,7 @@ if(CMake_TEST_FindRuby) --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) set_tests_properties(FindRuby.Fail PROPERTIES - PASS_REGULAR_EXPRESSION "Could NOT find Ruby: Found unsuitable version \".*\", but required is.*least \"[0-9]+\\.[0-9]+\\.[0-9]+\" \\(found .*\\)") + PASS_REGULAR_EXPRESSION "Could NOT find Ruby.*(Required is at least version \"[0-9]+\\.[0-9]+\\.[0-9]+\")") # Looks for 1.9.9 EXACTLY, which unlike the "FindRuby" test above will fail on every machine # since this version doesn't exist (ruby goes from 1.9.3 to 2.0.0) @@ -41,4 +41,17 @@ if(CMake_TEST_FindRuby) set_tests_properties(FindRuby.FailExact PROPERTIES PASS_REGULAR_EXPRESSION "Could NOT find Ruby: Found unsuitable version \".*\", but required is.*exact version \"[0-9]+\\.[0-9]+\\.[0-9]+\" \\(found .*\\)") + # RVM specific test + if(CMake_TEST_FindRuby_RVM) + add_test(NAME FindRuby.Rvm COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindRuby/Rvm" + "${CMake_BINARY_DIR}/Tests/FindRuby/Rvm" + ${build_generator_args} + --build-project TestRVM + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + endif() endif() diff --git a/Tests/FindRuby/Rvm/CMakeLists.txt b/Tests/FindRuby/Rvm/CMakeLists.txt new file mode 100644 index 0000000..545fc94 --- /dev/null +++ b/Tests/FindRuby/Rvm/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.17) +project(TestRVM LANGUAGES NONE) + +include(CTest) + +# To run this test, you need to have at least one RVM ruby installed +# and to ensure that the env variable 'MY_RUBY_HOME' is set to a valid RVM ruby when you run the test +# (which is the case if you have done `rvm use x.y.z`, but could be manually set too) + +# Properly using rvm would require sourcing a shell script, eg `source "$HOME/.rvm/scripts/rvm"` +# Instead, I'll just rely on the env variable MY_RUBY_HOME +set(MY_RUBY_HOME "$ENV{MY_RUBY_HOME}") +if(NOT MY_RUBY_HOME) + message(FATAL_ERROR "Env variable MY_RUBY_HOME should be set to a valid RVM ruby location, or you should call `rvm use x.y.z` before") +endif() +execute_process (COMMAND "${MY_RUBY_HOME}/bin/ruby" -e "puts RUBY_VERSION" + RESULT_VARIABLE result + OUTPUT_VARIABLE RVM_RUBY_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if (result) + message (FATAL_ERROR "Unable to detect RVM ruby version from `${MY_RUBY_HOME}/bin/ruby`: ${RVM_RUBY_VERSION}") +endif() + +execute_process(COMMAND "${CMAKE_COMMAND}" -E env --unset=MY_RUBY_HOME --unset=PATH + "which" "ruby" + RESULT_VARIABLE result + OUTPUT_VARIABLE SYSTEM_RUBY + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if (SYSTEM_RUBY MATCHES "^${MY_RUBY_HOME}/.+") + message(FATAL_ERROR "Unable to find system ruby, found ${SYSTEM_RUBY} which is part of MY_RUBY_HOME=${MY_RUBY_HOME}") +endif() + +# Check version of the system ruby executable. +execute_process (COMMAND "${SYSTEM_RUBY}" -e "puts RUBY_VERSION" + RESULT_VARIABLE result + OUTPUT_VARIABLE SYSTEM_RUBY_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if (result) + message (FATAL_ERROR "Unable to detect system ruby version from '${SYSTEM_RUBY}': ${SYSTEM_RUBY_VERSION}") +endif() + +if(SYSTEM_RUBY_VERSION VERSION_EQUAL RVM_RUBY_VERSION) + message(FATAL_ERROR "Your RVM Ruby Version and your System ruby version are the same (${RVM_RUBY_VERSION}).") +endif() + +message("Found System Ruby (${SYSTEM_RUBY_VERSION}): ${SYSTEM_RUBY}") +message("Found RVM Ruby (${RVM_RUBY_VERSION}): ${MY_RUBY_HOME}/bin/ruby") + +add_test(NAME FindRuby.RvmDefault + COMMAND "${CMAKE_COMMAND}" -E env "MY_RUBY_HOME=${MY_RUBY_HOME}" + "${CMAKE_COMMAND}" "-DRUBY_HOME=${MY_RUBY_HOME}" + -P "${CMAKE_CURRENT_LIST_DIR}/RvmDefault.cmake") + +add_test(NAME FindRuby.RvmOnly + COMMAND "${CMAKE_COMMAND}" -E env --unset=PATH + "MY_RUBY_HOME=${MY_RUBY_HOME}" + "${CMAKE_COMMAND}" "-DRUBY_HOME=${MY_RUBY_HOME}" + "-DRVM_RUBY_VERSION=${RVM_RUBY_VERSION}" "-DSYSTEM_RUBY_VERSION=${SYSTEM_RUBY_VERSION}" + -P "${CMAKE_CURRENT_LIST_DIR}/RvmOnly.cmake") +add_test(NAME FindRuby.UnsetRvmOnly + COMMAND "${CMAKE_COMMAND}" -E env --unset=MY_RUBY_HOME "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" + "${CMAKE_COMMAND}" "-DRVM_RUBY_VERSION=${RVM_RUBY_VERSION}" "-DSYSTEM_RUBY_VERSION=${SYSTEM_RUBY_VERSION}" + -P "${CMAKE_CURRENT_LIST_DIR}/RvmOnly.cmake") + +add_test(NAME FindRuby.RvmStandard + COMMAND "${CMAKE_COMMAND}" -E env "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" + "MY_RUBY_HOME=${MY_RUBY_HOME}" + "${CMAKE_COMMAND}" "-DRUBY_HOME=${MY_RUBY_HOME}" + -P "${CMAKE_CURRENT_LIST_DIR}/RvmStandard.cmake") diff --git a/Tests/FindRuby/Rvm/RvmDefault.cmake b/Tests/FindRuby/Rvm/RvmDefault.cmake new file mode 100644 index 0000000..a66b911 --- /dev/null +++ b/Tests/FindRuby/Rvm/RvmDefault.cmake @@ -0,0 +1,17 @@ +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES "") + +find_package (Ruby 2.1.1 REQUIRED) +if (NOT RUBY_EXECUTABLE MATCHES "^${RUBY_HOME}/.+") + message (FATAL_ERROR "Failed to use RVM environment: ${RUBY_EXECUTABLE}, ${RUBY_HOME}") +endif() + +find_package (Ruby 2.1 REQUIRED) +if (NOT RUBY_EXECUTABLE MATCHES "^${RUBY_HOME}/.+") + message (FATAL_ERROR "Failed to use RVM environment: ${RUBY_EXECUTABLE}, ${RUBY_HOME}") +endif() + +find_package (Ruby REQUIRED) +if (NOT RUBY_EXECUTABLE MATCHES "^${RUBY_HOME}/.+") + message (FATAL_ERROR "Failed to use RVM environment: ${RUBY_EXECUTABLE}, ${RUBY_HOME}") +endif() diff --git a/Tests/FindRuby/Rvm/RvmOnly.cmake b/Tests/FindRuby/Rvm/RvmOnly.cmake new file mode 100644 index 0000000..3851a7c --- /dev/null +++ b/Tests/FindRuby/Rvm/RvmOnly.cmake @@ -0,0 +1,41 @@ +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES "") + +set(Ruby_FIND_VIRTUALENV ONLY) + +# Test: FindRuby.RvmOnly +if (RUBY_HOME) + # => Trying to find exactly system ruby using ONLY virtual environment should fail + find_package (Ruby ${SYSTEM_RUBY_VERSION} EXACT QUIET) + if(Ruby_FOUND) + message (FATAL_ERROR "Ruby unexpectedly found.") + endif() + # And should work to find the rvm version + find_package (Ruby ${RVM_RUBY_VERSION} EXACT QUIET) + if(Ruby_FOUND) + message (FATAL_ERROR "Ruby unexpectedly found.") + endif() +endif() + + +# Test: FindRuby.UnsetRvmOnly +if (NOT RUBY_HOME) + + # If ENV{MY_RUBY_HOME} isn't defined, it should default back to "STANDARD" + # At which point: + + # It shouldn't find the RVM ruby + find_package (Ruby ${RVM_RUBY_VERSION} EXACT QUIET) + if(Ruby_FOUND) + message(FATAL_ERROR "Found RVM ruby when expecting system") + endif() + + # it should find the system ruby + find_package (Ruby ${SYSTEM_RUBY_VERSION} EXACT QUIET) + if(NOT Ruby_FOUND) + message (FATAL_ERROR "Ruby not found.") + endif() + if (Ruby_FOUND MATCHES "^${RUBY_HOME}/.+") + message(FATAL_ERROR "Failed to find system ruby") + endif() +endif() diff --git a/Tests/FindRuby/Rvm/RvmStandard.cmake b/Tests/FindRuby/Rvm/RvmStandard.cmake new file mode 100644 index 0000000..26befdb7 --- /dev/null +++ b/Tests/FindRuby/Rvm/RvmStandard.cmake @@ -0,0 +1,9 @@ +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES "") + +set (Ruby_FIND_VIRTUALENV STANDARD) +find_package (Ruby REQUIRED) + +if (RUBY_EXECUTABLE MATCHES "^${RUBY_HOME}/.+") + message (FATAL_ERROR "RVM ruby unexpectedly found at ${RUBY_EXECUTABLE}, matches ${RUBY_HOME}") +endif() |