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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ Check the [wiki on how to use](https://github.com/oneclick/rubyinstaller2/wiki/F
| | | | "installer-inno" => executable installer file
| | | '------- "msvcrt" => older type of C standard library
| | | "ucrt" => new type of C standard library
| | '------- "x86" => 32 bit ruby and MSYS2 version
| | "x64" => 64 bit version
| | '------- "x86" => 32 bit x86 ruby and MSYS2 version
| | "x64" => 64 bit x86_64 version
| | "arm" => ARM64 version
| '------ "x.x.x" => ruby version to build
| "head" => latest development snapshot of ruby
'------ "ri" => RubyInstaller without Devkit
Expand Down
1 change: 1 addition & 0 deletions lib/ruby_installer/build.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Build
autoload :ComponentsInstaller, 'ruby_installer/build/components_installer'
autoload :DllDirectory, 'ruby_installer/build/dll_directory'
autoload :ErbCompiler, 'ruby_installer/build/erb_compiler'
autoload :ManifestUpdater, 'ruby_installer/build/manifest_updater'
autoload :Msys2Installation, 'ruby_installer/build/msys2_installation'
autoload :GEM_VERSION, 'ruby_installer/build/gem_version'
autoload :Task, 'ruby_installer/build/task'
Expand Down
1 change: 1 addition & 0 deletions lib/ruby_installer/build/components/03_dev_tools.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def description
'mingw32' => PACKAGES_MINGW32,
'mingw64' => PACKAGES_MINGW64,
'ucrt64' => PACKAGES_MINGW64,
'clangarm64' => PACKAGES_MINGW64,
}

def execute(args)
Expand Down
35 changes: 35 additions & 0 deletions lib/ruby_installer/build/manifest_updater.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module RubyInstaller
module Build
class ManifestUpdater
def self.update_file(from_fname, manifest_xml_string, to_fname)
image = File.binread(from_fname)
update_blob(image, manifest_xml_string, filename: from_fname)
File.binwrite(to_fname, image)
end

def self.update_blob(dll_or_exe_data, manifest_xml_string, filename: nil)
# There are two regular options to add a custom manifest:
# 1. Change a given exe file per Microsofts "mt.exe" after the build
# 2. Specify a the manifest while linking with the MINGW toolchain
#
# Since we don't want to depend on particular Microsoft tools and want to avoid additional patching of the ruby build, we do a nifty trick here.
# We patch the exe file manually.
# Removing unnecessary spaces and comments from the embedded XML manifest gives us enough space to add the above XML elements.
# Then the default MINGW manifest gets replaced by our custom XML content.
# The rest of the available bytes is simply padded with spaces, so that we don't change positions within the EXE image.
success = false
dll_or_exe_data.gsub!(/<\?xml.*?<assembly.*?<\/assembly>\n/m) do |m|
success = true
newm = m.gsub(/^\s*<\/assembly>\s*$/, manifest_xml_string + "</assembly>")
.gsub(/<!--.*?-->/m, "")
.gsub(/^ +/, "")
.gsub(/\n+/m, "\n")

