diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54e6fea15..312b4e241 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,11 +190,33 @@ jobs: require "rake" puts "rexml #{REXML::VERSION}, csv #{CSV::VERSION}, rake #{Rake::VERSION}" RUBY + # ironruby is the launcher, as jruby is JRuby's; RbConfig.ruby has to be a file, + # since libraries spawn it, and ir is the short name, which has to keep working. + cat > names.rb <<'RUBY' + abort "ruby_install_name: #{RbConfig::CONFIG["ruby_install_name"]}" unless RbConfig::CONFIG["ruby_install_name"] == "ironruby" + abort "no #{RbConfig.ruby}" unless File.file?(RbConfig.ruby) + puts "#{RbConfig.ruby} exists" + RUBY + # ironrubyw.exe, as rubyw.exe: the same interpreter as a Windows GUI program (PE + # subsystem 2), so it gets no console window. It still writes to a pipe it is given. + # (A heredoc's end has to start its line, so this one is not inside the if.) + cat > subsystem.rb <<'RUBY' + data = File.binread(ARGV[0], 4096) + subsystem = data[data[0x3c, 4].unpack1("V") + 24 + 68, 2].unpack1("v") + abort "#{ARGV[0]}: subsystem #{subsystem}" unless subsystem == 2 + RUBY if [ "$RUNNER_OS" = Windows ]; then - cmd //c ir.cmd smoke.rb - cmd //c ir.cmd Util/windows-desktop-check.rb + cmd //c ironruby.cmd smoke.rb + cmd //c ironruby.cmd names.rb + cmd //c ir.cmd -e "puts RUBY_ENGINE" + cmd //c ironruby.cmd Util/windows-desktop-check.rb + rubyw="Src/Console/bin/Debug/$TFM/ironrubyw.exe" + ruby subsystem.rb "$rubyw" + "$rubyw" -e 'require "set"; puts "ironrubyw: #{RUBY_ENGINE}"' | grep -x "ironrubyw: ironruby" else - ./ir.sh smoke.rb + ./ironruby smoke.rb + ./ironruby names.rb + ./ir.sh -e 'puts RUBY_ENGINE' fi # IO#write_nonblock on a socket claims only what the kernel took (#14). On Linux the diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eb2fb1ebd..f4e9d44e4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,12 +1,14 @@ name: Release # Binary builds: a self-contained IronRuby for each platform, made by -# Util/package-release.sh, and the launch video, rendered from media/launch. Pushing a -# tag v* publishes them as a GitHub release (a pre-release while the version has a -# suffix such as -preview1), with Docs/releases/.md as the notes when there is one; -# running the workflow by hand, or a pull request that changes the packaging or the -# video, only keeps them as workflow artifacts. Run by hand with video_for set to a tag, -# it renders only the video and replaces it, and its SHA256SUMS line, on that release. +# Util/package-release.sh. Pushing a tag v* publishes them as a GitHub release (a +# pre-release while the version has a suffix such as -preview1), with +# Docs/releases/.md as the notes when there is one; running the workflow by hand, or +# a pull request that changes the packaging, only keeps them as workflow artifacts. +# The launch video, rendered from media/launch, is only rendered when asked for by hand - +# it takes about 7 minutes of every run otherwise: with render_video it is kept as an +# artifact, and with video_for set to a tag it alone is rendered and replaces the video, +# and its SHA256SUMS line, on that release (or adds them to one published without). on: push: tags: ['v*'] @@ -14,9 +16,13 @@ on: paths: - .github/workflows/release.yml - Util/package-release.sh - - media/launch/** workflow_dispatch: inputs: + render_video: + description: Render the launch video as well, as a workflow artifact + type: boolean + required: false + default: false video_for: description: Render only the launch video and replace it on this release (a tag, such as v4.0.0) required: false @@ -157,6 +163,7 @@ jobs: # does not render does not hold the archives back. video: name: launch video + if: github.event_name == 'workflow_dispatch' && (inputs.render_video || inputs.video_for != '') runs-on: ubuntu-latest continue-on-error: true # A render takes about 7 minutes; a failed one can leave hyperframes waiting. @@ -207,8 +214,9 @@ jobs: release: name: GitHub release - if: github.ref_type == 'tag' - needs: [package, video] + # A pushed tag only: a run by hand keeps its archives as artifacts, even on a tag. + if: github.event_name == 'push' && github.ref_type == 'tag' + needs: package runs-on: ubuntu-latest permissions: contents: write @@ -217,7 +225,7 @@ jobs: with: sparse-checkout: Docs/releases - # ironruby-* only: the archives and the video, not the review stills. + # ironruby-* only: the archives, not the review stills (the video is not rendered here). - uses: actions/download-artifact@v8 with: path: dist diff --git a/Docs/rails-on-windows.md b/Docs/rails-on-windows.md index 4b024dc00..d40907d47 100644 --- a/Docs/rails-on-windows.md +++ b/Docs/rails-on-windows.md @@ -43,7 +43,9 @@ CRuby, the CSRF meta tags are there, and a POST without a token is refused with `ruby_install_name`, which is `ir`, so they start `#!/usr/bin/env ir.exe"`; like MRI, the command line and prism skip a `#!` line without "ruby" in it. A `#!` line naming IronRuby's own launcher now counts as Ruby. `RubyUtils.ShebangNamesIronRuby`, `RubyCommandLine.cs`, - `PrismAstBridge.cs`. + `PrismAstBridge.cs`. Since then the launcher is called `ironruby`, as JRuby's is `jruby`, + and so is `ruby_install_name`: new binstubs say `#!/usr/bin/env ironruby` and need no + special case; this one keeps those written with `ir` running. 5. **`TZInfo::DataSourceNotFound` in the first initializer.** Windows has no zoneinfo, so the Gemfile has `gem "tzinfo-data", platforms: %i[windows jruby]`; Bundler filters such gems by the *generic* platform, and IronRuby's `universal-dotnet` is generic `ruby`. For the dotnet diff --git a/README.md b/README.md index 68dd06745..e88d31260 100644 --- a/README.md +++ b/README.md @@ -90,15 +90,23 @@ IronRuby. `io/console` is a C extension in CRuby, so IronRuby implements it over Scripts run the same way, and gems install with real TLS: ```console -$ ./ir.sh script.rb # prism front end, vendored stdlib, JIT and OSR on -$ ./igem.sh install rack # or: ./ir.sh -S gem install rack -$ ./ir.sh -S bundle install +$ ./ironruby script.rb # prism front end, vendored stdlib, JIT and OSR on +$ ./igem.sh install rack # or: ./ironruby -S gem install rack +$ ./ironruby -S bundle install ``` -`ir` / `igem` / `iirb` / `irubyc` are the i-prefixed names IronRuby has used since 1.x, so -they can sit on `PATH` beside CRuby's `ruby` and `gem` — the same reason JRuby ships -`jruby`, `jgem`, `jirb` and `jrubyc`. The unprefixed `gem`, `irb`, `bundle`, `bundler` and -`irubyc` live in `Src/StdLib/bin` and are what `ir -S ` finds. +The interpreter is `ironruby` (`ironruby.cmd` on Windows), as JRuby's is `jruby`: it is +RbConfig's `ruby_install_name`, so the binstubs Bundler and Rails write start +`#!/usr/bin/env ironruby` - a `#!` line with "ruby" in it, which Ruby runs as Ruby. (Those +RubyGems writes for an installed gem name the launcher by its path instead, `#!/ironruby`, +so they only work where that path still does.) `ir.sh` and `ir.cmd` are its short name, the +one IronRuby has used since 1.x, and run the same thing. +`igem` / `iirb` / `irubyc` keep the i-prefix so they can sit on `PATH` beside CRuby's `gem` +and `irb`, as JRuby's `jgem`, `jirb` and `jrubyc` do. The unprefixed `gem`, `irb`, `bundle`, +`bundler` and `irubyc` live in `Src/StdLib/bin` and are what `ironruby -S ` finds. +On Windows the build also has `ironrubyw.exe` next to `ir.exe`, as CRuby has `rubyw.exe` and +JRuby `jrubyw.exe`: the same interpreter as a Windows GUI program, which gets no console +window - for Windows Forms and WPF programs; `Samples\Notepad\notepad.cmd` starts it. ```ruby # all of this runs today @@ -502,6 +510,8 @@ $ ./irb.sh $ ./igem.sh install rack ``` +4.0.1 has `ir.sh` and `ir.cmd`; releases after it also have `ironruby` and `ironruby.cmd` +(see above), and `ir.sh` / `ir.cmd` keep working there. On Windows, unzip it and use `ir.cmd`, `irb.cmd` and `igem.cmd`, or double-click `Samples\Notepad\notepad.cmd`. The archive has the same layout as a checkout, with the Release build in `Src/Console/bin/Release/net8.0`, so everything above applies to it diff --git a/Ruby.sln b/Ruby.sln index 008a21e08..38b51d358 100644 --- a/Ruby.sln +++ b/Ruby.sln @@ -22,10 +22,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ruby.ConsoleAny", "Src\Console\Ruby.ConsoleAny.csproj", "{6EE7A428-D803-41BC-8248-1297C3ACE369}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ruby.WinConsole", "Src\WinConsole\Ruby.WinConsole.csproj", "{B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ruby.WinConsoleAny", "Src\WinConsole\Ruby.WinConsoleAny.csproj", "{F231EB3F-75E7-499F-B1F2-C26E56601E1B}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{BBF4E796-17F9-4B55-A144-5CE412991105}" ProjectSection(SolutionItems) = preProject Build\After.targets = Build\After.targets @@ -126,26 +122,6 @@ Global {6EE7A428-D803-41BC-8248-1297C3ACE369}.v2Debug|Any CPU.Build.0 = v2Debug|Any CPU {6EE7A428-D803-41BC-8248-1297C3ACE369}.v2Release|Any CPU.ActiveCfg = v2Release|Any CPU {6EE7A428-D803-41BC-8248-1297C3ACE369}.v2Release|Any CPU.Build.0 = v2Release|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.FxCop|Any CPU.ActiveCfg = FxCop|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.FxCop|Any CPU.Build.0 = FxCop|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.Release|Any CPU.Build.0 = Release|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.v2Debug|Any CPU.ActiveCfg = v2Debug|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.v2Debug|Any CPU.Build.0 = v2Debug|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.v2Release|Any CPU.ActiveCfg = v2Release|Any CPU - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329}.v2Release|Any CPU.Build.0 = v2Release|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.FxCop|Any CPU.ActiveCfg = FxCop|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.FxCop|Any CPU.Build.0 = FxCop|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.Release|Any CPU.Build.0 = Release|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.v2Debug|Any CPU.ActiveCfg = v2Debug|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.v2Debug|Any CPU.Build.0 = v2Debug|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.v2Release|Any CPU.ActiveCfg = v2Release|Any CPU - {F231EB3F-75E7-499F-B1F2-C26E56601E1B}.v2Release|Any CPU.Build.0 = v2Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/Notepad/notepad.cmd b/Samples/Notepad/notepad.cmd index 2ea5459c6..6665df23b 100644 --- a/Samples/Notepad/notepad.cmd +++ b/Samples/Notepad/notepad.cmd @@ -1,16 +1,21 @@ @echo off rem IronRuby Notepad. Double-click it, drop a file on it, or run: notepad.cmd file.txt rem -rem ir.exe is a console program, so Windows gives it a console window. "start /b" leaves -rem that console to ir.exe alone once this batch file has ended, and notepad.rb then -rem lets go of it, which closes the window. To keep the console for Ruby's output, run -rem ..\..\ir.cmd notepad.rb instead. The build is chosen as ir.cmd chooses it. +rem ironrubyw.exe is ironruby without a console window, as rubyw.exe is ruby's: a Windows +rem Forms program has no use for one. To keep a console for Ruby's output, run +rem ..\..\ironruby.cmd notepad.rb instead. The build is chosen as ironruby.cmd chooses it. +rem +rem A build from before ironrubyw has only ir.exe, a console program, which Windows gives +rem a console window: "start /b" leaves that console to ir.exe alone once this batch file +rem has ended, and notepad.rb then lets go of it, which closes the window. (Single-line +rem ifs: a dropped file name with a ")" in it would end a parenthesized block.) setlocal set "IR_ROOT=%~dp0..\.." if "%IR_CONFIG%"=="" if not exist "%IR_ROOT%\Src\Console\bin\Debug\" if exist "%IR_ROOT%\Src\Console\bin\Release\" set "IR_CONFIG=Release" if "%IR_CONFIG%"=="" set "IR_CONFIG=Debug" if "%IR_TFM%"=="" set "IR_TFM=net8.0" -set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\win-x64\ir.exe" -if not exist "%IR_BIN%" set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\ir.exe" +set "IR_DIR=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\win-x64" +if not exist "%IR_DIR%\ir.exe" set "IR_DIR=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%" set "S=%IR_ROOT%\Src\StdLib" -start "" /b "%IR_BIN%" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" "%~dp0notepad.rb" %* +if exist "%IR_DIR%\ironrubyw.exe" start "" "%IR_DIR%\ironrubyw.exe" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" "%~dp0notepad.rb" %* +if not exist "%IR_DIR%\ironrubyw.exe" start "" /b "%IR_DIR%\ir.exe" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" "%~dp0notepad.rb" %* diff --git a/Samples/Notepad/notepad.rb b/Samples/Notepad/notepad.rb index 2a3b3b20f..3da5da63d 100644 --- a/Samples/Notepad/notepad.rb +++ b/Samples/Notepad/notepad.rb @@ -1,7 +1,7 @@ # IronRuby Notepad: Windows Notepad, written in Ruby, on IronRuby and Windows Forms. # -# notepad.cmd [file] double-click it, drop a file on it, or run it -# ..\..\ir.cmd notepad.rb [file] the same, keeping the console for Ruby's output +# notepad.cmd [file] double-click it, drop a file on it, or run it +# ..\..\ironruby.cmd notepad.rb [file] the same, keeping the console for Ruby's output # # What Notepad does, this does: New, New Window, Open, Save, Save As, Page Setup and # Print with a header and page numbers; Undo and Redo, Cut, Copy, Paste, Delete, Find, @@ -50,8 +50,9 @@ def self.caret_position D::Point.new(*point[0, 8].unpack("l2")) end - # ir.exe is a console program, so started from Explorer it gets a console window of - # its own. When nobody else is attached to it, let go of it: that closes the window. + # ir.exe and ironruby.exe are console programs, so started from Explorer they get a + # console window of their own. When nobody else is attached to it, let go of it: that + # closes the window. Under ironrubyw.exe, which notepad.cmd uses, there is none. def self.detach_console_if_alone list = Fiddle::Pointer.malloc(64) return unless CONSOLE_PROCESSES.call(list, 16) == 1 diff --git a/Src/Console/Ruby.Console.csproj b/Src/Console/Ruby.Console.csproj index 250d2d750..da74b56f5 100644 --- a/Src/Console/Ruby.Console.csproj +++ b/Src/Console/Ruby.Console.csproj @@ -32,6 +32,38 @@ file this process has LOCK_EX'd. Turn the emulation off. --> + + + + + + + + + + + + + + + diff --git a/Src/Ruby/Hosting/RubyCommandLine.cs b/Src/Ruby/Hosting/RubyCommandLine.cs index 54a264ebc..2f9ef5ba7 100644 --- a/Src/Ruby/Hosting/RubyCommandLine.cs +++ b/Src/Ruby/Hosting/RubyCommandLine.cs @@ -82,11 +82,11 @@ protected override int Run() { } } - // `ruby` with no -e and no script argument reads the program from stdin when - // stdin is redirected. Only a real terminal gets the interactive loop — and - // the banner that goes with it. A script argument of "-" says to read stdin - // outright, whether or not it is redirected, and is how the CRuby test suite - // runs a program in a child process; ARGV is what follows it. + // A script argument of "-" says to read the program from stdin, and is how the CRuby + // test suite runs a program in a child process; ARGV is what follows it. The options + // parser gives "-" when there is neither -e nor a script, so `ironruby` alone reads + // stdin as `ruby` does - at a terminal too, until EOF. A host that skips the parser + // and gives neither still gets stdin when it is redirected. if (Options.Command == null && (Options.FileName == "-" || (Options.FileName == null && System.Console.IsInputRedirected))) { // The program is read as bytes: a magic comment may say they are not UTF-8, and diff --git a/Src/Ruby/Hosting/RubyOptionsParser.cs b/Src/Ruby/Hosting/RubyOptionsParser.cs index b9dee8f11..ffe713fcf 100644 --- a/Src/Ruby/Hosting/RubyOptionsParser.cs +++ b/Src/Ruby/Hosting/RubyOptionsParser.cs @@ -842,6 +842,15 @@ protected override void AfterParse() { ConsoleOptions.PrintVersion = true; ConsoleOptions.Exit = true; } + + // `ruby` with neither -e nor a script reads the program from stdin until EOF - at a + // terminal too - as if "-" had been given, and $0 is "-" (MRI, JRuby). IronRuby used to + // start the DLR's interactive console there; irb is `irb` / `iirb`. ironrubyw, which has + // no console, then reads nothing and exits, as rubyw does. + if (!ConsoleOptions.Exit && ConsoleOptions.Command == null && ConsoleOptions.FileName == null) { + ConsoleOptions.FileName = "-"; + LanguageSetup.Options["MainFile"] = "-"; + } } /// diff --git a/Src/Ruby/Runtime/RubyUtils.cs b/Src/Ruby/Runtime/RubyUtils.cs index 1255c24f6..ab7af1649 100644 --- a/Src/Ruby/Runtime/RubyUtils.cs +++ b/Src/Ruby/Runtime/RubyUtils.cs @@ -1971,8 +1971,9 @@ public static bool IsRubyThreadExit(Exception e) { /// Whether the first line of a script is a #! line that runs IronRuby's own launcher. MRI /// and prism take a #! line without "ruby" in it as the start of some other program and /// look further down for the Ruby one; but RubyGems and Rails write binstubs from - /// RbConfig's ruby_install_name, which is "ir", so `rails new` starts bin/rails with - /// "#!/usr/bin/env ir.exe" - a Ruby script that does not say "ruby". + /// RbConfig's ruby_install_name, which was "ir", so `rails new` started bin/rails with + /// "#!/usr/bin/env ir.exe" - a Ruby script that does not say "ruby". It is "ironruby" + /// now, which does; this keeps the binstubs written before that running. /// public static bool ShebangNamesIronRuby(string/*!*/ code) { if (code == null || !code.StartsWith("#!", StringComparison.Ordinal)) { diff --git a/Src/StdLib/ironruby/rbconfig.rb b/Src/StdLib/ironruby/rbconfig.rb index ca1cf5fc1..8e8a1d0e9 100644 --- a/Src/StdLib/ironruby/rbconfig.rb +++ b/Src/StdLib/ironruby/rbconfig.rb @@ -39,9 +39,13 @@ module RbConfig CONFIG["RUBY_PROGRAM_VERSION"] = RUBY_VERSION.dup CONFIG["RUBY_API_VERSION"] = "#{CONFIG["MAJOR"]}.#{CONFIG["MINOR"]}" CONFIG["EXEEXT"] = windows ? ".exe" : "" - # This value is used by libraries to spawn new processes to run Ruby scripts. Hence it needs to match the ir.exe name - CONFIG["ruby_install_name"] = "ir" - CONFIG["RUBY_INSTALL_NAME"] = "ir" + # Libraries spawn RbConfig.ruby to run Ruby scripts, so this has to be a file in bindir: + # the build puts an ironruby apphost beside ir (Ruby.Console.csproj). And Bundler and + # Rails write it into binstubs as `#!/usr/bin/env ironruby`, which the ironruby launcher + # answers - a #! line with "ruby" in it, as JRuby's "jruby" is. (RubyGems' own binstubs + # name the launcher by its path: rubygems/defaults/ironruby.rb.) + CONFIG["ruby_install_name"] = "ironruby" + CONFIG["RUBY_INSTALL_NAME"] = "ironruby" CONFIG["RUBY_SO_NAME"] = "IronRuby" CONFIG["PATH_SEPARATOR"] = File::PATH_SEPARATOR.dup diff --git a/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb b/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb index de29bea5b..7c9fd80c1 100644 --- a/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb +++ b/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb @@ -227,11 +227,12 @@ def self.path end ## - # RbConfig.ruby names the `ir` apphost, which starts without the -X:StdLib + # RbConfig.ruby names the `ironruby` apphost, which starts without the -X:StdLib # argument that gives it Ruby 4's standard library. RubyGems and # Bundler shell out to Gem.ruby to run binstubs and extconf.rb, so point it - # at the ir.sh (ir.cmd on Windows) wrapper next to the source tree when there - # is one. + # at the ironruby (ironruby.cmd on Windows) launcher next to the source tree + # when there is one - or at ir.sh (ir.cmd), its short name, in a tree from + # before the launcher was called ironruby. def self.ruby @ruby ||= begin @@ -239,9 +240,8 @@ def self.ruby begin # /Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb -> root = File.expand_path("../../../../../..", __dir__) - name = Gem.win_platform? ? "ir.cmd" : "ir.sh" - candidate = File.join(root, name) - wrapper = candidate if File.file?(candidate) + names = Gem.win_platform? ? %w[ironruby.cmd ir.cmd] : %w[ironruby ir.sh] + wrapper = names.map { |name| File.join(root, name) }.find { |candidate| File.file?(candidate) } rescue StandardError wrapper = nil end @@ -254,10 +254,11 @@ def self.ruby ## # A binstub RubyGems writes gets `#!/usr/bin/env ` by - # default, and RbConfig's ruby_install_name here is "ir" - the apphost, which - # is not on PATH and which would start without the arguments that make it a - # Ruby 4 interpreter anyway. Turn the env shebang off for every install, so - # the line becomes `#!`, the ir.sh wrapper. That also makes + # default, and RbConfig's ruby_install_name here is "ironruby" - which is the + # launcher only where its directory is on PATH, and otherwise the apphost, + # which would start without the arguments that make it a Ruby 4 interpreter. + # Turn the env shebang off for every install, so the line becomes + # `#!`, the ironruby launcher. That also makes # Bundler's CLI::Exec#ruby_shebang? recognise the binstub - it matches # "#!#{Gem.ruby}" - so `bundle exec ` loads it in this process # instead of exec'ing it into whatever `ruby` is on PATH. diff --git a/Src/WinConsole/Program.cs b/Src/WinConsole/Program.cs deleted file mode 100644 index 20d918e86..000000000 --- a/Src/WinConsole/Program.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using IronRuby.Hosting; -using IronRuby.Runtime; -using System.Windows.Forms; -using Microsoft.Scripting.Hosting.Shell; -using Microsoft.Scripting.Hosting; - -internal sealed class Host : RubyConsoleHost { - protected override ConsoleOptions ParseOptions(string/*!*/[]/*!*/ args, ScriptRuntimeSetup/*!*/ runtimeSetup, LanguageSetup/*!*/ languageSetup) { - var rubyOptions = (RubyConsoleOptions)base.ParseOptions(args, runtimeSetup, languageSetup); - if (rubyOptions == null) { - return null; - } - - if (rubyOptions.ChangeDirectory != null) { - Environment.CurrentDirectory = rubyOptions.ChangeDirectory; - } - - if (rubyOptions.Introspection || rubyOptions.Command == null && rubyOptions.FileName == null) { - PrintHelp(); - return null; - } - - return rubyOptions; - } - - protected override void ReportInvalidOption(InvalidOptionException e) { - MessageBox.Show(e.Message); - } - - [STAThread] - [RubyStackTraceHidden] - static int Main(string[] args) { - return new Host().Run(args); - } - - protected override void PrintHelp() { - MessageBox.Show(GetHelp(), "IronRuby Window Console Help"); - } -} \ No newline at end of file diff --git a/Src/WinConsole/Properties/AssemblyInfo.cs b/Src/WinConsole/Properties/AssemblyInfo.cs deleted file mode 100644 index b06e9f6a1..000000000 --- a/Src/WinConsole/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using IronRuby.Runtime; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("RubyConsole")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("RubyConsole")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4fcc9697-d2dd-48a1-be74-41db600df98d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -//[assembly: AssemblyVersion(RubyContext.IronRubyVersionString)] -//[assembly: AssemblyFileVersion(RubyContext.IronRubyVersionString)] diff --git a/Src/WinConsole/Ruby.WinConsole.csproj b/Src/WinConsole/Ruby.WinConsole.csproj deleted file mode 100644 index d3fa9c3ce..000000000 --- a/Src/WinConsole/Ruby.WinConsole.csproj +++ /dev/null @@ -1,58 +0,0 @@ - - - - - 2.0 - {B17FEFC8-EA7C-4CFA-B46E-B9003CE1F329} - WinExe - Properties - IronRuby - irw - x86 - Ruby.WinConsole.ruleset - - - - - - - - - - - - - - - - - {77323B06-15A2-4CF4-8A7A-86EAA2B66498} - IronRuby.Libraries - - - {7F6984B4-EE6D-4E6F-ABB1-E210D7DC4FDD} - Ruby - - - - - - - Properties\AssemblyVersion.cs - - - - - - App.Debug.config - - - App.Release.config - - - - - - - - \ No newline at end of file diff --git a/Src/WinConsole/Ruby.WinConsole.ruleset b/Src/WinConsole/Ruby.WinConsole.ruleset deleted file mode 100644 index 9a2c075e1..000000000 --- a/Src/WinConsole/Ruby.WinConsole.ruleset +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Src/WinConsole/Ruby.WinConsoleAny.csproj b/Src/WinConsole/Ruby.WinConsoleAny.csproj deleted file mode 100644 index 779eb8887..000000000 --- a/Src/WinConsole/Ruby.WinConsoleAny.csproj +++ /dev/null @@ -1,56 +0,0 @@ - - - - - 2.0 - {F231EB3F-75E7-499F-B1F2-C26E56601E1B} - WinExe - Properties - IronRuby - irw64 - - - - - - - - - - - - - - - - - {77323B06-15A2-4CF4-8A7A-86EAA2B66498} - IronRuby.Libraries - - - {7F6984B4-EE6D-4E6F-ABB1-E210D7DC4FDD} - Ruby - - - - - - - Properties\AssemblyVersion.cs - - - - - - App.Debug.config - - - App.Release.config - - - - - - - - \ No newline at end of file diff --git a/Util/package-release.sh b/Util/package-release.sh index e897ff80e..c81b0a5f0 100755 --- a/Util/package-release.sh +++ b/Util/package-release.sh @@ -37,8 +37,8 @@ dotnet publish "$IR_ROOT/Src/Console/Ruby.Console.csproj" \ rm -f "$STAGE/Src/Console/bin/Release/$IR_TFM"/*.pdb case "$RID" in - win-*) launchers=(ir.cmd irb.cmd igem.cmd iirb.cmd irubyc.cmd) ;; - *) launchers=(ir.sh irb.sh igem.sh iirb.sh irubyc.sh) ;; + win-*) launchers=(ironruby.cmd ir.cmd irb.cmd igem.cmd iirb.cmd irubyc.cmd) ;; + *) launchers=(ironruby ir.sh irb.sh igem.sh iirb.sh irubyc.sh) ;; esac for f in "${launchers[@]}" README.md; do cp "$IR_ROOT/$f" "$STAGE/" @@ -111,10 +111,20 @@ esac # A quick check that the unpacked tree starts, before it is archived - and on Windows # that Windows Forms and WPF load from it, which a missing framework reference breaks # without breaking anything else. +# One command per line: set -e does not stop at a failure on the left of && - nor at a +# case whose last && list failed that way - so a chain would let a broken tree through. case "$RID" in - win-*) (cd "$STAGE" && cmd //c ir.cmd -e 'puts RUBY_DESCRIPTION' && - cmd //c ir.cmd "$(cygpath -w "$IR_ROOT/Util/windows-desktop-check.rb")") ;; - *) "$STAGE/ir.sh" -e 'puts RUBY_DESCRIPTION' ;; + win-*) + test -f "$STAGE/Src/Console/bin/Release/$IR_TFM/ironrubyw.exe" + (cd "$STAGE" + cmd //c ironruby.cmd -e 'puts RUBY_DESCRIPTION' + cmd //c ir.cmd -e 'puts RUBY_ENGINE' + cmd //c ir.cmd "$(cygpath -w "$IR_ROOT/Util/windows-desktop-check.rb")") + ;; + *) + "$STAGE/ironruby" -e 'puts RUBY_DESCRIPTION' + "$STAGE/ir.sh" -e 'puts RUBY_ENGINE' + ;; esac cd "$OUT" diff --git a/igem.cmd b/igem.cmd index 70c2049ec..341bfe741 100644 --- a/igem.cmd +++ b/igem.cmd @@ -1,3 +1,3 @@ @echo off -rem IronRuby's gem on Windows. The same thing as `ir.cmd -S gem`. -"%~dp0ir.cmd" -S gem %* +rem IronRuby's gem on Windows. The same thing as `ironruby.cmd -S gem`. +"%~dp0ironruby.cmd" -S gem %* diff --git a/igem.sh b/igem.sh index 4af817ff1..fc56efed0 100755 --- a/igem.sh +++ b/igem.sh @@ -1,7 +1,7 @@ #!/bin/sh -# IronRuby's gem. The same thing as `./ir.sh -S gem`, under the i-prefixed name +# IronRuby's gem. The same thing as `./ironruby -S gem`, under the i-prefixed name # IronRuby has used since 1.x -- the point of the prefix is co-installation: when # CRuby is also on PATH, plain `gem` is ambiguous. (JRuby ships jgem for the same # reason, alongside its unprefixed bin/gem.) IR_ROOT="$(dirname "$(readlink -f "$0")")" -exec "$IR_ROOT/ir.sh" -S gem "$@" +exec "$IR_ROOT/ironruby" -S gem "$@" diff --git a/iirb.cmd b/iirb.cmd index c843085a9..55dc7c6c8 100644 --- a/iirb.cmd +++ b/iirb.cmd @@ -1,3 +1,3 @@ @echo off -rem IronRuby's irb on Windows, i-prefixed. Same as irb.cmd / `ir.cmd -S irb`. -"%~dp0ir.cmd" -S irb %* +rem IronRuby's irb on Windows, i-prefixed. Same as irb.cmd / `ironruby.cmd -S irb`. +"%~dp0ironruby.cmd" -S irb %* diff --git a/iirb.sh b/iirb.sh index 15e82bc44..464ad8844 100755 --- a/iirb.sh +++ b/iirb.sh @@ -2,4 +2,4 @@ # IronRuby's irb under the i-prefixed name (IronRuby 1.x shipped iirb.bat; JRuby # ships jirb). irb.sh is the same thing under the plainer name. IR_ROOT="$(dirname "$(readlink -f "$0")")" -exec "$IR_ROOT/ir.sh" -S irb "$@" +exec "$IR_ROOT/ironruby" -S irb "$@" diff --git a/ir.cmd b/ir.cmd index fe51087d0..b3724ceee 100644 --- a/ir.cmd +++ b/ir.cmd @@ -1,46 +1,4 @@ -@echo off -rem Runs the built ir with the prism front end and the bundled standard library. -rem The Windows twin of ir.sh; see it for why each switch is here. -rem -rem ir.cmd -e "puts RUBY_DESCRIPTION" -rem set RUBY_EXE=%CD%\ir.cmd -rem -setlocal -set "IR_ROOT=%~dp0" -if "%IR_ROOT:~-1%"=="\" set "IR_ROOT=%IR_ROOT:~0,-1%" - -rem IR_CONFIG=Release runs the optimized build instead. Debug stays the default, -rem exactly as in ir.sh. -rem A binary release (Util/package-release.sh) ships only the Release build: when -rem IR_CONFIG is not set and there is no Debug build, run that one. -if "%IR_CONFIG%"=="" if not exist "%IR_ROOT%\Src\Console\bin\Debug\" if exist "%IR_ROOT%\Src\Console\bin\Release\" set "IR_CONFIG=Release" -if "%IR_CONFIG%"=="" set "IR_CONFIG=Debug" - -rem IR_TFM picks the target framework out of the multi-targeted build (net8.0;net10.0), -rem exactly as in ir.sh. net8.0 stays the default. -if "%IR_TFM%"=="" set "IR_TFM=net8.0" - -rem A tree built on Windows puts ir.exe straight in %IR_TFM%; one cross-published from -rem Linux with -r win-x64 puts it in %IR_TFM%\win-x64. Take whichever exists. -set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\win-x64\ir.exe" -if not exist "%IR_BIN%" set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\ir.exe" -if not exist "%IR_BIN%" ( - echo ir.cmd: no %IR_CONFIG% build at %IR_BIN% 1>&2 - echo ir.cmd: build it with: dotnet build Src\Console\Ruby.Console.csproj -c %IR_CONFIG% -r win-x64 --self-contained false 1>&2 - exit /b 127 -) - -set "S=%IR_ROOT%\Src\StdLib" - -rem -S searches RUBYPATH before PATH, so `ir.cmd -S irb` runs the irb shipped here. -rem The directory ir.exe is in comes next: it is RubyGems' bindir (RbConfig's bindir), -rem where `igem install` writes the binstubs of installed gems, so `ir.cmd -S ` finds the one written for IronRuby before a host Ruby's - as in ir.sh. -for %%I in ("%IR_BIN%") do set "IR_BINDIR=%%~dpI" -set "IR_BINDIR=%IR_BINDIR:~0,-1%" -if "%RUBYPATH%"=="" (set "RUBYPATH=%S%\bin;%IR_BINDIR%") else (set "RUBYPATH=%S%\bin;%IR_BINDIR%;%RUBYPATH%") - -rem -X:StdLib is split on Path.PathSeparator, which is ';' on Windows - a ':' list would -rem be cut apart at every drive letter. -"%IR_BIN%" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" %* -exit /b %ERRORLEVEL% +@echo off +rem The short name for ironruby.cmd, which it runs with the same arguments. Not `call`: +rem that would double every ^ in them. +"%~dp0ironruby.cmd" %* diff --git a/ir.sh b/ir.sh index 1ab7f70f6..01edfbaf8 100755 --- a/ir.sh +++ b/ir.sh @@ -1,74 +1,3 @@ #!/bin/sh -# Runs the built ir with the prism front end and the bundled standard library. -# Used as RUBY_EXE when running ruby/spec: -# -# RUBY_EXE=./ir.sh ./ir.sh -Imspec/lib mspec/bin/mspec-run spec/language -# -IR_ROOT="$(dirname "$(readlink -f "$0")")" - -# apphost needs DOTNET_ROOT when the SDK isn't on the default search path -if [ -z "$DOTNET_ROOT" ] && [ -x /usr/local/dotnet/dotnet ]; then - DOTNET_ROOT=/usr/local/dotnet - export DOTNET_ROOT -fi - -# IronRuby's own library (the core prelude and what MRI implements as C -# extensions) comes first, then Ruby 4.0's standard library. -X:StdLib puts them -# on $LOAD_PATH after -I, RUBYOPT's -I and RUBYLIB, where MRI keeps its own -# library directories. -S="$IR_ROOT/Src/StdLib" -# IR_CONFIG=Release runs the optimized build instead (build it with -# `dotnet build Src/Console/Ruby.Console.csproj -c Release ...`). It is about 1.8x -# faster across Util/bench - the Debug build is compiled with optimizations off, which -# marks the assemblies non-optimizable, so the JIT leaves the whole runtime unoptimized -# too - and it passes the same specs and the same IronRuby.Tests. Util/run-tests.sh and -# regen-initializers.sh read IR_CONFIG as well, so one export covers a whole session. -# Debug stays the default because every worktree and every agent script builds it. -# A binary release (Util/package-release.sh) ships only the Release build: when -# IR_CONFIG is not set and there is no Debug build, run that one. -if [ -z "$IR_CONFIG" ]; then - IR_CONFIG=Debug - if [ ! -x "$IR_ROOT/Src/Console/bin/Debug/${IR_TFM:-net8.0}/ir" ] && - [ -x "$IR_ROOT/Src/Console/bin/Release/${IR_TFM:-net8.0}/ir" ]; then - IR_CONFIG=Release - fi -fi - -# IR_TFM picks the target framework, the same way IR_CONFIG picks the configuration. The -# tree multi-targets net8.0;net10.0 (Directory.Build.props), so one `dotnet build` leaves -# both side by side and IR_TFM=net10.0 runs the same IL on the .NET 10 runtime. net8.0 -# stays the default: it is what every worktree, agent script and baseline was taken on. -: "${IR_TFM:=net8.0}" - -IR_BIN="$IR_ROOT/Src/Console/bin/$IR_CONFIG/$IR_TFM/ir" -# Say which configuration is missing rather than let the shell's "not found" - which a -# filtered spec log swallows - be the only clue. Getting IR_CONFIG=Release past a tree -# that has only ever been built Debug is the whole reason this check is here. -if [ ! -x "$IR_BIN" ]; then - echo "ir.sh: no $IR_CONFIG build at $IR_BIN" >&2 - if [ "$IR_CONFIG" = "R2R" ]; then - # Not a build configuration: a ReadyToRun publish, which starts about 0.45s - # faster than Release because IronRuby's own assemblies are already native. - echo "ir.sh: build it with: IR_TFM=$IR_TFM Util/publish-r2r.sh" >&2 - else - echo "ir.sh: build it with: dotnet build Src/Console/Ruby.Console.csproj -c $IR_CONFIG -p:DlrSourceDir=..." >&2 - echo "ir.sh: (that builds every framework in IronRubyTargetFrameworks, including $IR_TFM)" >&2 - fi - exit 127 -fi - -# -S searches RUBYPATH before PATH; Src/StdLib/bin holds the executables the -# bundled library ships (irb), so `./ir.sh -S irb` runs IronRuby's own rather -# than whatever binstub happens to be on PATH. The directory ir itself is in -# is RubyGems' bindir here (RbConfig's bindir), where `igem install` writes the -# binstubs of installed gems; it comes next, so `./ir.sh -S ` -# finds the binstub written for IronRuby before a host Ruby's version of the -# same command - or a version manager's shim, which is a native executable and -# not a script at all. An existing RUBYPATH is searched after both - IronRuby's -# own commands come first, as they always have for Src/StdLib/bin - and still -# beats PATH for anything not found here. ir.cmd uses the same order. -RUBYPATH="$S/bin:$(dirname "$IR_BIN")${RUBYPATH:+:$RUBYPATH}" -export RUBYPATH - -exec "$IR_BIN" \ - "-X:StdLib=$S/ironruby:$S/ruby/4.0" "$@" +# The short name for ./ironruby, which it runs with the same arguments. +exec "$(dirname "$(readlink -f "$0")")/ironruby" "$@" diff --git a/irb.cmd b/irb.cmd index 7a017b887..06b6ac600 100644 --- a/irb.cmd +++ b/irb.cmd @@ -1,3 +1,3 @@ @echo off -rem IronRuby's irb on Windows. The same thing as `ir.cmd -S irb`. -"%~dp0ir.cmd" -S irb %* +rem IronRuby's irb on Windows. The same thing as `ironruby.cmd -S irb`. +"%~dp0ironruby.cmd" -S irb %* diff --git a/irb.sh b/irb.sh index 8a299c80d..763f35571 100755 --- a/irb.sh +++ b/irb.sh @@ -1,5 +1,5 @@ #!/bin/sh -# IronRuby's irb. The same thing as `./ir.sh -S irb`, which also works; this is +# IronRuby's irb. The same thing as `./ironruby -S irb`, which also works; this is # here so that starting a REPL does not need to know about -S. IR_ROOT="$(dirname "$(readlink -f "$0")")" -exec "$IR_ROOT/ir.sh" -S irb "$@" +exec "$IR_ROOT/ironruby" -S irb "$@" diff --git a/ironruby b/ironruby new file mode 100755 index 000000000..2d7c4e196 --- /dev/null +++ b/ironruby @@ -0,0 +1,78 @@ +#!/bin/sh +# Runs the built ir with the prism front end and the bundled standard library. +# It is called ironruby as JRuby's is called jruby: RbConfig's ruby_install_name, and so +# the `#!/usr/bin/env ironruby` of the binstubs Bundler and Rails write, names it, and a #! +# line with "ruby" in it is one Ruby runs. (RubyGems writes this file's path instead, see +# rubygems/defaults/ironruby.rb.) ir.sh is the short name for it. +# Used as RUBY_EXE when running ruby/spec: +# +# RUBY_EXE=./ironruby ./ironruby -Imspec/lib mspec/bin/mspec-run spec/language +# +IR_ROOT="$(dirname "$(readlink -f "$0")")" + +# apphost needs DOTNET_ROOT when the SDK isn't on the default search path +if [ -z "$DOTNET_ROOT" ] && [ -x /usr/local/dotnet/dotnet ]; then + DOTNET_ROOT=/usr/local/dotnet + export DOTNET_ROOT +fi + +# IronRuby's own library (the core prelude and what MRI implements as C +# extensions) comes first, then Ruby 4.0's standard library. -X:StdLib puts them +# on $LOAD_PATH after -I, RUBYOPT's -I and RUBYLIB, where MRI keeps its own +# library directories. +S="$IR_ROOT/Src/StdLib" +# IR_CONFIG=Release runs the optimized build instead (build it with +# `dotnet build Src/Console/Ruby.Console.csproj -c Release ...`). It is about 1.8x +# faster across Util/bench - the Debug build is compiled with optimizations off, which +# marks the assemblies non-optimizable, so the JIT leaves the whole runtime unoptimized +# too - and it passes the same specs and the same IronRuby.Tests. Util/run-tests.sh and +# regen-initializers.sh read IR_CONFIG as well, so one export covers a whole session. +# Debug stays the default because every worktree and every agent script builds it. +# A binary release (Util/package-release.sh) ships only the Release build: when +# IR_CONFIG is not set and there is no Debug build, run that one. +if [ -z "$IR_CONFIG" ]; then + IR_CONFIG=Debug + if [ ! -x "$IR_ROOT/Src/Console/bin/Debug/${IR_TFM:-net8.0}/ir" ] && + [ -x "$IR_ROOT/Src/Console/bin/Release/${IR_TFM:-net8.0}/ir" ]; then + IR_CONFIG=Release + fi +fi + +# IR_TFM picks the target framework, the same way IR_CONFIG picks the configuration. The +# tree multi-targets net8.0;net10.0 (Directory.Build.props), so one `dotnet build` leaves +# both side by side and IR_TFM=net10.0 runs the same IL on the .NET 10 runtime. net8.0 +# stays the default: it is what every worktree, agent script and baseline was taken on. +: "${IR_TFM:=net8.0}" + +IR_BIN="$IR_ROOT/Src/Console/bin/$IR_CONFIG/$IR_TFM/ir" +# Say which configuration is missing rather than let the shell's "not found" - which a +# filtered spec log swallows - be the only clue. Getting IR_CONFIG=Release past a tree +# that has only ever been built Debug is the whole reason this check is here. +if [ ! -x "$IR_BIN" ]; then + echo "ironruby: no $IR_CONFIG build at $IR_BIN" >&2 + if [ "$IR_CONFIG" = "R2R" ]; then + # Not a build configuration: a ReadyToRun publish, which starts about 0.45s + # faster than Release because IronRuby's own assemblies are already native. + echo "ironruby: build it with: IR_TFM=$IR_TFM Util/publish-r2r.sh" >&2 + else + echo "ironruby: build it with: dotnet build Src/Console/Ruby.Console.csproj -c $IR_CONFIG -p:DlrSourceDir=..." >&2 + echo "ironruby: (that builds every framework in IronRubyTargetFrameworks, including $IR_TFM)" >&2 + fi + exit 127 +fi + +# -S searches RUBYPATH before PATH; Src/StdLib/bin holds the executables the +# bundled library ships (irb), so `./ironruby -S irb` runs IronRuby's own rather +# than whatever binstub happens to be on PATH. The directory ir itself is in +# is RubyGems' bindir here (RbConfig's bindir), where `igem install` writes the +# binstubs of installed gems; it comes next, so `./ironruby -S ` +# finds the binstub written for IronRuby before a host Ruby's version of the +# same command - or a version manager's shim, which is a native executable and +# not a script at all. An existing RUBYPATH is searched after both - IronRuby's +# own commands come first, as they always have for Src/StdLib/bin - and still +# beats PATH for anything not found here. ironruby.cmd uses the same order. +RUBYPATH="$S/bin:$(dirname "$IR_BIN")${RUBYPATH:+:$RUBYPATH}" +export RUBYPATH + +exec "$IR_BIN" \ + "-X:StdLib=$S/ironruby:$S/ruby/4.0" "$@" diff --git a/ironruby.cmd b/ironruby.cmd new file mode 100644 index 000000000..d561fd3b6 --- /dev/null +++ b/ironruby.cmd @@ -0,0 +1,48 @@ +@echo off +rem Runs the built ir with the prism front end and the bundled standard library. +rem The Windows twin of ironruby; see it for why each switch is here, and for the name. +rem ir.cmd is the short name for it. +rem +rem ironruby.cmd -e "puts RUBY_DESCRIPTION" +rem set RUBY_EXE=%CD%\ironruby.cmd +rem +setlocal +set "IR_ROOT=%~dp0" +if "%IR_ROOT:~-1%"=="\" set "IR_ROOT=%IR_ROOT:~0,-1%" + +rem IR_CONFIG=Release runs the optimized build instead. Debug stays the default, +rem exactly as in ironruby. +rem A binary release (Util/package-release.sh) ships only the Release build: when +rem IR_CONFIG is not set and there is no Debug build, run that one. +if "%IR_CONFIG%"=="" if not exist "%IR_ROOT%\Src\Console\bin\Debug\" if exist "%IR_ROOT%\Src\Console\bin\Release\" set "IR_CONFIG=Release" +if "%IR_CONFIG%"=="" set "IR_CONFIG=Debug" + +rem IR_TFM picks the target framework out of the multi-targeted build (net8.0;net10.0), +rem exactly as in ironruby. net8.0 stays the default. +if "%IR_TFM%"=="" set "IR_TFM=net8.0" + +rem A tree built on Windows puts ir.exe straight in %IR_TFM%; one cross-published from +rem Linux with -r win-x64 puts it in %IR_TFM%\win-x64. Take whichever exists. +set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\win-x64\ir.exe" +if not exist "%IR_BIN%" set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\ir.exe" +rem The path is quoted below: a ")" in it, as in "Program Files (x86)", would end the block. +if not exist "%IR_BIN%" ( + echo ironruby.cmd: no %IR_CONFIG% build at "%IR_BIN%" 1>&2 + echo ironruby.cmd: build it with: dotnet build Src\Console\Ruby.Console.csproj -c %IR_CONFIG% -r win-x64 --self-contained false 1>&2 + exit /b 127 +) + +set "S=%IR_ROOT%\Src\StdLib" + +rem -S searches RUBYPATH before PATH, so `ironruby.cmd -S irb` runs the irb shipped here. +rem The directory ir.exe is in comes next: it is RubyGems' bindir (RbConfig's bindir), +rem where `igem install` writes the binstubs of installed gems, so `ironruby.cmd -S ` finds the one written for IronRuby before a host Ruby's - as in ironruby. +for %%I in ("%IR_BIN%") do set "IR_BINDIR=%%~dpI" +set "IR_BINDIR=%IR_BINDIR:~0,-1%" +if "%RUBYPATH%"=="" (set "RUBYPATH=%S%\bin;%IR_BINDIR%") else (set "RUBYPATH=%S%\bin;%IR_BINDIR%;%RUBYPATH%") + +rem -X:StdLib is split on Path.PathSeparator, which is ';' on Windows - a ':' list would +rem be cut apart at every drive letter. +"%IR_BIN%" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" %* +exit /b %ERRORLEVEL% diff --git a/irubyc.cmd b/irubyc.cmd index 4ac7df5e1..5cea92574 100644 --- a/irubyc.cmd +++ b/irubyc.cmd @@ -1,4 +1,4 @@ @echo off -rem IronRuby's ahead-of-time compiler on Windows. The same thing as `ir.cmd -S irubyc`. +rem IronRuby's ahead-of-time compiler on Windows. The same thing as `ironruby.cmd -S irubyc`. rem Needs the .NET SDK; see irubyc.sh and `irubyc --help`. -"%~dp0ir.cmd" -S irubyc %* +"%~dp0ironruby.cmd" -S irubyc %* diff --git a/irubyc.sh b/irubyc.sh index 74c8461bd..2d9386692 100755 --- a/irubyc.sh +++ b/irubyc.sh @@ -1,6 +1,6 @@ #!/bin/sh # IronRuby's ahead-of-time compiler, the analogue of JRuby's jrubyc. The same -# thing as `./ir.sh -S irubyc`, under the i-prefixed name IronRuby has used +# thing as `./ironruby -S irubyc`, under the i-prefixed name IronRuby has used # since 1.x (see igem.sh for why the prefix is there). # # ./irubyc.sh -t /tmp/out app.rb lib/ @@ -10,4 +10,4 @@ # Ruby sources in the resulting assembly. The Ruby itself is still compiled by # IronRuby at startup -- irubyc does not emit IL for it. See --help. IR_ROOT="$(dirname "$(readlink -f "$0")")" -exec "$IR_ROOT/ir.sh" -S irubyc "$@" +exec "$IR_ROOT/ironruby" -S irubyc "$@" diff --git a/media/launch/README.md b/media/launch/README.md index d6009e108..fffd8c9de 100644 --- a/media/launch/README.md +++ b/media/launch/README.md @@ -47,7 +47,8 @@ npm run render # renders/ironruby-4-launch.mp4, 60 fps npm run preview # the HyperFrames studio, to scrub and edit ``` -`.github/workflows/release.yml` does the same on Ubuntu for every `v*` tag (and for pull -requests that touch this folder) and attaches the MP4 to the release. Run by hand with -`video_for: v4.0.0`, it renders only the film and replaces it on that release, along with -its line in `SHA256SUMS`. +`.github/workflows/release.yml` does the same on Ubuntu, but only when it is run by hand - +neither a `v*` tag nor a pull request renders the film. With `render_video` ticked it keeps +the MP4 as a workflow artifact; with `video_for: v4.0.0` it renders only the film and puts +it on that release, along with its line in `SHA256SUMS` (replacing the one there, or adding +both to a release published without it).