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 2.7 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 libraries needed to use ruby from C.
42 the version of ruby which was found, e.g. "1.8.7"
43 ``Ruby_VERSION_MAJOR``
45 ``Ruby_VERSION_MINOR``
47 ``Ruby_VERSION_PATCH``
51 The following variables are also provided for compatibility reasons,
52 don't use them in new code:
55 same as Ruby_EXECUTABLE.
57 same as Ruby_INCLUDE_DIRS.
59 same as Ruby_INCLUDE_DIRS.
71 Define the root directory of a Ruby installation.
73 ``Ruby_FIND_VIRTUALENV``
74 This variable defines the handling of virtual environments managed by
75 ``rvm``. It is meaningful only when a virtual environment
76 is active (i.e. the ``rvm`` script has been evaluated or at least the
77 ``MY_RUBY_HOME`` environment variable is set).
78 The ``Ruby_FIND_VIRTUALENV`` variable can be set to empty or
81 * ``FIRST``: The virtual environment is used before any other standard
82 paths to look-up for the interpreter. This is the default.
83 * ``ONLY``: Only the virtual environment is used to look-up for the
85 * ``STANDARD``: The virtual environment is not used to look-up for the
86 interpreter (assuming it isn't still in the PATH...)
88 #]=======================================================================]
90 # Backwards compatibility
91 # Define camel case versions of input variables
96 RUBY_CONFIG_INCLUDE_DIR
99 string(REPLACE "RUBY_" "Ruby_" Camel ${UPPER})
100 if (NOT DEFINED ${Camel})
101 set(${Camel} ${${UPPER}})
106 # Ruby_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'`
107 # Ruby_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'`
108 # Ruby_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'`
109 # Ruby_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'`
110 # Ruby_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'`
112 # uncomment the following line to get debug output for this file
113 # set(_Ruby_DEBUG_OUTPUT TRUE)
115 # Determine the list of possible names of the ruby executable depending
116 # on which version of ruby is required
117 set(_Ruby_POSSIBLE_EXECUTABLE_NAMES ruby)
119 # If not specified, allow everything as far back as 1.8.0
120 if(NOT DEFINED Ruby_FIND_VERSION_MAJOR)
121 set(Ruby_FIND_VERSION "1.8.0")
122 set(Ruby_FIND_VERSION_MAJOR 1)
123 set(Ruby_FIND_VERSION_MINOR 8)
124 set(Ruby_FIND_VERSION_PATCH 0)
127 if(_Ruby_DEBUG_OUTPUT)
128 message("Ruby_FIND_VERSION=${Ruby_FIND_VERSION}")
129 message("Ruby_FIND_VERSION_MAJOR=${Ruby_FIND_VERSION_MAJOR}")
130 message("Ruby_FIND_VERSION_MINOR=${Ruby_FIND_VERSION_MINOR}")
131 message("Ruby_FIND_VERSION_PATCH=${Ruby_FIND_VERSION_PATCH}")
134 set(Ruby_FIND_VERSION_SHORT_NODOT "${Ruby_FIND_VERSION_MAJOR}${Ruby_FIND_VERSION_MINOR}")
136 # Set name of possible executables, ignoring the minor
138 # 2.1.1 => from ruby27 to ruby21 included
139 # 2.1 => from ruby27 to ruby21 included
140 # 2 => from ruby26 to ruby20 included
141 # empty => from ruby27 to ruby18 included
142 if(NOT Ruby_FIND_VERSION_EXACT)
144 foreach(_ruby_version RANGE 27 18 -1)
145 string(SUBSTRING "${_ruby_version}" 0 1 _ruby_major_version)
146 string(SUBSTRING "${_ruby_version}" 1 1 _ruby_minor_version)
148 if(NOT "${_ruby_major_version}${_ruby_minor_version}" VERSION_LESS ${Ruby_FIND_VERSION_SHORT_NODOT})
149 # Append both rubyX.Y and rubyXY (eg: ruby2.7 ruby27)
150 list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby${_ruby_major_version}.${_ruby_minor_version} ruby${_ruby_major_version}${_ruby_minor_version})
157 list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES)
160 # virtual environments handling (eg RVM)
161 if (DEFINED ENV{MY_RUBY_HOME})
162 if(_Ruby_DEBUG_OUTPUT)
163 message("My ruby home is defined: $ENV{MY_RUBY_HOME}")
166 if (DEFINED Ruby_FIND_VIRTUALENV)
167 if (NOT Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$")
168 message (AUTHOR_WARNING "FindRuby: ${Ruby_FIND_VIRTUALENV}: invalid value for 'Ruby_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.")
169 set (_Ruby_FIND_VIRTUALENV "FIRST")
171 set (_Ruby_FIND_VIRTUALENV ${Ruby_FIND_VIRTUALENV})
174 set (_Ruby_FIND_VIRTUALENV FIRST)
177 if (DEFINED Ruby_FIND_VIRTUALENV)
178 message("Environment variable MY_RUBY_HOME isn't set, defaulting back to Ruby_FIND_VIRTUALENV=STANDARD")
180 set (_Ruby_FIND_VIRTUALENV STANDARD)
183 if(_Ruby_DEBUG_OUTPUT)
184 message("_Ruby_POSSIBLE_EXECUTABLE_NAMES=${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
185 message("_Ruby_FIND_VIRTUALENV=${_Ruby_FIND_VIRTUALENV}")
188 function (_RUBY_VALIDATE_INTERPRETER)
189 if (NOT Ruby_EXECUTABLE)
193 cmake_parse_arguments (PARSE_ARGV 0 _RVI "EXACT;CHECK_EXISTS" "" "")
194 if (_RVI_UNPARSED_ARGUMENTS)
195 set (expected_version ${_RVI_UNPARSED_ARGUMENTS})
197 unset (expected_version)
200 if (_RVI_CHECK_EXISTS AND NOT EXISTS "${Ruby_EXECUTABLE}")
201 # interpreter does not exist anymore
202 set (_Ruby_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${Ruby_EXECUTABLE}\"")
203 set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND")
207 # Check the version it returns
208 # executable found must have a specific version
209 execute_process (COMMAND "${Ruby_EXECUTABLE}" -e "puts RUBY_VERSION"
210 RESULT_VARIABLE result
211 OUTPUT_VARIABLE version
213 OUTPUT_STRIP_TRAILING_WHITESPACE)
214 if (result OR (_RVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version))
215 # interpreter not usable or has wrong major version
217 set (_Ruby_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${Ruby_EXECUTABLE}\"")
219 set (_Ruby_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${Ruby_EXECUTABLE}\"")
221 set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND")
228 # Virtual environments handling
229 if(_Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
230 if(_Ruby_DEBUG_OUTPUT)
231 message("Inside Matches")
233 find_program (Ruby_EXECUTABLE
234 NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}
236 PATHS ENV MY_RUBY_HOME
237 PATH_SUFFIXES bin Scripts
239 NO_CMAKE_ENVIRONMENT_PATH
240 NO_SYSTEM_ENVIRONMENT_PATH
241 NO_CMAKE_SYSTEM_PATH)
243 if(_Ruby_DEBUG_OUTPUT)
244 message("Ruby_EXECUTABLE=${Ruby_EXECUTABLE}")
247 _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}})
251 if(NOT _Ruby_FIND_VIRTUALENV STREQUAL "ONLY")
254 elseif(_Ruby_DEBUG_OUTPUT)
255 message("_Ruby_FIND_VIRTUALENV doesn't match: ${_Ruby_FIND_VIRTUALENV}")
258 # try using standard paths
259 find_program (Ruby_EXECUTABLE
260 NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}
262 _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION})
270 if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
271 function(_RUBY_CONFIG_VAR RBVAR OUTVAR)
272 execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['${RBVAR}']"
273 RESULT_VARIABLE _Ruby_SUCCESS
274 OUTPUT_VARIABLE _Ruby_OUTPUT
276 if(_Ruby_SUCCESS OR _Ruby_OUTPUT STREQUAL "")
277 execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print Config::CONFIG['${RBVAR}']"
278 RESULT_VARIABLE _Ruby_SUCCESS
279 OUTPUT_VARIABLE _Ruby_OUTPUT
282 set(${OUTVAR} "${_Ruby_OUTPUT}" PARENT_SCOPE)
286 # query the ruby version
287 _RUBY_CONFIG_VAR("MAJOR" Ruby_VERSION_MAJOR)
288 _RUBY_CONFIG_VAR("MINOR" Ruby_VERSION_MINOR)
289 _RUBY_CONFIG_VAR("TEENY" Ruby_VERSION_PATCH)
291 # query the different directories
292 _RUBY_CONFIG_VAR("archdir" Ruby_ARCH_DIR)
293 _RUBY_CONFIG_VAR("arch" Ruby_ARCH)
294 _RUBY_CONFIG_VAR("rubyhdrdir" Ruby_HDR_DIR)
295 _RUBY_CONFIG_VAR("rubyarchhdrdir" Ruby_ARCHHDR_DIR)
296 _RUBY_CONFIG_VAR("libdir" Ruby_POSSIBLE_LIB_DIR)
297 _RUBY_CONFIG_VAR("rubylibdir" Ruby_RUBY_LIB_DIR)
300 _RUBY_CONFIG_VAR("sitearchdir" Ruby_SITEARCH_DIR)
301 _RUBY_CONFIG_VAR("sitelibdir" Ruby_SITELIB_DIR)
303 # vendor_ruby available ?
304 execute_process(COMMAND ${Ruby_EXECUTABLE} -r vendor-specific -e "print 'true'"
305 OUTPUT_VARIABLE Ruby_HAS_VENDOR_RUBY ERROR_QUIET)
307 if(Ruby_HAS_VENDOR_RUBY)
308 _RUBY_CONFIG_VAR("vendorlibdir" Ruby_VENDORLIB_DIR)
309 _RUBY_CONFIG_VAR("vendorarchdir" Ruby_VENDORARCH_DIR)
312 # save the results in the cache so we don't have to run ruby the next time again
313 set(Ruby_VERSION_MAJOR ${Ruby_VERSION_MAJOR} CACHE PATH "The Ruby major version" FORCE)
314 set(Ruby_VERSION_MINOR ${Ruby_VERSION_MINOR} CACHE PATH "The Ruby minor version" FORCE)
315 set(Ruby_VERSION_PATCH ${Ruby_VERSION_PATCH} CACHE PATH "The Ruby patch version" FORCE)
316 set(Ruby_ARCH_DIR ${Ruby_ARCH_DIR} CACHE PATH "The Ruby arch dir" FORCE)
317 set(Ruby_HDR_DIR ${Ruby_HDR_DIR} CACHE PATH "The Ruby header dir (1.9+)" FORCE)
318 set(Ruby_ARCHHDR_DIR ${Ruby_ARCHHDR_DIR} CACHE PATH "The Ruby arch header dir (2.0+)" FORCE)
319 set(Ruby_POSSIBLE_LIB_DIR ${Ruby_POSSIBLE_LIB_DIR} CACHE PATH "The Ruby lib dir" FORCE)
320 set(Ruby_RUBY_LIB_DIR ${Ruby_RUBY_LIB_DIR} CACHE PATH "The Ruby ruby-lib dir" FORCE)
321 set(Ruby_SITEARCH_DIR ${Ruby_SITEARCH_DIR} CACHE PATH "The Ruby site arch dir" FORCE)
322 set(Ruby_SITELIB_DIR ${Ruby_SITELIB_DIR} CACHE PATH "The Ruby site lib dir" FORCE)
323 set(Ruby_HAS_VENDOR_RUBY ${Ruby_HAS_VENDOR_RUBY} CACHE BOOL "Vendor Ruby is available" FORCE)
324 set(Ruby_VENDORARCH_DIR ${Ruby_VENDORARCH_DIR} CACHE PATH "The Ruby vendor arch dir" FORCE)
325 set(Ruby_VENDORLIB_DIR ${Ruby_VENDORLIB_DIR} CACHE PATH "The Ruby vendor lib dir" FORCE)
332 Ruby_POSSIBLE_LIB_DIR
345 # In case Ruby_EXECUTABLE could not be executed (e.g. cross compiling)
346 # try to detect which version we found. This is not too good.
347 if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
348 # by default assume 1.8.0
349 set(Ruby_VERSION_MAJOR 1)
350 set(Ruby_VERSION_MINOR 8)
351 set(Ruby_VERSION_PATCH 0)
352 # check whether we found 1.9.x
353 if(${Ruby_EXECUTABLE} MATCHES "ruby1\\.?9")
354 set(Ruby_VERSION_MAJOR 1)
355 set(Ruby_VERSION_MINOR 9)
357 # check whether we found 2.0.x
358 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?0")
359 set(Ruby_VERSION_MAJOR 2)
360 set(Ruby_VERSION_MINOR 0)
362 # check whether we found 2.1.x
363 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?1")
364 set(Ruby_VERSION_MAJOR 2)
365 set(Ruby_VERSION_MINOR 1)
367 # check whether we found 2.2.x
368 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?2")
369 set(Ruby_VERSION_MAJOR 2)
370 set(Ruby_VERSION_MINOR 2)
372 # check whether we found 2.3.x
373 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?3")
374 set(Ruby_VERSION_MAJOR 2)
375 set(Ruby_VERSION_MINOR 3)
377 # check whether we found 2.4.x
378 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?4")
379 set(Ruby_VERSION_MAJOR 2)
380 set(Ruby_VERSION_MINOR 4)
382 # check whether we found 2.5.x
383 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?5")
384 set(Ruby_VERSION_MAJOR 2)
385 set(Ruby_VERSION_MINOR 5)
387 # check whether we found 2.6.x
388 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?6")
389 set(Ruby_VERSION_MAJOR 2)
390 set(Ruby_VERSION_MINOR 6)
392 # check whether we found 2.7.x
393 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?7")
394 set(Ruby_VERSION_MAJOR 2)
395 set(Ruby_VERSION_MINOR 7)
399 if(Ruby_VERSION_MAJOR)
400 set(Ruby_VERSION "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}.${Ruby_VERSION_PATCH}")
401 set(_Ruby_VERSION_SHORT "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}")
402 set(_Ruby_VERSION_SHORT_NODOT "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}")
403 set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}")
406 # FIXME: Currently we require both the interpreter and development components to be found
407 # in order to use either. See issue #20474.
408 find_path(Ruby_INCLUDE_DIR
413 /usr/lib/ruby/${_Ruby_VERSION_SHORT}/i586-linux-gnu/
416 set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIR})
418 # if ruby > 1.8 is required or if ruby > 1.8 was found, search for the config.h dir
419 if( Ruby_FIND_VERSION VERSION_GREATER_EQUAL "1.9" OR Ruby_VERSION VERSION_GREATER_EQUAL "1.9" OR Ruby_HDR_DIR)
420 find_path(Ruby_CONFIG_INCLUDE_DIR
421 NAMES ruby/config.h config.h
423 ${Ruby_HDR_DIR}/${Ruby_ARCH}
428 set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIRS} ${Ruby_CONFIG_INCLUDE_DIR} )
432 # Determine the list of possible names for the ruby library
433 set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION})
436 if(MSVC_TOOLSET_VERSION)
437 set(_Ruby_MSVC_RUNTIME "${MSVC_TOOLSET_VERSION}")
439 set(_Ruby_MSVC_RUNTIME "")
442 set(_Ruby_ARCH_PREFIX "")
443 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
444 set(_Ruby_ARCH_PREFIX "x64-")
447 list(APPEND _Ruby_POSSIBLE_LIB_NAMES
448 "${_Ruby_ARCH_PREFIX}msvcr${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_NODOT_VERSION}"
449 "${_Ruby_ARCH_PREFIX}msvcr${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_NODOT_VERSION}-static"
450 "${_Ruby_ARCH_PREFIX}msvcrt-ruby${_Ruby_NODOT_VERSION}"
451 "${_Ruby_ARCH_PREFIX}msvcrt-ruby${_Ruby_NODOT_VERSION}-static" )
454 find_library(Ruby_LIBRARY NAMES ${_Ruby_POSSIBLE_LIB_NAMES} HINTS ${Ruby_POSSIBLE_LIB_DIR} )
456 set(_Ruby_REQUIRED_VARS Ruby_EXECUTABLE Ruby_INCLUDE_DIR Ruby_LIBRARY)
457 if(_Ruby_VERSION_SHORT_NODOT GREATER 18)
458 list(APPEND _Ruby_REQUIRED_VARS Ruby_CONFIG_INCLUDE_DIR)
461 if(_Ruby_DEBUG_OUTPUT)
462 message(STATUS "--------FindRuby.cmake debug------------")
463 message(STATUS "_Ruby_POSSIBLE_EXECUTABLE_NAMES: ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
464 message(STATUS "_Ruby_POSSIBLE_LIB_NAMES: ${_Ruby_POSSIBLE_LIB_NAMES}")
465 message(STATUS "Ruby_ARCH_DIR: ${Ruby_ARCH_DIR}")
466 message(STATUS "Ruby_HDR_DIR: ${Ruby_HDR_DIR}")
467 message(STATUS "Ruby_POSSIBLE_LIB_DIR: ${Ruby_POSSIBLE_LIB_DIR}")
468 message(STATUS "Found Ruby_VERSION: \"${Ruby_VERSION}\" , short: \"${_Ruby_VERSION_SHORT}\", nodot: \"${_Ruby_VERSION_SHORT_NODOT}\"")
469 message(STATUS "_Ruby_REQUIRED_VARS: ${_Ruby_REQUIRED_VARS}")
470 message(STATUS "Ruby_EXECUTABLE: ${Ruby_EXECUTABLE}")
471 message(STATUS "Ruby_LIBRARY: ${Ruby_LIBRARY}")
472 message(STATUS "Ruby_INCLUDE_DIR: ${Ruby_INCLUDE_DIR}")
473 message(STATUS "Ruby_CONFIG_INCLUDE_DIR: ${Ruby_CONFIG_INCLUDE_DIR}")
474 message(STATUS "--------------------")
477 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
478 FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ruby REQUIRED_VARS ${_Ruby_REQUIRED_VARS}
479 VERSION_VAR Ruby_VERSION )
482 set(Ruby_LIBRARIES ${Ruby_LIBRARY})
489 Ruby_CONFIG_INCLUDE_DIR
492 # Set some variables for compatibility with previous version of this file (no need to provide a CamelCase version of that...)
493 set(RUBY_POSSIBLE_LIB_PATH ${Ruby_POSSIBLE_LIB_DIR})
494 set(RUBY_RUBY_LIB_PATH ${Ruby_RUBY_LIB_DIR})
495 set(RUBY_INCLUDE_PATH ${Ruby_INCLUDE_DIRS})
497 # Backwards compatibility
498 # Define upper case versions of output variables
512 Ruby_POSSIBLE_LIB_DIR
520 string(TOUPPER ${Camel} UPPER)
521 set(${UPPER} ${${Camel}})