Browse Source

FindRuby: Add rbenv support

cfis 11 months ago
parent
commit
ef2c3ca828

+ 1 - 0
.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 "")

+ 1 - 0
.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 "")

+ 58 - 17
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:
-
-  * ``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...)
+  .. versionadded:: 3.18
+
+  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

+ 14 - 0
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 $<CONFIGURATION>
+      --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 $<CONFIGURATION>
+      )
+  endif()
+
   # RVM specific test
   if(CMake_TEST_FindRuby_RVM)
     add_test(NAME FindRuby.Rvm COMMAND

+ 77 - 0
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")

+ 28 - 0
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()

+ 29 - 0
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()

+ 29 - 0
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()

+ 1 - 0
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)