Ruby: version.c Source File

Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)

version.c
1/**********************************************************************
2
3 version.c -
4
5 $Author$
6 created at: Thu Sep 30 20:08:01 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "internal/cmdlineopt.h"
13#include "internal/parse.h"
14#include "internal/gc.h"
15#include "ruby/internal/globals.h"
16#include "ruby/ruby.h"
17#include "version.h"
18#include "vm_core.h"
19#include "yjit.h"
20#include <stdio.h>
21
22#ifndef EXIT_SUCCESS
23#define EXIT_SUCCESS 0
24#endif
25
26#ifdef RUBY_REVISION
27# if RUBY_PATCHLEVEL == -1
28# define RUBY_API_VERSION_NAME "master"
29# ifndef RUBY_BRANCH_NAME
30# define RUBY_BRANCH_NAME RUBY_API_VERSION_NAME
31# endif
32# define RUBY_REVISION_STR " "RUBY_BRANCH_NAME" "RUBY_REVISION
33# else
34# define RUBY_REVISION_STR " revision "RUBY_REVISION
35# endif
36#else
37# define RUBY_REVISION "HEAD"
38# define RUBY_REVISION_STR ""
39#endif
40#ifndef RUBY_API_VERSION_NAME
41# define RUBY_API_VERSION_NAME RUBY_API_VERSION_STR
42#endif
43#if !defined RUBY_RELEASE_DATETIME || RUBY_PATCHLEVEL != -1
44# undef RUBY_RELEASE_DATETIME
45# define RUBY_RELEASE_DATETIME RUBY_RELEASE_DATE
46#endif
47
48#define PRINT(type) puts(ruby_##type)
49#define MKSTR(type) rb_obj_freeze(rb_usascii_str_new_static(ruby_##type, sizeof(ruby_##type)-1))
50#define MKINT(name) INT2FIX(ruby_##name)
51
52#define RUBY_API_VERSION_STR \
53 STRINGIZE(RUBY_API_VERSION_MAJOR) "." \
54 STRINGIZE(RUBY_API_VERSION_MINOR)
55 const int ruby_api_version[] = {
56 RUBY_API_VERSION_MAJOR,
57 RUBY_API_VERSION_MINOR,
58 RUBY_API_VERSION_TEENY,
59};
60#define RUBY_VERSION \
61 STRINGIZE(RUBY_VERSION_MAJOR) "." \
62 STRINGIZE(RUBY_VERSION_MINOR) "." \
63 STRINGIZE(RUBY_VERSION_TEENY) ""
64#ifndef RUBY_FULL_REVISION
65# define RUBY_FULL_REVISION RUBY_REVISION
66#endif
67#ifdef YJIT_SUPPORT
68#define YJIT_DESCRIPTION " +YJIT " STRINGIZE(YJIT_SUPPORT)
69#else
70#define YJIT_DESCRIPTION " +YJIT"
71#endif
72#ifdef ZJIT_SUPPORT
73#define ZJIT_DESCRIPTION " +ZJIT " STRINGIZE(ZJIT_SUPPORT)
74#else
75#define ZJIT_DESCRIPTION " +ZJIT"
76#endif
77#if USE_MODULAR_GC
78#define GC_DESCRIPTION " +GC"
79#else
80#define GC_DESCRIPTION ""
81#endif
82 const char ruby_version[] = RUBY_VERSION;
83const char ruby_revision[] = RUBY_FULL_REVISION;
84 const char ruby_release_date[] = RUBY_RELEASE_DATE;
85 const char ruby_platform[] = RUBY_PLATFORM;
86 const int ruby_patchlevel = RUBY_PATCHLEVEL;
87const char ruby_api_version_name[] = RUBY_API_VERSION_NAME;
88 const char ruby_description[] =
89 "ruby " RUBY_VERSION RUBY_PATCHLEVEL_STR " "
90 "(" RUBY_RELEASE_DATETIME RUBY_REVISION_STR ") "
91 "[" RUBY_PLATFORM "]";
92static const int ruby_description_opt_point =
93 (int)(sizeof(ruby_description) - sizeof(" [" RUBY_PLATFORM "]"));
94
95 const char ruby_copyright[] = "ruby - Copyright (C) "
96 RUBY_BIRTH_YEAR_STR "-" RUBY_RELEASE_YEAR_STR " "
97 RUBY_AUTHOR;
98 const char ruby_engine[] = "ruby";
99
100// Might change after initialization
101const char *rb_dynamic_description = ruby_description;
102
103static inline void
104define_ruby_const(VALUE mod, const char *name, VALUE value, bool toplevel)
105{
106 if (toplevel) {
107 rb_define_global_const(name, value);
108 name += rb_strlen_lit("RUBY_");
109 }
110 rb_define_const(mod, name, value);
111}
112
113/* RDoc needs rb_define_const */
114#define rb_define_const(mod, name, value) \
115 define_ruby_const(mod, (mod == mRuby ? "RUBY_" name : name), value, (mod == mRuby))
116
117void
118Init_Ruby_module(void)
119{
120 rb_define_module("Ruby");
121}
122
124void
125Init_version(void)
126{
127 /*
128 * The Ruby[rdoc-ref:Ruby] module that contains portable information among
129 * implementations.
130 *
131 * The constants defined here are aliased in the toplevel with
132 * +RUBY_+ prefix.
133 */
134 VALUE mRuby = rb_define_module("Ruby");
135
136 enum {ruby_patchlevel = RUBY_PATCHLEVEL};
137 VALUE version = MKSTR(version);
138 VALUE ruby_engine_name = MKSTR(engine);
139 // MKSTR macro is a marker for fake.rb
140
141 /*
142 * The running version of ruby
143 */
144 rb_define_const(mRuby, "VERSION", /* MKSTR(version) */ version);
145 /*
146 * The date this ruby was released
147 */
148 rb_define_const(mRuby, "RELEASE_DATE", MKSTR(release_date));
149 /*
150 * The platform for this ruby
151 */
152 rb_define_const(mRuby, "PLATFORM", MKSTR(platform));
153 /*
154 * The patchlevel for this ruby. If this is a development build of ruby
155 * the patchlevel will be -1
156 */
157 rb_define_const(mRuby, "PATCHLEVEL", MKINT(patchlevel));
158 /*
159 * The GIT commit hash for this ruby.
160 */
161 rb_define_const(mRuby, "REVISION", MKSTR(revision));
162 /*
163 * The copyright string for ruby
164 */
165 rb_define_const(mRuby, "COPYRIGHT", MKSTR(copyright));
166 /*
167 * The engine or interpreter this ruby uses.
168 */
169 rb_define_const(mRuby, "ENGINE", /* MKSTR(engine) */ ruby_engine_name);
170 ruby_set_script_name(ruby_engine_name);
171 /*
172 * The version of the engine or interpreter this ruby uses.
173 */
174 rb_define_const(mRuby, "ENGINE_VERSION", /* MKSTR(version) */ version);
175
176 rb_provide("ruby2_keywords.rb");
177}
178
179#if USE_YJIT
180#define YJIT_OPTS_ON opt->yjit
181#else
182#define YJIT_OPTS_ON 0
183#endif
184
185#if USE_ZJIT
186#define ZJIT_OPTS_ON opt->zjit
187#else
188#define ZJIT_OPTS_ON 0
189#endif
190
191int ruby_mn_threads_enabled;
192
193#ifndef RB_DEFAULT_PARSER
194#define RB_DEFAULT_PARSER RB_DEFAULT_PARSER_PRISM
195#endif
196static ruby_default_parser_enum default_parser = RB_DEFAULT_PARSER;
197
198ruby_default_parser_enum
199rb_ruby_default_parser(void)
200{
201 return default_parser;
202}
203
204void
205rb_ruby_default_parser_set(ruby_default_parser_enum parser)
206{
207 default_parser = parser;
208}
209
210static void
211define_ruby_description(const char *const jit_opt)
212{
213#define JIT_DESCRIPTION YJIT_DESCRIPTION ZJIT_DESCRIPTION
214
215 static char desc[
216 sizeof(ruby_description)
217 + rb_strlen_lit(JIT_DESCRIPTION)
218 + rb_strlen_lit(" +MN")
219 + rb_strlen_lit(" +PRISM")
220#if USE_MODULAR_GC
221 + rb_strlen_lit(GC_DESCRIPTION)
222 // Assume the active GC name can not be longer than 20 chars
223 // so that we don't have to use strlen and remove the static
224 // qualifier from desc.
225 + RB_GC_MAX_NAME_LEN + 3
226#endif
227
228 ];
229
230 int n = ruby_description_opt_point;
231 memcpy(desc, ruby_description, n);
232# define append(s) (n += (int)strlcpy(desc + n, s, sizeof(desc) - n))
233 if (*jit_opt) append(jit_opt);
234 RUBY_ASSERT(n <= ruby_description_opt_point + (int)rb_strlen_lit(JIT_DESCRIPTION));
235 if (ruby_mn_threads_enabled) append(" +MN");
236 if (rb_ruby_prism_p()) append(" +PRISM");
237#if USE_MODULAR_GC
238 append(GC_DESCRIPTION);
239 if (rb_gc_modular_gc_loaded_p()) {
240 append("[");
241 append(rb_gc_active_gc_name());
242 append("]");
243 }
244#endif
245 append(ruby_description + ruby_description_opt_point);
246# undef append
247
248 VALUE mRuby = rb_path2class("Ruby");
249 VALUE description = rb_obj_freeze(rb_usascii_str_new_static(desc, n));
250 rb_dynamic_description = desc;
251
252 /*
253 * The full ruby version string, like <tt>ruby -v</tt> prints
254 */
255 rb_define_const(mRuby, "DESCRIPTION", /* MKSTR(description) */ description);
256#undef JIT_DESCRIPTION
257}
258
259void
260Init_ruby_description(ruby_cmdline_options_t *opt)
261{
262 const char *const jit_opt =
263 YJIT_OPTS_ON ? YJIT_DESCRIPTION :
264 ZJIT_OPTS_ON ? ZJIT_DESCRIPTION :
265 "";
266 define_ruby_description(jit_opt);
267}
268
269void
270ruby_set_yjit_description(void)
271{
272 VALUE mRuby = rb_path2class("Ruby");
273 rb_const_remove(rb_cObject, rb_intern("RUBY_DESCRIPTION"));
274 rb_const_remove(mRuby, rb_intern("DESCRIPTION"));
275 define_ruby_description(YJIT_DESCRIPTION);
276}
277
278void
279ruby_set_zjit_description(void)
280{
281 VALUE mRuby = rb_path2class("Ruby");
282 rb_const_remove(rb_cObject, rb_intern("RUBY_DESCRIPTION"));
283 rb_const_remove(mRuby, rb_intern("DESCRIPTION"));
284 define_ruby_description(ZJIT_DESCRIPTION);
285}
286
287void
288ruby_show_version(void)
289{
290 puts(rb_dynamic_description);
291
292#ifdef RUBY_LAST_COMMIT_TITLE
293 fputs("last_commit=" RUBY_LAST_COMMIT_TITLE, stdout);
294#endif
295#ifdef HAVE_MALLOC_CONF
296 if (malloc_conf) printf("malloc_conf=%s\n", malloc_conf);
297#endif
298 fflush(stdout);
299}
300
301void
302ruby_show_copyright(void)
303{
304 PRINT(copyright);
305 fflush(stdout);
306}
RUBY_ASSERT
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
globals.h
Ruby-level global variables / constants, visible from C.
rb_define_module
VALUE rb_define_module(const char *name)
Defines a top-level module.
Definition class.c:1591
ruby_set_script_name
void ruby_set_script_name(VALUE name)
Identical to ruby_script(), except it takes the name as a Ruby String instance.
Definition ruby.c:3066
rb_obj_freeze
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition object.c:1342
ruby_show_copyright
void ruby_show_copyright(void)
Prints the copyright notice of the CRuby interpreter to stdout.
Definition version.c:302
ruby_show_version
void ruby_show_version(void)
Prints the version information of the CRuby interpreter to stdout.
Definition version.c:288
rb_provide
void rb_provide(const char *feature)
Declares that the given feature is already provided by someone else.
Definition load.c:695
rb_strlen_lit
#define rb_strlen_lit(str)
Length of a string literal.
Definition string.h:1693
rb_usascii_str_new_static
VALUE rb_usascii_str_new_static(const char *ptr, long len)
Identical to rb_str_new_static(), except it generates a string of "US ASCII" encoding instead of "bin...
Definition string.c:1195
rb_path2class
VALUE rb_path2class(const char *path)
Resolves a Q::W::E::R-style path string to the actual class it points.
Definition variable.c:494
rb_const_remove
VALUE rb_const_remove(VALUE space, ID name)
Identical to rb_mod_remove_const(), except it takes the name as ID instead of VALUE.
Definition variable.c:3579
rb_define_global_const
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
Definition variable.c:4048
ruby_api_version
const int ruby_api_version[3]
API versions, in { major, minor, teeny } order.
Definition version.c:55
ruby_engine
const char ruby_engine[]
This is just "ruby" for us.
Definition version.c:98
RUBY_API_VERSION_TEENY
#define RUBY_API_VERSION_TEENY
Teeny version.
Definition version.h:76
ruby_platform
const char ruby_platform[]
Target platform identifier, in a C string.
Definition version.c:85
ruby_version
const char ruby_version[]
Stringised version.
Definition version.c:82
RUBY_API_VERSION_MAJOR
#define RUBY_API_VERSION_MAJOR
Major version.
Definition version.h:64
RUBY_API_VERSION_MINOR
#define RUBY_API_VERSION_MINOR
Minor version.
Definition version.h:70
RUBY_AUTHOR
#define RUBY_AUTHOR
Author of this project.
Definition version.h:32
ruby_copyright
const char ruby_copyright[]
Copyright notice.
Definition version.c:95
ruby_release_date
const char ruby_release_date[]
Date of release, in a C string.
Definition version.c:84
ruby_patchlevel
const int ruby_patchlevel
This is a monotonic increasing integer that describes specific "patch" level.
Definition version.c:86
ruby_description
const char ruby_description[]
This is what ruby -v prints to the standard error.
Definition version.c:88
ruby.h
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40