require_relative '../../spec_helper' require_relative 'fixtures/common' newline = "\n" platform_is :windows do newline = "\r\n" end describe :process_spawn_does_not_close_std_streams, shared: true do it "does not close STDIN" do code = "puts STDIN.read" cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})" ruby_exe(cmd, args: "< #{fixture(__FILE__, "in.txt")} > #{@name}") File.binread(@name).should == %[stdin#{newline}] end it "does not close STDOUT" do code = "STDOUT.puts 'hello'" cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})" ruby_exe(cmd, args: "> #{@name}") File.binread(@name).should == "hello#{newline}" end it "does not close STDERR" do code = "STDERR.puts 'hello'" cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})" ruby_exe(cmd, args: "2> #{@name}") File.binread(@name).should =~ /hello#{newline}/ end end describe "Process.spawn" do ProcessSpecs.use_system_ruby(self) before :each do @name = tmp("process_spawn.txt") @var = "$FOO" platform_is :windows do @var = "%FOO%" end end after :each do rm_r @name end it "executes the given command" do -> { Process.wait Process.spawn("echo spawn") }.should output_to_fd("spawn\n") end it "returns the process ID of the new process as an Integer" do pid = Process.spawn(*ruby_exe, "-e", "exit") Process.wait pid pid.should be_an_instance_of(Integer) end it "returns immediately" do start = Time.now pid = Process.spawn(*ruby_exe, "-e", "sleep 10") (Time.now - start).should < 5 Process.kill :KILL, pid Process.wait pid end # argv processing describe "with a single argument" do platform_is_not :windows do it "subjects the specified command to shell expansion" do -> { Process.wait Process.spawn("echo *") }.should_not output_to_fd("*\n") end it "creates an argument array with shell parsing semantics for whitespace" do -> { Process.wait Process.spawn("echo a b c d") }.should output_to_fd("a b c d\n") end end platform_is :windows do # There is no shell expansion on Windows it "does not subject the specified command to shell expansion on Windows" do -> { Process.wait Process.spawn("echo *") }.should output_to_fd("*\n") end it "does not create an argument array with shell parsing semantics for whitespace on Windows" do -> { Process.wait Process.spawn("echo a b c d") }.should output_to_fd("a b c d\n") end end it "calls #to_str to convert the argument to a String" do o = mock("to_str") o.should_receive(:to_str).and_return("echo foo") -> { Process.wait Process.spawn(o) }.should output_to_fd("foo\n") end it "raises an ArgumentError if the command includes a null byte" do -> { Process.spawn "\000" }.should raise_error(ArgumentError) end it "raises a TypeError if the argument does not respond to #to_str" do -> { Process.spawn :echo }.should raise_error(TypeError) end end describe "with multiple arguments" do it "does not subject the arguments to shell expansion" do -> { Process.wait Process.spawn("echo", "*") }.should output_to_fd("*\n") end it "preserves whitespace in passed arguments" do out = "a b c d\n" platform_is :windows do # The echo command on Windows takes quotes literally out = "\"a b c d\"\n" end -> { Process.wait Process.spawn("echo", "a b c d") }.should output_to_fd(out) end it "calls #to_str to convert the arguments to Strings" do o = mock("to_str") o.should_receive(:to_str).and_return("foo") -> { Process.wait Process.spawn("echo", o) }.should output_to_fd("foo\n") end it "raises an ArgumentError if an argument includes a null byte" do -> { Process.spawn "echo", "\000" }.should raise_error(ArgumentError) end it "raises a TypeError if an argument does not respond to #to_str" do -> { Process.spawn "echo", :foo }.should raise_error(TypeError) end end describe "with a command array" do it "uses the first element as the command name and the second as the argv[0] value" do platform_is_not :windows do -> { Process.wait Process.spawn(["/bin/sh", "argv_zero"], "-c", "echo $0") }.should output_to_fd("argv_zero\n") end platform_is :windows do -> { Process.wait Process.spawn(["cmd.exe", "/C"], "/C", "echo", "argv_zero") }.should output_to_fd("argv_zero\n") end end it "does not subject the arguments to shell expansion" do -> { Process.wait Process.spawn(["echo", "echo"], "*") }.should output_to_fd("*\n") end it "preserves whitespace in passed arguments" do out = "a b c d\n" platform_is :windows do # The echo command on Windows takes quotes literally out = "\"a b c d\"\n" end -> { Process.wait Process.spawn(["echo", "echo"], "a b c d") }.should output_to_fd(out) end it "calls #to_ary to convert the argument to an Array" do o = mock("to_ary") platform_is_not :windows do o.should_receive(:to_ary).and_return(["/bin/sh", "argv_zero"]) -> { Process.wait Process.spawn(o, "-c", "echo $0") }.should output_to_fd("argv_zero\n") end platform_is :windows do o.should_receive(:to_ary).and_return(["cmd.exe", "/C"]) -> { Process.wait Process.spawn(o, "/C", "echo", "argv_zero") }.should output_to_fd("argv_zero\n") end end it "calls #to_str to convert the first element to a String" do o = mock("to_str") o.should_receive(:to_str).and_return("echo") -> { Process.wait Process.spawn([o, "echo"], "foo") }.should output_to_fd("foo\n") end it "calls #to_str to convert the second element to a String" do o = mock("to_str") o.should_receive(:to_str).and_return("echo") -> { Process.wait Process.spawn(["echo", o], "foo") }.should output_to_fd("foo\n") end it "raises an ArgumentError if the Array does not have exactly two elements" do -> { Process.spawn([]) }.should raise_error(ArgumentError) -> { Process.spawn([:a]) }.should raise_error(ArgumentError) -> { Process.spawn([:a, :b, :c]) }.should raise_error(ArgumentError) end it "raises an ArgumentError if the Strings in the Array include a null byte" do -> { Process.spawn ["\000", "echo"] }.should raise_error(ArgumentError) -> { Process.spawn ["echo", "\000"] }.should raise_error(ArgumentError) end it "raises a TypeError if an element in the Array does not respond to #to_str" do -> { Process.spawn ["echo", :echo] }.should raise_error(TypeError) -> { Process.spawn [:echo, "echo"] }.should raise_error(TypeError) end end # env handling after :each do ENV.delete("FOO") end it "sets environment variables in the child environment" do Process.wait Process.spawn({"FOO" => "BAR"}, "echo #{@var}>#{@name}") File.read(@name).should == "BAR\n" end it "unsets environment variables whose value is nil" do ENV["FOO"] = "BAR" -> do Process.wait Process.spawn({"FOO" => nil}, ruby_cmd("p ENV['FOO']")) end.should output_to_fd("nil\n") end platform_is_not :windows do it "uses the passed env['PATH'] to search the executable" do dir = tmp("spawn_path_dir") mkdir_p dir begin exe = 'process-spawn-executable-in-path' path = "#{dir}/#{exe}" File.write(path, "#!/bin/sh\necho $1") File.chmod(0755, path) env = { "PATH" => "#{dir}#{File::PATH_SEPARATOR}#{ENV['PATH']}" } Process.wait Process.spawn(env, exe, 'OK', out: @name) $?.should.success? File.read(@name).should == "OK\n" ensure rm_r dir end end end it "calls #to_hash to convert the environment" do o = mock("to_hash") o.should_receive(:to_hash).and_return({"FOO" => "BAR"}) Process.wait Process.spawn(o, "echo #{@var}>#{@name}") File.read(@name).should == "BAR\n" end it "calls #to_str to convert the environment keys" do o = mock("to_str") o.should_receive(:to_str).and_return("FOO") Process.wait Process.spawn({o => "BAR"}, "echo #{@var}>#{@name}") File.read(@name).should == "BAR\n" end it "calls #to_str to convert the environment values" do o = mock("to_str") o.should_receive(:to_str).and_return("BAR") Process.wait Process.spawn({"FOO" => o}, "echo #{@var}>#{@name}") File.read(@name).should == "BAR\n" end it "raises an ArgumentError if an environment key includes an equals sign" do -> do Process.spawn({"FOO=" => "BAR"}, "echo #{@var}>#{@name}") end.should raise_error(ArgumentError) end it "raises an ArgumentError if an environment key includes a null byte" do -> do Process.spawn({"\000" => "BAR"}, "echo #{@var}>#{@name}") end.should raise_error(ArgumentError) end it "raises an ArgumentError if an environment value includes a null byte" do -> do Process.spawn({"FOO" => "\000"}, "echo #{@var}>#{@name}") end.should raise_error(ArgumentError) end # :unsetenv_others before :each do @minimal_env = { "PATH" => ENV["PATH"], "HOME" => ENV["HOME"] } @common_env_spawn_args = [@minimal_env, "echo #{@var}>#{@name}"] end platform_is_not :windows do it "unsets other environment variables when given a true :unsetenv_others option" do ENV["FOO"] = "BAR" Process.wait Process.spawn(*@common_env_spawn_args, unsetenv_others: true) $?.success?.should be_true File.read(@name).should == "\n" end end it "does not unset other environment variables when given a false :unsetenv_others option" do ENV["FOO"] = "BAR" Process.wait Process.spawn(*@common_env_spawn_args, unsetenv_others: false) $?.success?.should be_true File.read(@name).should == "BAR\n" end platform_is_not :windows do it "does not unset environment variables included in the environment hash" do env = @minimal_env.merge({"FOO" => "BAR"}) Process.wait Process.spawn(env, "echo #{@var}>#{@name}", unsetenv_others: true) $?.success?.should be_true File.read(@name).should == "BAR\n" end end # :pgroup platform_is_not :windows do it "joins the current process group by default" do -> do Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)")) end.should output_to_fd(Process.getpgid(Process.pid).to_s) end it "joins the current process if pgroup: false" do -> do Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: false) end.should output_to_fd(Process.getpgid(Process.pid).to_s) end it "joins the current process if pgroup: nil" do -> do Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: nil) end.should output_to_fd(Process.getpgid(Process.pid).to_s) end it "joins a new process group if pgroup: true" do process = -> do Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: true) end process.should_not output_to_fd(Process.getpgid(Process.pid).to_s) process.should output_to_fd(/\d+/) end it "joins a new process group if pgroup: 0" do process = -> do Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: 0) end process.should_not output_to_fd(Process.getpgid(Process.pid).to_s) process.should output_to_fd(/\d+/) end it "joins the specified process group if pgroup: pgid" do pgid = Process.getpgid(Process.pid) # The process group is not available on all platforms. # See "man proc" - /proc/[pid]/stat - (5) pgrp # In Travis arm64 environment, the value is 0. # # $ cat /proc/[pid]/stat # 19179 (ruby) S 19160 0 0 ... unless pgid.zero? -> do Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: pgid) end.should output_to_fd(pgid.to_s) else skip "The process group is not available." end end it "raises an ArgumentError if given a negative :pgroup option" do -> { Process.spawn("echo", pgroup: -1) }.should raise_error(ArgumentError) end it "raises a TypeError if given a symbol as :pgroup option" do -> { Process.spawn("echo", pgroup: :true) }.should raise_error(TypeError) end end platform_is :windows do it "raises an ArgumentError if given :pgroup option" do -> { Process.spawn("echo", pgroup: false) }.should raise_error(ArgumentError) end end # :rlimit_core # :rlimit_cpu # :rlimit_data # :chdir it "uses the current working directory as its working directory" do -> do Process.wait Process.spawn(ruby_cmd("print Dir.pwd")) end.should output_to_fd(Dir.pwd) end describe "when passed :chdir" do before do @dir = tmp("spawn_chdir", false) Dir.mkdir @dir end after do rm_r @dir end it "changes to the directory passed for :chdir" do -> do Process.wait Process.spawn(ruby_cmd("print Dir.pwd"), chdir: @dir) end.should output_to_fd(@dir) end it "calls #to_path to convert the :chdir value" do dir = mock("spawn_to_path") dir.should_receive(:to_path).and_return(@dir) -> do Process.wait Process.spawn(ruby_cmd("print Dir.pwd"), chdir: dir) end.should output_to_fd(@dir) end end # chdir platform_is :linux do describe "inside Dir.chdir" do def child_pids(pid) `pgrep -P #{pid}`.lines.map { |child| Integer(child) } end it "does not create extra process without chdir" do pid = Process.spawn("sleep 10") begin child_pids(pid).size.should == 0 ensure Process.kill("TERM", pid) Process.wait(pid) end end it "kills extra chdir processes" do pid = nil Dir.chdir("/") do pid = Process.spawn("sleep 10") end children = child_pids(pid) children.size.should <= 1 Process.kill("TERM", pid) Process.wait(pid) if children.size > 0 # wait a bit for children to die sleep(1) children.each do |child| -> do Process.kill("TERM", child) end.should raise_error(Errno::ESRCH) end end end end end # :umask it "uses the current umask by default" do -> do Process.wait Process.spawn(ruby_cmd("print File.umask")) end.should output_to_fd(File.umask.to_s) end platform_is_not :windows do it "sets the umask if given the :umask option" do -> do Process.wait Process.spawn(ruby_cmd("print File.umask"), umask: 146) end.should output_to_fd("146") end end # redirection it "redirects STDOUT to the given file descriptor if out: Integer" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark", out: file.fileno) end.should output_to_fd("glark\n", file) end end it "redirects STDOUT to the given file if out: IO" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark", out: file) end.should output_to_fd("glark\n", file) end end it "redirects STDOUT to the given file if out: String" do Process.wait Process.spawn("echo glark", out: @name) File.read(@name).should == "glark\n" end it "redirects STDOUT to the given file if out: [String name, String mode]" do Process.wait Process.spawn("echo glark", out: [@name, 'w']) File.read(@name).should == "glark\n" end it "redirects STDERR to the given file descriptor if err: Integer" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark>&2", err: file.fileno) end.should output_to_fd("glark\n", file) end end it "redirects STDERR to the given file descriptor if err: IO" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark>&2", err: file) end.should output_to_fd("glark\n", file) end end it "redirects STDERR to the given file if err: String" do Process.wait Process.spawn("echo glark>&2", err: @name) File.read(@name).should == "glark\n" end it "redirects STDERR to child STDOUT if :err => [:child, :out]" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark>&2", :out => file, :err => [:child, :out]) end.should output_to_fd("glark\n", file) end end it "redirects both STDERR and STDOUT to the given file descriptor" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn(ruby_cmd("print(:glark); STDOUT.flush; STDERR.print(:bang)"), [:out, :err] => file.fileno) end.should output_to_fd("glarkbang", file) end end it "redirects both STDERR and STDOUT to the given IO" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn(ruby_cmd("print(:glark); STDOUT.flush; STDERR.print(:bang)"), [:out, :err] => file) end.should output_to_fd("glarkbang", file) end end it "redirects both STDERR and STDOUT at the time to the given name" do touch @name Process.wait Process.spawn(ruby_cmd("print(:glark); STDOUT.flush; STDERR.print(:bang)"), [:out, :err] => @name) File.read(@name).should == "glarkbang" end platform_is_not :windows, :android do it "closes STDERR in the child if :err => :close" do File.open(@name, 'w') do |file| -> do code = "begin; STDOUT.puts 'out'; STDERR.puts 'hello'; rescue => e; puts 'rescued'; end" Process.wait Process.spawn(ruby_cmd(code), :out => file, :err => :close) end.should output_to_fd("out\nrescued\n", file) end end end # :close_others platform_is_not :windows do context "defaults :close_others to" do it "false" do IO.pipe do |r, w| w.close_on_exec = false code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close" pid = Process.spawn(ruby_cmd(code)) w.close Process.wait(pid) r.read.should == "inherited\n" end end end context "when passed close_others: true" do before :each do @options = { close_others: true } end it "closes file descriptors >= 3 in the child process even if fds are set close_on_exec=false" do touch @name IO.pipe do |r, w| r.close_on_exec = false w.close_on_exec = false begin pid = Process.spawn(ruby_cmd("while File.exist? '#{@name}'; sleep 0.1; end"), @options) w.close r.read(1).should == nil ensure rm_r @name Process.wait(pid) if pid end end end it_should_behave_like :process_spawn_does_not_close_std_streams end context "when passed close_others: false" do before :each do @options = { close_others: false } end it "closes file descriptors >= 3 in the child process because they are set close_on_exec by default" do touch @name IO.pipe do |r, w| begin pid = Process.spawn(ruby_cmd("while File.exist? '#{@name}'; sleep 0.1; end"), @options) w.close r.read(1).should == nil ensure rm_r @name Process.wait(pid) if pid end end end it "does not close file descriptors >= 3 in the child process if fds are set close_on_exec=false" do IO.pipe do |r, w| r.close_on_exec = false w.close_on_exec = false code = "fd = IO.for_fd(#{w.fileno}); fd.autoclose = false; fd.write 'abc'; fd.close" pid = Process.spawn(ruby_cmd(code), @options) begin w.close r.read.should == 'abc' ensure Process.wait(pid) end end end it_should_behave_like :process_spawn_does_not_close_std_streams end end # error handling it "raises an ArgumentError if passed no command arguments" do -> { Process.spawn }.should raise_error(ArgumentError) end it "raises an ArgumentError if passed env or options but no command arguments" do -> { Process.spawn({}) }.should raise_error(ArgumentError) end it "raises an ArgumentError if passed env and options but no command arguments" do -> { Process.spawn({}, {}) }.should raise_error(ArgumentError) end it "raises an Errno::ENOENT for an empty string" do -> { Process.spawn "" }.should raise_error(Errno::ENOENT) end it "raises an Errno::ENOENT if the command does not exist" do -> { Process.spawn "nonesuch" }.should raise_error(Errno::ENOENT) end unless File.executable?(__FILE__) # Some FS (e.g. vboxfs) locate all files executable platform_is_not :windows do it "raises an Errno::EACCES when the file does not have execute permissions" do -> { Process.spawn __FILE__ }.should raise_error(Errno::EACCES) end end platform_is :windows do it "raises Errno::EACCES or Errno::ENOEXEC when the file is not an executable file" do -> { Process.spawn __FILE__ }.should raise_error(SystemCallError) { |e| [Errno::EACCES, Errno::ENOEXEC].should include(e.class) } end end end it "raises an Errno::EACCES or Errno::EISDIR when passed a directory" do -> { Process.spawn File.dirname(__FILE__) }.should raise_error(SystemCallError) { |e| [Errno::EACCES, Errno::EISDIR].should include(e.class) } end it "raises an ArgumentError when passed a string key in options" do -> { Process.spawn("echo", "chdir" => Dir.pwd) }.should raise_error(ArgumentError) end it "raises an ArgumentError when passed an unknown option key" do -> { Process.spawn("echo", nonesuch: :foo) }.should raise_error(ArgumentError) end platform_is_not :windows, :aix do describe "with Integer option keys" do before :each do @name = tmp("spawn_fd_map.txt") @io = new_io @name, "w+" @io.sync = true end after :each do @io.close unless @io.closed? rm_r @name end it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do File.open(__FILE__, "r") do |f| child_fd = f.fileno args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s]) pid = Process.spawn(*args, { child_fd => @io }) Process.waitpid pid @io.rewind @io.read.should == "writing to fd: #{child_fd}" end end end end end 54f907c5ee468b79de2afab97e8d'>README.ja
diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000000..05ff204541 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,134 @@ +--- +version: '{build}' +init: + - git config --global user.name git + - git config --global user.email svn-admin@ruby-lang.org + - git config --global core.autocrlf false + - git config --global core.eol lf + - git config --global advice.detachedHead 0 +shallow_clone: true +clone_depth: 10 +platform: + - x64 +skip_commits: + message: /\[DOC\]/ + files: + - doc/* + - '**/*.md' + - '**/*.rdoc' + - '**/.document' + - '**/*.[1-8]' + - '**/*.ronn' +environment: + ruby_version: "24-%Platform%" + matrix: + # Test only the oldest supported version because AppVeyor is unstable, its concurrency + # is limited, and compatibility issues that happen only in newer versions are rare. + # You may test some other stuff on GitHub Actions instead. + - build: vs + vs: 120 # Visual Studio 2013 + ssl: OpenSSL-v111 + # The worker image name. This is NOT the Visual Studio version we're using here. + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + GEMS_FOR_TEST: "" + RELINE_TEST_ENCODING: "UTF-8" +cache: + - c:\Tools\vcpkg\installed\ +for: +- + matrix: + only: + - build: vs + install: + - ver + - chcp + - SET BITS=%Platform:x86=32% + - SET BITS=%BITS:x=% + - SET OPENSSL_DIR=C:\%ssl%-Win%BITS% + - cd C:\Tools\vcpkg + - git pull -q + - .\bootstrap-vcpkg.bat + - ps: Start-FileDownload 'https://github.com/microsoft/vcpkg-tool/releases/download/2023-08-09/vcpkg.exe' -FileName 'C:\Tools\vcpkg\vcpkg.exe' + - cd %APPVEYOR_BUILD_FOLDER% + - vcpkg --triplet %Platform%-windows install --x-use-aria2 libffi libyaml readline zlib + - CALL SET vcvars=%%^VS%VS%COMNTOOLS^%%..\..\VC\vcvarsall.bat + - SET vcvars + - '"%vcvars%" %Platform:x64=amd64%' + - SET ruby_path=C:\Ruby%ruby_version:-x86=% + - SET PATH=\usr\local\bin;%ruby_path%\bin;%PATH%;C:\msys64\mingw64\bin;C:\msys64\usr\bin + - ruby --version + - 'cl' + - echo> Makefile srcdir=. + - echo>> Makefile MSC_VER=0 + - echo>> Makefile RT=none + - echo>> Makefile RT_VER=0 + - echo>> Makefile BUILTIN_ENCOBJS=nul + - type win32\Makefile.sub >> Makefile + - nmake %mflags% up VCSUP="echo Update OK" + - nmake %mflags% extract-extlibs + - del Makefile + - mkdir \usr\local\bin + - mkdir \usr\local\include + - mkdir \usr\local\lib + - for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I + - for %%I in (c:\Tools\vcpkg\installed\%Platform%-windows\bin\*.dll) do ( + if not %%~nI == readline mklink \usr\local\bin\%%~nxI %%I + ) + - attrib +r /s /d + - mkdir %Platform%-mswin_%vs% + build_script: + - set HAVE_GIT=no + - cd %APPVEYOR_BUILD_FOLDER% + - cd %Platform%-mswin_%vs% + - >- + ..\win32\configure.bat + --with-opt-dir="/usr/local;c:/Tools/vcpkg/installed/%Platform%-windows" + --with-openssl-dir=%OPENSSL_DIR:\=/% + - nmake -l + - nmake install-nodoc + - \usr\bin\ruby -v -e "p :locale => Encoding.find('locale'), :filesystem => Encoding.find('filesystem')" + - if not "%GEMS_FOR_TEST%" == "" \usr\bin\gem install --no-document %GEMS_FOR_TEST% + - \usr\bin\ruby -ropenssl -e "puts 'Build ' + OpenSSL::OPENSSL_VERSION, 'Runtime ' + OpenSSL::OPENSSL_LIBRARY_VERSION" + test_script: + - set /a JOBS=%NUMBER_OF_PROCESSORS% + - nmake -l "TESTOPTS=-v -q" btest + - nmake -l "TESTOPTS=-v -q" test-basic + - >- + nmake -l "TESTOPTS=--timeout-scale=3.0 + --excludes=../test/excludes/_appveyor -j%JOBS% + --exclude win32ole + --exclude test_bignum + --exclude test_syntax + --exclude test_open-uri + --exclude test_bundled_ca + " test-all + # separately execute tests without -j which may crash worker with -j. + - >- + nmake -l + "TESTOPTS=--timeout-scale=3.0 --excludes=../test/excludes/_appveyor" + TESTS=" + ../test/win32ole + ../test/ruby/test_bignum.rb + ../test/ruby/test_syntax.rb + ../test/open-uri/test_open-uri.rb + ../test/rubygems/test_bundled_ca.rb + " test-all + - nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows +notifications: + - provider: Webhook + method: POST + url: + secure: CcFlJNDJ/a6to7u3Z4Fnz6dScEPNx7hTha2GkSRlV+1U6dqmxY/7uBcLXYb9gR3jfQk6w+2o/HrjNAyXMNGU/JOka3s2WRI4VKitzM+lQ08owvJIh0R7LxrGH0J2e81U # ruby-lang slack: ruby/simpler-alerts-bot + body: >- + {{^isPullRequest}} + { + "ci": "AppVeyor CI", + "env": "Visual Studio 2013", + "url": "{{buildUrl}}", + "commit": "{{commitId}}", + "branch": "{{branch}}" + } + {{/isPullRequest}} + on_build_success: false + on_build_failure: true + on_build_status_changed: false diff --git a/.cvsignore b/.cvsignore deleted file mode 100644 index 76c9bc0b78..0000000000 --- a/.cvsignore +++ /dev/null @@ -1,52 +0,0 @@ -*.bak -*.orig -*.rej -*.sav -*~ -.*.list -.*.time -.ccmalloc -.ppack -.ext -.git -.svn -.pc -COPYING.LIB -ChangeLog.pre-alpha -ChangeLog.pre1_1 -ChangeLog-1.8.0 -Makefile -README.fat-patch -README.v6 -README.atheos -archive -autom4te*.cache -automake -beos -config.cache -config.h -config.h.in -config.log -config.status -configure -libruby.so.* -miniruby -newdate.rb -newver.rb -parse.c -patches -patches-master -pitest.rb -ppack -preview -rbconfig.rb -rename2.h -repack -riscos -rubicon -ruby -ruby-man.rd.gz -tmp -web -y.output -y.tab.c diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000000..8f4b96445c --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,39 @@ +;; Copyright (c) 2018 Urabe, Shyouhei. All rights reserved. +;; +;; This file is a part of the programming language Ruby. Permission is hereby +;; granted, to either redistribute and/or modify this file, provided that the +;; conditions mentioned in the file COPYING are met. Consult the file for +;; details. + +((nil . + ((indent-tabs-mode . nil) + (require-final-newline . t) + (tab-width . 8) + (show-trailing-whitespace . t) + (whitespace-line-column . 80))) ;; See also [Misc #12277] + + ;; (bat-mode . ((buffer-file-coding-system . utf-8-dos))) + + (ruby-mode . ((ruby-indent-level . 2))) + + (rdoc-mode . ((fill-column . 74))) + + (yaml-mode . ((yaml-indent-offset . 2))) + + (makefile-mode . ((indent-tabs-mode . t))) + + (c-mode . ((c-file-style . "ruby"))) + + (c++-mode . ((c-file-style . "ruby"))) + + (change-log-mode . + ((buffer-file-coding-system . us-ascii) + (indent-tabs-mode . t) + (change-log-indent-text . 2) + (add-log-time-format . (lambda (&optional x y) + (let* ((time (or x (current-time))) + (system-time-locale "C") + (diff (+ (cadr time) 32400)) + (lo (% diff 65536)) + (hi (+ (car time) (/ diff 65536)))) + (format-time-string "%a %b %e %H:%M:%S %Y" (list hi lo) t))))))) @@ -5,12 +5,50 @@ # Process all the C source files *.c +*.y -# the lib/ directory (which has its own .document file) +# prelude +prelude.rb +rbconfig.rb -lib +array.rb +ast.rb +dir.rb +gc.rb +io.rb +kernel.rb +marshal.rb +mjit.rb +numeric.rb +nilclass.rb +pack.rb +ractor.rb +string.rb +symbol.rb +timev.rb +thread_sync.rb +trace_point.rb +warning.rb +yjit.rb +# the lib/ directory (which has its own .document file) +lib # and some of the ext/ directory (which has its own .document file) - ext + +# rdoc files +NEWS.md + +README.md +README.ja.md + +COPYING +COPYING.ja + +LEGAL + +# win32/README.win32 linked from README.md +win32 + +doc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..4633a7acae --- /dev/null +++ b/.editorconfig @@ -0,0 +1,30 @@ +root = true + +[*] +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +tab_width = 8 +trim_trailing_whitespace = true + +[*.bat] +end_of_line = crlf + +[*.gemspec] +indent_size = 2 + +[*.rb] +indent_size = 2 + +[*.yml] +indent_size = 2 + +[{*[Mm]akefile*,*.mak,*.mk,depend}] +indent_style = tab + +[enc/*] +indent_size = 2 + +[reg*.[ch]] +indent_size = 2 @@ -1,102 +1,113 @@ +set startup-with-shell off + +define hook-run + set $color_type = 0 + set $color_highlite = 0 + set $color_end = 0 +end + +define ruby_gdb_init + if !$color_type + set $color_type = "\033[31m" + end + if !$color_highlite + set $color_highlite = "\033[36m" + end + if !$color_end + set $color_end = "\033[m" + end + if ruby_dummy_gdb_enums.special_consts + end +end + +# set prompt \033[36m(gdb)\033[m\040 + define rp - if (VALUE)$arg0 & RUBY_FIXNUM_FLAG - printf "FIXNUM: %ld\n", $arg0 >> 1 + ruby_gdb_init + if (VALUE)($arg0) & RUBY_FIXNUM_FLAG + printf "FIXNUM: %ld\n", (long)($arg0) >> 1 else - if ((VALUE)$arg0 & ~(~(VALUE)0<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG - printf "SYMBOL(%ld)\n", $arg0 >> RUBY_SPECIAL_SHIFT + if ((VALUE)($arg0) & ~(~(VALUE)0<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG + set $id = (($arg0) >> RUBY_SPECIAL_SHIFT) + printf "%sSYMBOL%s: ", $color_type, $color_end + rp_id $id else - if $arg0 == RUBY_Qfalse + if ($arg0) == RUBY_Qfalse echo false\n else - if $arg0 == RUBY_Qtrue + if ($arg0) == RUBY_Qtrue echo true\n else - if $arg0 == RUBY_Qnil + if ($arg0) == RUBY_Qnil echo nil\n else - if $arg0 == RUBY_Qundef + if ($arg0) == RUBY_Qundef echo undef\n else - if (VALUE)$arg0 & RUBY_IMMEDIATE_MASK - echo immediate\n + if (VALUE)($arg0) & RUBY_IMMEDIATE_MASK + if ((VALUE)($arg0) & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG + printf "%sFLONUM%s: %g\n", $color_type, $color_end, (double)rb_float_value($arg0) + else + echo immediate\n + end else - set $flags = ((struct RBasic*)$arg0)->flags + set $flags = ((struct RBasic*)($arg0))->flags + if ($flags & RUBY_FL_PROMOTED) == RUBY_FL_PROMOTED + printf "[PROMOTED] " + end if ($flags & RUBY_T_MASK) == RUBY_T_NONE - printf "T_NONE: " - print (struct RBasic *)$arg0 + printf "%sT_NONE%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_NIL - printf "T_NIL: " - print (struct RBasic *)$arg0 + printf "%sT_NIL%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_OBJECT - printf "T_OBJECT: " - print (struct RObject *)$arg0 + printf "%sT_OBJECT%s: ", $color_type, $color_end + print ((struct RObject *)($arg0))->basic + if ($flags & ROBJECT_EMBED) + print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (ROBJECT_EMBED_LEN_MAX+0) + else + print (((struct RObject *)($arg0))->as.heap) + if (((struct RObject*)($arg0))->as.heap.numiv) > 0 + print/x *(((struct RObject*)($arg0))->as.heap.ivptr) @ (((struct RObject*)($arg0))->as.heap.numiv) + end + end else if ($flags & RUBY_T_MASK) == RUBY_T_CLASS - printf "T_CLASS: " - print (struct RClass *)$arg0 + printf "%sT_CLASS%s%s: ", $color_type, ($flags & RUBY_FL_SINGLETON) ? "*" : "", $color_end + rp_class $arg0 else if ($flags & RUBY_T_MASK) == RUBY_T_ICLASS - printf "T_ICLASS: " - print (struct RClass *)$arg0 + printf "%sT_ICLASS%s: ", $color_type, $color_end + rp_class $arg0 else if ($flags & RUBY_T_MASK) == RUBY_T_MODULE - printf "T_MODULE: " - print (struct RClass *)$arg0 + printf "%sT_MODULE%s: ", $color_type, $color_end + rp_class $arg0 else if ($flags & RUBY_T_MASK) == RUBY_T_FLOAT - printf "T_FLOAT: %.16g ", (((struct RFloat*)$arg0)->float_value) - print (struct RFloat *)$arg0 + printf "%sT_FLOAT%s: %.16g ", $color_type, $color_end, (((struct RFloat*)($arg0))->float_value) + print (struct RFloat *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_STRING - printf "T_STRING: " - set print address off - output (char *)(($flags & RUBY_FL_USER1) ? \ - ((struct RString*)$arg0)->as.heap.ptr : \ - ((struct RString*)$arg0)->as.ary) - set print address on - printf " bytesize:%ld ", ($flags & RUBY_FL_USER1) ? \ - ((struct RString*)$arg0)->as.heap.len : \ - (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) - if !($flags & RUBY_FL_USER1) - printf "(embed) " - else - if ($flags & RUBY_FL_USER2) - printf "(shared) " - end - if ($flags & RUBY_FL_USER3) - printf "(assoc) " - end - end - printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT - if ($flags & RUBY_ENC_CODERANGE_MASK) == 0 - printf "coderange:unknown " - else - if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_7BIT - printf "coderange:7bit " - else - if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_VALID - printf "coderange:valid " - else - printf "coderange:broken " - end - end - end - print (struct RString *)$arg0 + printf "%sT_STRING%s: ", $color_type, $color_end + rp_string $arg0 $flags else if ($flags & RUBY_T_MASK) == RUBY_T_REGEXP - set $regsrc = ((struct RRegexp*)$arg0)->src + set $regsrc = ((struct RRegexp*)($arg0))->src set $rsflags = ((struct RBasic*)$regsrc)->flags - printf "T_REGEXP: " + printf "%sT_REGEXP%s: ", $color_type, $color_end + set $len = ($rsflags & RUBY_FL_USER1) ? \ + ((struct RString*)$regsrc)->as.heap.len : \ + (($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) set print address off - output (char *)(($rsflags & RUBY_FL_USER1) ? \ + output *(char *)(($rsflags & RUBY_FL_USER1) ? \ ((struct RString*)$regsrc)->as.heap.ptr : \ - ((struct RString*)$regsrc)->as.ary) + ((struct RString*)$regsrc)->as.ary) @ $len set print address on - printf " len:%ld ", ($rsflags & RUBY_FL_USER1) ? \ - ((struct RString*)$regsrc)->as.heap.len : \ - (($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + printf " len:%ld ", $len if $flags & RUBY_FL_USER6 printf "(none) " end @@ -107,119 +118,162 @@ define rp printf "(fixed) " end printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT - print (struct RRegexp *)$arg0 + print (struct RRegexp *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY if ($flags & RUBY_FL_USER1) set $len = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3)) - printf "T_ARRAY: len=%ld ", $len + printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len printf "(embed) " if ($len == 0) printf "{(empty)} " else - output/x *((VALUE*)((struct RArray*)$arg0)->as.ary) @ $len + print/x *((VALUE*)((struct RArray*)($arg0))->as.ary) @ $len printf " " end else - set $len = ((struct RArray*)$arg0)->as.heap.len - printf "T_ARRAY: len=%ld ", $len + set $len = ((struct RArray*)($arg0))->as.heap.len + printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len if ($flags & RUBY_FL_USER2) printf "(shared) shared=" - output/x ((struct RArray*)$arg0)->as.heap.aux.shared + output/x ((struct RArray*)($arg0))->as.heap.aux.shared_root printf " " else - printf "(ownership) capa=%ld ", ((struct RArray*)$arg0)->as.heap.aux.capa + printf "(ownership) capa=%ld ", ((struct RArray*)($arg0))->as.heap.aux.capa end if ($len == 0) printf "{(empty)} " else - output/x *((VALUE*)((struct RArray*)$arg0)->as.heap.ptr) @ $len + print/x *((VALUE*)((struct RArray*)($arg0))->as.heap.ptr) @ $len printf " " end end - print (struct RArray *)$arg0 + print (struct RArray *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM - printf "T_FIXNUM: " - print (struct RBasic *)$arg0 + printf "%sT_FIXNUM%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_HASH - printf "T_HASH: ", - if ((struct RHash *)$arg0)->ntbl - printf "len=%ld ", ((struct RHash *)$arg0)->ntbl->num_entries + printf "%sT_HASH%s: ", $color_type, $color_end, + if (((struct RHash *)($arg0))->basic.flags & RHASH_ST_TABLE_FLAG) + printf "st len=%ld ", ((struct RHash *)($arg0))->as.st->num_entries + else + printf "li len=%ld bound=%ld ", \ + ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT), \ + ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_BOUND_MASK) >> RHASH_AR_TABLE_BOUND_SHIFT) end - print (struct RHash *)$arg0 + print (struct RHash *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT - printf "T_STRUCT: len=%ld ", \ - (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ + set $len = (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ ($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) >> (RUBY_FL_USHIFT+1) : \ - ((struct RStruct *)$arg0)->as.heap.len) - print (struct RStruct *)$arg0 - x/xw (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ - ((struct RStruct *)$arg0)->as.ary : \ - ((struct RStruct *)$arg0)->as.heap.len) + ((struct RStruct *)($arg0))->as.heap.len) + printf "%sT_STRUCT%s: len=%ld ", $color_type, $color_end, $len + print (struct RStruct *)($arg0) + output/x *(($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ + ((struct RStruct *)($arg0))->as.ary : \ + ((struct RStruct *)($arg0))->as.heap.ptr) @ $len else if ($flags & RUBY_T_MASK) == RUBY_T_BIGNUM - printf "T_BIGNUM: sign=%d len=%ld ", \ - (($flags & RUBY_FL_USER1) != 0), \ - (($flags & RUBY_FL_USER2) ? \ - ($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \ - ((struct RBignum*)$arg0)->as.heap.len) - if $flags & RUBY_FL_USER2 - printf "(embed) " - end - print (struct RBignum *)$arg0 - x/xw (($flags & RUBY_FL_USER2) ? \ - ((struct RBignum*)$arg0)->as.ary : \ - ((struct RBignum*)$arg0)->as.heap.digits) + rp_bignum $arg0 else if ($flags & RUBY_T_MASK) == RUBY_T_RATIONAL - printf "T_RATIONAL: " - print (struct RRational *)$arg0 + printf "%sT_RATIONAL%s: ", $color_type, $color_end + print (struct RRational *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_COMPLEX - printf "T_COMPLEX: " - print (struct RComplex *)$arg0 + printf "%sT_COMPLEX%s: ", $color_type, $color_end + print (struct RComplex *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_FILE - printf "T_FILE: " - print (struct RFile *)$arg0 - output *((struct RFile *)$arg0)->fptr + printf "%sT_FILE%s: ", $color_type, $color_end + print (struct RFile *)($arg0) + output *((struct RFile *)($arg0))->fptr printf "\n" else if ($flags & RUBY_T_MASK) == RUBY_T_TRUE - printf "T_TRUE: " - print (struct RBasic *)$arg0 + printf "%sT_TRUE%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_FALSE - printf "T_FALSE: " - print (struct RBasic *)$arg0 + printf "%sT_FALSE%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_DATA - printf "T_DATA: " - print (struct RData *)$arg0 + if ((struct RTypedData *)($arg0))->typed_flag == 1 + printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((struct RTypedData *)($arg0))->type->wrap_struct_name + print (struct RTypedData *)($arg0) + else + printf "%sT_DATA%s: ", $color_type, $color_end + print (struct RData *)($arg0) + end else if ($flags & RUBY_T_MASK) == RUBY_T_MATCH - printf "T_MATCH: " - print (struct RMatch *)$arg0 + printf "%sT_MATCH%s: ", $color_type, $color_end + print (struct RMatch *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_SYMBOL - printf "T_SYMBOL: " - print (struct RBasic *)$arg0 + printf "%sT_SYMBOL%s: ", $color_type, $color_end + print (struct RSymbol *)($arg0) + set $id_type = ((struct RSymbol *)($arg0))->id & RUBY_ID_SCOPE_MASK + if $id_type == RUBY_ID_LOCAL + printf "l" + else + if $id_type == RUBY_ID_INSTANCE + printf "i" + else + if $id_type == RUBY_ID_GLOBAL + printf "G" + else + if $id_type == RUBY_ID_ATTRSET + printf "a" + else + if $id_type == RUBY_ID_CONST + printf "C" + else + if $id_type == RUBY_ID_CLASS + printf "c" + else + printf "j" + end + end + end + end + end + end + set $id_fstr = ((struct RSymbol *)($arg0))->fstr + rp_string $id_fstr else if ($flags & RUBY_T_MASK) == RUBY_T_UNDEF - printf "T_UNDEF: " - print (struct RBasic *)$arg0 + printf "%sT_UNDEF%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) + else + if ($flags & RUBY_T_MASK) == RUBY_T_IMEMO + printf "%sT_IMEMO%s(", $color_type, $color_end + output (enum imemo_type)(($flags>>RUBY_FL_USHIFT)&RUBY_IMEMO_MASK) + printf "): " + rp_imemo $arg0 else if ($flags & RUBY_T_MASK) == RUBY_T_NODE - printf "T_NODE(" + printf "%sT_NODE%s(", $color_type, $color_end output (enum node_type)(($flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT) printf "): " - print *(NODE *)$arg0 + print *(NODE *)($arg0) + else + if ($flags & RUBY_T_MASK) == RUBY_T_ZOMBIE + printf "%sT_ZOMBIE%s: ", $color_type, $color_end + print (struct RData *)($arg0) + else + if ($flags & RUBY_T_MASK) == RUBY_T_MOVED + printf "%sT_MOVED%s: ", $color_type, $color_end + print *(struct RMoved *)$arg0 else - printf "unknown: " - print (struct RBasic *)$arg0 + printf "%sunknown%s: ", $color_type, $color_end + print (struct RBasic *)($arg0) + end + end + end end end end @@ -256,22 +310,312 @@ document rp Print a Ruby's VALUE. end +define rp_id + set $id = (ID)$arg0 + if $id == '!' || $id == '+' || $id == '-' || $id == '*' || $id == '/' || $id == '%' || $id == '<' || $id == '>' || $id == '`' + printf "(:%c)\n", $id + else + if $id == idDot2 + printf "(:..)\n" + else + if $id == idDot3 + printf "(:...)\n" + else + if $id == idUPlus + printf "(:+@)\n" + else + if $id == idUMinus + printf "(:-@)\n" + else + if $id == idPow + printf "(:**)\n" + else + if $id == idCmp + printf "(:<=>)\n" + else + if $id == idLTLT + printf "(:<<)\n" + else + if $id == idGTGT + printf "(:>>)\n" + else + if $id == idLE + printf "(:<=)\n" + else + if $id == idGE + printf "(:>=)\n" + else + if $id == idEq + printf "(:==)\n" + else + if $id == idEqq + printf "(:===)\n" + else + if $id == idNeq + printf "(:!=)\n" + else + if $id == idEqTilde + printf "(:=~)\n" + else + if $id == idNeqTilde + printf "(:!~)\n" + else + if $id == idAREF + printf "(:[])\n" + else + if $id == idASET + printf "(:[]=)\n" + else + if $id == idCOLON2 + printf "(:'::')\n" + else + if $id == idANDOP + printf "(:&&)\n" + else + if $id == idOROP + printf "(:||)\n" + else + if $id == idANDDOT + printf "(:&.)\n" + else + if $id <= tLAST_OP_ID + printf "O" + else + set $id_type = $id & RUBY_ID_SCOPE_MASK + if $id_type == RUBY_ID_LOCAL + printf "l" + else + if $id_type == RUBY_ID_INSTANCE + printf "i" + else + if $id_type == RUBY_ID_GLOBAL + printf "G" + else + if $id_type == RUBY_ID_ATTRSET + printf "a" + else + if $id_type == RUBY_ID_CONST + printf "C" + else + if $id_type == RUBY_ID_CLASS + printf "c" + else + printf "j" + end + end + end + end + end + end + end + printf "(%ld): ", $id + print_id $id + echo \n + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end +end +document rp_id + Print an ID. +end + +define output_string + set $flags = ((struct RBasic*)($arg0))->flags + set $len = ($flags & RUBY_FL_USER1) ? \ + ((struct RString*)($arg0))->as.heap.len : \ + (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + if $len > 0 + output *(char *)(($flags & RUBY_FL_USER1) ? \ + ((struct RString*)($arg0))->as.heap.ptr : \ + ((struct RString*)($arg0))->as.ary) @ $len + else + output "" + end +end + +define print_string + set $flags = ((struct RBasic*)($arg0))->flags + set $len = ($flags & RUBY_FL_USER1) ? \ + ((struct RString*)($arg0))->as.heap.len : \ + (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + if $len > 0 + printf "%s", *(char *)(($flags & RUBY_FL_USER1) ? \ + ((struct RString*)($arg0))->as.heap.ptr : \ + ((struct RString*)($arg0))->as.ary) @ $len + end +end + +define rp_string + output_string $arg0 + printf " bytesize:%ld ", $len + if !($flags & RUBY_FL_USER1) + printf "(embed) " + else + if ($flags & RUBY_FL_USER2) + printf "(shared) " + end + if ($flags & RUBY_FL_USER3) + printf "(assoc) " + end + end + printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT + if ($flags & RUBY_ENC_CODERANGE_MASK) == 0 + printf "coderange:unknown " + else + if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_7BIT + printf "coderange:7bit " + else + if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_VALID + printf "coderange:valid " + else + printf "coderange:broken " + end + end + end + print (struct RString *)($arg0) +end +document rp_string + Print the content of a String. +end + +define rp_bignum + set $flags = ((struct RBignum*)($arg0))->basic.flags + set $len = (($flags & RUBY_FL_USER2) ? \ + ($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \ + ((struct RBignum*)($arg0))->as.heap.len) + printf "%sT_BIGNUM%s: sign=%d len=%ld ", $color_type, $color_end, \ + (($flags & RUBY_FL_USER1) != 0), $len + if $flags & RUBY_FL_USER2 + printf "(embed) " + end + print (struct RBignum *)($arg0) + set $ptr = (($flags & RUBY_FL_USER2) ? \ + ((struct RBignum*)($arg0))->as.ary : \ + ((struct RBignum*)($arg0))->as.heap.digits) + set $len = $len-1 + printf "0x%x", $ptr[$len] + while $len > 0 + set $len = $len-1 + set $val = $ptr[$len] + set $w = sizeof($ptr[0]) + printf "_" + if $w > 8 + printf "%.32x", $val + else + if $w > 4 + printf "%.16x", $val + else + if $w > 2 + printf "%.8x", $val + else + if $w > 1 + printf "%.4x", $val + else + printf "%.2x", $val + end + end + end + end + end + printf "\n" +end +document rp_bignum + Print the content of a Bignum. +end + +define rp_class + printf "(struct RClass *) %p", (void*)$arg0 + if RCLASS_ORIGIN((struct RClass *)($arg0)) != $arg0 + printf " -> %p", RCLASS_ORIGIN((struct RClass *)($arg0)) + end + printf "\n" + rb_classname $arg0 + print/x *(struct RClass *)($arg0) + print *RCLASS_EXT((struct RClass *)($arg0)) +end +document rp_class + Print the content of a Class/Module. +end + +define rp_imemo + set $flags = (enum imemo_type)((((struct RBasic *)($arg0))->flags >> RUBY_FL_USHIFT) & RUBY_IMEMO_MASK) + if $flags == imemo_cref + printf "(rb_cref_t *) %p\n", (void*)$arg0 + print *(rb_cref_t *)$arg0 + else + if $flags == imemo_svar + printf "(struct vm_svar *) %p\n", (void*)$arg0 + print *(struct vm_svar *)$arg0 + else + if $flags == imemo_throw_data + printf "(struct vm_throw_data *) %p\n", (void*)$arg0 + print *(struct vm_throw_data *)$arg0 + else + if $flags == imemo_ifunc + printf "(struct vm_ifunc *) %p\n", (void*)$arg0 + print *(struct vm_ifunc *)$arg0 + else + if $flags == imemo_memo + printf "(struct MEMO *) %p\n", (void*)$arg0 + print *(struct MEMO *)$arg0 + else + if $flags == imemo_ment + printf "(rb_method_entry_t *) %p\n", (void*)$arg0 + print *(rb_method_entry_t *)$arg0 + else + if $flags == imemo_iseq + printf "(rb_iseq_t *) %p\n", (void*)$arg0 + print *(rb_iseq_t *)$arg0 + else + printf "(struct RIMemo *) %p\n", (void*)$arg0 + print *(struct RIMemo *)$arg0 + end + end + end + end + end + end + end +end +document rp_imemo + Print the content of a memo +end + define nd_type - print (enum node_type)((((NODE*)$arg0)->flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT) + print (enum node_type)((((NODE*)($arg0))->flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT) end document nd_type Print a Ruby' node type. end define nd_file - print ((NODE*)$arg0)->nd_file + print ((NODE*)($arg0))->nd_file end document nd_file Print the source file name of a node. end define nd_line - print ((unsigned int)((((NODE*)$arg0)->flags>>RUBY_NODE_LSHIFT)&RUBY_NODE_LMASK)) + print ((unsigned int)((((NODE*)($arg0))->flags>>RUBY_NODE_LSHIFT)&RUBY_NODE_LMASK)) end document nd_line Print the source line number of a node. @@ -280,274 +624,727 @@ end # Print members of ruby node. define nd_head - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_alen - printf "u2.argc: " - p $arg0.u2.argc + printf "%su2.argc%s: ", $color_highlite, $color_end + p ($arg0).u2.argc end define nd_next - printf "u3.node: " - rp $arg0.u3.node + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_cond - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_body - printf "u2.node: " - rp $arg0.u2.node + printf "%su2.node%s: ", $color_highlite, $color_end + rp ($arg0).u2.node end define nd_else - printf "u3.node: " - rp $arg0.u3.node + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_orig - printf "u3.value: " - rp $arg0.u3.value + printf "%su3.value%s: ", $color_highlite, $color_end + rp ($arg0).u3.value end define nd_resq - printf "u2.node: " - rp $arg0.u2.node + printf "%su2.node%s: ", $color_highlite, $color_end + rp ($arg0).u2.node end define nd_ensr - printf "u3.node: " - rp $arg0.u3.node + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_1st - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_2nd - printf "u2.node: " - rp $arg0.u2.node + printf "%su2.node%s: ", $color_highlite, $color_end + rp ($arg0).u2.node end define nd_stts - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_entry - printf "u3.entry: " - p $arg0.u3.entry + printf "%su3.entry%s: ", $color_highlite, $color_end + p ($arg0).u3.entry end define nd_vid - printf "u1.id: " - p $arg0.u1.id + printf "%su1.id%s: ", $color_highlite, $color_end + p ($arg0).u1.id end define nd_cflag - printf "u2.id: " - p $arg0.u2.id + printf "%su2.id%s: ", $color_highlite, $color_end + p ($arg0).u2.id end define nd_cval - printf "u3.value: " - rp $arg0.u3.value -end - - -define nd_cnt - printf "u3.cnt: " - p $arg0.u3.cnt + printf "%su3.value%s: ", $color_highlite, $color_end + rp ($arg0).u3.value end define nd_tbl - printf "u1.tbl: " - p $arg0.u1.tbl + printf "%su1.tbl%s: ", $color_highlite, $color_end + p ($arg0).u1.tbl end define nd_var - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_ibdy - printf "u2.node: " - rp $arg0.u2.node + printf "%su2.node%s: ", $color_highlite, $color_end + rp ($arg0).u2.node end define nd_iter - printf "u3.node: " - rp $arg0.u3.node + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_value - printf "u2.node: " - rp $arg0.u2.node + printf "%su2.node%s: ", $color_highlite, $color_end + rp ($arg0).u2.node end define nd_aid - printf "u3.id: " - p $arg0.u3.id + printf "%su3.id%s: ", $color_highlite, $color_end + p ($arg0).u3.id end define nd_lit - printf "u1.value: " - rp $arg0.u1.value -end - - -define nd_frml - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.value%s: ", $color_highlite, $color_end + rp ($arg0).u1.value end define nd_rest - printf "u2.argc: " - p $arg0.u2.argc + printf "%su2.argc%s: ", $color_highlite, $color_end + p ($arg0).u2.argc end define nd_opt - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_recv - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_mid - printf "u2.id: " - p $arg0.u2.id + printf "%su2.id%s: ", $color_highlite, $color_end + p ($arg0).u2.id end define nd_args - printf "u3.node: " - rp $arg0.u3.node -end - - -define nd_noex - printf "u1.id: " - p $arg0.u1.id + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_defn - printf "u3.node: " - rp $arg0.u3.node + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_old - printf "u1.id: " - p $arg0.u1.id + printf "%su1.id%s: ", $color_highlite, $color_end + p ($arg0).u1.id end define nd_new - printf "u2.id: " - p $arg0.u2.id -end - - -define nd_cfnc - printf "u1.cfunc: " - p $arg0.u1.cfunc -end - -define nd_argc - printf "u2.argc: " - p $arg0.u2.argc + printf "%su2.id%s: ", $color_highlite, $color_end + p ($arg0).u2.id end define nd_cname - printf "u1.id: " - p $arg0.u1.id + printf "%su1.id%s: ", $color_highlite, $color_end + p ($arg0).u1.id end define nd_super - printf "u3.node: " - rp $arg0.u3.node + printf "%su3.node%s: ", $color_highlite, $color_end + rp ($arg0).u3.node end define nd_modl - printf "u1.id: " - p $arg0.u1.id + printf "%su1.id%s: ", $color_highlite, $color_end + p ($arg0).u1.id end define nd_clss - printf "u1.value: " - rp $arg0.u1.value + printf "%su1.value%s: ", $color_highlite, $color_end + rp ($arg0).u1.value end define nd_beg - printf "u1.node: " - rp $arg0.u1.node + printf "%su1.node%s: ", $color_highlite, $color_end + rp ($arg0).u1.node end define nd_end - printf "u2.node: " - rp $arg0.u2.node + printf "%su2.node%s: ", $color_highlite, $color_end + rp ($arg0).u2.node end define nd_state - printf "u3.state: " - p $arg0.u3.state + printf "%su3.state%s: ", $color_highlite, $color_end + p ($arg0).u3.state end define nd_rval - printf "u2.value: " - rp $arg0.u2.value + printf "%su2.value%s: ", $color_highlite, $color_end + rp ($arg0).u2.value end define nd_nth - printf "u2.argc: " - p $arg0.u2.argc + printf "%su2.argc%s: ", $color_highlite, $color_end + p ($arg0).u2.argc end define nd_tag - printf "u1.id: " - p $arg0.u1.id + printf "%su1.id%s: ", $color_highlite, $color_end + p ($arg0).u1.id end define nd_tval - printf "u2.value: " - rp $arg0.u2.value + printf "%su2.value%s: ", $color_highlite, $color_end + rp ($arg0).u2.value +end + +define nd_tree + set $buf = (struct RString *)rb_str_buf_new(0) + call dump_node((VALUE)($buf), rb_str_tmp_new(0), 0, ($arg0)) + printf "%s\n", $buf->as.heap.ptr end define rb_p call rb_p($arg0) end +define rb_numtable_entry + set $rb_numtable_tbl = $arg0 + set $rb_numtable_id = (st_data_t)$arg1 + set $rb_numtable_key = 0 + set $rb_numtable_rec = 0 + if $rb_numtable_tbl->entries_packed + set $rb_numtable_p = $rb_numtable_tbl->as.packed.bins + while $rb_numtable_p && $rb_numtable_p < $rb_numtable_tbl->as.packed.bins+$rb_numtable_tbl->num_entries + if $rb_numtable_p.k == $rb_numtable_id + set $rb_numtable_key = $rb_numtable_p.k + set $rb_numtable_rec = $rb_numtable_p.v + set $rb_numtable_p = 0 + else + set $rb_numtable_p = $rb_numtable_p + 1 + end + end + else + set $rb_numtable_p = $rb_numtable_tbl->as.big.bins[st_numhash($rb_numtable_id) % $rb_numtable_tbl->num_bins] + while $rb_numtable_p + if $rb_numtable_p->key == $rb_numtable_id + set $rb_numtable_key = $rb_numtable_p->key + set $rb_numtable_rec = $rb_numtable_p->record + set $rb_numtable_p = 0 + else + set $rb_numtable_p = $rb_numtable_p->next + end + end + end +end + define rb_id2name - call rb_id2name($arg0) + ruby_gdb_init + printf "%sID%s: ", $color_type, $color_end + rp_id $arg0 +end +document rb_id2name + Print the name of id +end + +define rb_method_entry + set $rb_method_entry_klass = (struct RClass *)$arg0 + set $rb_method_entry_id = (ID)$arg1 + set $rb_method_entry_me = (rb_method_entry_t *)0 + while !$rb_method_entry_me && $rb_method_entry_klass + rb_numtable_entry $rb_method_entry_klass->m_tbl_wrapper->tbl $rb_method_entry_id + set $rb_method_entry_me = (rb_method_entry_t *)$rb_numtable_rec + if !$rb_method_entry_me + set $rb_method_entry_klass = (struct RClass *)RCLASS_SUPER($rb_method_entry_klass) + end + end + if $rb_method_entry_me + print *$rb_method_entry_klass + print *$rb_method_entry_me + else + echo method not found\n + end +end +document rb_method_entry + Search method entry by class and id end define rb_classname - call classname($arg0) - rb_p $ - print *(struct RClass*)$arg0 + # up to 128bit int + set $rb_classname = rb_mod_name($arg0) + if $rb_classname != RUBY_Qnil + rp $rb_classname + else + echo anonymous class/module\n + end +end + +define rb_ancestors + set $rb_ancestors_module = $arg0 + while $rb_ancestors_module + rp_class $rb_ancestors_module + set $rb_ancestors_module = RCLASS_SUPER($rb_ancestors_module) + end +end +document rb_ancestors + Print ancestors. end define rb_backtrace call rb_backtrace() end + +define iseq + if ruby_dummy_gdb_enums.special_consts + end + if ($arg0)->type == ISEQ_ELEMENT_NONE + echo [none]\n + end + if ($arg0)->type == ISEQ_ELEMENT_LABEL + print *(LABEL*)($arg0) + end + if ($arg0)->type == ISEQ_ELEMENT_INSN + print *(INSN*)($arg0) + if ((INSN*)($arg0))->insn_id != YARVINSN_jump + set $i = 0 + set $operand_size = ((INSN*)($arg0))->operand_size + set $operands = ((INSN*)($arg0))->operands + while $i < $operand_size + rp $operands[$i++] + end + end + end + if ($arg0)->type == ISEQ_ELEMENT_ADJUST + print *(ADJUST*)($arg0) + end +end + +define rb_ps + rb_ps_vm ruby_current_vm_ptr +end +document rb_ps +Dump all threads and their callstacks +end + +define rb_ps_vm + print $ps_vm = (rb_vm_t*)$arg0 + set $ps_thread_ln = $ps_vm->ractor.main_ractor.threads.set.n.next + set $ps_thread_ln_last = $ps_vm->ractor.main_ractor.threads.set.n.prev + while 1 + set $ps_thread_th = (rb_thread_t *)$ps_thread_ln + set $ps_thread = (VALUE)($ps_thread_th->self) + rb_ps_thread $ps_thread + if $ps_thread_ln == $ps_thread_ln_last + loop_break + end + set $ps_thread_ln = $ps_thread_ln->next + end +end +document rb_ps_vm +Dump all threads in a (rb_vm_t*) and their callstacks +end + +define print_lineno + set $cfp = $arg0 + set $iseq = $cfp->iseq + set $pos = $cfp->pc - $iseq->body->iseq_encoded + if $pos != 0 + set $pos = $pos - 1 + end + + set $index = 0 + set $size = $iseq->body->insns_info.size + set $table = $iseq->body->insns_info.body + set $positions = $iseq->body->insns_info.positions + #printf "size: %d\n", $size + if $size == 0 + else + if $size == 1 + printf "%d", $table[0].line_no + else + if $positions + # get_insn_info_linear_search + set $index = 1 + while $index < $size + #printf "table[%d]: position: %d, line: %d, pos: %d\n", $i, $positions[$i], $table[$i].line_no, $pos + if $positions[$index] > $pos + loop_break + end + set $index = $index + 1 + if $positions[$index] == $pos + loop_break + end + end + else + # get_insn_info_succinct_bitvector + set $sd = $iseq->body->insns_info.succ_index_table + set $immediate_table_size = sizeof($sd->imm_part) / sizeof(uint64_t) * 9 + if $pos < $immediate_table_size + set $i = $pos / 9 + set $j = $pos % 9 + set $index = ((int)($sd->imm_part[$i] >> ($j * 7))) & 0x7f + else + set $block_index = ($pos - $immediate_table_size) / 512 + set $block = &$sd->succ_part[$block_index] + set $block_bit_index = ($pos - $immediate_table_size) % 512 + set $small_block_index = $block_bit_index / 64 + set $small_block_popcount = $small_block_index == 0 ? 0 : (((int)($block->small_block_ranks >> (($small_block_index - 1) * 9))) & 0x1ff) + set $x = $block->bits[$small_block_index] << (63 - $block_bit_index % 64) + set $x = ($x & 0x5555555555555555) + ($x >> 1 & 0x5555555555555555) + set $x = ($x & 0x3333333333333333) + ($x >> 2 & 0x3333333333333333) + set $x = ($x & 0x0707070707070707) + ($x >> 4 & 0x0707070707070707) + set $x = ($x & 0x001f001f001f001f) + ($x >> 8 & 0x001f001f001f001f) + set $x = ($x & 0x0000003f0000003f) + ($x >>16 & 0x0000003f0000003f) + set $popcnt = ($x & 0x7f) + ($x >>32 & 0x7f) + set $index = $block->rank + $small_block_popcount + $popcnt + end + end + printf "%d", $table[$index-1].line_no + end + end +end + +define check_method_entry + set $imemo = (struct RBasic *)$arg0 + if $imemo != RUBY_Qfalse + set $type = ($imemo->flags >> 12) & 0x07 + if $type == imemo_ment + set $me = (rb_callable_method_entry_t *)$imemo + else + if $type == imemo_svar + set $imemo = ((struct vm_svar *)$imemo)->cref_or_me + check_method_entry $imemo + end + end + end +end + +define print_id + set $id = $arg0 + # rb_id_to_serial + if $id > tLAST_OP_ID + set $serial = (rb_id_serial_t)($id >> RUBY_ID_SCOPE_SHIFT) + else + set $serial = (rb_id_serial_t)$id + end + if $serial && $serial <= ruby_global_symbols.last_id + set $idx = $serial / ID_ENTRY_UNIT + set $ids = (struct RArray *)ruby_global_symbols.ids + set $flags = $ids->basic.flags + if ($flags & RUBY_FL_USER1) + set $idsptr = $ids->as.ary + set $idslen = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3)) + else + set $idsptr = $ids->as.heap.ptr + set $idslen = $ids->as.heap.len + end + if $idx < $idslen + set $t = 0 + set $ary = (struct RArray *)$idsptr[$idx] + if $ary != RUBY_Qnil + set $flags = $ary->basic.flags + if ($flags & RUBY_FL_USER1) + set $aryptr = $ary->as.ary + set $arylen = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3)) + else + set $aryptr = $ary->as.heap.ptr + set $arylen = $ary->as.heap.len + end + set $result = $aryptr[($serial % ID_ENTRY_UNIT) * ID_ENTRY_SIZE + $t] + if $result != RUBY_Qnil + print_string $result + else + echo undef + end + end + end + end +end + +define print_pathobj + set $flags = ((struct RBasic*)($arg0))->flags + if ($flags & RUBY_T_MASK) == RUBY_T_STRING + print_string $arg0 + end + if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY + if $flags & RUBY_FL_USER1 + set $str = ((struct RArray*)($arg0))->as.ary[0] + else + set $str = ((struct RArray*)($arg0))->as.heap.ptr[0] + end + print_string $str + end +end + +define rb_ps_thread + set $ps_thread = (struct RTypedData*)$arg0 + set $ps_thread_th = (rb_thread_t*)$ps_thread->data + printf "* #<Thread:%p rb_thread_t:%p native_thread:%p>\n", \ + $ps_thread, $ps_thread_th, $ps_thread_th->thread_id + set $cfp = $ps_thread_th->ec->cfp + set $cfpend = (rb_control_frame_t *)($ps_thread_th->ec->vm_stack + $ps_thread_th->ec->vm_stack_size)-1 + while $cfp < $cfpend + if $cfp->iseq + if !((VALUE)$cfp->iseq & RUBY_IMMEDIATE_MASK) && (((imemo_ifunc << RUBY_FL_USHIFT) | RUBY_T_IMEMO)==$cfp->iseq->flags & ((RUBY_IMEMO_MASK << RUBY_FL_USHIFT) | RUBY_T_MASK)) + printf "%d:ifunc ", $cfpend-$cfp + set print symbol-filename on + output/a $cfp->iseq.body + set print symbol-filename off + printf "\n" + else + if $cfp->pc + set $location = $cfp->iseq->body->location + printf "%d:", $cfpend-$cfp + print_pathobj $location.pathobj + printf ":" + print_lineno $cfp + printf ":in `" + print_string $location.label + printf "'\n" + else + printf "%d: ???.rb:???:in `???'\n", $cfpend-$cfp + end + end + else + # if VM_FRAME_TYPE($cfp->flag) == VM_FRAME_MAGIC_CFUNC + set $ep = $cfp->ep + if ($ep[0] & 0xffff0001) == 0x55550001 + #define VM_ENV_FLAG_LOCAL 0x02 + #define VM_ENV_PREV_EP(ep) GC_GUARDED_PTR_REF(ep[VM_ENV_DATA_INDEX_SPECVAL]) + set $me = 0 + set $env_specval = $ep[-1] + set $env_me_cref = $ep[-2] + while ($env_specval & 0x02) != 0 + check_method_entry $env_me_cref + if $me != 0 + loop_break + end + set $ep = $ep[0] + set $env_specval = $ep[-1] + set $env_me_cref = $ep[-2] + end + if $me == 0 + check_method_entry $env_me_cref + end + printf "%d:", $cfpend-$cfp + set print symbol-filename on + output/a $me->def->body.cfunc.func + set print symbol-filename off + set $mid = $me->def->original_id + printf ":in `" + print_id $mid + printf "'\n" + else + printf "%d:unknown_frame:???:in `???'\n", $cfpend-$cfp + end + end + set $cfp = $cfp + 1 + end +end + +define rb_count_objects + set $objspace = ruby_current_vm_ptr->objspace + set $counts_00 = 0 + set $counts_01 = 0 + set $counts_02 = 0 + set $counts_03 = 0 + set $counts_04 = 0 + set $counts_05 = 0 + set $counts_06 = 0 + set $counts_07 = 0 + set $counts_08 = 0 + set $counts_09 = 0 + set $counts_0a = 0 + set $counts_0b = 0 + set $counts_0c = 0 + set $counts_0d = 0 + set $counts_0e = 0 + set $counts_0f = 0 + set $counts_10 = 0 + set $counts_11 = 0 + set $counts_12 = 0 + set $counts_13 = 0 + set $counts_14 = 0 + set $counts_15 = 0 + set $counts_16 = 0 + set $counts_17 = 0 + set $counts_18 = 0 + set $counts_19 = 0 + set $counts_1a = 0 + set $counts_1b = 0 + set $counts_1c = 0 + set $counts_1d = 0 + set $counts_1e = 0 + set $counts_1f = 0 + set $total = 0 + set $i = 0 + while $i < $objspace->heap_pages.allocated_pages + printf "\rcounting... %d/%d", $i, $objspace->heap_pages.allocated_pages + set $page = $objspace->heap_pages.sorted[$i] + set $p = $page->start + set $pend = $p + $page->total_slots + while $p < $pend + set $flags = $p->as.basic.flags & 0x1f + eval "set $counts_%02x = $counts_%02x + 1", $flags, $flags + set $p = $p + 1 + end + set $total = $total + $page->total_slots + set $i = $i + 1 + end + printf "\rTOTAL: %d, FREE: %d\n", $total, $counts_00 + printf "T_OBJECT: %d\n", $counts_01 + printf "T_CLASS: %d\n", $counts_02 + printf "T_MODULE: %d\n", $counts_03 + printf "T_FLOAT: %d\n", $counts_04 + printf "T_STRING: %d\n", $counts_05 + printf "T_REGEXP: %d\n", $counts_06 + printf "T_ARRAY: %d\n", $counts_07 + printf "T_HASH: %d\n", $counts_08 + printf "T_STRUCT: %d\n", $counts_09 + printf "T_BIGNUM: %d\n", $counts_0a + printf "T_FILE: %d\n", $counts_0b + printf "T_DATA: %d\n", $counts_0c + printf "T_MATCH: %d\n", $counts_0d + printf "T_COMPLEX: %d\n", $counts_0e + printf "T_RATIONAL: %d\n", $counts_0f + #printf "UNKNOWN_10: %d\n", $counts_10 + printf "T_NIL: %d\n", $counts_11 + printf "T_TRUE: %d\n", $counts_12 + printf "T_FALSE: %d\n", $counts_13 + printf "T_SYMBOL: %d\n", $counts_14 + printf "T_FIXNUM: %d\n", $counts_15 + printf "T_UNDEF: %d\n", $counts_16 + #printf "UNKNOWN_17: %d\n", $counts_17 + #printf "UNKNOWN_18: %d\n", $counts_18 + #printf "UNKNOWN_19: %d\n", $counts_19 + printf "T_IMEMO: %d\n", $counts_1a + printf "T_NODE: %d\n", $counts_1b + printf "T_ICLASS: %d\n", $counts_1c + printf "T_ZOMBIE: %d\n", $counts_1d + #printf "UNKNOWN_1E: %d\n", $counts_1e + printf "T_MASK: %d\n", $counts_1f +end +document rb_count_objects + Counts all objects grouped by type. +end + +# Details: https://bugs.ruby-lang.org/projects/ruby-master/wiki/MachineInstructionsTraceWithGDB +define trace_machine_instructions + set logging on + set height 0 + set width 0 + display/i $pc + while !$exit_code + info line *$pc + si + end +end + +define SDR + call rb_vmdebug_stack_dump_raw_current() +end + +define rbi + if ((LINK_ELEMENT*)$arg0)->type == ISEQ_ELEMENT_LABEL + p *(LABEL*)$arg0 + else + if ((LINK_ELEMENT*)$arg0)->type == ISEQ_ELEMENT_INSN + p *(INSN*)$arg0 + else + if ((LINK_ELEMENT*)$arg0)->type == ISEQ_ELEMENT_ADJUST + p *(ADJUST*)$arg0 + else + print *$arg0 + end + end + end +end + +define dump_node + set $str = rb_parser_dump_tree($arg0, 0) + set $flags = ((struct RBasic*)($str))->flags + printf "%s", (char *)(($flags & RUBY_FL_USER1) ? \ + ((struct RString*)$str)->as.heap.ptr : \ + ((struct RString*)$str)->as.ary) +end + +define print_flags + printf "RUBY_FL_WB_PROTECTED: %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_WB_PROTECTED ? "1" : "0" + printf "RUBY_FL_PROMOTED0 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED0 ? "1" : "0" + printf "RUBY_FL_PROMOTED1 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED1 ? "1" : "0" + printf "RUBY_FL_FINALIZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FINALIZE ? "1" : "0" + printf "RUBY_FL_SHAREABLE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_SHAREABLE ? "1" : "0" + printf "RUBY_FL_EXIVAR : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_EXIVAR ? "1" : "0" + printf "RUBY_FL_FREEZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FREEZE ? "1" : "0" + + printf "RUBY_FL_USER0 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER0 ? "1" : "0" + printf "RUBY_FL_USER1 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER1 ? "1" : "0" + printf "RUBY_FL_USER2 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER2 ? "1" : "0" + printf "RUBY_FL_USER3 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER3 ? "1" : "0" + printf "RUBY_FL_USER4 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER4 ? "1" : "0" + printf "RUBY_FL_USER5 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER5 ? "1" : "0" + printf "RUBY_FL_USER6 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER6 ? "1" : "0" + printf "RUBY_FL_USER7 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER7 ? "1" : "0" + printf "RUBY_FL_USER8 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER8 ? "1" : "0" + printf "RUBY_FL_USER9 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER9 ? "1" : "0" + printf "RUBY_FL_USER10 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER10 ? "1" : "0" + printf "RUBY_FL_USER11 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER11 ? "1" : "0" + printf "RUBY_FL_USER12 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER12 ? "1" : "0" + printf "RUBY_FL_USER13 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER13 ? "1" : "0" + printf "RUBY_FL_USER14 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER14 ? "1" : "0" + printf "RUBY_FL_USER15 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER15 ? "1" : "0" + printf "RUBY_FL_USER16 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER16 ? "1" : "0" + printf "RUBY_FL_USER17 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER17 ? "1" : "0" + printf "RUBY_FL_USER18 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER18 ? "1" : "0" +end diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..6c5eac5a0f --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,23 @@ +# This is a file used by GitHub to ignore the following commits on `git blame`. +# +# You can also do the same thing in your local repository with: +# $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs + +# Expand tabs +5b21e94bebed90180d8ff63dad03b8b948361089 + +# Enable Style/StringLiterals cop for RubyGems/Bundler +d7ffd3fea402239b16833cc434404a7af82d44f3 + +# [ruby/digest] Revert tab-expansion in external files +48b09aae7ec5632209229dcc294dd0d75a93a17f +8a65cf3b61c60e4cb886f59a73ff6db44364bfa9 +39dc9f9093901d40d2998653948d5da38b18ee2c + +# [ruby/io-nonblock] Revert tab expansion +f28287d34c03f472ffe90ea262bdde9affd4b965 +0d842fecb4f75ab3b1d4097ebdb8e88f51558041 +4ba2c66761d6a293abdfba409241d31063cefd62 + +# Make benchmark indentation consistent +fc4acf8cae82e5196186d3278d831f2438479d91 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..d0c2d266b4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +*.gemspec diff=ruby +*.rb diff=ruby +bin svn-properties=svn:ignore=ruby +bin/* diff=ruby +tool/update-deps diff=ruby +tool/make-snapshot diff=ruby +tool/format-release diff=ruby +tool/leaked-globals diff=ruby diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000..56baa29942 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Supported Versions + +See <https://www.ruby-lang.org/en/downloads/branches/>. + +## Reporting a Vulnerability + +See <https://www.ruby-lang.org/en/security/>. diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000000..91f82b842b --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,3 @@ +name: "CodeQL config for the Ruby language" + +languages: cpp diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..bc63aca35b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'monthly' diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml new file mode 100644 index 0000000000..ebaafe3bf0 --- /dev/null +++ b/.github/workflows/baseruby.yml @@ -0,0 +1,80 @@ +name: BASERUBY Check + +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + baseruby: + name: BASERUBY + runs-on: ubuntu-22.04 + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + strategy: + matrix: + ruby: + - ruby-2.2 +# - ruby-2.3 +# - ruby-2.4 +# - ruby-2.5 +# - ruby-2.6 +# - ruby-2.7 + - ruby-3.0 + - ruby-3.1 + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: .downloaded-cache + key: downloaded-cache + - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 + with: + ruby-version: ${{ matrix.ruby }} + bundler: none + - run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - run: sudo apt-get install build-essential autoconf bison libyaml-dev + - run: ./autogen.sh + - run: ./configure --disable-install-doc + - run: make common-srcs + - run: make incs + - run: make all + - run: make test + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / BASERUBY @ ${{ matrix.ruby }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml new file mode 100644 index 0000000000..070c0fa1dd --- /dev/null +++ b/.github/workflows/bundled_gems.yml @@ -0,0 +1,166 @@ +name: bundled_gems + +on: + push: + branches: [ "master" ] + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + pull_request: + branches: [ "master" ] + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + merge_group: + branches: [ "master" ] + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + schedule: + - cron: '45 6 * * *' + workflow_dispatch: + +permissions: # added using https://github.com/step-security/secure-workflows + contents: read + +jobs: + update: + permissions: + contents: write # for Git to git push + if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }} + name: update ${{ github.workflow }} + runs-on: ubuntu-latest + steps: + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + echo "TODAY=$(date +%F)" >> $GITHUB_ENV + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: .downloaded-cache + key: downloaded-cache-${{ github.sha }} + restore-keys: | + downloaded-cache + + - name: Download previous gems list + run: | + data=bundled_gems.json + mkdir -p .downloaded-cache + ln -s .downloaded-cache/$data . + curl -O -R -z ./$data https://stdgems.org/$data + + - name: Update bundled gems list + run: | + ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems + + - name: Maintain updated gems list in NEWS + run: | + #!ruby + require 'json' + news = File.read("NEWS.md") + prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1] + prevs = [prev, prev.sub(/\.\d+\z/, '')] + %W[bundled].each do |type| + last = JSON.parse(File.read("#{type}_gems.json"))['gems'].filter_map do |g| + v = g['versions'].values_at(*prevs).compact.first + g = g['gem'] + g = 'RubyGems' if g == 'rubygems' + [g, v] if v + end.to_h + changed = File.foreach("gems/#{type}_gems").filter_map do |l| + next if l.start_with?("#") + g, v = l.split(" ", 3) + [g, v] unless last[g] == v + end + changed, added = changed.partition {|g, _| last[g]} + news.sub!(/^\*( +)The following #{type} gems? are updated\.\n+\K(?: \1\*( +).*\n)*/) do + mark = "#{$1} *#{$2}" + changed.map {|g, v|"#{mark}#{g} #{v}\n"}.join("") + end or next + news.sub!(/^\*( +)The following default gems are now bundled gems\.\n+\K(?: \1\*( +).*\n)*/) do + mark = "#{$1} *#{$2}" + added.map {|g, v|"#{mark}#{g} #{v}\n"}.join("") + end or next unless added.empty? + File.write("NEWS.md", news) + end + shell: ruby {0} + + - name: Check diffs + id: diff + run: | + git add -- NEWS.md + git diff --no-ext-diff --ignore-submodules --quiet -- gems/bundled_gems + continue-on-error: true + + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + if: ${{ steps.diff.outcome == 'failure' }} + + - name: Build + run: | + ./autogen.sh + ./configure -C --disable-install-doc + make + if: ${{ steps.diff.outcome == 'failure' }} + + - name: Prepare bundled gems + run: | + make -s prepare-gems + if: ${{ steps.diff.outcome == 'failure' }} + + - name: Test bundled gems + run: | + make -s test-bundled-gems + git add -- gems/bundled_gems + timeout-minutes: 30 + env: + RUBY_TESTOPTS: "-q --tty=no" + TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" + if: ${{ steps.diff.outcome == 'failure' }} + + - name: Show diffs + id: show + run: | + git diff --cached --color --no-ext-diff --ignore-submodules --exit-code -- + continue-on-error: true + + - name: Commit + run: | + git pull --ff-only origin ${GITHUB_REF#refs/heads/} + message="Update bundled gems list at " + if [ ${{ steps.diff.outcome }} = success ]; then + git commit --message="${message}${GITHUB_SHA:0:30} [ci skip]" + else + git commit --message="${message}${TODAY}" + fi + git push origin ${GITHUB_REF#refs/heads/} + env: + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + if: ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && steps.show.outcome == 'failure' }} + + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / update", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml new file mode 100644 index 0000000000..79b2916feb --- /dev/null +++ b/.github/workflows/check_dependencies.yml @@ -0,0 +1,78 @@ +name: Check Dependencies +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + update-deps: + strategy: + matrix: + os: [ubuntu-22.04] + fail-fast: true + runs-on: ${{ matrix.os }} + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + if: ${{ contains(matrix.os, 'ubuntu') }} + - name: Install libraries + run: | + brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline + if: ${{ contains(matrix.os, 'macos') }} + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: .downloaded-cache + key: downloaded-cache + - run: ./autogen.sh + - name: Run configure + run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g' + - run: make all golf + - run: ruby tool/update-deps --fix + - run: git diff --no-ext-diff --ignore-submodules --exit-code + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ matrix.os }} / Dependencies need to update", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000000..8dba76fbe2 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,75 @@ +name: "Code scanning - action" + +on: + # push: + # paths-ignore: + # - 'doc/**' + # - '**/man' + # - '**.md' + # - '**.rdoc' + # - '**/.document' + # pull_request: + # paths-ignore: + # - 'doc/**' + # - '**/man' + # - '**.md' + # - '**.rdoc' + # - '**/.document' + schedule: + - cron: '0 12 * * *' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: # added using https://github.com/step-security/secure-workflows + contents: read + +jobs: + CodeQL-Build: + + # CodeQL runs on ubuntu-latest and windows-latest + permissions: + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report + runs-on: ubuntu-latest + # CodeQL fails to run pull requests from dependabot due to missing write access to upload results. + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') && github.event.head_commit.pusher.name != 'dependabot[bot]' }} + + env: + enable_install_doc: no + + steps: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: .downloaded-cache + key: downloaded-cache + + - name: Remove an obsolete rubygems vendored file + run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb + + - name: Initialize CodeQL + uses: github/codeql-action/init@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37 + with: + config-file: ./.github/codeql/codeql-config.yml + trap-caching: false + + - name: Set ENV + run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + + - name: Autobuild + uses: github/codeql-action/autobuild@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37 diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml new file mode 100644 index 0000000000..caf12cc0f4 --- /dev/null +++ b/.github/workflows/compilers.yml @@ -0,0 +1,281 @@ +name: Compilations + +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +# GitHub actions does not support YAML anchors. This creative use of +# environment variables (plus the "echo $GITHUB_ENV" hack) is to reroute that +# restriction. +env: + default_cc: clang-15 + append_cc: '' + + # -O1 is faster than -O3 in our tests... Majority of time are consumed trying + # to optimize binaries. Also GitHub Actions run on relatively modern CPUs + # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native` + # because compilers tend not understand what the CPU is. + optflags: '-O1' + + # -g0 disables backtraces when SEGV. Do not set that. + debugflags: '-ggdb3' + + default_configure: >- + --enable-debug-env + --disable-install-doc + --with-ext=-test-/cxxanyargs,+ + append_configure: >- + --without-valgrind + --without-jemalloc + --without-gmp + + UPDATE_UNICODE: >- + UNICODE_FILES=. + UNICODE_PROPERTY_FILES=. + UNICODE_AUXILIARY_FILES=. + UNICODE_EMOJI_FILES=. + CONFIGURE_TTY: never + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + RUBY_DEBUG: ci rgengc + RUBY_TESTOPTS: >- + -q + --color=always + --tty=no + +permissions: + contents: read + +jobs: + compile: + strategy: + fail-fast: false + matrix: + env: + - {} + entry: + - { name: gcc-12, env: { default_cc: gcc-12 } } + - { name: gcc-11, env: { default_cc: gcc-11 } } + - { name: gcc-10, env: { default_cc: gcc-10 } } + - { name: gcc-9, env: { default_cc: gcc-9 } } + - { name: gcc-8, env: { default_cc: gcc-8 } } + - { name: gcc-7, env: { default_cc: gcc-7 } } + - name: 'gcc-13 LTO' + container: gcc-13 + env: + default_cc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch' + optflags: '-O2' + shared: disable + # check: true + - { name: clang-16, env: { default_cc: clang-16 } } + - { name: clang-15, env: { default_cc: clang-15 } } + - { name: clang-14, env: { default_cc: clang-14 } } + - { name: clang-13, env: { default_cc: clang-13 } } + - { name: clang-12, env: { default_cc: clang-12 } } + - { name: clang-11, env: { default_cc: clang-11 } } + - { name: clang-10, env: { default_cc: clang-10 } } + # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o. + - { name: clang-9, env: { default_cc: clang-9, append_configure: '--disable-yjit' } } + - { name: clang-8, env: { default_cc: clang-8, append_configure: '--disable-yjit' } } + - { name: clang-7, env: { default_cc: clang-7, append_configure: '--disable-yjit' } } + - { name: clang-6.0, env: { default_cc: clang-6.0, append_configure: '--disable-yjit' } } + - name: 'clang-16 LTO' + container: clang-16 + env: + default_cc: 'clang-16 -flto=auto' + optflags: '-O2' + shared: disable + # check: true + +# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 } +# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi } +# - { name: arm-linux-gnueabihf, crosshost: arm-linux-gnueabihf } +# - { name: i686-w64-mingw32, crosshost: i686-w64-mingw32 } +# - { name: powerpc-linux-gnu, crosshost: powerpc-linux-gnu } +# - { name: powerpc64le-linux-gnu, crosshost: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el } +# - { name: s390x-linux-gnu, crosshost: s390x-linux-gnu, container: crossbuild-essential-s390x } +# - { name: x86_64-w64-mingw32, crosshost: x86_64-w64-mingw32, container: mingw-w64 } + + # -Wno-strict-prototypes is necessary with current clang-15 since + # older autoconf generate functions without prototype and -pedantic + # now implies strict-prototypes. Disabling the error but leaving the + # warning generates a lot of noise from use of ANYARGS in + # rb_define_method() and friends. + # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94 + - { name: c99, env: { append_cc: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } +# - { name: c11, env: { append_cc: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } +# - { name: c17, env: { append_cc: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } + - { name: c2x, env: { append_cc: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } + - { name: c++98, env: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } +# - { name: c++11, env: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } +# - { name: c++14, env: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } +# - { name: c++17, env: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { name: c++2a, env: { CXXFLAGS: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + + - { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } } +# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true } + + - { name: gmp, env: { append_configure: '--with-gmp' } } + - { name: jemalloc, env: { append_configure: '--with-jemalloc' } } + - { name: valgrind, env: { append_configure: '--with-valgrind' } } + - { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } } + - { name: 'coroutine=pthread', env: { append_configure: '--with-coroutine=pthread' } } + - { name: disable-jit-support, env: { append_configure: '--disable-jit-support' } } + - { name: disable-dln, env: { append_configure: '--disable-dln' } } + - { name: enable-mkmf-verbose, env: { append_configure: '--enable-mkmf-verbose' } } + - { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } } + - { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } } + + - { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } } + - { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } } + - { name: OPT_THREADED_CODE=3, env: { cppflags: '-DOPT_THREADED_CODE=3' } } + + - { name: NDEBUG, env: { cppflags: '-DNDEBUG' } } + - { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } } +# - { name: ARRAY_DEBUG, env: { cppflags: '-DARRAY_DEBUG' } } +# - { name: BIGNUM_DEBUG, env: { cppflags: '-DBIGNUM_DEBUG' } } +# - { name: CCAN_LIST_DEBUG, env: { cppflags: '-DCCAN_LIST_DEBUG' } } +# - { name: CPDEBUG=-1, env: { cppflags: '-DCPDEBUG=-1' } } +# - { name: ENC_DEBUG, env: { cppflags: '-DENC_DEBUG' } } +# - { name: GC_DEBUG, env: { cppflags: '-DGC_DEBUG' } } +# - { name: HASH_DEBUG, env: { cppflags: '-DHASH_DEBUG' } } +# - { name: ID_TABLE_DEBUG, env: { cppflags: '-DID_TABLE_DEBUG' } } +# - { name: RGENGC_DEBUG=-1, env: { cppflags: '-DRGENGC_DEBUG=-1' } } +# - { name: SYMBOL_DEBUG, env: { cppflags: '-DSYMBOL_DEBUG' } } + +# - { name: RGENGC_CHECK_MODE, env: { cppflags: '-DRGENGC_CHECK_MODE' } } +# - { name: TRANSIENT_HEAP_CHECK_MODE, env: { cppflags: '-DTRANSIENT_HEAP_CHECK_MODE' } } +# - { name: VM_CHECK_MODE, env: { cppflags: '-DVM_CHECK_MODE' } } + + - { name: USE_EMBED_CI=0, env: { cppflags: '-DUSE_EMBED_CI=0' } } + - name: USE_FLONUM=0, + env: + cppflags: '-DUSE_FLONUM=0' + # yjit requires FLONUM for the pointer tagging scheme + append_configure: '--disable-yjit' +# - { name: USE_GC_MALLOC_OBJ_INFO_DETAILS, env: { cppflags: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } } + - { name: USE_LAZY_LOAD, env: { cppflags: '-DUSE_LAZY_LOAD' } } +# - { name: USE_RINCGC=0, env: { cppflags: '-DUSE_RINCGC=0' } } +# - { name: USE_SYMBOL_GC=0, env: { cppflags: '-DUSE_SYMBOL_GC=0' } } +# - { name: USE_THREAD_CACHE=0, env: { cppflags: '-DUSE_THREAD_CACHE=0' } } +# - { name: USE_TRANSIENT_HEAP=0, env: { cppflags: '-DUSE_TRANSIENT_HEAP=0' } } +# - { name: USE_RUBY_DEBUG_LOG=1, env: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } } + - { name: USE_RVARGC=0, env: { cppflags: '-DUSE_RVARGC=0' } } +# - { name: USE_RVARGC=1, env: { cppflags: '-DUSE_RVARGC=1' } } +# - { name: USE_DEBUG_COUNTER, env: { cppflags: '-DUSE_DEBUG_COUNTER=1', RUBY_DEBUG_COUNTER_DISABLE: '1' } } + + - { name: DEBUG_FIND_TIME_NUMGUESS, env: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } } + - { name: DEBUG_INTEGER_PACK, env: { cppflags: '-DDEBUG_INTEGER_PACK' } } +# - { name: ENABLE_PATH_CHECK, env: { cppflags: '-DENABLE_PATH_CHECK' } } + + - { name: GC_DEBUG_STRESS_TO_CLASS, env: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } } +# - { name: GC_ENABLE_LAZY_SWEEP=0, env: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } } +# - { name: GC_PROFILE_DETAIL_MEMOTY, env: { cppflags: '-DGC_PROFILE_DETAIL_MEMOTY' } } +# - { name: GC_PROFILE_MORE_DETAIL, env: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } } + +# - { name: CALC_EXACT_MALLOC_SIZE, env: { cppflags: '-DCALC_EXACT_MALLOC_SIZE' } } +# - { name: MALLOC_ALLOCATED_SIZE_CHECK, env: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } } + +# - { name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, env: { cppflags: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } } + +# - { name: RGENGC_ESTIMATE_OLDMALLOC, env: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } } +# - { name: RGENGC_FORCE_MAJOR_GC, env: { cppflags: '-DRGENGC_FORCE_MAJOR_GC' } } +# - { name: RGENGC_OBJ_INFO, env: { cppflags: '-DRGENGC_OBJ_INFO' } } +# - { name: RGENGC_OLD_NEWOBJ_CHECK, env: { cppflags: '-DRGENGC_OLD_NEWOBJ_CHECK' } } +# - { name: RGENGC_PROFILE, env: { cppflags: '-DRGENGC_PROFILE' } } + +# - { name: VM_DEBUG_BP_CHECK, env: { cppflags: '-DVM_DEBUG_BP_CHECK' } } +# - { name: VM_DEBUG_VERIFY_METHOD_CACHE, env: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } } + + - { name: MJIT_FORCE_ENABLE, env: { cppflags: '-DMJIT_FORCE_ENABLE' } } + - { name: YJIT_FORCE_ENABLE, env: { cppflags: '-DYJIT_FORCE_ENABLE' } } + + name: ${{ matrix.entry.name }} + runs-on: ubuntu-latest + container: + image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-15' }} + options: --user root + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + env: ${{ matrix.entry.env || matrix.env }} + steps: + - run: id + working-directory: + - run: mkdir build + working-directory: + - name: setenv + run: | + echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> $GITHUB_ENV + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: > + ../src/configure -C ${default_configure} ${append_configure} + --${{ + matrix.entry.crosshost && 'host' || 'with-gcc' + }}=${{ + matrix.entry.crosshost || '"${default_cc}${append_cc:+ $append_cc}"' + }} + --${{ matrix.entry.shared || 'enable' }}-shared + - run: make extract-extlibs + - run: make incs + - run: make showflags + - run: make + - run: make leaked-globals + - run: make test + - run: make install + if: ${{ matrix.entry.check }} + - run: make test-tool + if: ${{ matrix.entry.check }} + - run: make test-all TESTS='-- ruby -ext-' + if: ${{ matrix.entry.check }} + - run: make test-spec + env: + CHECK_LEAKS: true + if: ${{ matrix.entry.check }} + - run: make test-annocheck + if: ${{ matrix.entry.check && endsWith(matrix.entry.name, 'annocheck') }} + + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.entry.name }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 0000000000..d8dc58b119 --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,113 @@ +name: macOS +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + test_task: ["check"] # "test-bundler-parallel", "test-bundled-gems" + os: + - macos-13 + - macos-14 + - macos-15 + fail-fast: false + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + runs-on: ${{ matrix.os }} + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Install libraries + run: | + brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline bison + working-directory: src + - name: Set ENV + run: | + echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV + echo "PATH="/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin:$PATH"" >> $GITHUB_ENV + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: ../src/configure -C --disable-install-doc --with-openssl-dir=$(brew --prefix openssl@1.1) --with-readline-dir=$(brew --prefix readline) + - run: make incs + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + - run: make + - run: make leaked-globals + if: ${{ matrix.test_task == 'check' }} + - name: make ${{ matrix.test_task }} + run: | + make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} + timeout-minutes: 40 + env: + RUBY_TESTOPTS: "-q --tty=no" + TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} + TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" + PRECHECK_BUNDLED_GEMS: "no" + - name: make skipped tests + run: | + make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + env: + GNUMAKEFLAGS: "" + RUBY_TESTOPTS: "-v --tty=no" + TESTS: ${{ matrix.skipped_tests }} + PRECHECK_BUNDLED_GEMS: "no" + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml new file mode 100644 index 0000000000..0df917d3d8 --- /dev/null +++ b/.github/workflows/mingw.yml @@ -0,0 +1,179 @@ +name: MinGW +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +# Notes: +# Actions console encoding causes issues, see test-all & test-spec steps +# +jobs: + make: + runs-on: windows-2022 + name: ${{ github.workflow }} (${{ matrix.msystem }}) + env: + MSYSTEM: ${{ matrix.msystem }} + MSYS2_ARCH: x86_64 + CHOST: "x86_64-w64-mingw32" + CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe" + CXXFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe" + CPPFLAGS: "-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048" + LDFLAGS: "-pipe" + UPDATE_UNICODE: "UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=." + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + strategy: + matrix: + include: + # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses. + - msystem: "UCRT64" + base_ruby: head + test_task: "check" + test-all-opts: "--name=!/TestObjSpace#test_reachable_objects_during_iteration/" + fail-fast: false + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: git config + run: | + git config --global core.autocrlf false + git config --global core.eol lf + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Set up Ruby & MSYS2 + uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 + with: + ruby-version: ${{ matrix.base_ruby }} + - name: set env + run: | + echo "GNUMAKEFLAGS=-j$((2 * NUMBER_OF_PROCESSORS))" >> $GITHUB_ENV + + - name: where check + run: | + # show where + mv /c/Windows/System32/libcrypto-1_1-x64.dll /c/Windows/System32/libcrypto-1_1-x64.dll_ + mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_ + result=true + for e in gcc.exe ragel.exe make.exe bison.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do + echo '##['group']'$'\033[93m'$e$'\033[m' + where $e || result=false + echo '##['endgroup']' + done + $result + + - name: version check + run: | + # show version + result=true + for e in gcc ragel make bison "openssl version"; do + case "$e" in *" "*) ;; *) e="$e --version";; esac + echo '##['group']'$'\033[93m'$e$'\033[m' + $e || result=false + echo '##['endgroup']' + done + $result + + - name: autogen + run: | + ./autogen.sh + working-directory: src + + - name: configure + run: > + ../src/configure --disable-install-doc --prefix=/. + --build=$CHOST --host=$CHOST --target=$CHOST + + - name: update + run: | + make incs + + - name: download gems + run: | + make update-gems + + - name: make all + timeout-minutes: 30 + run: | + make + + - run: make leaked-globals + + - name: make install + run: | + make DESTDIR=../install install-nodoc + + - name: test + timeout-minutes: 5 + run: | + make test + if: ${{matrix.test_task == 'check' || matrix.test_task == 'test'}} + + - name: test-all + timeout-minutes: 45 + run: | + # Actions uses UTF8, causes test failures, similar to normal OS setup + chcp.com 437 + make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }} + env: + RUBY_TESTOPTS: >- + --retry --job-status=normal --show-skip --timeout-scale=1.5 + ${{ matrix.test-all-opts }} + BUNDLER_VERSION: + if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/')}} + + - name: test-spec + timeout-minutes: 10 + run: | + make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }} + if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/')}} + + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} ${{ matrix.msystem }} / ${{ matrix.test_task }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build + shell: sh diff --git a/.github/workflows/mjit-bindgen.yml b/.github/workflows/mjit-bindgen.yml new file mode 100644 index 0000000000..26f8a1b2aa --- /dev/null +++ b/.github/workflows/mjit-bindgen.yml @@ -0,0 +1,104 @@ +name: MJIT bindgen +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + include: + - task: mjit-bindgen + fail-fast: false + runs-on: ubuntu-22.04 + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y \ + build-essential \ + libssl-dev libyaml-dev libreadline6-dev \ + zlib1g-dev libncurses5-dev libffi-dev \ + libclang1-14 \ + bison autoconf + sudo apt-get install -q -y pkg-config || : + - name: Set up Ruby + uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 + with: + ruby-version: '3.1' + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install --enable-yjit=dev_nodebug + - run: make incs + - run: make + - run: make install + - run: make ${{ matrix.task }} + - run: git diff --exit-code + working-directory: src + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/mjit.yml b/.github/workflows/mjit.yml new file mode 100644 index 0000000000..6f7181489a --- /dev/null +++ b/.github/workflows/mjit.yml @@ -0,0 +1,113 @@ +name: MJIT +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + - '**.[1-8]' + - '**.ronn' + merge_group: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + - '**/.document' + - '**.[1-8]' + - '**.ronn' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + test_task: [check] # to make job names consistent + mjit_opts: [--mjit-wait] + fail-fast: false + runs-on: ubuntu-latest + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + env: + TESTOPTS: '-q --tty=no' + RUN_OPTS: '--disable-gems ${{ matrix.mjit_opts }} --mjit-debug=-ggdb3' + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + steps: + - run: mkdir build + working-directory: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: ../src/configure -C --disable-install-doc cppflags=-DVM_CHECK_MODE + - run: make incs + - run: make + - run: sudo make -s install + - name: Run test + run: | + unset GNUMAKEFLAGS + make -s test RUN_OPTS="$RUN_OPTS" + timeout-minutes: 60 + # - name: Run test-all + # run: | + # ulimit -c unlimited + # make -s test-all RUN_OPTS="$RUN_OPTS" + # timeout-minutes: 60 + - name: Run test-spec + run: | + unset GNUMAKEFLAGS + make -s test-spec RUN_OPTS="$RUN_OPTS" + timeout-minutes: 60 + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.mjit_opts }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..5d4474d978 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,18 @@ +name: Start release workflow +on: + push: + tags: + - '*' + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Build release package + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/actions/dispatches \ + -d '{"event_type": "${{ github.ref }}"}' diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 0000000000..c12a95362d --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,72 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecards supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '22 4 * * 2' + push: + branches: [ "master" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecards analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@ea651e62978af7915d09fe2e282747c798bf2dab # v2.4.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecards on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.27 + with: + sarif_file: results.sarif diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml new file mode 100644 index 0000000000..4521195a2b --- /dev/null +++ b/.github/workflows/spec_guards.yml @@ -0,0 +1,71 @@ +name: Rubyspec Version Guards Check + +on: + push: + paths: + - 'spec/**' + - '!spec/*.md' + pull_request: + paths: + - 'spec/**' + - '!spec/*.md' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + rubyspec: + name: Rubyspec + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Document') + || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + )}} + + strategy: + matrix: + # Specs from ruby/spec should still run on all supported Ruby versions. + # This also ensures the needed ruby_version_is guards are there, see spec/README.md. + ruby: + - ruby-3.1 + - ruby-3.2 + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 + with: + ruby-version: ${{ matrix.ruby }} + bundler: none + + - run: gem install webrick + + - run: ruby ../mspec/bin/mspec + working-directory: spec/ruby + env: + CHECK_LEAKS: true + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / rubyspec @ ${{ matrix.ruby }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml new file mode 100644 index 0000000000..4fbca1170e --- /dev/null +++ b/.github/workflows/ubuntu.yml @@ -0,0 +1,146 @@ +name: Ubuntu +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + # main variables included in the job name + test_task: [check] + configure: [cppflags=-DRUBY_DEBUG] # default to use more assertions + arch: [''] + # specify all jobs with `include` to avoid testing duplicated things + include: + - test_task: check + - test_task: check + arch: i686 + configure: '' # test without -DRUBY_DEBUG as well + - test_task: check + configure: "--enable-shared --enable-load-relative" + - test_task: test-all TESTS=--repeat-count=2 + - test_task: test-bundler-parallel + - test_task: test-bundled-gems + fail-fast: false + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + RUBY_DEBUG: ci + SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }} + runs-on: ubuntu-22.04 + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - name: Install libraries + env: + arch: ${{matrix.arch}} + run: | + set -x + arch=${arch:+:${arch/i[3-6]86/i386}} + ${arch:+sudo dpkg --add-architecture ${arch#:}} + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y \ + ${arch:+cross}build-essential${arch/:/-} \ + libssl-dev${arch} libyaml-dev${arch} libreadline6-dev${arch} \ + zlib1g-dev${arch} libncurses5-dev${arch} libffi-dev${arch} \ + bison autoconf ruby + sudo apt-get install -q -y pkg-config${arch} || : + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - run: ./autogen.sh + working-directory: src + - name: Run configure + env: + arch: ${{matrix.arch}} + run: >- + $SETARCH ../src/configure -C --disable-install-doc ${{ matrix.configure }} + ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + - run: $SETARCH make incs + - run: $SETARCH make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + - run: $SETARCH make + - run: $SETARCH make leaked-globals + if: ${{ matrix.test_task == 'check' }} + - name: Create dummy files in build dir + run: | + $SETARCH ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}' + if: ${{ matrix.test_task == 'check' }} + - name: make ${{ matrix.test_task }} + run: | + $SETARCH make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} + timeout-minutes: 40 + env: + RUBY_TESTOPTS: "-q --tty=no" + TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} + TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" + PRECHECK_BUNDLED_GEMS: "no" + - name: make skipped tests + run: | + $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + env: + GNUMAKEFLAGS: "" + RUBY_TESTOPTS: "-v --tty=no" + TESTS: ${{ matrix.skipped_tests }} + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml new file mode 100644 index 0000000000..27920b5821 --- /dev/null +++ b/.github/workflows/wasm.yml @@ -0,0 +1,146 @@ +name: WebAssembly +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: # added using https://github.com/step-security/secure-workflows + contents: read + +jobs: + make: + strategy: + matrix: + entry: +# # wasmtime can't compile non-optimized Asyncified binary due to locals explosion +# - { name: O0-debuginfo, optflags: "-O0", debugflags: "-g", wasmoptflags: "-O1" } +# - { name: O1, optflags: "-O1", debugflags: "" , wasmoptflags: "-O1" } + - { name: O2, optflags: "-O2", debugflags: "" , wasmoptflags: "-O2" } +# - { name: O3, optflags: "-O3", debugflags: "" , wasmoptflags: "-O3" } +# # -O4 is equivalent to -O3 in clang, but it's different in wasm-opt +# - { name: O4, optflags: "-O3", debugflags: "" , wasmoptflags: "-O4" } +# - { name: Oz, optflags: "-Oz", debugflags: "" , wasmoptflags: "-Oz" } + fail-fast: false + env: + RUBY_TESTOPTS: '-q --tty=no' + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + WASI_SDK_VERSION_MAJOR: 14 + WASI_SDK_VERSION_MINOR: 0 + BINARYEN_VERSION: 109 + WASMTIME_VERSION: v0.33.0 + runs-on: ubuntu-22.04 + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - name: Install libraries + run: | + set -ex + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y ruby bison make autoconf git wget + + wasi_sdk_deb="wasi-sdk_${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}_amd64.deb" + wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}" + sudo dpkg -i "$wasi_sdk_deb" + rm -f "$wasi_sdk_deb" + + mkdir build-sdk + pushd build-sdk + + wasmtime_url="https://github.com/bytecodealliance/wasmtime/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-x86_64-linux.tar.xz" + wget -O - "$wasmtime_url" | tar xJf - + sudo ln -fs "$PWD/wasmtime-${WASMTIME_VERSION}-x86_64-linux/wasmtime" /usr/local/bin/wasmtime + + binaryen_tarball="binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz" + binaryen_url="https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/${binaryen_tarball}" + wget -O - "$binaryen_url" | tar xfz - + sudo ln -fs "$PWD/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt" /usr/local/bin/wasm-opt + working-directory: src + - name: Set ENV + run: | + echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV + echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV + - run: ./autogen.sh + working-directory: src + + - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 + with: + ruby-version: '3.0' + bundler: none + + - name: Download config.guess with wasi version + run: | + rm tool/config.guess tool/config.sub + ruby tool/downloader.rb -d tool -e gnu config.guess config.sub + working-directory: src + + - name: Run configure + run: | + ../src/configure \ + --host wasm32-unknown-wasi \ + --with-static-linked-ext \ + LDFLAGS=" \ + -Xlinker --stack-first \ + -Xlinker -z -Xlinker stack-size=16777216 \ + " \ + optflags="${{ matrix.entry.optflags }}" \ + debugflags="${{ matrix.entry.debugflags }}" \ + wasmoptflags="${{ matrix.entry.wasmoptflags }} ${{ matrix.entry.debugflags }}" + + # miniruby may not be built when cross-compling + - run: make mini ruby + - name: Run basictest + run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb + working-directory: src + - name: Run bootstraptest (no thread) + run: | + NO_THREAD_TESTS="$(grep -L Thread -R ./bootstraptest | awk -F/ '{ print $NF }' | uniq | sed -n 's/test_\(.*\).rb/\1/p' | paste -s -d, -)" + ruby ./bootstraptest/runner.rb --ruby="$(which wasmtime) run $PWD/../build/ruby --mapdir /::./ -- " --verbose "--sets=$NO_THREAD_TESTS" + working-directory: src + + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.name }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000000..c2bd4881c2 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,149 @@ +name: Windows +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + include: + - vs: 2022 + vcvers: -vcvars_ver=14.2 + fail-fast: false + runs-on: windows-${{ matrix.vs }} + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + name: VisualStudio ${{ matrix.vs }} + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + PATCH: C:\msys64\usr\bin\patch.exe + OS_VER: windows-${{ matrix.vs }} + steps: + - run: md build + working-directory: + - uses: msys2/setup-msys2@61f9e5e925871ba6c9e3e8da24ede83ea27fa91f # v2.27.0 + id: setup-msys2 + with: + update: true + install: bison patch + - name: patch path + shell: msys2 {0} + run: echo PATCH=$(cygpath -wa $(command -v patch)) >> $GITHUB_ENV + if: ${{ steps.setup-msys2.outcome == 'success' }} + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: C:\vcpkg\installed + key: ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}- + ${{ runner.os }}-vcpkg-installed-windows- + - name: Install libraries with vcpkg + run: | + iex "& {$(irm get.scoop.sh)} -RunAsAdmin" + Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH + scoop install cmake@3.31.6 + vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib + shell: + pwsh + - name: git config + run: | + git config --global core.autocrlf false + git config --global core.eol lf + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: setup env + # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent. + # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302 + # msys2/setup-msys2 installs MSYS2 to D:/a/_temp/msys64/usr/bin + run: | + set Path=D:/a/_temp/msys64/usr/bin;%Path% + if not "%VCVARS%" == "" goto :vcset + set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + :vcset + set | C:\msys64\usr\bin\sort > old.env + call %VCVARS% ${{ matrix.vcvers || ''}} + set TMP=%USERPROFILE%\AppData\Local\Temp + set TEMP=%USERPROFILE%\AppData\Local\Temp + set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul + set | C:\msys64\usr\bin\sort > new.env + C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% + del *.env + - name: compiler version + run: cl + - name: link libraries + run: | + for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do ( + if not %%~nI == readline mklink %%~nxI %%I + ) + for %%I in (libcrypto-1_1-x64 libssl-1_1-x64) do ( + ren c:\Windows\System32\%%I.dll %%I.dll_ + ) + - name: Configure + run: >- + ../src/win32/configure.bat --disable-install-doc + --with-opt-dir=C:/vcpkg/installed/x64-windows + - run: nmake incs + - run: nmake extract-extlibs + - run: nmake + env: + YACC: bison.exe + - run: nmake test + timeout-minutes: 5 + - run: nmake test-spec + timeout-minutes: 10 + - run: nmake test-all + env: + RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --job-status=normal + timeout-minutes: 60 + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build + shell: cmd diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml new file mode 100644 index 0000000000..0b7b9046e9 --- /dev/null +++ b/.github/workflows/yjit-ubuntu.yml @@ -0,0 +1,170 @@ +name: YJIT Ubuntu +on: + push: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + merge_group: + paths-ignore: + - 'doc/**' + - '**/man' + - '**.md' + - '**.rdoc' + - '**/.document' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + cargo: + name: Rust cargo test + # GitHub Action's image seems to already contain a Rust 1.58.0. + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + # For now we can't run cargo test --offline because it complains about the + # capstone dependency, even though the dependency is optional + #- run: cargo test --offline + - run: RUST_BACKTRACE=1 cargo test + working-directory: yjit + # Also compile and test with all features enabled + - run: RUST_BACKTRACE=1 cargo test --all-features + working-directory: yjit + # Check that we can build in release mode too + - run: cargo build --release + working-directory: yjit + make: + strategy: + fail-fast: false + matrix: + include: + - test_task: 'yjit-bindgen' + hint: 'To fix: use patch in logs' + configure: '--with-gcc=clang-14 --enable-yjit=dev' + libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1' + + - test_task: "check" + # YJIT should be automatically built in release mode on x86-64 Linux with rustc present + #configure: "--enable-yjit RUSTC='rustc +1.58.0'" + configure: "RUSTC='rustc +1.58.0'" + rust_version: "1.58.0" + + - test_task: "check" + configure: "--enable-yjit=dev" + + - test_task: "check" + configure: "--enable-yjit=dev" + yjit_opts: "--yjit-call-threshold=1 --yjit-verify-ctx" + + - test_task: "test-all TESTS=--repeat-count=2" + configure: "--enable-yjit=dev" + + - test_task: "test-bundled-gems" + configure: "--enable-yjit=dev" + + - test_task: "yjit-bench" + configure: "--enable-yjit=dev" + yjit_bench_opts: "--yjit-stats" + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + RUN_OPTS: ${{ matrix.yjit_opts }} + YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }} + RUBY_DEBUG: ci + BUNDLE_JOBS: 8 # for yjit-bench + runs-on: ubuntu-22.04 + if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + - name: Install Rust + if: ${{ matrix.rust_version }} + run: rustup install ${{ matrix.rust_version }} --profile minimal + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + path: src + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }} + - run: make incs + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + - run: make -j + - run: make leaked-globals + if: ${{ matrix.test_task == 'check' }} + - name: Create dummy files in build dir + run: | + ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}' + if: ${{ matrix.test_task == 'check' }} + - name: Enable YJIT through ENV + run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + # Check that the binary was built with YJIT + - name: Check YJIT enabled + run: ./miniruby --yjit -v | grep "+YJIT" + - name: make ${{ matrix.test_task }} + run: make -s -j ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: "-q --tty=no" + TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" + PRECHECK_BUNDLED_GEMS: "no" + LIBCLANG_PATH: ${{ matrix.libclang_path }} + continue-on-error: ${{ matrix.test_task == 'yjit-bench' }} + - name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison + run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}" + env: + BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + if: ${{ matrix.test_task == 'yjit-bench' && startsWith(github.event_name, 'pull') }} + - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.configure }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} + +defaults: + run: + working-directory: build diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..99d32a1825 --- /dev/null +++ b/.gitignore @@ -0,0 +1,250 @@ +*-*-*.def +*-*-*.exp +*-*-*.lib +*.a +*.bak +*.bc +*.bundle +*.dSYM +*.dmyh +*.dylib +*.elc +*.i +*.ii +*.inc +*.log +*.o +*.o.tmp +*.obj +*.old +*.orig +*.pch +*.pdb +*.rbinc +*.rej +*.s +*.sav +*.sl +*.so +*.so.* +*.swp +*.yarb +*~ +.*.list +.*.time +.DS_Store +.bundle +.ccmalloc +.ext +.pc +.ppack +.svn +.time +.ruby-version +Makefile +cygruby*.def +extconf.h +y.output +y.tab.c +*.gcda +*.gcno +*.gcov +*.vscode +lcov*.info + +# / +/*-fake.rb +/*.dll +/*.exe +/*.res +/*.pc +/*.rc +/*_prelude.c +/.downloaded-cache +/.top-enc.mk +/build*/ +/COPYING.LIB +/ChangeLog +/Doxyfile +/GNUmakefile +/README.atheos +/README.fat-patch +/README.v6 +/TAGS +/archive +/autom4te*.cache +/automake +/benchmark/benchmark-driver +/beos +/bmlog-* +/breakpoints.gdb +/config.cache +/config.h +/config.h.in +/config.status +/config.status.lineno +/configure +/coverage/simplecov +/coverage/simplecov-html +/coverage/doclie +/coverage/.last_run.json +/coverage/.resultset.json* +/coverage/assets +/coverage/index.html +/doc/capi +/enc.mk +/encdb.h +/exts.mk +/goruby +/id.[ch] +/largefile.h +/lcov-c-out +/lcov-rb-out +/lcov-out +/lex.c +/libruby*.* +/miniprelude.c +/miniruby +/newdate.rb +/newline.c +/newver.rb +/parse.c +/parse.h +/patches +/patches-master +/pitest.rb +/ppack +/prelude.c +/preview +/probes.dmyh +/probes.h +/rbconfig.rb +/rename2.h +/repack +/revision.h +/revision.tmp +/riscos +/rubicon +/ruby +/ruby-runner +/ruby-runner.h +/ruby-man.rd.gz +/rubyspec_temp +/run.gdb +/sizes.c +/static-ruby +/test.rb +/test-coverage.dat +/tmp +/transdb.h +/uncommon.mk +/verconf.h +/verconf.mk +/web +/yasmdata.rb + +# /bin/ + +/bin/*.exe +/bin/*.dll +/bin/goruby +/bin/ruby + +# /benchmark/ +/benchmark/bm_require.data +/benchmark/bmx_*.rb +/benchmark/fasta.output.* +/benchmark/wc.input + +/enc/*.def +/enc/*.exp +/enc/*.lib +/enc/jis/props.h +/enc/unicode/data + +# /coroutine/ +!/coroutine/**/*.s + +# /enc/trans/ +/enc/trans/*.c +/enc/trans/*.def +/enc/trans/*.exp +/enc/trans/*.lib + +# /exe/ +/exe/goruby +/exe/ruby + +# /ext/ +/ext/extinit.c +/ext/configure-ext.mk +/ext/*/exts.mk + +# /ext/-test-/cxxanyargs +/ext/-test-/cxxanyargs/failure*.failed + +# /ext/-test-/win32/dln/ +/ext/-test-/win32/dln/dlntest.dll +/ext/-test-/win32/dln/dlntest.exp +/ext/-test-/win32/dln/dlntest.lib + +# /ext/-test-/gems +/ext/-test-/gems + +# /ext/etc/ +/ext/etc/constdefs.h + +# /ext/fiddle/ +/ext/fiddle/libffi-* + +# /ext/rbconfig/ +/ext/rbconfig/sizeof/sizes.c +/ext/rbconfig/sizeof/limits.c + +# /ext/ripper/ +/ext/ripper/eventids1.c +/ext/ripper/.eventids2-check +/ext/ripper/eventids2table.c +/ext/ripper/ripper.* +/ext/ripper/ids1 +/ext/ripper/ids2 + +# /ext/socket/ +/ext/socket/constants.h +/ext/socket/constdefs.h +/ext/socket/constdefs.c + +# /gems +/gems/*.gem +/gems/src +/gems/*-* + +# /lib/ +/lib/ruby/[1-9]*.* +/lib/ruby/vendor_ruby + +# /misc/ +/misc/**/__pycache__ + +# /spec/bundler +/.rspec_status + +# /tool/ +/tool/config.guess +/tool/config.sub + +# /win32/ +/win32/*.ico + +# MJIT +/include/ruby-*/*/rb_mjit_min_header-*.h +/lib/ruby_vm/mjit/instruction.rb +/mjit_config.h +/rb_mjit_header.h + +# YJIT +/yjit-bench +/yjit_exit_locations.dump + +# /wasm/ +/wasm/tests/*.wasm diff --git a/.indent.pro b/.indent.pro new file mode 100644 index 0000000000..1d61cbcad1 --- /dev/null +++ b/.indent.pro @@ -0,0 +1,32 @@ +-bap +-nbbb +-nbc +-br +-brs +-nbs +-ncdb +-nce +-cdw +-cli2 +-cbi2 +-ndj +-ncs +-nfc1 +-i4 +-l120 +-lp +-npcs +-psl +-sc +-sob +-sbi4 +-nut +-par + +-TID +-TVALUE +-Tst_data_t +-Tst_index_t +-Tst_table +-Trb_data_type_t +-TFILE diff --git a/.rdoc_options b/.rdoc_options new file mode 100644 index 0000000000..760507c7a2 --- /dev/null +++ b/.rdoc_options @@ -0,0 +1,4 @@ +--- +page_dir: doc +main_page: README.md +title: Documentation for Ruby development version diff --git a/.rspec_parallel b/.rspec_parallel new file mode 100644 index 0000000000..aaff198a32 --- /dev/null +++ b/.rspec_parallel @@ -0,0 +1,2 @@ +--format progress +--format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log @@ -0,0 +1,22 @@ +Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..13df6087ca --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1 @@ +See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions. @@ -1,56 +1,56 @@ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>. -You can redistribute it and/or modify it under either the terms of the GPL -version 2 (see the file GPL), or the conditions below: +You can redistribute it and/or modify it under either the terms of the +2-clause BSDL (see the file BSDL), or the conditions below: - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. +1. You may make and give away verbatim copies of the source form of the + software without restriction, provided that you duplicate all of the + original copyright notices and associated disclaimers. - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: +2. You may modify your copy of the software in any way, provided that + you do at least ONE of the following: - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. + a. place your modifications in the Public Domain or otherwise + make them Freely Available, such as by posting said + modifications to Usenet or an equivalent medium, or by allowing + the author to include your modifications in the software. - b) use the modified software only within your corporation or - organization. + b. use the modified software only within your corporation or + organization. - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. + c. give non-standard binaries non-standard names, with + instructions on where to get the original software distribution. - d) make other distribution arrangements with the author. + d. make other distribution arrangements with the author. - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: +3. You may distribute the software in object code or binary form, + provided that you do at least ONE of the following: - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. + a. distribute the binaries and library files of the software, + together with instructions (in the manual page or equivalent) + on where to get the original distribution. - b) accompany the distribution with the machine-readable source of - the software. + b. accompany the distribution with the machine-readable source of + the software. - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. + c. give non-standard binaries non-standard names, with + instructions on where to get the original software distribution. - d) make other distribution arrangements with the author. + d. make other distribution arrangements with the author. - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. +4. You may modify and include the part of the software into any other + software (possibly commercial). But some files in the distribution + are not written by the author, so that they are not under these terms. - For the list of those files and their copying conditions, see the - file LEGAL. + For the list of those files and their copying conditions, see the + file LEGAL. - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. +5. The scripts and library files supplied as input to or produced as + output from the software do not automatically fall under the + copyright of the software, but belong to whomever generated them, + and may be sold commercially, and may be aggregated with this + software. - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. +6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. diff --git a/COPYING.ja b/COPYING.ja index aa2a163848..230376bc60 100644 --- a/COPYING.ja +++ b/COPYING.ja @@ -1,51 +1,51 @@ -$BK\%W%m%0%i%`$O%U%j!<%=%U%H%&%'%"$G$9!%(BGPL (the GNU General -Public License)$B%P!<%8%g%s(B2$B$^$?$O0J2<$K<($9>r7o$GK\%W%m%0%i%`(B -$B$r:FG[I[$G$-$^$9!%(BGPL$B$K$D$$$F$O(BGPL$B%U%!%$%k$r;2>H$7$F2<$5$$!%(B +本プログラムはフリーソフトウェアです.2-clause BSDL +または以下に示す条件で本プログラムを再配布できます +2-clause BSDLについてはBSDLファイルを参照して下さい. - 1. $BJ#@=$O@)8B$J$/<+M3$G$9!%(B +1. 複製は制限なく自由です. - 2. $B0J2<$N>r7o$N$$$:$l$+$rK~$?$9;~$KK\%W%m%0%i%`$N%=!<%9$r(B - $B<+M3$KJQ99$G$-$^$9!%(B +2. 以下の条件のいずれかを満たす時に本プログラムのソースを + 自由に変更できます. - (a) $B%M%C%H%K%e!<%:$K%]%9%H$7$?$j!$:n<T$KJQ99$rAwIU$9$k(B - $B$J$I$NJ}K!$G!$JQ99$r8x3+$9$k!%(B + a. ネットニューズにポストしたり,作者に変更を送付する + などの方法で,変更を公開する. - (b) $BJQ99$7$?K\%W%m%0%i%`$r<+J,$N=jB0$9$kAH?%FbIt$@$1$G(B - $B;H$&!%(B + b. 変更した本プログラムを自分の所属する組織内部だけで + 使う. - (c) $BJQ99E@$rL@<($7$?$&$(!$%=%U%H%&%'%"$NL>A0$rJQ99$9$k!%(B - $B$=$N%=%U%H%&%'%"$rG[I[$9$k;~$K$OJQ99A0$NK\%W%m%0%i(B - $B%`$bF1;~$KG[I[$9$k!%$^$?$OJQ99A0$NK\%W%m%0%i%`$N%=!<(B - $B%9$NF~<jK!$rL@<($9$k!%(B + c. 変更点を明示したうえ,ソフトウェアの名前を変更する. + そのソフトウェアを配布する時には変更前の本プログラ + ムも同時に配布する.または変更前の本プログラムのソー + スの入手法を明示する. - (d) $B$=$NB>$NJQ99>r7o$r:n<T$H9g0U$9$k!%(B + d. その他の変更条件を作者と合意する. - 3. $B0J2<$N>r7o$N$$$:$l$+$rK~$?$9;~$KK\%W%m%0%i%`$r%3%s%Q%$(B - $B%k$7$?%*%V%8%'%/%H%3!<%I$d<B9T7A<0$G$bG[I[$G$-$^$9!%(B +3. 以下の条件のいずれかを満たす時に本プログラムをコンパイ + ルしたオブジェクトコードや実行形式でも配布できます. - (a) $B%P%$%J%j$r<u$1<h$C$??M$,%=!<%9$rF~<j$G$-$k$h$&$K!$(B - $B%=!<%9$NF~<jK!$rL@<($9$k!%(B + a. バイナリを受け取った人がソースを入手できるように, + ソースの入手法を明示する. - (b) $B5!3#2DFI$J%=!<%9%3!<%I$rE:IU$9$k!%(B + b. 機械可読なソースコードを添付する. - (c) $BJQ99$r9T$C$?%P%$%J%j$OL>A0$rJQ99$7$?$&$(!$%*%j%8%J(B - $B%k$N%=!<%9%3!<%I$NF~<jK!$rL@<($9$k!%(B + c. 変更を行ったバイナリは名前を変更したうえ,オリジナ + ルのソースコードの入手法を明示する. - (d) $B$=$NB>$NG[I[>r7o$r:n<T$H9g0U$9$k!%(B + d. その他の配布条件を作者と合意する. - 4. $BB>$N%W%m%0%i%`$X$N0zMQ$O$$$+$J$kL\E*$G$"$l<+M3$G$9!%$?(B - $B$@$7!$K\%W%m%0%i%`$K4^$^$l$kB>$N:n<T$K$h$k%3!<%I$O!$$=(B - $B$l$>$l$N:n<T$N0U8~$K$h$k@)8B$,2C$($i$l$k>l9g$,$"$j$^$9!%(B +4. 他のプログラムへの引用はいかなる目的であれ自由です.た + だし,本プログラムに含まれる他の作者によるコードは,そ + れぞれの作者の意向による制限が加えられる場合があります. - $B$=$l$i%U%!%$%k$N0lMw$H$=$l$>$l$NG[I[>r7o$J$I$KIU$$$F$O(B - LEGAL$B%U%!%$%k$r;2>H$7$F$/$@$5$$!%(B + それらファイルの一覧とそれぞれの配布条件などに付いては + LEGALファイルを参照してください. - 5. $BK\%W%m%0%i%`$X$NF~NO$H$J$k%9%/%j%W%H$*$h$S!$K\%W%m%0%i(B - $B%`$+$i$N=PNO$N8"Mx$OK\%W%m%0%i%`$N:n<T$G$O$J$/!$$=$l$>(B - $B$l$NF~=PNO$r@8@.$7$??M$KB0$7$^$9!%$^$?!$K\%W%m%0%i%`$K(B - $BAH$_9~$^$l$k$?$a$N3HD%%i%$%V%i%j$K$D$$$F$bF1MM$G$9!%(B +5. 本プログラムへの入力となるスクリプトおよび,本プログラ + ムからの出力の権利は本プログラムの作者ではなく,それぞ + れの入出力を生成した人に属します.また,本プログラムに + 組み込まれるための拡張ライブラリについても同様です. - 6. $BK\%W%m%0%i%`$OL5J]>Z$G$9!%:n<T$OK\%W%m%0%i%`$r%5%]!<%H(B - $B$9$k0U;V$O$"$j$^$9$,!$%W%m%0%i%`<+?H$N%P%0$"$k$$$OK\%W(B - $B%m%0%i%`$N<B9T$J$I$+$iH/@8$9$k$$$+$J$kB;32$KBP$7$F$b@U(B - $BG$$r;}$A$^$;$s!%(B +6. 本プログラムは無保証です.作者は本プログラムをサポート + する意志はありますが,プログラム自身のバグあるいは本プ + ログラムの実行などから発生するいかなる損害に対しても責 + 任を持ちません. diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 374d57ca7c..0000000000 --- a/ChangeLog +++ /dev/null |