Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions bootstraptest/test_yjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4081,6 +4081,26 @@ def bar(&block)
bar { }
}

# unshareable bmethod call through Method#to_proc#call
assert_equal '1000', %q{
define_method(:bmethod) do
self
end

Ractor.new do
errors = 0
1000.times do
p = method(:bmethod).to_proc
begin
p.call
rescue RuntimeError
errors += 1
end
end
errors
end.value
}

# test for return stub lifetime issue
assert_equal '1', %q{
def foo(n)
Expand Down
1 change: 0 additions & 1 deletion ext/json/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ typedef struct JSON_ParserStruct {
int max_nesting;
bool allow_nan;
bool allow_trailing_comma;
bool parsing_name;
bool symbolize_names;
bool freeze;
} JSON_ParserConfig;
Expand Down
5 changes: 2 additions & 3 deletions jit_hook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ class Module
# This method is removed in jit_undef.rb.
private def with_jit(&block) # :nodoc:
# ZJIT currently doesn't compile Array#each properly, so it's disabled for now.
if defined?(RubyVM::ZJIT) && Primitive.rb_zjit_option_enabled_p && false # TODO: remove `&& false` (Shopify/ruby#667)
# We don't support lazily enabling ZJIT yet, so we can call the block right away.
block.call
if defined?(RubyVM::ZJIT) && false # TODO: remove `&& false` (Shopify/ruby#667)
RubyVM::ZJIT.send(:add_jit_hook, block)
elsif defined?(RubyVM::YJIT)
RubyVM::YJIT.send(:add_jit_hook, block)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/bundler/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CLI < Thor

AUTO_INSTALL_CMDS = %w[show binstubs outdated exec open console licenses clean].freeze
PARSEABLE_COMMANDS = %w[check config help exec platform show version].freeze
EXTENSIONS = ["c", "rust"].freeze
EXTENSIONS = ["c", "rust", "go"].freeze

COMMAND_ALIASES = {
"check" => "c",
Expand Down
16 changes: 15 additions & 1 deletion lib/bundler/cli/gem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class CLI::Gem
"test-unit" => "3.0",
}.freeze

DEFAULT_GITHUB_USERNAME = "[USERNAME]"

attr_reader :options, :gem_name, :thor, :name, :target, :extension

def initialize(options, gem_name, thor)
Expand Down Expand Up @@ -72,7 +74,7 @@ def run
bundle: options[:bundle],
bundler_version: bundler_dependency_version,
git: use_git,
github_username: github_username.empty? ? "[USERNAME]" : github_username,
github_username: github_username.empty? ? DEFAULT_GITHUB_USERNAME : github_username,
required_ruby_version: required_ruby_version,
rust_builder_required_rubygems_version: rust_builder_required_rubygems_version,
minitest_constant_name: minitest_constant_name,
Expand Down Expand Up @@ -231,6 +233,18 @@ def run
)
end

if extension == "go"
templates.merge!(
"ext/newgem/go.mod.tt" => "ext/#{name}/go.mod",
"ext/newgem/extconf-go.rb.tt" => "ext/#{name}/extconf.rb",
"ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h",
"ext/newgem/newgem.go.tt" => "ext/#{name}/#{underscored_name}.go",
"ext/newgem/newgem-go.c.tt" => "ext/#{name}/#{underscored_name}.c",
)

config[:go_module_username] = config[:github_username] == DEFAULT_GITHUB_USERNAME ? "username" : config[:github_username]
end

