diff --git a/.gitlab/ci/configure_debian12_ninja_common.cmake b/.gitlab/ci/configure_debian12_ninja_common.cmake index 751a6c8089..3912daabde 100644 --- a/.gitlab/ci/configure_debian12_ninja_common.cmake +++ b/.gitlab/ci/configure_debian12_ninja_common.cmake @@ -89,6 +89,7 @@ set(CMake_TEST_FindPython3 "ON" CACHE BOOL "") set(CMake_TEST_FindPython3_IronPython "ON" CACHE BOOL "") set(CMake_TEST_FindPython3_PyPy "ON" CACHE BOOL "") set(CMake_TEST_FindRuby "ON" CACHE BOOL "") +#set(CMake_TEST_FindRuby_RBENV "ON" CACHE BOOL "") # fails because system and rbenv versions are same set(CMake_TEST_FindRuby_RVM "ON" CACHE BOOL "") set(CMake_TEST_FindSDL "ON" CACHE BOOL "") set(CMake_TEST_FindSQLite3 "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora41_makefiles.cmake b/.gitlab/ci/configure_fedora41_makefiles.cmake index de57fded34..2a57087c35 100644 --- a/.gitlab/ci/configure_fedora41_makefiles.cmake +++ b/.gitlab/ci/configure_fedora41_makefiles.cmake @@ -88,6 +88,7 @@ set(CMake_TEST_FindPython3_NumPy "ON" CACHE BOOL "") set(CMake_TEST_FindPython2_PyPy "ON" CACHE BOOL "") set(CMake_TEST_FindPython3_PyPy "ON" CACHE BOOL "") set(CMake_TEST_FindRuby "ON" CACHE BOOL "") +set(CMake_TEST_FindRuby_RBENV "ON" CACHE BOOL "") set(CMake_TEST_FindRuby_RVM "ON" CACHE BOOL "") set(CMake_TEST_FindSDL "ON" CACHE BOOL "") set(CMake_TEST_FindSQLite3 "ON" CACHE BOOL "") diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index c967839506..343ce6c180 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -17,8 +17,7 @@ standard syntax, e.g. # OR find_package(Ruby 3.2) -Virtual environments such as RVM are handled as well, by passing -the argument ``Ruby_FIND_VIRTUALENV`` +Virtual environments, such as RVM or RBENV, are supported. Result Variables ^^^^^^^^^^^^^^^^ @@ -64,23 +63,26 @@ This module will set the following variables in your project: Hints ^^^^^ -.. versionadded:: 3.18 - ``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: + .. versionadded:: 3.18 - * ``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...) + This variable defines the handling of virtual environments. + It can be left empty or be set to one of the following values: + * ``FIRST``: Virtual Ruby environments are searched for first, + then the system Ruby installation. + This is the default. + * ``ONLY``: Only virtual environments are searched + * ``STANDARD``: Only the system Ruby installation is searched. + + Virtual environments may be provided by: + + ``rvm`` + Requires that the ``MY_RUBY_HOME`` environment environment is defined. + + ``rbenv`` + Requires that ``rbenv`` is installed in ``~/.rbenv/bin`` + or that the ``RBENV_ROOT`` environment variable is defined. #]=======================================================================] # Backwards compatibility @@ -202,6 +204,40 @@ function (_RUBY_CHECK_RVM) endif() endfunction() +#### Check RBENV virtual environment ### +function (_RUBY_CHECK_RBENV) + find_program (Ruby_RBENV_EXECUTABLE + NAMES rbenv + NAMES_PER_DIR + PATHS "$ENV{HOME}/.rbenv/bin/rbenv" ENV RBENV_ROOT + PATH_SUFFIXES bin Scripts + NO_CACHE + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + + execute_process (COMMAND "${Ruby_RBENV_EXECUTABLE}" "which" "ruby" + RESULT_VARIABLE result + OUTPUT_VARIABLE ruby_exe + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT result EQUAL 0) + return() + endif() + cmake_path(GET ruby_exe PARENT_PATH ruby_dir) + + find_program (Ruby_EXECUTABLE + NAMES ruby + NAMES_PER_DIR + PATHS ${ruby_dir} + VALIDATOR _RUBY_VALIDATE_INTERPRETER + NO_DEFAULT_PATH) + + if(Ruby_EXECUTABLE) + set(Ruby_ENV "RBENV" CACHE INTERNAL "Ruby environment") + endif() +endfunction() + #### Check system installed Ruby ### function (_RUBY_CHECK_SYSTEM) find_program (Ruby_EXECUTABLE @@ -216,7 +252,12 @@ endfunction() # Find Ruby if(NOT Ruby_EXECUTABLE AND Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") + # First check for RVM virtual environments _RUBY_CHECK_RVM() + # Second check for RBENV virtual environments + if(NOT Ruby_EXECUTABLE) + _RUBY_CHECK_RBENV() + endif() endif() # Check for system installed Ruby diff --git a/Tests/FindRuby/CMakeLists.txt b/Tests/FindRuby/CMakeLists.txt index a6f602c866..a6de4d69af 100644 --- a/Tests/FindRuby/CMakeLists.txt +++ b/Tests/FindRuby/CMakeLists.txt @@ -41,6 +41,20 @@ if(CMake_TEST_FindRuby) set_tests_properties(FindRuby.FailExact PROPERTIES PASS_REGULAR_EXPRESSION "Could NOT find Ruby.*Required[ \n]+is[ \n]+exact[ \n]+version[ \n]+\"1\\.9\\.9\"") + # RBENV specific test + if(CMake_TEST_FindRuby_RBENV) + add_test(NAME FindRuby.Rbenv COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindRuby/Rbenv" + "${CMake_BINARY_DIR}/Tests/FindRuby/Rbenv" + ${build_generator_args} + --build-project TestRBENV + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) + endif() + # RVM specific test if(CMake_TEST_FindRuby_RVM) add_test(NAME FindRuby.Rvm COMMAND diff --git a/Tests/FindRuby/Rbenv/CMakeLists.txt b/Tests/FindRuby/Rbenv/CMakeLists.txt new file mode 100644 index 0000000000..3994c684a8 --- /dev/null +++ b/Tests/FindRuby/Rbenv/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.31) +project(TestRBENV LANGUAGES NONE) + +include(CTest) + +# Test environment has RBENV_ROOT setup +find_program (rbenv + NAMES rbenv + NAMES_PER_DIR + PATHS "$ENV{HOME}/.rbenv/bin/rbenv" ENV RBENV_ROOT + PATH_SUFFIXES bin Scripts + NO_CACHE) +execute_process (COMMAND "${rbenv}" "which" "ruby" + RESULT_VARIABLE result + OUTPUT_VARIABLE RBENV_RUBY + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + +# Make sure we found a valid Ruby interpreter +if(NOT RBENV_RUBY) + message(FATAL_ERROR "Unable to find RBENV using RBENV_ROOT ${RBENV_ROOT}") +endif() + +# Get the version of rbenv Ruby +execute_process (COMMAND "${RBENV_RUBY}" -e "puts RUBY_VERSION" + RESULT_VARIABLE result + OUTPUT_VARIABLE RBENV_RUBY_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if (result) + message (FATAL_ERROR "Unable to detect rbenv ruby version from '${RBENV_RUBY}': ${RBENV_RUBY_VERSION}") +endif() + +# Find system Ruby +execute_process(COMMAND "${CMAKE_COMMAND}" -E env PATH=/usr/bin:/bin "which" "ruby" + RESULT_VARIABLE result + OUTPUT_VARIABLE SYSTEM_RUBY + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if (SYSTEM_RUBY MATCHES "${RBENV_RUBY}") + message(FATAL_ERROR "System Ruby (${SYSTEM_RUBY}) matches rbenv Ruby (${RBENV_RUBY})") +endif() + +# Get version of the system Ruby +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 RBENV_RUBY_VERSION) + message(FATAL_ERROR "Your RBENV Ruby Version and standard ruby version are the same (${RBENV_RUBY_VERSION}).") +endif() + +message(STATUS "Found standard Ruby (${SYSTEM_RUBY_VERSION}): ${SYSTEM_RUBY}") +message(STATUS "Found rbenv Ruby (${RBENV_RUBY_VERSION}): ${RBENV_RUBY}") + +add_test(NAME FindRuby.RbenvDefault + COMMAND "${CMAKE_COMMAND}" -E env "RBENV_ROOT=$ENV{RBENV_ROOT}" + "${CMAKE_COMMAND}" "-DRBENV_RUBY=${RBENV_RUBY}" "-DSYSTEM_RUBY=${SYSTEM_RUBY}" "-DRBENV_RUBY_VERSION=${RBENV_RUBY_VERSION}" "-DSYSTEM_RUBY_VERSION=${SYSTEM_RUBY_VERSION}" + -P "${CMAKE_CURRENT_LIST_DIR}/RbenvDefault.cmake") + +add_test(NAME FindRuby.RbenvOnly + COMMAND "${CMAKE_COMMAND}" -E env "RBENV_ROOT=$ENV{RBENV_ROOT}" + "${CMAKE_COMMAND}" "-DRBENV_RUBY=${RBENV_RUBY}" "-DSYSTEM_RUBY=${SYSTEM_RUBY}" "-DRBENV_RUBY_VERSION=${RBENV_RUBY_VERSION}" "-DSYSTEM_RUBY_VERSION=${SYSTEM_RUBY_VERSION}" + -P "${CMAKE_CURRENT_LIST_DIR}/RbenvOnly.cmake") + +add_test(NAME FindRuby.RbenvStandard + COMMAND "${CMAKE_COMMAND}" -E env "RBENV_ROOT=$ENV{RBENV_ROOT}" + "${CMAKE_COMMAND}" "-DRBENV_RUBY=${RBENV_RUBY}" "-DSYSTEM_RUBY=${SYSTEM_RUBY}" "-DRBENV_RUBY_VERSION=${RBENV_RUBY_VERSION}" "-DSYSTEM_RUBY_VERSION=${SYSTEM_RUBY_VERSION}" + -P "${CMAKE_CURRENT_LIST_DIR}/RbenvStandard.cmake") diff --git a/Tests/FindRuby/Rbenv/RbenvDefault.cmake b/Tests/FindRuby/Rbenv/RbenvDefault.cmake new file mode 100644 index 0000000000..86f2264568 --- /dev/null +++ b/Tests/FindRuby/Rbenv/RbenvDefault.cmake @@ -0,0 +1,28 @@ +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES "") + +unset(ENV{MY_RUBY_HOME}) # Suppress RVM code path for this test. + +# Should find rbenv Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby REQUIRED) +if (NOT "${Ruby_EXECUTABLE}" STREQUAL "${RBENV_RUBY}") + message (FATAL_ERROR "Failed to find rbenv Ruby: ${Ruby_EXECUTABLE}") +endif() + +# Should find rbenv Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby ${RBENV_RUBY_VERSION} REQUIRED) +if (NOT Ruby_EXECUTABLE MATCHES "${RBENV_RUBY}") + message (FATAL_ERROR "Failed to find rbenv Ruby: ${Ruby_EXECUTABLE}") +endif() + +# Should find standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby ${SYSTEM_RUBY_VERSION} EXACT) +if (NOT Ruby_EXECUTABLE STREQUAL "${SYSTEM_RUBY}") + message (FATAL_ERROR "Failed to find system Ruby: ${Ruby_EXECUTABLE}") +endif() diff --git a/Tests/FindRuby/Rbenv/RbenvOnly.cmake b/Tests/FindRuby/Rbenv/RbenvOnly.cmake new file mode 100644 index 0000000000..b524596d6b --- /dev/null +++ b/Tests/FindRuby/Rbenv/RbenvOnly.cmake @@ -0,0 +1,29 @@ +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES "") + +set(Ruby_FIND_VIRTUALENV ONLY) +unset(ENV{MY_RUBY_HOME}) # Suppress RVM code path for this test. + +# We should find the rbenv Ruby not standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby QUIET) +if (NOT Ruby_EXECUTABLE STREQUAL "${RBENV_RUBY}") + message (FATAL_ERROR "Failed to find rbenv Ruby: ${Ruby_EXECUTABLE}") +endif() + +# We should find the rbenv Ruby not standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby ${RBENV_RUBY_VERSION} QUIET) +if (NOT Ruby_EXECUTABLE STREQUAL "${RBENV_RUBY}") + message (FATAL_ERROR "Failed to find rbenv Ruby: ${Ruby_EXECUTABLE}") +endif() + +# We should not find standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby ${SYSTEM_RUBY_VERSION} EXACT QUIET) +if (NOT Ruby_EXECUTABLE STREQUAL "Ruby_EXECUTABLE-NOTFOUND") + message (FATAL_ERROR "Incorrectly found Ruby: ${Ruby_EXECUTABLE}") +endif() diff --git a/Tests/FindRuby/Rbenv/RbenvStandard.cmake b/Tests/FindRuby/Rbenv/RbenvStandard.cmake new file mode 100644 index 0000000000..75cff89527 --- /dev/null +++ b/Tests/FindRuby/Rbenv/RbenvStandard.cmake @@ -0,0 +1,29 @@ +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES "") + +set (Ruby_FIND_VIRTUALENV STANDARD) +unset(ENV{MY_RUBY_HOME}) # Suppress RVM code path for this test. + +# We should find the standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby QUIET) +if (NOT Ruby_EXECUTABLE STREQUAL "${SYSTEM_RUBY}") + message (FATAL_ERROR "Failed to find standard Ruby: ${Ruby_EXECUTABLE}") +endif() + +# We should not find the rbenv Ruby or standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby ${RBENV_RUBY_VERSION} EXACT QUIET) +if (NOT Ruby_EXECUTABLE STREQUAL "Ruby_EXECUTABLE-NOTFOUND") + message (FATAL_ERROR "Incorrectly found rbenv Ruby: ${Ruby_EXECUTABLE}") +endif() + +# We should find standard Ruby +unset(Ruby_EXECUTABLE CACHE) +unset(RUBY_EXECUTABLE) # compatibility variable +find_package (Ruby ${SYSTEM_RUBY_VERSION} EXACT QUIET) +if (NOT Ruby_EXECUTABLE MATCHES "${SYSTEM_RUBY}") + message (FATAL_ERROR "Failed to find standard Ruby: ${Ruby_EXECUTABLE}") +endif() diff --git a/Tests/FindRuby/Rvm/RvmOnly.cmake b/Tests/FindRuby/Rvm/RvmOnly.cmake index 86b32db250..d47a880fe8 100644 --- a/Tests/FindRuby/Rvm/RvmOnly.cmake +++ b/Tests/FindRuby/Rvm/RvmOnly.cmake @@ -2,6 +2,7 @@ set(CMAKE_FIND_LIBRARY_PREFIXES "") set(CMAKE_FIND_LIBRARY_SUFFIXES "") set(Ruby_FIND_VIRTUALENV ONLY) +set(Ruby_RBENV_EXECUTABLE "") # Suppress rbenv code path for this test. # Test: FindRuby.RvmOnly if (RUBY_HOME)