raise "replacement manifest too big #{m.bytesize} < #{newm.bytesize}" if m.bytesize < newm.bytesize
newm + " " * (m.bytesize - newm.bytesize)
end
raise "no manifest found#{ "in #{filename}" if filename}" unless success
end
end
end
end
11 changes: 11 additions & 0 deletions lib/ruby_installer/build/msys2_installation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def initialize(msys_path: nil, mingwarch: nil, mingw_package_prefix: nil, ruby_b
when /x64.*ucrt/ then 'ucrt64'
when /x64.*mingw32/ then 'mingw64'
when /i386.*mingw32/ then 'mingw32'
when /aarch64-mingw-ucrt/ then 'clangarm64'
else raise "unsupported ruby platform #{RUBY_PLATFORM.inspect}"
end
)
Expand All @@ -34,6 +35,7 @@ def initialize(msys_path: nil, mingwarch: nil, mingw_package_prefix: nil, ruby_b
when 'mingw32' then "mingw-w64-i686"
when 'mingw64' then "mingw-w64-x86_64"
when 'ucrt64' then "mingw-w64-ucrt-x86_64"
when 'clangarm64' then "mingw-w64-clang-aarch64"
else raise "unknown mingwarch #{@mingwarch.inspect}"
end
end
Expand Down Expand Up @@ -128,6 +130,9 @@ def mingw_prefix
def enable_dll_search_paths
@mingwdir ||= begin
DllDirectory.set_defaults
# Add bundled dll directory for libcrypto.dll loading zlib.dll and legacy.dll loading libcrypto.dll
DllDirectory.new(RbConfig::CONFIG["rubyarchdir"])
# Add MSYS2-MINGW DLL directory for user-installed gems
path = mingw_bin_path
DllDirectory.new(path) if File.directory?(path)
rescue MsysNotFound
Expand Down Expand Up @@ -182,6 +187,12 @@ def disable_dll_search_paths
vars['MSYSTEM_CHOST'] = 'x86_64-w64-mingw32'
vars['MINGW_CHOST'] = vars['MSYSTEM_CHOST']
vars['MINGW_PREFIX'] = vars['MSYSTEM_PREFIX']
when 'clangarm64'
vars['MSYSTEM_PREFIX'] = '/clangarm64'
vars['MSYSTEM_CARCH'] = 'aarch64'
vars['MSYSTEM_CHOST'] = 'aarch64-w64-mingw32'
vars['MINGW_CHOST'] = vars['MSYSTEM_CHOST']
vars['MINGW_PREFIX'] = vars['MSYSTEM_PREFIX']
else raise "unknown mingwarch #{@mingwarch.inspect}"
end

Expand Down
14 changes: 11 additions & 3 deletions packages/ri-msys/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ class RubyPackage < RubyInstaller::Build::Openstruct
self.mingwdir = "mingw32"
self.packagenamearch = "x86"
self.default_instdir = "C:\\Ruby#{rubyver2.gsub(".","")}"
when 'arm-ucrt'
self.pacman_arch = "mingw-w64-clang-aarch64"
self.ruby_arch = "aarch64-mingw-ucrt"
self.msys_arch = "x86_64"
self.msysdir = "msys64"
self.mingwdir = "clangarm64"
self.packagenamearch = "arm"
self.default_instdir = "C:\\Ruby#{rubyver2.gsub(".","")}-arm"
else
raise "invalid arch #{arch}"
end
Expand All @@ -50,13 +58,13 @@ end

ovl_glob('recipes/*/task.rake').each{|f| load(ovl_expand_file(f)) }

ruby_arch_packages = %w[x64-ucrt].map do |arch|
ruby_arch_packages = %w[x64-ucrt x86-msvcrt].map do |arch|
%w[3.1.6-1 3.2.6-1 3.3.6-2 3.4.1-1 head].map do |packagever|
RubyPackage.new( packagever: packagever, arch: arch, rootdir: __dir__ ).freeze
end
end
ruby_arch_packages += %w[x86-msvcrt].map do |arch|
%w[3.1.6-1 3.2.6-1 3.3.6-2 3.4.1-1 head].map do |packagever|
ruby_arch_packages += %w[arm-ucrt].map do |arch|
%w[3.4.1-1 head].map do |packagever|
RubyPackage.new( packagever: packagever, arch: arch, rootdir: __dir__ ).freeze
end
end
Expand Down
12 changes: 9 additions & 3 deletions packages/ri/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class RubyPackage < RubyInstaller::Build::Openstruct
self.mingwdir = "mingw32"
self.default_instdir = "C:\\Ruby#{rubyver2.gsub(".","")}"
self.packagenamearch = "x86"
when 'arm-ucrt'
self.pacman_arch = "mingw-w64-clang-aarch64"
self.ruby_arch = "aarch64-mingw-ucrt"
self.mingwdir = "clangarm64"
self.default_instdir = "C:\\Ruby#{rubyver2.gsub(".","")}-arm"
self.packagenamearch = "arm"
else
raise "invalid arch #{arch}"
end
Expand All @@ -45,13 +51,13 @@ end

ovl_glob('recipes/*/task.rake').each{|f| load(ovl_expand_file(f)) }

ruby_arch_packages = %w[x64-ucrt].map do |arch|
ruby_arch_packages = %w[x64-ucrt x86-msvcrt].map do |arch|
%w[3.1.6-1 3.2.6-1 3.3.6-2 3.4.1-1 head].map do |packagever|
RubyPackage.new( packagever: packagever, arch: arch, rootdir: __dir__ ).freeze
end
end
ruby_arch_packages += %w[x86-msvcrt].map do |arch|
%w[3.1.6-1 3.2.6-1 3.3.6-2 3.4.1-1 head].map do |packagever|
ruby_arch_packages += %w[arm-ucrt].map do |arch|
%w[3.4.1-1 head].map do |packagever|
RubyPackage.new( packagever: packagever, arch: arch, rootdir: __dir__ ).freeze
end
end
Expand Down
2 changes: 1 addition & 1 deletion recipes/installer-inno/events.iss
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ begin
ModifyRubyopt(['-Eutf-8']);
#endif

if IsComponentSelected('msys2') then
if WizardIsComponentSelected('msys2') then
DeleteRubyMsys2Directory();

end else
Expand Down
15 changes: 8 additions & 7 deletions recipes/installer-inno/ri_gui.iss
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,23 @@ begin

if update then
if msysdir <> '' then
if IsComponentSelected('msys2') then
if WizardIsComponentSelected('msys2') then
CompLabel.Caption := 'ATTENTION: MSYS2 is already present in ' + msysdir + '. It will be deleted now and then re-installed. Additional installed pacman packages will be removed. Some gems might not work afterwards and must be re-installed.'
else
CompLabel.Caption := 'Ruby in ' + ExpandConstant('{app}') + ' will be updated. MSYS2 seems to be already present in ' + msysdir + ' . It will kept untouched and will be reused for this Ruby installation. Optionally it can be updated per `ridk install` on the last page of the installer.'
else
if IsComponentSelected('msys2') then
if WizardIsComponentSelected('msys2') then
CompLabel.Caption := 'Ruby in ' + ExpandConstant('{app}') + ' will be updated and MSYS2 will be installed into ' + ExpandConstant('{app}\{#MsysDir}') + '. Please run `ridk install` on the last installer page to initialize it. It can be updated later per `ridk install` as well.'
else
CompLabel.Caption := 'Ruby in ' + ExpandConstant('{app}') + ' will be updated. It''s possible to install MSYS2 at the last page of the installer or to reuse an existing MSYS2 installation.'
else
if msysdir <> '' then
if IsComponentSelected('msys2') then
if WizardIsComponentSelected('msys2') then
CompLabel.Caption := 'ATTENTION: MSYS2 is already present in ' + msysdir + '. It will be deleted now and then re-installed. Additional installed pacman packages will be removed. Some gems might not work afterwards and must be re-installed.'
else
CompLabel.Caption := 'Ruby will be installed into ' + ExpandConstant('{app}') + '. MSYS2 seems to be already present in ' + msysdir + ' . It will kept untouched and will be re-used for this Ruby installation. Optionally it can be updated per `ridk install` on the last page of the installer.'
else
if IsComponentSelected('msys2') then
if WizardIsComponentSelected('msys2') then
CompLabel.Caption := 'Ruby will be installed into ' + ExpandConstant('{app}') + ' and MSYS2 will be installed into ' + ExpandConstant('{app}\{#MsysDir}') + '. Please run `ridk install` on the last installer page to initialize it. It can be updated later per `ridk install` as well.'
else
CompLabel.Caption := 'Ruby will be installed into ' + ExpandConstant('{app}') + ' without MSYS2. It''s possible to install MSYS2 at the last page of the installer or to reuse an existing MSYS2 installation.';
Expand All @@ -129,9 +129,10 @@ end;

procedure EnableMsys2Component(enable: Boolean);
begin
{* InnoSetup doesn't provide corresponding setter for IsComponentSelected, so that we alter the ComponentsList directly. *}
if WizardForm.ComponentsList.Items.Count > 2 then
WizardForm.ComponentsList.Checked[2] := enable;
if enable then
WizardSelectComponents('msys2')
else
WizardSelectComponents('!msys2');
end;

procedure InitializeGUI;
Expand Down
7 changes: 6 additions & 1 deletion recipes/installer-inno/rubyinstaller.iss.erb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ en.SelectDirDesc=
en.SelectDirLabel3=Setup will install [name] into the following folder. Click Install to continue or click Browse to use a different one.
en.SelectDirBrowseLabel=Please avoid any folder name that contains spaces (e.g. Program Files).
en.DiskSpaceMBLabel=Required free disk space: ~[mb] MB
en.DirExists=The folder:%n%n%1%n%nalready exists. Would you like to install to that folder anyway?%n%nOverwriting a Ruby version with the same major and minor version usually works, but for example Ruby-2.5.0 over 2.4.0 doesn't.
en.DirExists=The folder:%n%n%1%n%nalready exists. Would you like to install to that folder anyway?%n%nOverwriting a Ruby version with the same major and minor version usually works, but for example Ruby-3.4.0 over 3.3.0 doesn't.

[CustomMessages]
AddPath=Add Ruby executables to your PATH
Expand Down Expand Up @@ -133,11 +133,16 @@ Root: <%= regroot %>; Subkey: Software\Classes\<%= rubyname %>File\shell\open\co
; So use Innosetup to add described permissions and icacls to disable unwanted inheritance.
[Dirs]
Name: {app}; Permissions: creatorowner-full users-readexec admins-full
Name: "{app}/<%= package.rubyver2 =~ /^3\.[23]$/ ? "bin/etc" : "lib/ruby/#{ package.rubylibver }/etc" %>"

[Run]
; Set permissions on install directories
Filename: "icacls.exe"; Parameters: """{app}"" /inheritancelevel:r "; WorkingDir: "{app}"; StatusMsg: "Changing install Directory Permissions"; Flags: runhidden
<% if with_msys %>
Filename: "icacls.exe"; Parameters: """{app}\<%= package.msysdir %>\tmp"" /inheritancelevel:r /grant *S-1-5-32-545:(CI)(WD,AD,WEA,WA) /grant *S-1-3-0:(OI)(CI)(IO)(F) /grant *S-1-5-32-544:(OI)(CI)(F) /grant *S-1-5-32-545:(NP)(RX) "; WorkingDir: "{app}"; StatusMsg: "Changing MSYS2 /tmp Directory Permissions"; Flags: runhidden; Components: msys2
<% end %>
; Add link to SSL CA certs so that OpenSSL finds them based on the libssl.dll location
Filename: "{cmd}"; Parameters: "/c mklink /j <%= package.rubyver2 =~ /^3\.[23]$/ ? "bin" : "lib\\ruby\\#{package.rubylibver}" %>\etc\ssl ssl"; WorkingDir: "{app}"; StatusMsg: "Add link to SSL CA certs"; Flags: runhidden

[Icons]
Name: {autoprograms}\{#InstallerName}\{cm:InteractiveRubyTitle}; Filename: {app}\bin\irb.<%= package.rubyver2 < '3.1' ? "cmd" : "bat" %>; IconFilename: {app}\bin\ruby.exe
Expand Down
6 changes: 3 additions & 3 deletions recipes/sandbox/20-define-import-files.rake
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ self.import_files.merge!({
"resources/files/setrbvars.cmd" => "bin/setrbvars.cmd",
"resources/files/operating_system.rb" => "lib/ruby/#{package.rubylibver}/rubygems/defaults/operating_system.rb",
"resources/icons/ruby-doc.ico" => "share/doc/ruby/html/images/ruby-doc.ico",
"resources/ssl/cacert.pem" => "#{"bin/etc/" if package.rubyver2 >= "3.2"}ssl/cert.pem",
"resources/ssl/README-SSL.md" => "#{"bin/etc/" if package.rubyver2 >= "3.2"}ssl/README-SSL.md",
"resources/ssl/c_rehash.rb" => "#{"bin/etc/" if package.rubyver2 >= "3.2"}ssl/certs/c_rehash.rb",
"resources/ssl/cacert.pem" => "ssl/cert.pem",
"resources/ssl/README-SSL.md" => "ssl/README-SSL.md",
"resources/ssl/c_rehash.rb" => "ssl/certs/c_rehash.rb",
"#{thisdir}/LICENSE.txt" => "LICENSE.txt",
})
88 changes: 88 additions & 0 deletions recipes/sandbox/60-side-by-side-assembly-ruby-3.123.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Move bundled RubyInstaller DLLs to a subdirectory.
# This avoids interferences with other apps when ruby.exe is in the PATH.

if package.rubyver2 < "3.4"
libruby_regex = /(msvcrt|ucrt)-ruby\d+\.dll$/i
bin_dir = File.join(sandboxdir, "bin")
dlls_dir = File.join(sandboxdir, "bin/ruby_builtin_dlls")
directory bin_dir
directory dlls_dir

# Select the DLLs from "bin/" which shall be moved into "bin/ruby_builtin_dlls/"
dlls = self.sandboxfiles.select do |destpath|
destpath.start_with?(bin_dir+"/") && destpath =~ /\.dll$/i && destpath !~ libruby_regex
end

dlls.each do |destpath|
# Add tasks to write the DLLs into the sub directory
new_destpath = File.join(File.dirname(destpath), "ruby_builtin_dlls", File.basename(destpath))
file new_destpath => [destpath.sub(sandboxdir, unpackdirmgw), dlls_dir] do |t|
cp(t.prerequisites.first, t.name)
end

# Move the DLLs in the dependent files list to the subdirectory
self.sandboxfiles.delete(destpath)
self.sandboxfiles << new_destpath
end

# Add a custom manifest to both ruby.exe and rubyw.exe, so that they find the DLLs to be moved
self.sandboxfiles.select do |destpath|
destpath =~ /\/rubyw?\.exe$/i
end.each do |destpath|
file destpath => [destpath.sub(sandboxdir, unpackdirmgw), bin_dir] do |t|
puts "patching manifest of #{t.name}"
libruby = File.basename(self.sandboxfiles.find{|a| a=~libruby_regex })

image = File.binread(t.prerequisites.first)
# The XML elements we want to add to the default MINGW manifest:
new = <<-EOT
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<ws2:longPathAware>true</ws2:longPathAware>
</windowsSettings>
</application>
<dependency>
<dependentAssembly>
<assemblyIdentity version="1.0.0.0" type="win32" name="ruby_builtin_dlls" />
</dependentAssembly>
</dependency>
<file name="#{ libruby }"/>
EOT

# There are two regular options to add a custom manifest:
# 1. Change a given exe file per Microsofts "mt.exe" after the build
# 2. Specify a the manifest while linking with the MINGW toolchain
#
# Since we don't want to depend on particular Microsoft tools and want to avoid additional patching of the ruby build, we do a nifty trick here.
# We patch the exe file manually.
# Removing unnecessary spaces and comments from the embedded XML manifest gives us enough space to add the above XML elements.
# Then the default MINGW manifest gets replaced by our custom XML content.
# The rest of the available bytes is simply padded with spaces, so that we don't change positions within the EXE image.
image.gsub!(/<\?xml.*?<assembly.*?<\/assembly>\n/m) do |m|
newm = m.gsub(/^\s*<\/assembly>\s*$/, new + "</assembly>")
.gsub(/<!--.*?-->/m, "")
.gsub(/^ +/, "")
.gsub(/\n+/m, "\n")

raise "replacement manifest to big #{m.bytesize} < #{newm.bytesize}" if m.bytesize < newm.bytesize
newm + " " * (m.bytesize - newm.bytesize)
end
File.binwrite(t.name, image)
end
end

# Add a detached manifest file within the sub directory that lists all DLLs in question
manifest2 = File.join(sandboxdir, "bin/ruby_builtin_dlls/ruby_builtin_dlls.manifest")
file manifest2 => [dlls_dir] do |t|
puts "generate #{t.name}"
File.binwrite t.name, <<-EOT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="ruby_builtin_dlls" version="1.0.0.0"></assemblyIdentity>

#{ dlls.map{|dll| %Q{<file name="#{File.basename(dll)}"/>} }.join }
</assembly>
EOT
end
self.sandboxfiles << manifest2
end
Loading
Loading