123456789_123456789_123456789_123456789_123456789_

Class: RubyInstaller::Build::ManifestUpdater

Relationships & Source Files
Inherits: Object
Defined in: lib/ruby_installer/build/manifest_updater.rb

Class Method Summary

Class Method Details

.update_blob(dll_or_exe_data, manifest_xml_string, filename: nil)

[ GitHub ]

  
# File 'lib/ruby_installer/build/manifest_updater.rb', line 10

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

.update_file(from_fname, manifest_xml_string, to_fname)

[ GitHub ]

  
# File 'lib/ruby_installer/build/manifest_updater.rb', line 4

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