FindRuby: Add support for RVM installations

This commit is contained in:
Julien Marrec
2020-03-23 13:16:39 +01:00
parent e6699b9b59
commit 905d5667e8
6 changed files with 248 additions and 5 deletions

View File

@@ -22,6 +22,9 @@ standard syntax, e.g.
It also determines what the name of the library is. 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 Result Variables
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@@ -49,6 +52,28 @@ Also:
``Ruby_INCLUDE_PATH`` ``Ruby_INCLUDE_PATH``
same as Ruby_INCLUDE_DIRS, only provided for compatibility reasons, don't use it 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 # Backwards compatibility
@@ -121,8 +146,32 @@ if(NOT Ruby_FIND_VERSION_EXACT)
list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES) list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES)
endif() 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) if(_Ruby_DEBUG_OUTPUT)
message("_Ruby_POSSIBLE_EXECUTABLE_NAMES=${_Ruby_POSSIBLE_EXECUTABLE_NAMES}") message("_Ruby_POSSIBLE_EXECUTABLE_NAMES=${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
message("_Ruby_FIND_VIRTUALENV=${_Ruby_FIND_VIRTUALENV}")
endif() endif()
function (_RUBY_VALIDATE_INTERPRETER) function (_RUBY_VALIDATE_INTERPRETER)
@@ -164,11 +213,48 @@ function (_RUBY_VALIDATE_INTERPRETER)
endfunction() endfunction()
find_program (Ruby_EXECUTABLE while(1)
NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES} # Virtual environments handling
NAMES_PER_DIR if(_Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
) if(_Ruby_DEBUG_OUTPUT)
_RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}) 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) if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
function(_RUBY_CONFIG_VAR RBVAR OUTVAR) function(_RUBY_CONFIG_VAR RBVAR OUTVAR)
@@ -306,6 +392,8 @@ if(Ruby_VERSION_MAJOR)
set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}") set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}")
endif() 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 find_path(Ruby_INCLUDE_DIR
NAMES ruby.h NAMES ruby.h
HINTS HINTS

View File

@@ -41,4 +41,17 @@ if(CMake_TEST_FindRuby)
set_tests_properties(FindRuby.FailExact PROPERTIES 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 .*\\)") 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() endif()

View File

@@ -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")

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()