-
Notifications
You must be signed in to change notification settings - Fork 51
[Feature #21264] Replace C extension with pure Ruby implementation for Ruby >= 3.3 #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
bae5812
0cdfd42
802e0c2
d4aa1aa
8909ef5
d276c80
2b938aa
fb37439
ea0355e
a65aca6
7e80db9
a9255c0
aa536c6
1b3b1ef
fd03c6f
997de16
e2698ea
a539110
c211307
e67f196
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,47 @@ | ||
| require "bundler/gem_tasks" | ||
| require "rake/testtask" | ||
| require "shellwords" | ||
| require "rake/extensiontask" | ||
|
|
||
| extask = Rake::ExtensionTask.new("date") do |ext| | ||
| ext.name = "date_core" | ||
| ext.lib_dir.sub!(%r[(?=/|\z)], "/#{RUBY_VERSION}/#{ext.platform}") | ||
| end | ||
| if RUBY_VERSION >= "3.3" | ||
| # Pure Ruby — no compilation needed | ||
| Rake::TestTask.new(:test) do |t| | ||
| t.libs << "lib" | ||
| t.libs << "test/lib" | ||
| t.ruby_opts << "-rhelper" | ||
| t.test_files = FileList['test/**/test_*.rb'] | ||
| end | ||
|
|
||
| Rake::TestTask.new(:test) do |t| | ||
| t.libs << extask.lib_dir | ||
| t.libs << "test/lib" | ||
| t.ruby_opts << "-rhelper" | ||
| t.test_files = FileList['test/**/test_*.rb'] | ||
| end | ||
| task :compile # no-op | ||
|
|
||
| else | ||
| # C extension for Ruby < 3.3 | ||
| require "shellwords" | ||
| require "rake/extensiontask" | ||
|
|
||
| extask = Rake::ExtensionTask.new("date") do |ext| | ||
| ext.name = "date_core" | ||
| ext.lib_dir.sub!(%r[(?=/|\z)], "/#{RUBY_VERSION}/#{ext.platform}") | ||
| end | ||
|
|
||
| Rake::TestTask.new(:test) do |t| | ||
| t.libs << extask.lib_dir | ||
| t.libs << "test/lib" | ||
| t.ruby_opts << "-rhelper" | ||
| t.test_files = FileList['test/**/test_*.rb'] | ||
| end | ||
|
|
||
| task test: :compile | ||
|
|
||
| task compile: "ext/date/zonetab.h" | ||
| file "ext/date/zonetab.h" => "ext/date/zonetab.list" do |t| | ||
| dir, hdr = File.split(t.name) | ||
| make_program_name = | ||
| ENV['MAKE'] || ENV['make'] || | ||
| RbConfig::CONFIG['configure_args'][/with-make-prog\=\K\w+/] || | ||
| (/mswin/ =~ RUBY_PLATFORM ? 'nmake' : 'make') | ||
| make_program = Shellwords.split(make_program_name) | ||
| sh(*make_program, "-f", "prereq.mk", "top_srcdir=.."+"/.."*dir.count("/"), | ||
| hdr, chdir: dir) | ||
| task compile: "ext/date/zonetab.h" | ||
| file "ext/date/zonetab.h" => "ext/date/zonetab.list" do |t| | ||
| dir, hdr = File.split(t.name) | ||
| make_program_name = | ||
| ENV['MAKE'] || ENV['make'] || | ||
| RbConfig::CONFIG['configure_args'][/with-make-prog\=\K\w+/] || | ||
| (/mswin/ =~ RUBY_PLATFORM ? 'nmake' : 'make') | ||
| make_program = Shellwords.split(make_program_name) | ||
| sh(*make_program, "-f", "prereq.mk", "top_srcdir=.."+"/.."*dir.count("/"), | ||
| hdr, chdir: dir) | ||
| end | ||
| end | ||
|
|
||
| task :default => [:compile, :test] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,16 @@ | ||
| # frozen_string_literal: true | ||
| require 'mkmf' | ||
|
|
||
| config_string("strict_warnflags") {|w| $warnflags += " #{w}"} | ||
|
|
||
| append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7." | ||
| have_func("rb_category_warn") | ||
| with_werror("", {:werror => true}) do |opt, | | ||
| have_var("timezone", "time.h", opt) | ||
| have_var("altzone", "time.h", opt) | ||
| if RUBY_VERSION >= "3.3" | ||
| # Pure Ruby implementation; skip C extension build | ||
| File.write("Makefile", dummy_makefile($srcdir).join("")) | ||
| else | ||
| config_string("strict_warnflags") {|w| $warnflags += " #{w}"} | ||
| append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7." | ||
| have_func("rb_category_warn") | ||
| with_werror("", {:werror => true}) do |opt, | | ||
| have_var("timezone", "time.h", opt) | ||
| have_var("altzone", "time.h", opt) | ||
| end | ||
| create_makefile('date_core') | ||
| end | ||
|
|
||
| create_makefile('date_core') |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||||||||||||||||||||||||||||||||||||
| # -*- mode: ruby -*- | ||||||||||||||||||||||||||||||||||||||||
| # Generate lib/date/zonetab.rb from ext/date/zonetab.list | ||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||
| # Usage: ruby -C ext/date generate-zonetab-rb | ||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||
| # This script reads zonetab.list (the same source used to generate zonetab.h | ||||||||||||||||||||||||||||||||||||||||
| # via gperf) and produces the equivalent Ruby hash table. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| list_path = File.join(__dir__, 'zonetab.list') | ||||||||||||||||||||||||||||||||||||||||
| output_path = File.join(__dir__, '..', '..', 'lib', 'date', 'zonetab.rb') | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+10
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| entries = {} | ||||||||||||||||||||||||||||||||||||||||
| in_entries = false | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| File.foreach(list_path) do |line| | ||||||||||||||||||||||||||||||||||||||||
| line.chomp! | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+16
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| if line == '%%' | ||||||||||||||||||||||||||||||||||||||||
| if in_entries | ||||||||||||||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||
| in_entries = true | ||||||||||||||||||||||||||||||||||||||||
| next | ||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||
| next unless in_entries | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+25
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| abbr, offset_expr = line.split(',', 2) | ||||||||||||||||||||||||||||||||||||||||
| next unless offset_expr | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| abbr.strip! | ||||||||||||||||||||||||||||||||||||||||
| offset_expr.strip! | ||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to strip, as
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| # Evaluate offset expression (e.g., "0*3600", "-5*3600", "-(1*3600+1800)", "16200") | ||||||||||||||||||||||||||||||||||||||||
| offset = eval(offset_expr) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| entries[abbr] = offset | ||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| sorted = entries.sort_by { |k, _| k } | ||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| max_key_len = sorted.map { |k, _| k.length }.max | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| File.open(output_path, 'w') do |f| | ||||||||||||||||||||||||||||||||||||||||
| f.puts '# frozen_string_literal: true' | ||||||||||||||||||||||||||||||||||||||||
| f.puts | ||||||||||||||||||||||||||||||||||||||||
| f.puts '# Timezone name => UTC offset (seconds) mapping table.' | ||||||||||||||||||||||||||||||||||||||||
| f.puts '# Auto-generated from ext/date/zonetab.list by ext/date/generate-zonetab-rb.' | ||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| f.puts '# Do not edit manually.' | ||||||||||||||||||||||||||||||||||||||||
| f.puts 'class Date' | ||||||||||||||||||||||||||||||||||||||||
| f.puts ' ZONE_TABLE = {' | ||||||||||||||||||||||||||||||||||||||||
| sorted.each do |abbr, offset| | ||||||||||||||||||||||||||||||||||||||||
| key = abbr.include?(' ') ? %Q("#{abbr}") : %Q("#{abbr}") | ||||||||||||||||||||||||||||||||||||||||
| f.puts " %-#{max_key_len + 3}s => %d," % [key, offset] | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+52
to
+53
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both sides look the same expression.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||
| f.puts ' }.freeze' | ||||||||||||||||||||||||||||||||||||||||
| f.puts 'end' | ||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| puts "Generated #{output_path} with #{entries.size} entries." | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.