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``
54 same as Ruby_INCLUDE_DIRS, only provided for compatibility reasons, don't use it
60 Define the root directory of a Ruby installation.
62 ``Ruby_FIND_VIRTUALENV``
63 This variable defines the handling of virtual environments managed by
64 ``rvm``. It is meaningful only when a virtual environment
65 is active (i.e. the ``rvm`` script has been evaluated or at least the
66 ``MY_RUBY_HOME`` environment variable is set).
67 The ``Ruby_FIND_VIRTUALENV`` variable can be set to empty or
70 * ``FIRST``: The virtual environment is used before any other standard
71 paths to look-up for the interpreter. This is the default.
72 * ``ONLY``: Only the virtual environment is used to look-up for the
74 * ``STANDARD``: The virtual environment is not used to look-up for the
75 interpreter (assuming it isn't still in the PATH...)
77 #]=======================================================================]
79 # Backwards compatibility
80 # Define camel case versions of input variables
85 RUBY_CONFIG_INCLUDE_DIR
88 string(REPLACE "RUBY_" "Ruby_" Camel ${UPPER})
89 if (NOT DEFINED ${Camel})
90 set(${Camel} ${${UPPER}})
95 # Ruby_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'`
96 # Ruby_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'`
97 # Ruby_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'`
98 # Ruby_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'`
99 # Ruby_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'`
101 # uncomment the following line to get debug output for this file
102 # set(_Ruby_DEBUG_OUTPUT TRUE)
104 # Determine the list of possible names of the ruby executable depending
105 # on which version of ruby is required
106 set(_Ruby_POSSIBLE_EXECUTABLE_NAMES ruby)
108 # If not specified, allow everything as far back as 1.8.0
109 if(NOT DEFINED Ruby_FIND_VERSION_MAJOR)
110 set(Ruby_FIND_VERSION "1.8.0")
111 set(Ruby_FIND_VERSION_MAJOR 1)
112 set(Ruby_FIND_VERSION_MINOR 8)
113 set(Ruby_FIND_VERSION_PATCH 0)
116 if(_Ruby_DEBUG_OUTPUT)
117 message("Ruby_FIND_VERSION=${Ruby_FIND_VERSION}")
118 message("Ruby_FIND_VERSION_MAJOR=${Ruby_FIND_VERSION_MAJOR}")
119 message("Ruby_FIND_VERSION_MINOR=${Ruby_FIND_VERSION_MINOR}")
120 message("Ruby_FIND_VERSION_PATCH=${Ruby_FIND_VERSION_PATCH}")
123 set(Ruby_FIND_VERSION_SHORT_NODOT "${Ruby_FIND_VERSION_MAJOR}${Ruby_FIND_VERSION_MINOR}")
125 # Set name of possible executables, ignoring the minor
127 # 2.1.1 => from ruby27 to ruby21 included
128 # 2.1 => from ruby27 to ruby21 included
129 # 2 => from ruby26 to ruby20 included
130 # empty => from ruby27 to ruby18 included
131 if(NOT Ruby_FIND_VERSION_EXACT)
133 foreach(_ruby_version RANGE 27 18 -1)
134 string(SUBSTRING "${_ruby_version}" 0 1 _ruby_major_version)
135 string(SUBSTRING "${_ruby_version}" 1 1 _ruby_minor_version)
137 if(NOT "${_ruby_major_version}${_ruby_minor_version}" VERSION_LESS ${Ruby_FIND_VERSION_SHORT_NODOT})
138 # Append both rubyX.Y and rubyXY (eg: ruby2.7 ruby27)
139 list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby${_ruby_major_version}.${_ruby_minor_version} ruby${_ruby_major_version}${_ruby_minor_version})
146 list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES)
149 # virtual environments handling (eg RVM)
150 if (DEFINED ENV{MY_RUBY_HOME})
151 if(_Ruby_DEBUG_OUTPUT)
152 message("My ruby home is defined: $ENV{MY_RUBY_HOME}")
155 if (DEFINED Ruby_FIND_VIRTUALENV)
156 if (NOT Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$")
157 message (AUTHOR_WARNING "FindRuby: ${Ruby_FIND_VIRTUALENV}: invalid value for 'Ruby_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.")
158 set (_Ruby_FIND_VIRTUALENV "FIRST")
160 set (_Ruby_FIND_VIRTUALENV ${Ruby_FIND_VIRTUALENV})
163 set (_Ruby_FIND_VIRTUALENV FIRST)
166 if (DEFINED Ruby_FIND_VIRTUALENV)
167 message("Environment variable MY_RUBY_HOME isn't set, defaulting back to Ruby_FIND_VIRTUALENV=STANDARD")
169 set (_Ruby_FIND_VIRTUALENV STANDARD)
172 if(_Ruby_DEBUG_OUTPUT)
173 message("_Ruby_POSSIBLE_EXECUTABLE_NAMES=${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
174 message("_Ruby_FIND_VIRTUALENV=${_Ruby_FIND_VIRTUALENV}")
177 function (_RUBY_VALIDATE_INTERPRETER)
178 if (NOT Ruby_EXECUTABLE)
182 cmake_parse_arguments (PARSE_ARGV 0 _RVI "EXACT;CHECK_EXISTS" "" "")
183 if (_RVI_UNPARSED_ARGUMENTS)
184 set (expected_version ${_RVI_UNPARSED_ARGUMENTS})
186 unset (expected_version)
189 if (_RVI_CHECK_EXISTS AND NOT EXISTS "${Ruby_EXECUTABLE}")
190 # interpreter does not exist anymore
191 set (_Ruby_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${Ruby_EXECUTABLE}\"")
192 set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND")
196 # Check the version it returns
197 # executable found must have a specific version
198 execute_process (COMMAND "${Ruby_EXECUTABLE}" -e "puts RUBY_VERSION"
199 RESULT_VARIABLE result
200 OUTPUT_VARIABLE version
202 OUTPUT_STRIP_TRAILING_WHITESPACE)
203 if (result OR (_RVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version))
204 # interpreter not usable or has wrong major version
206 set (_Ruby_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${Ruby_EXECUTABLE}\"")
208 set (_Ruby_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${Ruby_EXECUTABLE}\"")
210 set_property (CACHE Ruby_EXECUTABLE PROPERTY VALUE "Ruby_EXECUTABLE-NOTFOUND")
217 # Virtual environments handling
218 if(_Ruby_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
219 if(_Ruby_DEBUG_OUTPUT)
220 message("Inside Matches")
222 find_program (Ruby_EXECUTABLE
223 NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}
225 PATHS ENV MY_RUBY_HOME
226 PATH_SUFFIXES bin Scripts
228 NO_CMAKE_ENVIRONMENT_PATH
229 NO_SYSTEM_ENVIRONMENT_PATH
230 NO_CMAKE_SYSTEM_PATH)
232 if(_Ruby_DEBUG_OUTPUT)
233 message("Ruby_EXECUTABLE=${Ruby_EXECUTABLE}")
236 _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}})
240 if(NOT _Ruby_FIND_VIRTUALENV STREQUAL "ONLY")
243 elseif(_Ruby_DEBUG_OUTPUT)
244 message("_Ruby_FIND_VIRTUALENV doesn't match: ${_Ruby_FIND_VIRTUALENV}")
247 # try using standard paths
248 find_program (Ruby_EXECUTABLE
249 NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}
251 _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION})
259 if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
260 function(_RUBY_CONFIG_VAR RBVAR OUTVAR)
261 execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['${RBVAR}']"
262 RESULT_VARIABLE _Ruby_SUCCESS
263 OUTPUT_VARIABLE _Ruby_OUTPUT
265 if(_Ruby_SUCCESS OR _Ruby_OUTPUT STREQUAL "")
266 execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print Config::CONFIG['${RBVAR}']"
267 RESULT_VARIABLE _Ruby_SUCCESS
268 OUTPUT_VARIABLE _Ruby_OUTPUT
271 set(${OUTVAR} "${_Ruby_OUTPUT}" PARENT_SCOPE)
275 # query the ruby version
276 _RUBY_CONFIG_VAR("MAJOR" Ruby_VERSION_MAJOR)
277 _RUBY_CONFIG_VAR("MINOR" Ruby_VERSION_MINOR)
278 _RUBY_CONFIG_VAR("TEENY" Ruby_VERSION_PATCH)
280 # query the different directories
281 _RUBY_CONFIG_VAR("archdir" Ruby_ARCH_DIR)
282 _RUBY_CONFIG_VAR("arch" Ruby_ARCH)
283 _RUBY_CONFIG_VAR("rubyhdrdir" Ruby_HDR_DIR)
284 _RUBY_CONFIG_VAR("rubyarchhdrdir" Ruby_ARCHHDR_DIR)
285 _RUBY_CONFIG_VAR("libdir" Ruby_POSSIBLE_LIB_DIR)
286 _RUBY_CONFIG_VAR("rubylibdir" Ruby_RUBY_LIB_DIR)
289 _RUBY_CONFIG_VAR("sitearchdir" Ruby_SITEARCH_DIR)
290 _RUBY_CONFIG_VAR("sitelibdir" Ruby_SITELIB_DIR)
292 # vendor_ruby available ?
293 execute_process(COMMAND ${Ruby_EXECUTABLE} -r vendor-specific -e "print 'true'"
294 OUTPUT_VARIABLE Ruby_HAS_VENDOR_RUBY ERROR_QUIET)
296 if(Ruby_HAS_VENDOR_RUBY)
297 _RUBY_CONFIG_VAR("vendorlibdir" Ruby_VENDORLIB_DIR)
298 _RUBY_CONFIG_VAR("vendorarchdir" Ruby_VENDORARCH_DIR)
301 # save the results in the cache so we don't have to run ruby the next time again
302 set(Ruby_VERSION_MAJOR ${Ruby_VERSION_MAJOR} CACHE PATH "The Ruby major version" FORCE)
303 set(Ruby_VERSION_MINOR ${Ruby_VERSION_MINOR} CACHE PATH "The Ruby minor version" FORCE)
304 set(Ruby_VERSION_PATCH ${Ruby_VERSION_PATCH} CACHE PATH "The Ruby patch version" FORCE)
305 set(Ruby_ARCH_DIR ${Ruby_ARCH_DIR} CACHE PATH "The Ruby arch dir" FORCE)
306 set(Ruby_HDR_DIR ${Ruby_HDR_DIR} CACHE PATH "The Ruby header dir (1.9+)" FORCE)
307 set(Ruby_ARCHHDR_DIR ${Ruby_ARCHHDR_DIR} CACHE PATH "The Ruby arch header dir (2.0+)" FORCE)
308 set(Ruby_POSSIBLE_LIB_DIR ${Ruby_POSSIBLE_LIB_DIR} CACHE PATH "The Ruby lib dir" FORCE)
309 set(Ruby_RUBY_LIB_DIR ${Ruby_RUBY_LIB_DIR} CACHE PATH "The Ruby ruby-lib dir" FORCE)
310 set(Ruby_SITEARCH_DIR ${Ruby_SITEARCH_DIR} CACHE PATH "The Ruby site arch dir" FORCE)
311 set(Ruby_SITELIB_DIR ${Ruby_SITELIB_DIR} CACHE PATH "The Ruby site lib dir" FORCE)
312 set(Ruby_HAS_VENDOR_RUBY ${Ruby_HAS_VENDOR_RUBY} CACHE BOOL "Vendor Ruby is available" FORCE)
313 set(Ruby_VENDORARCH_DIR ${Ruby_VENDORARCH_DIR} CACHE PATH "The Ruby vendor arch dir" FORCE)
314 set(Ruby_VENDORLIB_DIR ${Ruby_VENDORLIB_DIR} CACHE PATH "The Ruby vendor lib dir" FORCE)
321 Ruby_POSSIBLE_LIB_DIR
334 # In case Ruby_EXECUTABLE could not be executed (e.g. cross compiling)
335 # try to detect which version we found. This is not too good.
336 if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
337 # by default assume 1.8.0
338 set(Ruby_VERSION_MAJOR 1)
339 set(Ruby_VERSION_MINOR 8)
340 set(Ruby_VERSION_PATCH 0)
341 # check whether we found 1.9.x
342 if(${Ruby_EXECUTABLE} MATCHES "ruby1\\.?9")
343 set(Ruby_VERSION_MAJOR 1)
344 set(Ruby_VERSION_MINOR 9)
346 # check whether we found 2.0.x
347 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?0")
348 set(Ruby_VERSION_MAJOR 2)
349 set(Ruby_VERSION_MINOR 0)
351 # check whether we found 2.1.x
352 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?1")
353 set(Ruby_VERSION_MAJOR 2)
354 set(Ruby_VERSION_MINOR 1)
356 # check whether we found 2.2.x
357 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?2")
358 set(Ruby_VERSION_MAJOR 2)
359 set(Ruby_VERSION_MINOR 2)
361 # check whether we found 2.3.x
362 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?3")
363 set(Ruby_VERSION_MAJOR 2)
364 set(Ruby_VERSION_MINOR 3)
366 # check whether we found 2.4.x
367 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?4")
368 set(Ruby_VERSION_MAJOR 2)
369 set(Ruby_VERSION_MINOR 4)
371 # check whether we found 2.5.x
372 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?5")
373 set(Ruby_VERSION_MAJOR 2)
374 set(Ruby_VERSION_MINOR 5)
376 # check whether we found 2.6.x
377 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?6")
378 set(Ruby_VERSION_MAJOR 2)
379 set(Ruby_VERSION_MINOR 6)
381 # check whether we found 2.7.x
382 if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?7")
383 set(Ruby_VERSION_MAJOR 2)
384 set(Ruby_VERSION_MINOR 7)
388 if(Ruby_VERSION_MAJOR)
389 set(Ruby_VERSION "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}.${Ruby_VERSION_PATCH}")
390 set(_Ruby_VERSION_SHORT "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}")
391 set(_Ruby_VERSION_SHORT_NODOT "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}")
392 set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}")
395 # FIXME: Currently we require both the interpreter and development components to be found
396 # in order to use either. See issue #20474.
397 find_path(Ruby_INCLUDE_DIR
402 /usr/lib/ruby/${_Ruby_VERSION_SHORT}/i586-linux-gnu/
405 set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIR})
407 # if ruby > 1.8 is required or if ruby > 1.8 was found, search for the config.h dir
408 if( Ruby_FIND_VERSION VERSION_GREATER_EQUAL "1.9" OR Ruby_VERSION VERSION_GREATER_EQUAL "1.9" OR Ruby_HDR_DIR)
409 find_path(Ruby_CONFIG_INCLUDE_DIR
410 NAMES ruby/config.h config.h
412 ${Ruby_HDR_DIR}/${Ruby_ARCH}
417 set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIRS} ${Ruby_CONFIG_INCLUDE_DIR} )
421 # Determine the list of possible names for the ruby library
422 set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION})
425 if(MSVC_TOOLSET_VERSION)
426 set(_Ruby_MSVC_RUNTIME "${MSVC_TOOLSET_VERSION}")
428 set(_Ruby_MSVC_RUNTIME "")
431 set(_Ruby_ARCH_PREFIX "")
432 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
433 set(_Ruby_ARCH_PREFIX "x64-")
436 list(APPEND _Ruby_POSSIBLE_LIB_NAMES
437 "${_Ruby_ARCH_PREFIX}msvcr${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_NODOT_VERSION}"
438 "${_Ruby_ARCH_PREFIX}msvcr${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_NODOT_VERSION}-static"
439 "${_Ruby_ARCH_PREFIX}msvcrt-ruby${_Ruby_NODOT_VERSION}"
440 "${_Ruby_ARCH_PREFIX}msvcrt-ruby${_Ruby_NODOT_VERSION}-static" )
443 find_library(Ruby_LIBRARY NAMES ${_Ruby_POSSIBLE_LIB_NAMES} HINTS ${Ruby_POSSIBLE_LIB_DIR} )
445 set(_Ruby_REQUIRED_VARS Ruby_EXECUTABLE Ruby_INCLUDE_DIR Ruby_LIBRARY)
446 if(_Ruby_VERSION_SHORT_NODOT GREATER 18)
447 list(APPEND _Ruby_REQUIRED_VARS Ruby_CONFIG_INCLUDE_DIR)
450 if(_Ruby_DEBUG_OUTPUT)
451 message(STATUS "--------FindRuby.cmake debug------------")
452 message(STATUS "_Ruby_POSSIBLE_EXECUTABLE_NAMES: ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}")
453 message(STATUS "_Ruby_POSSIBLE_LIB_NAMES: ${_Ruby_POSSIBLE_LIB_NAMES}")
454 message(STATUS "Ruby_ARCH_DIR: ${Ruby_ARCH_DIR}")
455 message(STATUS "Ruby_HDR_DIR: ${Ruby_HDR_DIR}")
456 message(STATUS "Ruby_POSSIBLE_LIB_DIR: ${Ruby_POSSIBLE_LIB_DIR}")
457 message(STATUS "Found Ruby_VERSION: \"${Ruby_VERSION}\" , short: \"${_Ruby_VERSION_SHORT}\", nodot: \"${_Ruby_VERSION_SHORT_NODOT}\"")
458 message(STATUS "_Ruby_REQUIRED_VARS: ${_Ruby_REQUIRED_VARS}")
459 message(STATUS "Ruby_EXECUTABLE: ${Ruby_EXECUTABLE}")
460 message(STATUS "Ruby_LIBRARY: ${Ruby_LIBRARY}")
461 message(STATUS "Ruby_INCLUDE_DIR: ${Ruby_INCLUDE_DIR}")
462 message(STATUS "Ruby_CONFIG_INCLUDE_DIR: ${Ruby_CONFIG_INCLUDE_DIR}")
463 message(STATUS "--------------------")
466 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
467 FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ruby REQUIRED_VARS ${_Ruby_REQUIRED_VARS}
468 VERSION_VAR Ruby_VERSION )
471 set(Ruby_LIBRARIES ${Ruby_LIBRARY})
478 Ruby_CONFIG_INCLUDE_DIR
481 # Set some variables for compatibility with previous version of this file (no need to provide a CamelCase version of that...)
482 set(RUBY_POSSIBLE_LIB_PATH ${Ruby_POSSIBLE_LIB_DIR})
483 set(RUBY_RUBY_LIB_PATH ${Ruby_RUBY_LIB_DIR})
484 set(RUBY_INCLUDE_PATH ${Ruby_INCLUDE_DIRS})
486 # Backwards compatibility
487 # Define upper case versions of output variables
502 Ruby_POSSIBLE_LIB_DIR
510 string(TOUPPER ${Camel} UPPER)
511 set(${UPPER} ${${Camel}})