summaryrefslogtreecommitdiff
path: root/defs
diff options
context:
space:
mode:
Diffstat (limited to 'defs')
-rw-r--r--defs/gmake.mk462
-rw-r--r--defs/id.def48
-rw-r--r--defs/jit.mk107
-rw-r--r--defs/keywords2
-rw-r--r--defs/known_errors.def314
-rw-r--r--defs/lex.c.src2
-rw-r--r--defs/opt_insn_unif.def8
-rw-r--r--defs/tags.mk18
-rw-r--r--defs/universal.mk5
9 files changed, 668 insertions, 298 deletions
diff --git a/defs/gmake.mk b/defs/gmake.mk
index 316ff18c20..0320f9b7d5 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -1,23 +1,33 @@
# -*- mode: makefile-gmake; indent-tabs-mode: t -*-
reconfig config.status: export MAKE:=$(MAKE)
+export BASERUBY:=$(BASERUBY)
+export GIT
override gnumake_recursive := $(if $(findstring n,$(firstword $(MFLAGS))),,+)
override mflags := $(filter-out -j%,$(MFLAGS))
MSPECOPT += $(if $(filter -j%,$(MFLAGS)),-j)
nproc = $(subst -j,,$(filter -j%,$(MFLAGS)))
-ifneq ($(filter %darwin%,$(arch)),)
-INSTRUBY_ENV += SDKROOT=/
+ifeq ($(GITHUB_ACTIONS),true)
+# 93(bright yellow) is copied from .github/workflows/mingw.yml
+override ACTIONS_GROUP = @echo "::group::$(@:yes-%=%)"
+override ACTIONS_ENDGROUP = @echo "::endgroup::"
endif
+ifneq ($(filter darwin%,$(target_os)),)
+INSTRUBY_ENV += SDKROOT=
+endif
+INSTRUBY_ARGS += --gnumake
+
+ifeq ($(DOT_WAIT),)
CHECK_TARGETS := great exam love check test check% test% btest%
# expand test targets, and those dependents
TEST_TARGETS := $(filter $(CHECK_TARGETS),$(MAKECMDGOALS))
TEST_DEPENDS := $(filter-out commit $(TEST_TARGETS),$(MAKECMDGOALS))
TEST_TARGETS := $(patsubst great,exam,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out great $(TEST_TARGETS),$(TEST_DEPENDS))
-TEST_TARGETS := $(patsubst exam,check,$(TEST_TARGETS))
-TEST_TARGETS := $(patsubst check,test-spec test-all test-tool test-short,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst exam,test-bundled-gems test-bundler-parallel check,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst check,test-syntax-suggest test-spec test-all test-tool test-short,$(TEST_TARGETS))
TEST_TARGETS := $(patsubst test-rubyspec,test-spec,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out exam check test-spec $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst love,check,$(TEST_TARGETS))
@@ -27,15 +37,19 @@ TEST_DEPENDS := $(filter-out test-all $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst test,test-short,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out test $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst test-short,btest-ruby test-knownbug test-basic,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-basic,test-basic test-leaked-globals,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-spec test-bundled-gems-run,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems-run,test-bundled-gems-run $(PREPARE_BUNDLED_GEMS),$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems-prepare,test-bundled-gems-prepare $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundler-parallel,test-bundler-parallel $(PREPARE_BUNDLER),$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-syntax-suggest,test-syntax-suggest $(PREPARE_SYNTAX_SUGGEST),$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out test-short $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_DEPENDS += $(if $(filter great exam love check,$(MAKECMDGOALS)),all exts)
+TEST_TARGETS := $(patsubst yes-%,%,$(filter-out no-%,$(TEST_TARGETS)))
+endif
in-srcdir := $(if $(filter-out .,$(srcdir)),$(CHDIR) $(srcdir) &&)
-ifneq ($(filter -O0 -Od,$(optflags)),)
-override XCFLAGS := $(filter-out -D_FORTIFY_SOURCE=%,$(XCFLAGS))
-endif
-
ifeq ($(if $(filter all main exts enc trans libencs libenc libtrans \
prog program ruby ruby$(EXEEXT) \
wprogram rubyw rubyw$(EXEEXT) \
@@ -44,6 +58,13 @@ ifeq ($(if $(filter all main exts enc trans libencs libenc libtrans \
-include $(SHOWFLAGS)
endif
+ifeq ($(HAVE_BASERUBY):$(HAVE_GIT),yes:yes)
+override modified := $(shell $(BASERUBY) -C $(srcdir) tool/file2lastrev.rb --modified='%Y %m %d')
+override RUBY_RELEASE_YEAR := $(word 1,$(modified))
+override RUBY_RELEASE_MONTH := $(word 2,$(modified))
+override RUBY_RELEASE_DAY := $(word 3,$(modified))
+endif
+
ifneq ($(filter universal-%,$(arch)),)
define archcmd
%.$(1).S: %.c
@@ -59,10 +80,11 @@ define archcmd
%.i: %.$(1).i
endef
-$(foreach arch,$(arch_flags),\
+$(foreach arch,$(filter -arch=%,$(subst -arch ,-arch=,$(ARCH_FLAG))),\
$(eval $(call archcmd,$(patsubst -arch=%,%,$(value arch)),$(patsubst -arch=%,-arch %,$(value arch)))))
endif
+ifeq ($(DOT_WAIT),)
.PHONY: $(addprefix yes-,$(TEST_TARGETS))
ifneq ($(filter-out btest%,$(TEST_TARGETS)),)
@@ -70,14 +92,34 @@ $(addprefix yes-,$(TEST_TARGETS)): $(TEST_DEPENDS)
endif
ORDERED_TEST_TARGETS := $(filter $(TEST_TARGETS), \
- btest-ruby test-knownbug test-basic \
+ btest-ruby test-knownbug test-leaked-globals test-basic \
test-testframework test-tool test-ruby test-all \
- test-spec test-bundler-prepare test-bundler test-bundler-parallel \
+ test-spec test-syntax-suggest-prepare test-syntax-suggest \
+ test-bundler-prepare test-bundler test-bundler-parallel \
+ test-bundled-gems-precheck test-bundled-gems-fetch \
+ test-bundled-gems-prepare test-bundled-gems-run \
+ test-bundled-gems-spec \
+ )
+
+# grep ^yes-test-.*-precheck: template/Makefile.in defs/gmake.mk common.mk
+test_prechecks := $(filter $(ORDERED_TEST_TARGETS),\
+ test-leaked-globals \
+ test-all \
+ test-spec \
+ test-syntax-suggest \
+ test-bundler \
+ test-bundler-parallel \
+ test-bundled-gems\
)
-prev_test := $(if $(filter test-spec,$(ORDERED_TEST_TARGETS)),test-spec-precheck)
+prev_test := $(subst test-bundler-parallel,test-bundler,$(test_prechecks))
+prev_test := $(addsuffix -precheck,$(prev_test))
+first_test_prechecks := $(prev_test)
+
$(foreach test,$(ORDERED_TEST_TARGETS), \
- $(eval yes-$(value test) no-$(value test): $(value prev_test)); \
+ $(eval yes-$(value test): $(addprefix yes-,$(value prev_test))); \
+ $(eval no-$(value test): $(addprefix no-,$(value prev_test))); \
$(eval prev_test := $(value test)))
+endif
ifneq ($(if $(filter install,$(MAKECMDGOALS)),$(filter uninstall,$(MAKECMDGOALS))),)
install-targets := $(filter install uninstall,$(MAKECMDGOALS))
@@ -100,12 +142,16 @@ yes-test-bundler-parallel: PARALLELRSPECOPTS += $(if $(nproc),-n$(shell expr $(n
# Cross reference needs to parse all files at once
love install reinstall: RDOCFLAGS = --force-update
+ifneq ($(if $(filter -flto%,$(CFLAGS)),$(subst darwin,,$(arch)),$(arch)),$(arch))
+override EXE_LDFLAGS = $(filter-out -g%,$(LDFLAGS))
+endif
+
$(srcdir)/missing/des_tables.c: $(srcdir)/missing/crypt.c
ifeq ($(if $(filter yes,$(CROSS_COMPILING)),,$(CC)),)
touch $@
else
@$(ECHO) building make_des_table
- $(CC) $(INCFLAGS) $(CPPFLAGS) -DDUMP $(LDFLAGS) $(XLDFLAGS) $(LIBS) -omake_des_table $(srcdir)/missing/crypt.c
+ $(CC) $(INCFLAGS) $(CPPFLAGS) -DDUMP $(EXE_LDFLAGS) $(XLDFLAGS) $(LIBS) -omake_des_table $(srcdir)/missing/crypt.c
@[ -x ./make_des_table ]
@$(ECHO) generating $@
$(Q) $(MAKEDIRS) $(@D)
@@ -116,10 +162,14 @@ endif
config.status: $(wildcard config.cache)
+ifneq (ruby,$(PROGRAM))
+ruby: $(PROGRAM);
+endif
+
STUBPROGRAM = rubystub$(EXEEXT)
IGNOREDPATTERNS = %~ .% %.orig %.rej \#%\#
SCRIPTBINDIR := $(if $(EXEEXT),,exec/)
-SCRIPTPROGRAMS = $(addprefix $(SCRIPTBINDIR),$(addsuffix $(EXEEXT),$(filter-out $(IGNOREDPATTERNS),$(notdir $(wildcard $(srcdir)/libexec/*)))))
+SCRIPTPROGRAMS = $(addprefix $(SCRIPTBINDIR),$(addsuffix $(EXEEXT),$(filter-out $(IGNOREDPATTERNS),$(notdir $(wildcard $(srcdir)/bin/*)))))
stub: $(STUBPROGRAM)
scriptbin: $(SCRIPTPROGRAMS)
@@ -134,7 +184,7 @@ $(STUBPROGRAM): rubystub.$(OBJEXT) $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SE
rubystub$(EXEEXT):
@rm -f $@
$(ECHO) linking $@
- $(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) rubystub.$(OBJEXT) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@
+ $(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) rubystub.$(OBJEXT) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@
$(Q) $(POSTLINK)
$(if $(STRIP),$(Q) $(STRIP) $@)
@@ -145,28 +195,34 @@ $(SCRIPTBINDIR)%$(EXEEXT): bin/% $(STUBPROGRAM) \
$(Q) chmod +x $@
$(Q) $(POSTLINK)
-$(TIMESTAMPDIR)/.exec.time:
- $(Q) mkdir exec
- $(Q) exit > $@
+$(SCRIPTBINDIR):
+ $(Q) mkdir $@
.PHONY: commit
-commit: $(if $(filter commit,$(MAKECMDGOALS)),$(filter-out commit,$(MAKECMDGOALS))) up
+COMMIT_PREPARE := $(subst :,\:,$(filter-out commit do-commit,$(MAKECMDGOALS))) up
+
+commit: pre-commit $(DOT_WAIT) do-commit $(DOT_WAIT) post_commit
+pre-commit: $(COMMIT_PREPARE)
+do-commit: $(if $(DOT_WAIT),,pre-commit)
@$(BASERUBY) -C "$(srcdir)" -I./tool/lib -rvcs -e 'VCS.detect(".").commit'
+post-commit: $(if $(DOT_WAIT),,do-commit)
+$(Q) \
{ \
$(in-srcdir) \
- exec sed -f tool/prereq.status defs/gmake.mk template/Makefile.in common.mk; \
+ exec sed -f tool/prereq.status defs/gmake.mk template/Makefile.in common.mk depend; \
} | \
- $(MAKE) $(mflags) Q=$(Q) ECHO=$(ECHO) srcdir="$(srcdir)" srcs_vpath="" CHDIR="$(CHDIR)" \
- BOOTSTRAPRUBY="$(BOOTSTRAPRUBY)" MINIRUBY="$(BASERUBY)" BASERUBY="$(BASERUBY)" \
+ $(MAKE) $(mflags) Q=$(Q) ECHO=$(ECHO) \
+ top_srcdir="$(top_srcdir)" srcdir="$(srcdir)" srcs_vpath="" CHDIR="$(CHDIR)" \
+ BOOTSTRAPRUBY="$(BOOTSTRAPRUBY)" BOOTSTRAPRUBY_OPT="$(BOOTSTRAPRUBY_OPT)" \
+ MINIRUBY="$(BASERUBY)" BASERUBY="$(BASERUBY)" HAVE_BASERUBY="$(HAVE_BASERUBY)" \
VCSUP="" ENC_MK=.top-enc.mk REVISION_FORCE=PHONY CONFIGURE="$(CONFIGURE)" -f - \
update-src srcs all-incs
GITHUB_RUBY_URL = https://github.com/ruby/ruby
PR =
-COMMIT_GPG_SIGN = $(shell git -C "$(srcdir)" config commit.gpgsign)
-REMOTE_GITHUB_URL = $(shell git -C "$(srcdir)" config remote.github.url)
+COMMIT_GPG_SIGN = $(shell $(GIT_IN_SRC) config commit.gpgsign)
+REMOTE_GITHUB_URL = $(shell $(GIT_IN_SRC) config remote.github.url)
COMMITS_NOTES = commits
.PHONY: fetch-github
@@ -179,21 +235,21 @@ define fetch-github
exit 1; \
)
$(eval REMOTE_GITHUB_URL := $(REMOTE_GITHUB_URL))
- $(if $(REMOTE_GITHUB_URL),, \
- echo adding $(GITHUB_RUBY_URL) as remote github; \
- git -C "$(srcdir)" remote add github $(GITHUB_RUBY_URL); \
- git -C "$(srcdir)" config --add remote.github.fetch +refs/notes/$(COMMITS_NOTES):refs/notes/$(COMMITS_NOTES)
- $(eval REMOTE_GITHUB_URL := $(GITHUB_RUBY_URL)) \
+ $(if $(REMOTE_GITHUB_URL),,
+ echo adding $(GITHUB_RUBY_URL) as remote github
+ $(GIT_IN_SRC) remote add github $(GITHUB_RUBY_URL)
+ $(GIT_IN_SRC) config --add remote.github.fetch +refs/notes/$(COMMITS_NOTES):refs/notes/$(COMMITS_NOTES)
+ $(eval REMOTE_GITHUB_URL := $(GITHUB_RUBY_URL))
)
- $(if $(git -C "$(srcdir)" rev-parse "github/pull/$(1)/head" -- 2> /dev/null), \
- git -C "$(srcdir)" branch -f "gh-$(1)" "github/pull/$(1)/head", \
- git -C "$(srcdir)" fetch -f github "pull/$(1)/head:gh-$(1)" \
+ $(if $(shell $(GIT_IN_SRC) rev-parse "github/pull/$(1)/head" -- 2> /dev/null),
+ $(GIT_IN_SRC) branch -f "gh-$(1)" "github/pull/$(1)/head",
+ $(GIT_IN_SRC) fetch -f github "pull/$(1)/head:gh-$(1)"
)
endef
.PHONY: checkout-github
checkout-github: fetch-github
- git -C "$(srcdir)" checkout "gh-$(PR)"
+ $(GIT_IN_SRC) checkout "gh-$(PR)"
.PHONY: update-github
update-github: fetch-github
@@ -206,30 +262,31 @@ update-github: fetch-github
$(eval PR_BRANCH := $(word 2,$(PULL_REQUEST_FORK_BRANCH)))
$(eval GITHUB_UPDATE_WORKTREE := $(shell mktemp -d "$(srcdir)/gh-$(PR)-XXXXXX"))
- git -C "$(srcdir)" worktree add $(notdir $(GITHUB_UPDATE_WORKTREE)) "gh-$(PR)"
- git -C "$(GITHUB_UPDATE_WORKTREE)" merge master --no-edit
+ $(GIT_IN_SRC) worktree add $(notdir $(GITHUB_UPDATE_WORKTREE)) "gh-$(PR)"
+ $(GIT) -C "$(GITHUB_UPDATE_WORKTREE)" merge master --no-edit
@$(BASERUBY) -e 'print "Are you sure to push this to PR=$(PR)? [Y/n]: "; exit(gets.chomp != "n")'
- git -C "$(srcdir)" remote add fork-$(PR) git@github.com:$(FORK_REPO).git
- git -C "$(GITHUB_UPDATE_WORKTREE)" push fork-$(PR) gh-$(PR):$(PR_BRANCH)
- git -C "$(srcdir)" remote rm fork-$(PR)
- git -C "$(srcdir)" worktree remove $(notdir $(GITHUB_UPDATE_WORKTREE))
- git -C "$(srcdir)" branch -D gh-$(PR)
+ $(GIT_IN_SRC) remote add fork-$(PR) git@github.com:$(FORK_REPO).git
+ $(GIT) -C "$(GITHUB_UPDATE_WORKTREE)" push fork-$(PR) gh-$(PR):$(PR_BRANCH)
+ $(GIT_IN_SRC) remote rm fork-$(PR)
+ $(GIT_IN_SRC) worktree remove $(notdir $(GITHUB_UPDATE_WORKTREE))
+ $(GIT_IN_SRC) branch -D gh-$(PR)
.PHONY: pull-github
pull-github: fetch-github
$(call pull-github,$(PR))
define pull-github
- $(eval GITHUB_MERGE_BASE := $(shell git -C "$(srcdir)" log -1 --format=format:%H))
- $(eval GITHUB_MERGE_BRANCH := $(shell git -C "$(srcdir)" symbolic-ref --short HEAD))
+ $(eval GITHUB_MERGE_BASE := $(shell $(GIT_IN_SRC) rev-parse HEAD)
+ $(eval GITHUB_MERGE_BRANCH := $(shell $(GIT_IN_SRC) symbolic-ref --short HEAD))
$(eval GITHUB_MERGE_WORKTREE := $(shell mktemp -d "$(srcdir)/gh-$(1)-XXXXXX"))
- git -C "$(srcdir)" worktree add $(notdir $(GITHUB_MERGE_WORKTREE)) "gh-$(1)"
- git -C "$(GITHUB_MERGE_WORKTREE)" rebase $(GITHUB_MERGE_BRANCH)
+ $(GIT_IN_SRC) worktree prune
+ $(GIT_IN_SRC) worktree add $(notdir $(GITHUB_MERGE_WORKTREE)) "gh-$(1)"
+ $(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase $(GITHUB_MERGE_BRANCH)
$(eval COMMIT_GPG_SIGN := $(COMMIT_GPG_SIGN))
$(if $(filter true,$(COMMIT_GPG_SIGN)), \
- git -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "git commit --amend --no-edit -S" "$(GITHUB_MERGE_BASE)"; \
+ $(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "$(GIT) commit --amend --no-edit -S" "$(GITHUB_MERGE_BASE)"; \
)
- git -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "git notes add --message 'Merged: $(GITHUB_RUBY_URL)/pull/$(1)'" "$(GITHUB_MERGE_BASE)"
+ $(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "$(GIT) notes add --message 'Merged: $(GITHUB_RUBY_URL)/pull/$(1)'" "$(GITHUB_MERGE_BASE)"
endef
.PHONY: fetch-github-%
@@ -238,23 +295,48 @@ fetch-github-%:
.PHONY: checkout-github-%
checkout-github-%: fetch-github-%
- git -C "$(srcdir)" checkout "gh-$*"
+ $(GIT_IN_SRC) checkout "gh-$*"
.PHONY: pr-% pull-github-%
pr-% pull-github-%: fetch-github-%
$(call pull-github,$*)
HELP_EXTRA_TASKS = \
- " checkout-github: checkout GitHub Pull Request [PR=1234]" \
- " pull-github: rebase GitHub Pull Request to new worktree [PR=1234]" \
- " update-github: merge master branch and push it to Pull Request [PR=1234]" \
+ " checkout-github: checkout GitHub Pull Request [PR=1234]" \
+ " pull-github: rebase GitHub Pull Request to new worktree [PR=1234]" \
+ " update-github: merge master branch and push it to Pull Request [PR=1234]" \
+ " tags: generate TAGS file" \
""
-extract-gems: $(HAVE_BASERUBY:yes=update-gems)
-
-bundled-gems := $(shell sed '/^[ ]*\#/d;/^[ ]*$$/d;s/[ ][ ]*/-/;s/[ ].*//' $(srcdir)/gems/bundled_gems)
-
-update-gems: | $(patsubst %,gems/%.gem,$(bundled-gems))
+# 1. squeeze spaces
+# 2. strip and skip comment/empty lines
+# 3. "gem x.y.z URL xxxxxx" -> "gem|x.y.z|xxxxxx|URL"
+# 4. "gem x.y.z URL" -> "gem-x.y.z"
+bundled-gems := $(shell sed \
+ -e 's/[ ][ ]*/ /g' \
+ -e 's/^ //;s/\#.*//;s/ *$$//;/^$$/d' \
+ $(if $(filter yes,$(HAVE_GIT)), \
+ -e 's/^\(.*\) \(.*\) \(.*\) \(.*\)/\1|\2|\4|\3/' \
+ ) \
+ -e 's/ /-/;s/ .*//' \
+ $(srcdir)/gems/bundled_gems)
+
+bundled-gems-rev := $(filter-out $(subst |,,$(bundled-gems)),$(bundled-gems))
+bundled-gems := $(filter-out $(bundled-gems-rev),$(bundled-gems))
+
+# calls $(1) with name, version, revision, URL
+foreach-bundled-gems-rev = \
+ $(foreach g,$(bundled-gems-rev),$(call foreach-bundled-gems-rev-0,$(1),$(subst |, ,$(value g))))
+foreach-bundled-gems-rev-0 = \
+ $(call $(1),$(word 1,$(2)),$(word 2,$(2)),$(word 3,$(2)),$(word 4,$(2)))
+bundled-gem-gemfile = $(srcdir)/gems/$(1)-$(2).gem
+bundled-gem-gemspec = $(srcdir)/gems/src/$(1)/$(1).gemspec
+bundled-gem-extracted = $(srcdir)/.bundle/gems/$(1)-$(2)
+bundled-gem-revision = $(srcdir)/.bundle/.timestamp/$(1).revision
+
+update-gems: | $(patsubst %,$(srcdir)/gems/%.gem,$(bundled-gems))
+update-gems: | $(call foreach-bundled-gems-rev,bundled-gem-gemfile)
+update-gems: | $(call foreach-bundled-gems-rev,bundled-gem-gemspec)
test-bundler-precheck: | $(srcdir)/.bundle/cache
@@ -262,7 +344,7 @@ $(srcdir)/.bundle/cache:
$(MAKEDIRS) $(@D) $(CACHE_DIR)
$(LN_S) ../.downloaded-cache $@
-gems/%.gem:
+$(srcdir)/gems/%.gem:
$(ECHO) Downloading bundled gem $*...
$(Q) $(BASERUBY) -C "$(srcdir)" \
-I./tool -rdownloader \
@@ -273,73 +355,109 @@ gems/%.gem:
-e 'File.unlink(*old) and' \
-e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})'
-extract-gems: | $(patsubst %,.bundle/gems/%,$(bundled-gems))
+extract-gems: | $(patsubst %,$(srcdir)/.bundle/gems/%,$(bundled-gems))
+extract-gems: | $(call foreach-bundled-gems-rev,bundled-gem-extracted)
-.bundle/gems/%: gems/%.gem | .bundle/gems
+$(srcdir)/.bundle/gems/%: $(srcdir)/gems/%.gem | .bundle/gems
$(ECHO) Extracting bundle gem $*...
$(Q) $(BASERUBY) -C "$(srcdir)" \
- -Itool -rgem-unpack \
- -e 'Gem.unpack("gems/$(@F).gem", ".bundle/gems")'
+ -Itool/lib -rbundled_gem \
+ -e 'BundledGem.unpack("gems/$(@F).gem", ".bundle")'
+
+$(srcdir)/.bundle/.timestamp:
+ $(MAKEDIRS) $@
+
+define build-gem
+$(srcdir)/gems/src/$(1)/.git: | $(srcdir)/gems/src
+ $(ECHO) Cloning $(4)
+ $(Q) $(GIT) clone --depth=1 --no-tags $(4) $$(@D)
+
+$(bundled-gem-revision): \
+ $(if $(if $(wildcard $$(@)),$(filter $(3),$(shell cat $$(@)))),,PHONY) \
+ | $(srcdir)/.bundle/.timestamp $(srcdir)/gems/src/$(1)/.git
+ $(ECHO) Update $(1) to $(3)
+ $(Q) $(CHDIR) "$(srcdir)/gems/src/$(1)" && \
+ if [ `$(GIT) rev-parse HEAD` != $(3) ]; then \
+ $(GIT) fetch origin $(3) && \
+ $(GIT) checkout --detach $(3) && \
+ :; \
+ fi
+ echo $(3) | $(IFCHANGE) $$(@) -
+
+# The repository of minitest does not include minitest.gemspec because it uses hoe.
+# This creates a dummy gemspec.
+$(bundled-gem-gemspec): $(bundled-gem-revision) \
+ | $(srcdir)/gems/src/$(1)/.git
+ $(Q) $(BASERUBY) -I$(tooldir)/lib -rbundled_gem -e 'BundledGem.dummy_gemspec(*ARGV)' $$(@)
+
+$(bundled-gem-gemfile): $(bundled-gem-gemspec) $(bundled-gem-revision)
+ $(ECHO) Building $(1)@$(3) to $$(@)
+ $(Q) $(BASERUBY) -C "$(srcdir)" \
+ -Itool/lib -rbundled_gem \
+ -e 'BundledGem.build("gems/src/$(1)/$(1).gemspec", "$(2)", "gems", validation: false)'
+
+endef
+define build-gem-0
+$(eval $(call build-gem,$(1),$(2),$(3),$(4)))
+endef
+
+$(call foreach-bundled-gems-rev,build-gem-0)
+
+$(srcdir)/gems/src:
+ $(MAKEDIRS) $@
$(srcdir)/.bundle/gems:
$(MAKEDIRS) $@
+ifneq ($(DOT_WAIT),)
+up:: $(DOT_WAIT) after-update
+after-update:: MINIRUBY = $(BASERUBY)
+endif
+
ifneq ($(filter update-bundled_gems refresh-gems,$(MAKECMDGOALS)),)
update-gems: update-bundled_gems
endif
-ifeq ($(filter 0 1,$(words $(arch_flags))),)
-$(foreach x,$(patsubst -arch=%,%,$(arch_flags)), \
- $(eval $$(MJIT_HEADER:.h=)-$(value x).h \
- $$(MJIT_MIN_HEADER:.h=)-$(value x).h \
- $$(TIMESTAMPDIR)/$$(MJIT_HEADER:.h=)-$(value x).time \
- : ARCH_FLAG := -arch $(value x)))
-
-$(foreach x,$(patsubst -arch=%,%,$(arch_flags)), \
- $(eval $$(MJIT_HEADER:.h=)-$(value x).h: \
- $$(TIMESTAMPDIR)/$$(MJIT_HEADER:.h=)-$(value x).time))
-
-mjit_min_headers := $(patsubst -arch=%,$(MJIT_MIN_HEADER:.h=-%.h),$(arch_flags))
-$(MJIT_MIN_HEADER): $(mjit_min_headers) $(PREP)
- @ set -e; set $(patsubst -arch=%,%,$(arch_flags)); \
- cd $(@D); h=$(@F:.h=); \
- exec > $(@F).new; \
- echo '#if 0'; \
- for arch; do\
- echo "#elif defined __$${arch}__"; \
- echo "# include \"$$h-$$arch.h\""; \
- done; \
- echo "#else"; echo "# error unsupported platform"; echo "#endif"
- $(IFCHANGE) $@ $@.new
- $(Q) $(MAKEDIRS) $(MJIT_HEADER_INSTALL_DIR)
- $(Q) $(MAKE_LINK) $@ $(MJIT_HEADER_INSTALL_DIR)/$(@F)
-
+.SECONDARY: update-unicode-files
+.SECONDARY: update-unicode-auxiliary-files
+.SECONDARY: update-unicode-ucd-emoji-files
+.SECONDARY: update-unicode-emoji-files
+
+ifneq ($(DOT_WAIT),)
+.NOTPARALLEL: update-unicode
+.NOTPARALLEL: update-unicode-files
+.NOTPARALLEL: update-unicode-auxiliary-files
+.NOTPARALLEL: update-unicode-ucd-emoji-files
+.NOTPARALLEL: update-unicode-emoji-files
+.NOTPARALLEL: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
+.NOTPARALLEL: $(UNICODE_AUXILIARY_FILES)
+.NOTPARALLEL: $(UNICODE_UCD_EMOJI_FILES) $(UNICODE_EMOJI_FILES)
endif
-ifeq ($(if $(wildcard $(filter-out .,$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES))),,\
- $(wildcard $(srcdir)/lib/unicode_normalize/tables.rb)),)
-# Needs the dependency when any Unicode data file exists, or
-# normalization tables script doesn't. Otherwise, when the target
-# only exists, use it as-is.
-.PHONY: $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time
-UNICODE_TABLES_TIMESTAMP =
-$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: \
- $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
+ifeq ($(HAVE_GIT),yes)
+REVISION_LATEST := $(shell $(GIT_IN_SRC) rev-parse HEAD 2>/dev/null)
+else
+REVISION_LATEST := update
+endif
+REVISION_IN_HEADER := $(shell sed '/^\#define RUBY_FULL_REVISION "\(.*\)"/!d;s//\1/;q' $(wildcard $(srcdir)/revision.h revision.h) /dev/null 2>/dev/null)
+ifeq ($(REVISION_IN_HEADER),)
+REVISION_IN_HEADER := none
endif
-
-REVISION_IN_HEADER := $(shell sed -n 's/^\#define RUBY_FULL_REVISION "\(.*\)"/\1/p' $(srcdir)/revision.h 2>/dev/null)
-REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && git log -1 --format=%H 2>/dev/null)
ifneq ($(REVISION_IN_HEADER),$(REVISION_LATEST))
-# GNU make treat the target as unmodified when its dependents get
-# updated but it is not updated, while others may not.
-$(srcdir)/revision.h: $(REVISION_H)
+$(REVISION_H): PHONY
endif
+include $(top_srcdir)/yjit/yjit.mk
+include $(top_srcdir)/zjit/zjit.mk
+include $(top_srcdir)/defs/jit.mk
+
# Query on the generated rdoc
#
# $ make rdoc:Integer#+
-rdoc\:%: PHONY
- $(Q)$(RUNRUBY) $(srcdir)/libexec/ri --no-standard-docs --doc-dir=$(RDOCOUT) $(patsubst rdoc:%,%,$@)
+rdoc\:%: PHONY programs $(RDOCOUT) update-default-gemspecs
+ $(Q)$(RUNRUBY) $(RUNOPT0) -I$(tooldir)/lib -rbundled_gem \
+ -e "load BundledGem.command('rdoc', 'ri')" -- \
+ --no-standard-docs --doc-dir=$(RDOCOUT) $(patsubst rdoc:%,%,$@)
test_%.rb test/%: programs PHONY
$(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) -- $(patsubst test/%,%,$@)
@@ -350,8 +468,11 @@ spec/bundler/%: PHONY
spec/bundler: test-bundler-parallel
$(Q)$(NULLCMD)
-spec/%: programs exts PHONY
- $(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@)
+# workaround to avoid matching non ruby files with "spec/%/" under GNU make 3.81
+spec/%_spec.c:
+ $(empty)
+$(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h:
+ $(empty)
benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY
$(Q)$(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \
@@ -359,6 +480,10 @@ benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY
--executables="built-ruby::$(BENCH_RUBY) --disable-gem" \
$(srcdir)/$@ $(BENCH_OPTS) $(OPTS)
+clean-local:: TARGET_SO = $(PROGRAM) $(WPROGRAM) $(LIBRUBY_SO) $(STATIC_RUBY) miniruby goruby
+clean-local::
+ -$(Q)$(RMALL) $(cleanlibs)
+
clean-srcs-ext::
$(Q)$(RM) $(patsubst $(srcdir)/%,%,$(EXT_SRCS))
@@ -374,27 +499,128 @@ endif
update-deps:
$(eval update_deps := $(shell date +update-deps-%Y%m%d))
$(eval deps_dir := $(shell mktemp -d)/$(update_deps))
- $(eval GIT_DIR := $(shell git -C $(srcdir) rev-parse --absolute-git-dir))
- git --git-dir=$(GIT_DIR) worktree add $(deps_dir)
+ $(eval GIT_DIR := $(shell $(GIT_IN_SRC) rev-parse --absolute-git-dir))
+ $(GIT) --git-dir=$(GIT_DIR) worktree add $(deps_dir)
cp $(tooldir)/config.guess $(tooldir)/config.sub $(deps_dir)/tool
[ -f config.status ] && cp config.status $(deps_dir)
cd $(deps_dir) && autoconf && \
exec ./configure -q -C --enable-load-relative --disable-install-doc --disable-rubygems 'optflags=-O0' 'debugflags=-save-temps=obj -g'
$(RUNRUBY) -C $(deps_dir) tool/update-deps --fix
- git -C $(deps_dir) diff --no-ext-diff --ignore-submodules --exit-code || \
- git -C $(deps_dir) commit --all --message='Update dependencies'
- git --git-dir=$(GIT_DIR) worktree remove $(deps_dir)
+ $(GIT) -C $(deps_dir) diff --no-ext-diff --ignore-submodules --exit-code || \
+ $(GIT) -C $(deps_dir) commit --all --message='Update dependencies'
+ $(GIT) --git-dir=$(GIT_DIR) worktree remove $(deps_dir)
$(RMDIR) $(dir $(deps_dir))
- git --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps)
- git --git-dir=$(GIT_DIR) branch --delete $(update_deps)
+ $(GIT) --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps)
+ $(GIT) --git-dir=$(GIT_DIR) branch --delete $(update_deps)
+
+fix-depends check-depends: all hello
+ $(BASERUBY) -C $(srcdir) tool/update-deps $(if $(filter fix-%,$@),--fix)
# order-only-prerequisites doesn't work for $(RUBYSPEC_CAPIEXT)
# because the same named directory exists in the source tree.
-$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h $(RUBY_H_INCLUDES) $(LIBRUBY_SO)
- $(ECHO) building $@
+$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(RUBYSPEC_CAPIEXT_DEPS) \
+ | build-ext yes-rubyspec-capiext
+ $(no_silence:no=$(ECHO) building $@)
$(Q) $(MAKEDIRS) $(@D)
- $(Q) $(DLDSHARED) $(XDLDFLAGS) $(XLDFLAGS) $(ARCH_FLAG) $(ARCH_FLAG) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBY_SO)
+ $(Q) $(DLDSHARED) -L. $(XDLDFLAGS) $(XLDFLAGS) $(LDFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBYARG)
+ifneq ($(POSTLINK),)
+ $(Q) $(POSTLINK)
+endif
$(Q) $(RMALL) $@.*
-rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c)))
- @ $(NULLCMD)
+RUBYSPEC_CAPIEXT_EXTS := $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c)))
+rubyspec-capiext: $(RUBYSPEC_CAPIEXT_EXTS)
+
+spec/%/ spec/%_spec.rb: programs exts $(RUBYSPEC_CAPIEXT_BUILD) PHONY
+ +$(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@)
+
+ruby.pc: $(filter-out ruby.pc,$(ruby_pc))
+
+# `make matz`: bump up the MINOR;
+# Copying NEWS.md to doc/NEWS/, and empty the details in NEWS.md.
+#
+# `make matz NEW=x.y`: bump up to x.y.0;
+# Just update the version in the title of NEWS.md.
+
+matz: up
+matz-commit: OLD := $(MAJOR).$(MINOR).0
+ifdef NEW
+matz-commit: MAJOR := $(word 1,$(subst ., ,$(NEW)))
+matz-commit: MINOR := $(word 2,$(subst ., ,$(NEW)))
+matz-commit: $(DOT_WAIT) bump_news
+bump_news$(DOT_WAIT): up
+bump_headers$(DOT_WAIT): bump_news
+else
+matz-commit: MINOR := $(shell expr $(MINOR) + 1)
+matz-commit: $(DOT_WAIT) reset_news
+flush_news$(DOT_WAIT): up
+bump_headers$(DOT_WAIT): reset_news
+endif
+
+matz: $(DOT_WAIT) matz-commit
+matz-commit: bump_headers
+matz-commit: override NEW := $(MAJOR).$(MINOR).0
+matz-commit: files := include/ruby/version.h include/ruby/internal/abi.h
+matz-commit: message := Development of $(NEW) started.
+
+flush_news:
+ $(GIT_IN_SRC) mv -f NEWS.md doc/NEWS/NEWS-$(OLD).md
+ $(GIT_IN_SRC) commit -m "[DOC] Flush NEWS.md"
+
+.PHONY: flush_news reset_news bump_news bump_headers
+
+bump_headers:
+ sed -i~ \
+ -e "s/^\(#define RUBY_API_VERSION_MAJOR\) .*/\1 $(MAJOR)/" \
+ -e "s/^\(#define RUBY_API_VERSION_MINOR\) .*/\1 $(MINOR)/" \
+ -e "s/^\(#define RUBY_ABI_VERSION\) .*/\1 0/" \
+ $(files:%=$(srcdir)/%)
+
+reset_news: flush_news
+ $(BASERUBY) -C $(srcdir) -p -00 \
+ -e 'BEGIN {old, new = ARGV.shift(2); STDOUT.reopen(ARGV.shift)}' \
+ -e 'case $$.' \
+ -e 'when 1; $$_.sub!(/Ruby \K[0-9.]+/, new)' \
+ -e 'when 2; $$_.sub!(/\*\*\K[0-9.]+(?=\*\*)/, old)' \
+ -e 'end' \
+ -e 'next if /^[\[ *]/ =~ $$_' \
+ -e '$$_.sub!(/\n{2,}\z/, "\n\n")' \
+ $(OLD) $(NEW) NEWS.md doc/NEWS/NEWS-$(OLD).md
+
+bump_news:
+ $(BASERUBY) -C $(srcdir) -p -i \
+ -e 'BEGIN {new = ARGV.shift; print gets("").sub(/Ruby \K[0-9.]+/, new)}' \
+ $(NEW) NEWS.md
+
+matz: matz-commit matz-push
+
+matz-commit:
+ $(GIT_IN_SRC) add NEWS.md $(files)
+ $(GIT_IN_SRC) commit -m "$(message)"
+
+GIT_REMOTE_ORIGIN = origin
+
+matz-push: matz-commit
+ $(eval origin_url := $(shell $(GIT_IN_SRC) remote get-url $(GIT_REMOTE_ORIGIN)))
+ $(if $(origin_url),,@false)
+ $(eval last_commit := $(shell $(GIT_IN_SRC) log -n1 --format=%H --author=matz HEAD~..HEAD))
+ $(if $(last_commit),,$(ECHO) No matz commits 1>&2; false)
+ $(if $(filter 12-25 12-26,$(shell date +%m-%d)),,$(ECHO) Not the release date 1>&2; false)
+ $(ECHO) $$'\e[31m'Pushing to $$'\e[7m'$(GIT_REMOTE_ORIGIN)$$'\e[27m'" ($(origin_url))"$$'\e[m'
+ $(GIT_IN_SRC) push $(GIT_REMOTE_ORIGIN)
+
+tags:
+ $(MAKE) GIT="$(GIT)" -C "$(srcdir)" -f defs/tags.mk
+
+
+# ripper_srcs makes all sources at once. invoking this target multiple
+# times in parallel means all sources will be built for the number of
+# sources times respectively.
+ifneq ($(DOT_WAIT),)
+.NOTPARALLEL: ripper_srcs
+else
+ripper_src =
+$(foreach r,$(RIPPER_SRCS),$(eval $(value r): | $(value ripper_src))\
+ $(eval ripper_src := $(value r)))
+ripper_srcs: $(ripper_src)
+endif
diff --git a/defs/id.def b/defs/id.def
index fc7a04ffbc..344b072e76 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -2,11 +2,14 @@
firstline, predefined = __LINE__+1, %[\
max
min
+ hash
freeze
nil?
inspect
intern
object_id
+ __id__
+ const_added
const_missing
method_missing MethodMissing
method_added
@@ -24,7 +27,8 @@ firstline, predefined = __LINE__+1, %[\
lambda
send
__send__
- __attached__
+ __recursive_key__
+ clone
initialize
initialize_copy
initialize_clone
@@ -56,6 +60,12 @@ firstline, predefined = __LINE__+1, %[\
quo
name
nil
+ path
+ pack
+ buffer
+ include?
+ aborted
+ exited
_ UScore
@@ -69,10 +79,13 @@ firstline, predefined = __LINE__+1, %[\
_7 NUMPARAM_7
_8 NUMPARAM_8
_9 NUMPARAM_9
+ <it> ItImplicit
+ it It
"/*NULL*/" NULL
empty?
eql?
+ default
respond_to? Respond_to
respond_to_missing? Respond_to_missing
<IFUNC>
@@ -86,12 +99,15 @@ firstline, predefined = __LINE__+1, %[\
core#hash_merge_ptr
core#hash_merge_kwd
core#raise
+ core#sprintf
- debug#created_info
$_ LASTLINE
$~ BACKREF
$! ERROR_INFO
+
+ Ruby
]
# VM ID OP Parser Token
@@ -138,6 +154,21 @@ class KeywordError < RuntimeError
end
end
+def id2varname(token, prefix = nil)
+ if /#/ =~ token
+ token = "_#{token.gsub(/\W+/, '_')}"
+ else
+ token = token.sub(/\?/, 'P')
+ token = prefix + token if prefix
+ token.sub!(/\A[a-z]/) {$&.upcase}
+ token.sub!(/\A\$/, "_G_")
+ token.sub!(/\A@@/, "_C_")
+ token.sub!(/\A@/, "_I_")
+ token.gsub!(/\W+/, "")
+ end
+ token
+end
+
predefined_ids = {}
preserved_ids = []
local_ids = []
@@ -153,16 +184,7 @@ predefined.split(/^/).each_with_index do |line, num|
line.sub!(/\s+#.*/, '')
name, token = line.split
next unless name
- token ||= name
- if /#/ =~ token
- token = "_#{token.gsub(/\W+/, '_')}"
- else
- token = token.sub(/\?/, 'P').sub(/\A[a-z]/) {$&.upcase}
- token.sub!(/\A\$/, "_G_")
- token.sub!(/\A@@/, "_C_")
- token.sub!(/\A@/, "_I_")
- token.gsub!(/\W+/, "")
- end
+ token = id2varname(token || name)
if name == '-'
preserved_ids << token
next
@@ -185,13 +207,14 @@ predefined.split(/^/).each_with_index do |line, num|
end << token
predefined_ids[token] = name
end
+index = 127
token_ops.split(/^/).each do |line|
next if /^#/ =~ line
line.sub!(/\s+#.*/, '')
id, op, token = line.split
next unless id and op
token ||= (id unless /\A\W\z/ =~ op)
- token_op_ids << [id, op, token]
+ token_op_ids << [id, op, token, (index += 1 if token)]
end
{
"LOCAL" => local_ids,
@@ -203,4 +226,5 @@ end
:preserved => preserved_ids,
:predefined => predefined_ids,
:token_op => token_op_ids,
+ :last_token => index,
}
diff --git a/defs/jit.mk b/defs/jit.mk
new file mode 100644
index 0000000000..2c1e819684
--- /dev/null
+++ b/defs/jit.mk
@@ -0,0 +1,107 @@
+# Make recipes that deal with the rust code of YJIT and ZJIT.
+#
+# $(gnumake_recursive) adds the '+' prefix to pass down GNU make's
+# jobserver resources to cargo/rustc as rust-lang.org recommends.
+# Without it, certain make version trigger a warning. It does not
+# add the prefix when `make --dry-run` so dry runs are indeed dry.
+
+ifneq ($(JIT_CARGO_SUPPORT),no)
+
+# Show Cargo progress when doing `make V=1`
+CARGO_VERBOSE_0 = -q
+CARGO_VERBOSE_1 =
+CARGO_VERBOSE = $(CARGO_VERBOSE_$(V))
+
+# Because of Cargo cache, if the actual binary is not changed from the
+# previous build, the mtime is preserved as the cached file.
+# This means the target is not updated actually, and it will need to
+# rebuild at the next build.
+RUST_LIB_TOUCH = touch $@
+
+# NOTE: MACOSX_DEPLOYMENT_TARGET to match `rustc --print deployment-target` to avoid the warning below.
+# ld: warning: object file (target/debug/libjit.a(<libcapstone object>)) was built for
+# newer macOS version (15.2) than being linked (15.0)
+# This limits us to an older set of macOS API in the rust code, but we don't use any.
+$(RUST_LIB): $(srcdir)/ruby.rs target/.rustc-version
+ $(Q)if [ '$(ZJIT_SUPPORT)' != no -a '$(YJIT_SUPPORT)' != no ]; then \
+ echo 'building YJIT and ZJIT ($(JIT_CARGO_SUPPORT:yes=release) mode)'; \
+ elif [ '$(ZJIT_SUPPORT)' != no ]; then \
+ echo 'building ZJIT ($(JIT_CARGO_SUPPORT) mode)'; \
+ elif [ '$(YJIT_SUPPORT)' != no ]; then \
+ echo 'building YJIT ($(JIT_CARGO_SUPPORT) mode)'; \
+ fi
+ $(gnumake_recursive)$(Q)CARGO_TARGET_DIR='$(CARGO_TARGET_DIR)' \
+ CARGO_TERM_PROGRESS_WHEN='never' \
+ MACOSX_DEPLOYMENT_TARGET=11.0 \
+ $(CARGO) $(CARGO_VERBOSE) build --manifest-path '$(top_srcdir)/Cargo.toml' $(CARGO_BUILD_ARGS)
+ $(RUST_LIB_TOUCH)
+else ifneq ($(strip $(RLIB_DIR)),) # combo build
+
+$(RUST_LIB): $(srcdir)/ruby.rs target/.rustc-version
+ $(ECHO) 'building $(@F)'
+ $(gnumake_recursive)$(Q) $(RUSTC) --edition=2024 \
+ $(RUSTC_FLAGS) \
+ '-L$(@D)' \
+ --extern=yjit \
+ --extern=zjit \
+ --crate-type=staticlib \
+ --cfg 'feature="yjit"' \
+ --cfg 'feature="zjit"' \
+ '--out-dir=$(@D)' \
+ '$(top_srcdir)/ruby.rs'
+
+# Absolute path to avoid VPATH ambiguity
+JIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libjit.rlib
+$(YJIT_RLIB): $(JIT_RLIB)
+$(ZJIT_RLIB): $(JIT_RLIB)
+$(JIT_RLIB): target/.rustc-version
+ $(ECHO) 'building $(@F)'
+ $(gnumake_recursive)$(Q) $(RUSTC) --crate-name=jit \
+ --edition=2024 \
+ $(JIT_RUST_FLAGS) \
+ $(RUSTC_FLAGS) \
+ '--out-dir=$(@D)' \
+ '$(top_srcdir)/jit/src/lib.rs'
+endif # ifneq ($(JIT_CARGO_SUPPORT),no)
+
+RUST_LIB_SYMBOLS = $(RUST_LIB:.a=).symbols
+$(RUST_LIBOBJ): $(RUST_LIB)
+ $(ECHO) 'partial linking $(RUST_LIB) into $@'
+ifneq ($(findstring darwin,$(target_os)),)
+ $(Q) $(CC) -nodefaultlibs -r -o $@ -exported_symbols_list $(RUST_LIB_SYMBOLS) $(RUST_LIB)
+else
+ $(Q) $(LD) -r -o $@ --whole-archive $(RUST_LIB)
+ -$(Q) $(OBJCOPY) --wildcard --keep-global-symbol='$(SYMBOL_PREFIX)rb_*' $(@)
+endif
+
+rust-libobj: $(RUST_LIBOBJ)
+rust-lib: $(RUST_LIB)
+
+rustc-version-check: target/.rustc-version
+
+target/.rustc-version: PHONY
+ $(eval prev_version := $(if $(wildcard $@),$(shell cat $@)))
+ $(eval curr_version := $(shell $(RUSTC) -V | cut -d' ' -f2))
+ $(eval clean := $(filter-out $(prev_version),$(curr_version)))
+ $(if $(clean),$(ECHO) Cleaning $(@D) for rustc $(curr_version))
+ $(if $(clean),$(Q)$(RMALL) $(@D))
+ $(if $(clean),$(Q)$(MAKEDIRS) $(@D))
+ $(if $(clean),$(Q)echo $(curr_version) > $@)
+
+# For Darwin only: a list of symbols that we want the glommed Rust static lib to export.
+# Unfortunately, using wildcard like '_rb_*' with -exported-symbol does not work, at least
+# not on version 820.1. Assume llvm-nm, so XCode 8.0 (from 2016) or newer.
+#
+# The -exported_symbols_list pulls out the right archive members. Symbols not listed
+# in the list are made private extern, which are in turn made local as we're using `ld -r`.
+# Note, section about -keep_private_externs in ld's man page hints at this behavior on which
+# we rely.
+ifneq ($(findstring darwin,$(target_os)),)
+$(RUST_LIB_SYMBOLS): $(RUST_LIB)
+ $(Q) $(tooldir)/darwin-ar $(NM) --defined-only --extern-only $(RUST_LIB) | \
+ sed -n -e 's/.* //' -e '/^$(SYMBOL_PREFIX)rb_/p' \
+ -e '/^$(SYMBOL_PREFIX)rust_eh_personality/p' \
+ > $@
+
+$(RUST_LIBOBJ): $(RUST_LIB_SYMBOLS)
+endif
diff --git a/defs/keywords b/defs/keywords
index fc30ec2d15..a1b1f4f60f 100644
--- a/defs/keywords
+++ b/defs/keywords
@@ -2,7 +2,7 @@
struct kwtable {short name, id[2], state;};
const struct kwtable *rb_reserved_word(const char *, unsigned int);
#ifndef RIPPER
-static const struct kwtable *reserved_word(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/);
+static const struct kwtable *reserved_word(register const char *str, register size_t len);
#define rb_reserved_word(str, len) reserved_word(str, len)
%}
diff --git a/defs/known_errors.def b/defs/known_errors.def
index e9694cfbda..23e9e53507 100644
--- a/defs/known_errors.def
+++ b/defs/known_errors.def
@@ -1,157 +1,157 @@
-E2BIG
-EACCES
-EADDRINUSE
-EADDRNOTAVAIL
-EADV
-EAFNOSUPPORT
-EAGAIN
-EALREADY
-EAUTH
-EBADARCH
-EBADE
-EBADEXEC
-EBADF
-EBADFD
-EBADMACHO
-EBADMSG
-EBADR
-EBADRPC
-EBADRQC
-EBADSLT
-EBFONT
-EBUSY
-ECANCELED
-ECAPMODE
-ECHILD
-ECHRNG
-ECOMM
-ECONNABORTED
-ECONNREFUSED
-ECONNRESET
-EDEADLK
-EDEADLOCK
-EDESTADDRREQ
-EDEVERR
-EDOM
-EDOOFUS
-EDOTDOT
-EDQUOT
-EEXIST
-EFAULT
-EFBIG
-EFTYPE
-EHOSTDOWN
-EHOSTUNREACH
-EHWPOISON
-EIDRM
-EILSEQ
-EINPROGRESS
-EINTR
-EINVAL
-EIO
-EIPSEC
-EISCONN
-EISDIR
-EISNAM
-EKEYEXPIRED
-EKEYREJECTED
-EKEYREVOKED
-EL2HLT
-EL2NSYNC
-EL3HLT
-EL3RST
-ELAST
-ELIBACC
-ELIBBAD
-ELIBEXEC
-ELIBMAX
-ELIBSCN
-ELNRNG
-ELOOP
-EMEDIUMTYPE
-EMFILE
-EMLINK
-EMSGSIZE
-EMULTIHOP
-ENAMETOOLONG
-ENAVAIL
-ENEEDAUTH
-ENETDOWN
-ENETRESET
-ENETUNREACH
-ENFILE
-ENOANO
-ENOATTR
-ENOBUFS
-ENOCSI
-ENODATA
-ENODEV
-ENOENT
-ENOEXEC
-ENOKEY
-ENOLCK
-ENOLINK
-ENOMEDIUM
-ENOMEM
-ENOMSG
-ENONET
-ENOPKG
-ENOPOLICY
-ENOPROTOOPT
-ENOSPC
-ENOSR
-ENOSTR
-ENOSYS
-ENOTBLK
-ENOTCAPABLE
-ENOTCONN
-ENOTDIR
-ENOTEMPTY
-ENOTNAM
-ENOTRECOVERABLE
-ENOTSOCK
-ENOTSUP
-ENOTTY
-ENOTUNIQ
-ENXIO
-EOPNOTSUPP
-EOVERFLOW
-EOWNERDEAD
-EPERM
-EPFNOSUPPORT
-EPIPE
-EPROCLIM
-EPROCUNAVAIL
-EPROGMISMATCH
-EPROGUNAVAIL
-EPROTO
-EPROTONOSUPPORT
-EPROTOTYPE
-EPWROFF
-EQFULL
-ERANGE
-EREMCHG
-EREMOTE
-EREMOTEIO
-ERESTART
-ERFKILL
-EROFS
-ERPCMISMATCH
-ESHLIBVERS
-ESHUTDOWN
-ESOCKTNOSUPPORT
-ESPIPE
-ESRCH
-ESRMNT
-ESTALE
-ESTRPIPE
-ETIME
-ETIMEDOUT
-ETOOMANYREFS
-ETXTBSY
-EUCLEAN
-EUNATCH
-EUSERS
-EWOULDBLOCK
-EXDEV
-EXFULL
+E2BIG Argument list too long
+EACCES Permission denied
+EADDRINUSE Address already in use
+EADDRNOTAVAIL Address not available
+EADV Advertise error
+EAFNOSUPPORT Address family not supported
+EAGAIN Resource temporarily unavailable, try again (may be the same value as EWOULDBLOCK)
+EALREADY Connection already in progress
+EAUTH Authentication error
+EBADARCH Bad CPU type in executable
+EBADE Bad exchange
+EBADEXEC Bad executable
+EBADF Bad file descriptor
+EBADFD File descriptor in bad state
+EBADMACHO Malformed Macho file
+EBADMSG Bad message
+EBADR Invalid request descriptor
+EBADRPC RPC struct is bad
+EBADRQC Invalid request code
+EBADSLT Invalid slot
+EBFONT Bad font file format
+EBUSY Device or resource busy
+ECANCELED Operation canceled
+ECAPMODE Not permitted in capability mode
+ECHILD No child processes
+ECHRNG Channel number out of range
+ECOMM Communication error on send
+ECONNABORTED Connection aborted
+ECONNREFUSED Connection refused
+ECONNRESET Connection reset
+EDEADLK Resource deadlock avoided
+EDEADLOCK File locking deadlock error
+EDESTADDRREQ Destination address required
+EDEVERR Device error; e.g., printer paper out
+EDOM Mathematics argument out of domain of function
+EDOOFUS Improper function use
+EDOTDOT RFS specific error
+EDQUOT Disk quota exceeded
+EEXIST File exists
+EFAULT Bad address
+EFBIG File too large
+EFTYPE Invalid file type or format
+EHOSTDOWN Host is down
+EHOSTUNREACH Host is unreachable
+EHWPOISON Memory page has hardware error
+EIDRM Identifier removed
+EILSEQ Invalid or incomplete multibyte or wide character
+EINPROGRESS Operation in progress
+EINTR Interrupted function call
+EINVAL Invalid argument
+EIO Input/output error
+EIPSEC IPsec processing failure
+EISCONN Socket is connected
+EISDIR Is a directory
+EISNAM Is a named file type
+EKEYEXPIRED Key has expired
+EKEYREJECTED Key was rejected by service
+EKEYREVOKED Key has been revoked
+EL2HLT Level 2 halted
+EL2NSYNC Level 2 not synchronized
+EL3HLT Level 3 halted
+EL3RST Level 3 reset
+ELIBACC Cannot access a needed shared library
+ELIBBAD Accessing a corrupted shared library
+ELIBEXEC Cannot exec a shared library directly
+ELIBMAX Attempting to link in too many shared libraries
+ELIBSCN .lib section in a.out corrupted
+ELNRNG Link number out of range
+ELOOP Too many levels of symbolic links
+EMEDIUMTYPE Wrong medium type
+EMFILE Too many open files
+EMLINK Too many links
+EMSGSIZE Message too long
+EMULTIHOP Multihop attempted
+ENAMETOOLONG Filename too long
+ENAVAIL No XENIX semaphores available
+ENEEDAUTH Need authenticator
+ENETDOWN Network is down
+ENETRESET Connection aborted by network
+ENETUNREACH Network unreachable
+ENFILE Too many open files in system
+ENOANO No anode
+ENOATTR Attribute not found
+ENOBUFS No buffer space available
+ENOCSI No CSI structure available
+ENODATA No data available
+ENODEV No such device
+ENOENT No such file or directory
+ENOEXEC Exec format error
+ENOKEY Required key not available
+ENOLCK No locks available
+ENOLINK Link has been severed
+ENOMEDIUM No medium found
+ENOMEM Not enough space/cannot allocate memory
+ENOMSG No message of the desired type
+ENONET Machine is not on the network
+ENOPKG Package not installed
+ENOPOLICY No such policy
+ENOPROTOOPT Protocol not available
+ENOSPC No space left on device
+ENOSR No STREAM resources
+ENOSTR Not a STREAM
+ENOSYS Functionality not implemented
+ENOTBLK Block device required
+ENOTCAPABLE Capabilities insufficient
+ENOTCONN The socket is not connected
+ENOTDIR Not a directory
+ENOTEMPTY Directory not empty
+ENOTNAM Not a XENIX named type file
+ENOTRECOVERABLE State not recoverable
+ENOTSOCK Not a socket
+ENOTSUP Operation not supported
+ENOTTY Inappropriate I/O control operation
+ENOTUNIQ Name not unique on network
+ENXIO No such device or address
+EOPNOTSUPP Operation not supported on socket
+EOVERFLOW Value too large to be stored in data type
+EOWNERDEAD Owner died
+EPERM Operation not permitted
+EPFNOSUPPORT Protocol family not supported
+EPIPE Broken pipe
+EPROCLIM Too many processes
+EPROCUNAVAIL Bad procedure for program
+EPROGMISMATCH Program version wrong
+EPROGUNAVAIL RPC program isn't available
+EPROTO Protocol error
+EPROTONOSUPPORT Protocol not supported
+EPROTOTYPE Protocol wrong type for socket
+EPWROFF Device power is off
+EQFULL Interface output queue is full
+ERANGE Result too large
+EREMCHG Remote address changed
+EREMOTE Object is remote
+EREMOTEIO Remote I/O error
+ERESTART Interrupted system call should be restarted
+ERFKILL Operation not possible due to RF-kill
+EROFS Read-only file system
+ERPCMISMATCH RPC version wrong
+ESHLIBVERS Shared library version mismatch
+ESHUTDOWN Cannot send after transport endpoint shutdown
+ESOCKTNOSUPPORT Socket type not supported
+ESPIPE Illegal seek
+ESRCH No such process
+ESRMNT Server mount error
+ESTALE Stale file handle
+ESTRPIPE Streams pipe error
+ETIME Timer expired
+ETIMEDOUT Connection timed out
+ETOOMANYREFS Too many references: cannot splice
+ETXTBSY Text file busy
+EUCLEAN Structure needs cleaning
+EUNATCH Protocol driver not attached
+EUSERS Too many users
+EWOULDBLOCK Operation would block
+EXDEV Invalid cross-device link
+EXFULL Exchange full
+ELAST Largest errno value
diff --git a/defs/lex.c.src b/defs/lex.c.src
index fc30ec2d15..a1b1f4f60f 100644
--- a/defs/lex.c.src
+++ b/defs/lex.c.src
@@ -2,7 +2,7 @@
struct kwtable {short name, id[2], state;};
const struct kwtable *rb_reserved_word(const char *, unsigned int);
#ifndef RIPPER
-static const struct kwtable *reserved_word(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/);
+static const struct kwtable *reserved_word(register const char *str, register size_t len);
#define rb_reserved_word(str, len) reserved_word(str, len)
%}
diff --git a/defs/opt_insn_unif.def b/defs/opt_insn_unif.def
index 31ae2eb6a1..5ce67538f1 100644
--- a/defs/opt_insn_unif.def
+++ b/defs/opt_insn_unif.def
@@ -6,12 +6,12 @@
__END__
putobject putobject
-putobject putstring
+putobject dupstring
putobject setlocal
-putstring putstring
-putstring putobject
-putstring setlocal
+dupstring dupstring
+dupstring putobject
+dupstring setlocal
# putnil end
diff --git a/defs/tags.mk b/defs/tags.mk
new file mode 100644
index 0000000000..d29260c294
--- /dev/null
+++ b/defs/tags.mk
@@ -0,0 +1,18 @@
+# -*- mode: makefile-gmake; indent-tabs-mode: t -*-
+
+SRCS := $(shell $(GIT) ls-files \
+ *.[chy] *.def *.inc *.rb \
+ ccan/ coroutine/ include/ internal/ missing/ \
+ 'enc/**/*.[ch]' 'win32/**/*.[ch]' \
+ )
+
+TAGS: $(SRCS)
+ @echo updating $@
+ @tmp=$$(mktemp); \
+ trap 'rm -f "$$tmp"' 0; \
+ { \
+ $(GIT) grep -h --no-line-number -o '^ *# *define *RBIMPL_ATTR_[A-Z_]*(*' -- include | \
+ sed 's/^ *# *define *//;/_H$$/d;y/(/+/' | sort -u && \
+ echo 'NORETURN+'; \
+ } > "$$tmp" && \
+ ctags -e -I@"$$tmp" -h .def.inc --langmap=c:+.y.def.inc $(^)
diff --git a/defs/universal.mk b/defs/universal.mk
deleted file mode 100644
index c34a31b356..0000000000
--- a/defs/universal.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-arch_flags := $(filter -arch=%,$(subst -arch ,-arch=,$(ARCH_FLAG)))
-ifeq ($(filter 0 1,$(words $(arch_flags))),)
-override MJIT_HEADER_SUFFIX = -%
-override MJIT_HEADER_ARCH = -$(word 2,$(ARCH_FLAG))
-endif