if target.exist? && !target.directory?
Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`."
exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError]
Expand Down
4 changes: 2 additions & 2 deletions lib/bundler/man/bundle-gem.1
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ Add a \fBCHANGELOG\.md\fR file to the root of the generated project\. If this op
\fB\-\-no\-changelog\fR
Do not create a \fBCHANGELOG\.md\fR (overrides \fB\-\-changelog\fR specified in the global config)\.
.TP
\fB\-\-ext=c\fR, \fB\-\-ext=rust\fR
Add boilerplate for C or Rust (currently magnus \fIhttps://docs\.rs/magnus\fR based) extension code to the generated project\. This behavior is disabled by default\.
\fB\-\-ext=c\fR, \fB\-\-ext=go\fR, \fB\-\-ext=rust\fR
Add boilerplate for C, Go (currently go\-gem\-wrapper \fIhttps://github\.com/ruby\-go\-gem/go\-gem\-wrapper\fR based) or Rust (currently magnus \fIhttps://docs\.rs/magnus\fR based) extension code to the generated project\. This behavior is disabled by default\.
.TP
\fB\-\-no\-ext\fR
Do not add extension code (overrides \fB\-\-ext\fR specified in the global config)\.
Expand Down
4 changes: 2 additions & 2 deletions lib/bundler/man/bundle-gem.1.ronn
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ configuration file using the following names:
Do not create a `CHANGELOG.md` (overrides `--changelog` specified in the
global config).

* `--ext=c`, `--ext=rust`:
Add boilerplate for C or Rust (currently [magnus](https://docs.rs/magnus) based) extension code to the generated project. This behavior
* `--ext=c`, `--ext=go`, `--ext=rust`:
Add boilerplate for C, Go (currently [go-gem-wrapper](https://github.com/ruby-go-gem/go-gem-wrapper) based) or Rust (currently [magnus](https://docs.rs/magnus) based) extension code to the generated project. This behavior
is disabled by default.

* `--no-ext`:
Expand Down
2 changes: 1 addition & 1 deletion lib/bundler/rubygems_gem_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def ensure_writable_dir(dir)
end

def generate_plugins
return unless Gem::Installer.instance_methods(false).include?(:generate_plugins)
return unless Gem::Installer.method_defined?(:generate_plugins)

latest = Gem::Specification.stubs_for(spec.name).first
return if latest && latest.version > spec.version
Expand Down
12 changes: 12 additions & 0 deletions lib/bundler/templates/newgem/circleci/config.yml.tt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ jobs:
<%- if config[:ext] == 'rust' -%>
environment:
RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN: 'true'
<%- end -%>
<%- if config[:ext] == 'go' -%>
environment:
GO_VERSION: '1.23.0'
<%- end -%>
steps:
- checkout
Expand All @@ -16,6 +20,14 @@ jobs:
- run:
name: Install a RubyGems version that can compile rust extensions
command: gem update --system '<%= ::Gem.rubygems_version %>'
<%- end -%>
<%- if config[:ext] == 'go' -%>
- run:
name: Install Go
command: |
wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
tar -C /usr/local -xzf /tmp/go.tar.gz
echo 'export PATH=/usr/local/go/bin:"$PATH"' >> "$BASH_ENV"
<%- end -%>
- run:
name: Run the default task
Expand Down
11 changes: 11 additions & 0 deletions lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require "mkmf"
require "go_gem/mkmf"

# Makes all symbols private by default to avoid unintended conflict
# with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED
# selectively, or entirely remove this flag.
append_cflags("-fvisibility=hidden")

create_go_makefile(<%= config[:makefile_path].inspect %>)
5 changes: 5 additions & 0 deletions lib/bundler/templates/newgem/ext/newgem/go.mod.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/<%= config[:go_module_username] %>/<%= config[:underscored_name] %>

go 1.23

require github.com/ruby-go-gem/go-gem-wrapper latest
2 changes: 2 additions & 0 deletions lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "<%= config[:underscored_name] %>.h"
#include "_cgo_export.h"
31 changes: 31 additions & 0 deletions lib/bundler/templates/newgem/ext/newgem/newgem.go.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

/*
#include "<%= config[:underscored_name] %>.h"

VALUE rb_<%= config[:underscored_name] %>_sum(VALUE self, VALUE a, VALUE b);
*/
import "C"

import (
"github.com/ruby-go-gem/go-gem-wrapper/ruby"
)

//export rb_<%= config[:underscored_name] %>_sum
func rb_<%= config[:underscored_name] %>_sum(_ C.VALUE, a C.VALUE, b C.VALUE) C.VALUE {
longA := ruby.NUM2LONG(ruby.VALUE(a))
longB := ruby.NUM2LONG(ruby.VALUE(b))

sum := longA + longB

return C.VALUE(ruby.LONG2NUM(sum))
}

//export Init_<%= config[:underscored_name] %>
func Init_<%= config[:underscored_name] %>() {
rb_m<%= config[:constant_array].join %> := ruby.RbDefineModule(<%= config[:constant_name].inspect %>)
ruby.RbDefineSingletonMethod(rb_m<%= config[:constant_array].join %>, "sum", C.rb_<%= config[:underscored_name] %>_sum, 2)
}

func main() {
}
6 changes: 6 additions & 0 deletions lib/bundler/templates/newgem/github/workflows/main.yml.tt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ jobs:
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
<%- end -%>
<%- if config[:ext] == 'go' -%>
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: ext/<%= config[:underscored_name] %>/go.mod
<%- end -%>
- name: Run the default task
run: bundle exec rake
9 changes: 9 additions & 0 deletions lib/bundler/templates/newgem/gitlab-ci.yml.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ default:
<%- if config[:ext] == 'rust' -%>
- apt-get update && apt-get install -y clang
- gem update --system '<%= ::Gem.rubygems_version %>'
<%- end -%>
<%- if config[:ext] == 'go' -%>
- wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
- tar -C /usr/local -xzf /tmp/go.tar.gz
- export PATH=/usr/local/go/bin:$PATH
<%- end -%>
- gem install bundler -v <%= Bundler::VERSION %>
- bundle install
Expand All @@ -13,6 +18,10 @@ example_job:
<%- if config[:ext] == 'rust' -%>
variables:
RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN: 'true'
<%- end -%>
<%- if config[:ext] == 'go' -%>
variables:
GO_VERSION: '1.23.0'
<%- end -%>
script:
- bundle exec rake
5 changes: 4 additions & 1 deletion lib/bundler/templates/newgem/newgem.gemspec.tt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
<%- if config[:ext] == 'c' || config[:ext] == 'rust' -%>
<%- if %w(c rust go).include?(config[:ext]) -%>
spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
<%- end -%>

Expand All @@ -47,6 +47,9 @@ Gem::Specification.new do |spec|
<%- if config[:ext] == 'rust' -%>
spec.add_dependency "rb_sys", "~> 0.9.91"
<%- end -%>
<%- if config[:ext] == 'go' -%>
spec.add_dependency "go_gem", "~> 0.2"
<%- end -%>

# For more information and examples about making a new gem, check out our
# guide at: https://bundler.io/guides/creating_gem.html
Expand Down
19 changes: 11 additions & 8 deletions ruby.c
Original file line number Diff line number Diff line change
Expand Up @@ -1842,10 +1842,8 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
rb_yjit_init(opt->yjit);
#endif
#if USE_ZJIT
if (opt->zjit) {
extern void rb_zjit_init(void);
rb_zjit_init();
}
extern void rb_zjit_init(bool);
rb_zjit_init(opt->zjit);
#endif

ruby_set_script_name(opt->script_name);
Expand Down Expand Up @@ -2368,6 +2366,12 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
#if USE_ZJIT
if (!FEATURE_USED_P(opt->features, zjit) && env_var_truthy("RUBY_ZJIT_ENABLE")) {
FEATURE_SET(opt->features, FEATURE_BIT(zjit));

// When the --zjit flag is specified, we would have call setup_zjit_options(""),
// which would have called rb_zjit_prepare_options() internally. This ensures we
// go through the same set up but with less overhead than setup_zjit_options("").
extern void rb_zjit_prepare_options();
rb_zjit_prepare_options();
}
#endif
}
Expand All @@ -2383,10 +2387,9 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
}
#endif
#if USE_ZJIT
if (FEATURE_SET_P(opt->features, zjit) && !opt->zjit) {
extern void rb_zjit_prepare_options(void);
rb_zjit_prepare_options();
opt->zjit = true;
if (FEATURE_SET_P(opt->features, zjit)) {
bool rb_zjit_option_enable(void);
opt->zjit = rb_zjit_option_enable(); // set opt->zjit for Init_ruby_description() and calling rb_zjit_init()
}
#endif

Expand Down
Loading