1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
10 This module finds if Ruby is installed and determines where the
11 include files and libraries are. Ruby 1.8 through 3.1 are
14 The minimum required version of Ruby can be specified using the
19 find_package(Ruby 2.5.1 EXACT REQUIRED)
21 find_package(Ruby 2.4)
23 It also determines what the name of the library is.
25 Virtual environments such as RVM are handled as well, by passing
26 the argument ``Ruby_FIND_VIRTUALENV``
31 This module will set the following variables in your project:
34 set to true if ruby was found successfully
36 full path to the ruby binary
38 include dirs to be used when using the ruby library
40 .. versionadded:: 3.18
41 libraries needed to use ruby from C.
43 the version of ruby which was found, e.g. "1.8.7"
44 ``Ruby_VERSION_MAJOR``
46 ``Ruby_VERSION_MINOR``
48 ``Ruby_VERSION_PATCH``
51 .. versionchanged:: 3.18
52 Previous versions of CMake used the ``RUBY_`` prefix for all variables.
53 The following variables are provided for compatibility reasons,
54 don't use them in new code:
57 same as Ruby_EXECUTABLE.
59 same as Ruby_INCLUDE_DIRS.
61 same as Ruby_INCLUDE_DIRS.
72 .. versionadded:: 3.18
75 Define the root directory of a Ruby installation.
77 ``Ruby_FIND_VIRTUALENV``
78 This variable defines the handling of virtual environments managed by
79 ``rvm``. It is meaningful only when a virtual environment
80 is active (i.e. the ``rvm`` script has been evaluated or at least the
81 ``MY_RUBY_HOME`` environment variable is set).
82 The ``Ruby_FIND_VIRTUALENV`` variable can be set to empty or
85 * ``FIRST``: The virtual environment is used before any other standard
86 paths to look-up for the interpreter. This is the default.
87 * ``ONLY``: Only the virtual environment is used to look-up for the
89 * ``STANDARD``: The virtual environment is not used to look-up for the
90 interpreter (assuming it isn't still in the PATH...)
92 #]=======================================================================]
94 # Backwards compatibility
95 # Define camel case versions of input variables
100 RUBY_CONFIG_INCLUDE_DIR
102 if (DEFINED ${UPPER})
103 string(REPLACE "RUBY_" "Ruby_" Camel ${UPPER})
104 if (NOT DEFINED ${Camel})
105 set(${Camel} ${${UPPER}})
110 # Ruby_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'`
111 # Ruby_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'`
112 # Ruby_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'`
113 # Ruby_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'`
114 # Ruby_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'`
116 # uncomment the following line to get debug output for this file
117 # set(_Ruby_DEBUG_OUTPUT TRUE)
119 # Determine the list of possible names of the ruby executable depending
120 # on which version of ruby is required
121 set(_Ruby_POSSIBLE_EXECUTABLE_NAMES ruby)
123 # If not specified, allow everything as far back as 1.8.0
124 if(NOT DEFINED Ruby_FIND_VERSION_MAJOR)
125 set(Ruby_FIND_VERSION "1.8.0")
126 set(Ruby_FIND_VERSION_MAJOR 1)
127 set(Ruby_FIND_VERSION_MINOR 8)
128 set(Ruby_FIND_VERSION_PATCH 0)
131 if(_Ruby_DEBUG_OUTPUT)
132 message("Ruby_FIND_VERSION=${Ruby_FIND_VERSION}")
133 message("Ruby_FIND_VERSION_MAJOR=${Ruby_FIND_VERSION_MAJOR}")
134 message("Ruby_FIND_VERSION_MINOR=${Ruby_FIND_VERSION_MINOR}")
135 message("Ruby_FIND_VERSION_PATCH=${Ruby_FIND_VERSION_PATCH}")
138 set(Ruby_FIND_VERSION_SHORT_NODOT "${Ruby_FIND_VERSION_MAJOR}${Ruby_FIND_VERSION_MINOR}")
140 # Set name of possible executables, ignoring the minor
142 # 2.1.1 => from ruby31 to ruby21 included
143 # 2.1 => from ruby31 to ruby21 included
144 # 2 => from ruby31 to ruby20 included
145 # empty => from ruby31 to ruby18 included
146 if(NOT Ruby_FIND_VERSION_EXACT)
148 foreach(_ruby_version RANGE 31 18 -1)
149 string(SUBSTRING "${_ruby_version}" 0 1 _ruby_major_version)
150 string(SUBSTRING "${_ruby_version}" 1 1 _ruby_minor_version)
152 if(NOT "${_ruby_major_version}${_ruby_minor_version}" VERSION_LESS ${Ruby_FIND_VERSION_SHORT_NODOT})
153 # Append both rubyX.Y and rubyXY (eg: ruby2.7 ruby27)
154 list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby${_ruby_major_version}.${_ruby_minor_version} ruby${_ruby_major_version}${_ruby_minor_version})
161 list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES)
164 # virtual environments handling (eg RVM)
165 if (DEFINED ENV{MY_RUBY_HOME})
166 if(_Ruby_DEBUG_OUTPUT)
167 message("My ruby home is defined: $ENV{MY_RUBY_HOME}")
170 if (DEFINED Ruby_FIND_VIRTUALENV)
171 if (NOT Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$")
172 message (AUTHOR_WARNING "FindRuby: ${Ruby_FIND_VIRTUALENV}: invalid value for 'Ruby_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.")
173 set (_Ruby_FIND_VIRTUALENV "FIRST")
175 set (_Ruby_FIND_VIRTUALENV ${Ruby_FIND_VIRTUALENV})
178 set (_Ruby_FIND_VIRTUALENV FIRST)
181 if (DEFINED Ruby_FIND_VIRTUALENV)
182 message("Environment variable MY_RUBY_HOME isn't set, defaulting back to Ruby_FIND_VIRTUALENV=STANDARD")
184 set (_Ruby_FIND_VIRTUALENV STANDARD)
187 if(_Ruby_DEBUG_OUTPUT)
188 message("_Ruby_POSSIBLE_EXECUTABLE_NAMES=${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
189 message("_Ruby_FIND_VIRTUALENV=${_Ruby_FIND_VIRTUALENV}")
192 function (_RUBY_VALIDATE_INTERPRETER)
193 if (NOT Ruby_EXECUTABLE)
197 cmake_parse_arguments (PARSE_ARGV 0 _RVI "EXACT;CHECK_EXISTS" "" "")
198 if (_RVI_UNPARSED_ARGUMENTS)
199 set (expected_version ${_RVI_UNPARSED_ARGUMENTS})
201 unset (expected_version)
204 if (_RVI_CHECK_EXISTS AND NOT EXISTS "${Ruby_EXECUTABLE}")
205 # interpreter does not exist anymore
206 set (_Ruby_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${Ruby_EXECUTABLE}\"")
207 set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND")
211 # Check the version it returns
212 # executable found must have a specific version
213 execute_process (COMMAND "${Ruby_EXECUTABLE}" -e "puts RUBY_VERSION"
214 RESULT_VARIABLE result
215 OUTPUT_VARIABLE version
217 OUTPUT_STRIP_TRAILING_WHITESPACE)
218 if (result OR (_RVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version))
219 # interpreter not usable or has wrong major version
221 set (_Ruby_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${Ruby_EXECUTABLE}\"")
223 set (_Ruby_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${Ruby_EXECUTABLE}\"")
225 set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND")
232 # Virtual environments handling
233 if(_Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
234 if(_Ruby_DEBUG_OUTPUT)
235 message("Inside Matches")
237 find_program (Ruby_EXECUTABLE
238 NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}
240 PATHS ENV MY_RUBY_HOME
241 PATH_SUFFIXES bin Scripts
243 NO_CMAKE_ENVIRONMENT_PATH
244 NO_SYSTEM_ENVIRONMENT_PATH
245 NO_CMAKE_SYSTEM_PATH)
247 if(_Ruby_DEBUG_OUTPUT)
248 message("Ruby_EXECUTABLE=${Ruby_EXECUTABLE}")
251 _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}})
255 if(NOT _Ruby_FIND_VIRTUALENV STREQUAL "ONLY")
258 elseif(_Ruby_DEBUG_OUTPUT)
259 message("_Ruby_FIND_VIRTUALENV doesn't match: ${_Ruby_FIND_VIRTUALENV}")
262 # try using standard paths
263 find_program (Ruby_EXECUTABLE
264 NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}
266 _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION})
270 # Remove first entry from names list.
271 LIST(REMOVE_AT _Ruby_POSSIBLE_EXECUTABLE_NAMES 0)
273 # If the list is now empty, abort.
274 if (NOT _Ruby_POSSIBLE_EXECUTABLE_NAMES)
277 # Otherwise, continue with the remaining list. Make sure that we clear
278 # the cached variable.
279 unset(Ruby_EXECUTABLE CACHE)
285 if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
286 function(_RUBY_CONFIG_VAR RBVAR OUTVAR)
287 execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['${RBVAR}']"
288 RESULT_VARIABLE _Ruby_SUCCESS
289 OUTPUT_VARIABLE _Ruby_OUTPUT
291 if(_Ruby_SUCCESS OR _Ruby_OUTPUT STREQUAL "")
292 execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print Config::CONFIG['${RBVAR}']"
293 RESULT_VARIABLE _Ruby_SUCCESS
294 OUTPUT_VARIABLE _Ruby_OUTPUT
297 set(${OUTVAR} "${_Ruby_OUTPUT}" PARENT_SCOPE)
301 # query the ruby version
302 _RUBY_CONFIG_VAR("MAJOR" Ruby_VERSION_MAJOR)
303 _RUBY_CONFIG_VAR("MINOR" Ruby_VERSION_MINOR)
304 _RUBY_CONFIG_VAR("TEENY" Ruby_VERSION_PATCH)
306 # query the different directories
307 _RUBY_CONFIG_VAR("archdir" Ruby_ARCH_DIR)
308 _RUBY_CONFIG_VAR("arch" Ruby_ARCH)
309 _RUBY_CONFIG_VAR("rubyhdrdir" Ruby_HDR_DIR)
310 _RUBY_CONFIG_VAR("rubyarchhdrdir" Ruby_ARCHHDR_DIR)
311 _RUBY_CONFIG_VAR("libdir" Ruby_POSSIBLE_LIB_DIR)
312 _RUBY_CONFIG_VAR("rubylibdir" Ruby_RUBY_LIB_DIR)
315 _RUBY_CONFIG_VAR("sitearchdir" Ruby_SITEARCH_DIR)
316 _RUBY_CONFIG_VAR("sitelibdir" Ruby_SITELIB_DIR)
318 # vendor_ruby available ?
319 execute_process(COMMAND ${Ruby_EXECUTABLE} -r vendor-specific -e "print 'true'"
320 OUTPUT_VARIABLE Ruby_HAS_VENDOR_RUBY ERROR_QUIET)
322 if(Ruby_HAS_VENDOR_RUBY)
323 _RUBY_CONFIG_VAR("vendorlibdir" Ruby_VENDORLIB_DIR)
324 _RUBY_CONFIG_VAR("vendorarchdir" Ruby_VENDORARCH_DIR)
327 # save the results in the cache so we don't have to run ruby the next time again
328 set(Ruby_VERSION_MAJOR ${Ruby_VERSION_MAJOR} CACHE PATH "The Ruby major version" FORCE)
329 set(Ruby_VERSION_MINOR ${Ruby_VERSION_MINOR} CACHE PATH "The Ruby minor version" FORCE)
330 set(Ruby_VERSION_PATCH ${Ruby_VERSION_PATCH} CACHE PATH "The Ruby patch version" FORCE)
331 set(Ruby_ARCH_DIR ${Ruby_ARCH_DIR} CACHE PATH "The Ruby arch dir" FORCE)
332 set(Ruby_HDR_DIR ${Ruby_HDR_DIR} CACHE PATH "The Ruby header dir (1.9+)" FORCE)
333 set(Ruby_ARCHHDR_DIR ${Ruby_ARCHHDR_DIR} CACHE PATH "The Ruby arch header dir (2.0+)" FORCE)
334 set(Ruby_POSSIBLE_LIB_DIR ${Ruby_POSSIBLE_LIB_DIR} CACHE PATH "The Ruby lib dir" FORCE)
335 set(Ruby_RUBY_LIB_DIR ${Ruby_RUBY_LIB_DIR} CACHE PATH "The Ruby ruby-lib dir" FORCE)
336 set(Ruby_SITEARCH_DIR ${Ruby_SITEARCH_DIR} CACHE PATH "The Ruby site arch dir" FORCE)
337 set(Ruby_SITELIB_DIR ${Ruby_SITELIB_DIR} CACHE PATH "The Ruby site lib dir" FORCE)
338 set(Ruby_HAS_VENDOR_RUBY ${Ruby_HAS_VENDOR_RUBY} CACHE BOOL "Vendor Ruby is available" FORCE)
339 set(Ruby_VENDORARCH_DIR ${Ruby_VENDORARCH_DIR} CACHE PATH "The Ruby vendor arch dir" FORCE)
340 set(Ruby_VENDORLIB_DIR ${Ruby_VENDORLIB_DIR} CACHE PATH "The Ruby vendor lib dir" FORCE)
347 Ruby_POSSIBLE_LIB_DIR
360 # In case Ruby_EXECUTABLE could not be executed (e.g. cross compiling)
361 # try to detect which version we found. This is not too good.
362 if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
363 # by default assume 1.8.0
364 set(Ruby_VERSION_MAJOR 1)
365 set(Ruby_VERSION_MINOR 8)
366 set(Ruby_VERSION_PATCH 0)
367 # check whether we found 1.9.x
368 if(${Ruby_EXECUTABLE} MATCHES "ruby1\\.?9")
369 set(Ruby_VERSION_MAJOR 1)
370 set(Ruby_VERSION_MINOR 9)
372 # check whether we found 2.[0-7].x
373 if(${Ruby_EXECUTABLE} MATCHES "ruby2")
374 set(Ruby_VERSION_MAJOR 2)
375 string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby2\\.?([0-7])" "\\1" Ruby_VERSION_MINOR)
377 # check whether we found 3.[0-1].x
378 if(${Ruby_EXECUTABLE} MATCHES "ruby3")
379 set(Ruby_VERSION_MAJOR 3)
380 string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby3\\.?([0-1])" "\\1" Ruby_VERSION_MINOR)
385 if(Ruby_VERSION_MAJOR)
386 set(Ruby_VERSION "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}.${Ruby_VERSION_PATCH}")
387 set(_Ruby_VERSION_SHORT "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}")
388 set(_Ruby_VERSION_SHORT_NODOT "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}")
389 set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}")
390 set(_Ruby_NODOT_VERSION_ZERO_PATCH "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}0")
393 # FIXME: Currently we require both the interpreter and development components to be found
394 # in order to use either. See issue #20474.
395 find_path(Ruby_INCLUDE_DIR
400 /usr/lib/ruby/${_Ruby_VERSION_SHORT}/i586-linux-gnu/
403 set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIR})
405 # if ruby > 1.8 is required or if ruby > 1.8 was found, search for the config.h dir
406 if( Ruby_FIND_VERSION VERSION_GREATER_EQUAL "1.9" OR Ruby_VERSION VERSION_GREATER_EQUAL "1.9" OR Ruby_HDR_DIR)
407 find_path(Ruby_CONFIG_INCLUDE_DIR
408 NAMES ruby/config.h config.h
410 ${Ruby_HDR_DIR}/${Ruby_ARCH}
415 set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIRS} ${Ruby_CONFIG_INCLUDE_DIR} )
419 # Determine the list of possible names for the ruby library
420 set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby${_Ruby_NODOT_VERSION} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION})
423 set(_Ruby_POSSIBLE_MSVC_RUNTIMES "msvcrt;vcruntime140;vcruntime140_1")
424 if(MSVC_TOOLSET_VERSION)
425 list(APPEND _Ruby_POSSIBLE_MSVC_RUNTIMES "msvcr${MSVC_TOOLSET_VERSION}")
427 list(APPEND _Ruby_POSSIBLE_MSVC_RUNTIMES "msvcr")
430 set(_Ruby_POSSIBLE_VERSION_SUFFICES "${_Ruby_NODOT_VERSION};${_Ruby_NODOT_VERSION_ZERO_PATCH}")
432 set(_Ruby_ARCH_PREFIX "")
433 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
434 set(_Ruby_ARCH_PREFIX "x64-")
437 foreach(_Ruby_MSVC_RUNTIME ${_Ruby_POSSIBLE_MSVC_RUNTIMES})
438 foreach(_Ruby_VERSION_SUFFIX ${_Ruby_POSSIBLE_VERSION_SUFFICES})
439 list(APPEND _Ruby_POSSIBLE_LIB_NAMES
440 "${_Ruby_ARCH_PREFIX}${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_VERSION_SUFFIX}"
441 "${_Ruby_ARCH_PREFIX}${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_VERSION_SUFFIX}-static")
446 find_library(Ruby_LIBRARY NAMES ${_Ruby_POSSIBLE_LIB_NAMES} HINTS ${Ruby_POSSIBLE_LIB_DIR} )
448 set(_Ruby_REQUIRED_VARS Ruby_EXECUTABLE Ruby_INCLUDE_DIR Ruby_LIBRARY)
449 if(_Ruby_VERSION_SHORT_NODOT GREATER 18)
450 list(APPEND _Ruby_REQUIRED_VARS Ruby_CONFIG_INCLUDE_DIR)
453 if(_Ruby_DEBUG_OUTPUT)
454 message(STATUS "--------FindRuby.cmake debug------------")
455 message(STATUS "_Ruby_POSSIBLE_EXECUTABLE_NAMES: ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
456 message(STATUS "_Ruby_POSSIBLE_LIB_NAMES: ${_Ruby_POSSIBLE_LIB_NAMES}")
457 message(STATUS "Ruby_ARCH_DIR: ${Ruby_ARCH_DIR}")
458 message(STATUS "Ruby_HDR_DIR: ${Ruby_HDR_DIR}")
459 message(STATUS "Ruby_POSSIBLE_LIB_DIR: ${Ruby_POSSIBLE_LIB_DIR}")
460 message(STATUS "Found Ruby_VERSION: \"${Ruby_VERSION}\" , short: \"${_Ruby_VERSION_SHORT}\", nodot: \"${_Ruby_VERSION_SHORT_NODOT}\"")
461 message(STATUS "_Ruby_REQUIRED_VARS: ${_Ruby_REQUIRED_VARS}")
462 message(STATUS "Ruby_EXECUTABLE: ${Ruby_EXECUTABLE}")
463 message(STATUS "Ruby_LIBRARY: ${Ruby_LIBRARY}")
464 message(STATUS "Ruby_INCLUDE_DIR: ${Ruby_INCLUDE_DIR}")
465 message(STATUS "Ruby_CONFIG_INCLUDE_DIR: ${Ruby_CONFIG_INCLUDE_DIR}")
466 message(STATUS "--------------------")
469 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
470 FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ruby REQUIRED_VARS ${_Ruby_REQUIRED_VARS}
471 VERSION_VAR Ruby_VERSION )
474 set(Ruby_LIBRARIES ${Ruby_LIBRARY})
481 Ruby_CONFIG_INCLUDE_DIR
484 # Set some variables for compatibility with previous version of this file (no need to provide a CamelCase version of that...)
485 set(RUBY_POSSIBLE_LIB_PATH ${Ruby_POSSIBLE_LIB_DIR})
486 set(RUBY_RUBY_LIB_PATH ${Ruby_RUBY_LIB_DIR})
487 set(RUBY_INCLUDE_PATH ${Ruby_INCLUDE_DIRS})
489 # Backwards compatibility
490 # Define upper case versions of output variables
504 Ruby_POSSIBLE_LIB_DIR
513 string(TOUPPER ${Camel} UPPER)
514 set(${UPPER} ${${Camel}})