module Neri

Constants

BLOCK_LENGTH
VERSION

Attributes

options[R]

Public Class Methods

additional_dlls_dependencies() click to toggle source
# File lib/neri/build.rb, line 371
def additional_dlls_dependencies()
  dependencies = []
  options[:dlls].each do |dll|
    dependencies += Dir.glob(File.join(bindir, "**", dll))
    dependencies += Dir.glob(File.join(bindir, "**", dll + ".*"))
  end
  return dependencies.uniq
end
additional_gems_dependencies() click to toggle source
# File lib/neri/build.rb, line 392
def additional_gems_dependencies()
  require "rubygems"
  dependencies = []
  rubygems_dir = File.join(Gem.dir, "gems")
  options[:gems].each do |gem|
    gem.sub!(/\:(.+)/, "")
    targets = $1.to_s.split("|")
    targets.push("lib/**/*")
    gem += "-*" unless gem.match("-")
    gemdir = Dir.glob(File.join(rubygems_dir, gem)).sort.last
    next unless gemdir
    targets.each do |target|
      dependencies += Dir.glob(File.join(gemdir, target))
    end
  end
  return dependencies.uniq
end
additional_libs_dependencies() click to toggle source
# File lib/neri/build.rb, line 380
def additional_libs_dependencies()
  dependencies = []
  options[:libs].each do |lib|
    $LOAD_PATH.each do |path|
      dependencies += Dir.glob(File.join(path, lib))
      dependencies += Dir.glob(File.join(path, lib + ".*"))
      dependencies += Dir.glob(File.join(path, lib, "**", "*"))
    end
  end
  return dependencies.uniq
end
basename( ) click to toggle source
# File lib/neri/build.rb, line 90
def basename(  ); File.basename(scriptfile, ".*"); end
basepath( ) click to toggle source
# File lib/neri/build.rb, line 91
def basepath(  ); File.join(options[:output_dir], basename); end
bat_to_exe_converter() click to toggle source
# File lib/neri/build.rb, line 735
def bat_to_exe_converter()
  create_batfile
  begin
    `#{options[:b2ec_path]} /help`
  rescue
    error "Bat To Exe Converter not found !"
    return
  end
  
  batch_file = basepath + ".bat"
  exe_file   = basepath + ".exe"
  nputs "Creating exe_file '#{exe_file}' with Bat To Exe Converter."
  File.delete(exe_file) if File.exist?(exe_file)
  if options[:b2ec][:x64] == nil
    options[:b2ec][:x64] = true if RbConfig::CONFIG["target"].to_s.index("64")
  end
  args = %[ /bat "#{batch_file}" /exe "#{exe_file}"]
  args += options[:b2ec].map{|key, value|
    case value
    when String; %[ /#{key.to_s.tr("_", "-")} "#{value}"]
    when true;   %[ /#{key.to_s.tr("_", "-")}]
    else;        %[]
    end
  }.join("")
  
  
  unless nsystem "#{options[:b2ec_path]}#{args}"
    error "Failed to create exe_file !"
  end
end
bindir( ) click to toggle source
# File lib/neri/build.rb, line 86
def bindir(    ); RbConfig::CONFIG["bindir"] || File.join(rubydir, "bin"); end
check_dependencies() click to toggle source
# File lib/neri/build.rb, line 430
def check_dependencies()
  nputs "Running script '#{scriptfile}' to check dependencies."
  begin
    load File.expand_path(scriptfile)
  rescue SystemExit, Interrupt
  end
  nputs "Script '#{scriptfile}' end."
  
  if defined? DXRuby
    require "neri/dxruby"
    @use_dxruby = true
  end
  if defined? DXRuby::Tiled
    require "neri/dxruby_tiled"
    @use_dxruby_tiled = true
  end
  if defined? Ayame
    require "neri/ayame"
    @use_ayame = true
  end
  
  if options[:b2ec][:invisible] == nil &&
     (File.extname(scriptfile) == ".rbw" || @use_dxruby)
    options[:b2ec][:invisible] = true
  end
  if options[:pause_last] == nil
    options[:pause_last] = true unless options[:b2ec][:invisible]
  end
  
  require "rbconfig"
  dependencies = []
  dependencies += rb_dependencies
  dependencies += dll_dependencies
  dependencies += ruby_dependencies
  dependencies += additional_dlls_dependencies
  dependencies += additional_libs_dependencies
  dependencies += additional_gems_dependencies
  dependencies += encoding_dependencies
  dependencies = select_dependencies(dependencies)
  
  size = dependencies.map{|d| File.size(d)}.inject(&:+)
  nputs "#{dependencies.size} files, #{size} bytes dependencies."
  if options[:verbose]
    dependencies.each do |dependency|
      nputs_v "  - #{dependency}"
    end
  end
  
  return dependencies
end
check_options() click to toggle source
# File lib/neri/build.rb, line 185
def check_options
  nputs_v "Checking Neri options."
  while arg = ARGV.shift
    case arg
    when "--help", "-h"
      output_help
      exit
    when "--version", "-v"
      output_version
      exit
    when "--quiet", "-q"
      options[:quiet] = true
    when "--verbose", "-v"
      options[:verbose] = true
    when "--external_encoding"
      options[:external_encoding] = ARGV.shift
    when "--dll"
      options[:dlls] += ARGV.shift.split(",").map(&:strip)
    when "--lib"
      options[:libs] += ARGV.shift.split(",").map(&:strip)
    when "--gem"
      options[:gems] += ARGV.shift.split(",").map(&:strip)
    when "--no-enc"
      options[:encoding] = nil
    when "--encoding"
      options[:encoding] = ARGV.shift
    when "--enable-gems"
      options[:enable_gems] = true
    when "--enable-did-you-mean"
      options[:enable_did_you_mean] = true
    when "--chdir-first"
      options[:chdir_first] = true
    when "--pause-last"
      options[:pause_last] = true
    when "--no-pause-last"
      options[:pause_last] = false
    when "--pause-text"
      options[:pause_text] = ARGV.shift.encode("utf-8")
      options[:pause_last] = true
    when "--output-dir"
      options[:output_dir] = ARGV.shift.encode("utf-8")
    when "--system-dir"
      options[:system_dir] = ARGV.shift.encode("utf-8")
    when "--datafile"
      options[:datafile] = ARGV.shift.encode("utf-8")
    when "--encryption-key"
      options[:encryption_key] = ARGV.shift.encode("utf-8")
    when "--no-exe"
      options[:no_exe] = true
    when "--use-b2ec"
      options[:use_b2ec] = true
    when "--b2ec-path"
      options[:b2ec_path] = ARGV.shift.encode("utf-8")
    when "--icon"
      options[:b2ec][:icon] = ARGV.shift.encode("utf-8")
    when "--windows", "--invisible"
      options[:b2ec][:invisible] = true
    when "--console", "--visible"
      options[:b2ec][:invisible] = false
    when "--x64"
      options[:b2ec][:x64] = true
    when "--uac-admin"
      options[:b2ec][:uac_admin] = true
    when "--fileversion"
      options[:b2ec][:fileversion] = ARGV.shift
    when "--productversion"
      options[:b2ec][:productversion] = ARGV.shift
    when "--productname"
      options[:b2ec][:productname] = ARGV.shift.encode("utf-8")
    when "--originalfilename"
      options[:b2ec][:originalfilename] = ARGV.shift.encode("utf-8")
    when "--internalname"
      options[:b2ec][:internalname] = ARGV.shift.encode("utf-8")
    when "--description"
      options[:b2ec][:description] = ARGV.shift.encode("utf-8")
    when "--company"
      options[:b2ec][:company] = ARGV.shift.encode("utf-8")
    when "--trademarks"
      options[:b2ec][:trademarks] = ARGV.shift.encode("utf-8")
    when "--copyright"
      options[:b2ec][:copyright] = ARGV.shift.encode("utf-8")
    when "--privatebuild"
      options[:b2ec][:privatebuild] = ARGV.shift.encode("utf-8")
    when "--specialbuild"
      options[:b2ec][:specialbuild] = ARGV.shift.encode("utf-8")
    when "--comments"
      options[:b2ec][:comments] = ARGV.shift.encode("utf-8")
    when "--use-upx"
      options[:use_upx] = true
    when "--upx-path"
      options[:upx_path] = ARGV.shift.encode("utf-8")
    when "--upx-targets"
      options[:upx_targets] += ARGV.shift.split(",").map(&:strip)
    when "--upx-options"
      options[:upx_options] = ARGV.shift
    when "--zipfile"
      options[:zipfile] = ARGV.shift.encode("utf-8").sub(/\.zip$/, "") + ".zip"
    when "--7zip-path"
      options[:sevenzip_path] = ARGV.shift.encode("utf-8")
    when "--innosetup"
      options[:inno_script] = ARGV.shift.encode("utf-8")
    when "--iscc-path"
      options[:iscc_path] = ARGV.shift.encode("utf-8")
    when "--create-recipe"
      require "json"
      filename = ARGV.shift.encode("utf-8")
      nputs "Creating recipe_file '#{filename}'."
      open(filename, "w:utf-8"){ |file| create_recipe(file) }
      exit
    when "--recipe"
      filename = ARGV.shift.encode("utf-8")
      nputs_v "Loading recipe_file '#{filename}'."
      load File.expand_path(filename)
    when "--"
      break
    when /^(--.+)/
      error "Invalid Option '#{arg}'!"
      output_help
      exit
    else
      @data_files.push(arg.encode("utf-8"))
    end
  end
  
  if @data_files.empty?
    error "No Script File!"
    output_help
    exit
  end
  
  @args = ARGV.map{ |arg| %[ "#{arg}"] }.join("")
  @options[:external_encoding] ||= Encoding::default_external.name
  unless options[:enable_gems]
    @rubyopt += " --disable-gems" unless @rubyopt.index("--disable-gems")
  end
  unless options[:enable_did_you_mean]
    @rubyopt += " --disable-did_you_mean" unless @rubyopt.index("--disable-did_you_mean")
  end
end
copy_files(dependencies) click to toggle source
# File lib/neri/build.rb, line 507
def copy_files(dependencies)
  nputs "Copying dependencies."
  require "fileutils"
  src_dir  = rubydir
  desc_dir = File.join(options[:output_dir], options[:system_dir], "")
  
  system_files = dependencies.map do |file|
    [file, file.sub(src_dir, desc_dir)]
  end
  unless options[:enable_gems]
    system_files.each do |src, desc|
      desc.sub!(/\/gems(\/\d+\.\d+\.\d+\/)gems\/(.+?)\-[^\/]+\/lib\//, "/vendor_ruby\\1")
    end
  end
  
  system_files.each do |src, desc|
    FileUtils.makedirs(File.dirname(desc))
    if File.file?(src)
      FileUtils.copy(src, desc)
      nputs_v "  #{src}\n  -> #{desc}"
    end
  end
  FileUtils.copy(scriptfile, desc_dir) unless options[:datafile]
end
create_batfile() click to toggle source
# File lib/neri/build.rb, line 571
    def create_batfile()
      nputs "Creating batch_file '#{basepath}.bat'."
      
      pause_command = ""
      if options[:pause_last]
        pause_command += "echo.\n"
        if options[:pause_text]
          pause_command += "echo #{options[:pause_text]}\n" +
                           "pause > nul"
        else
          pause_command += "pause"
        end
      end
      chdir = options[:chdir_first] ? 'cd /d "%~dp0"' : ""
      
      open(basepath + ".bat", "w:#{options[:external_encoding]}") do |f|
        f.puts <<-EOF
@echo off
setlocal
set PATH=%~dp0#{options[:system_dir]}\\#{relative_path(bindir)};%PATH%
#{chdir}
if %~x0 == .exe ( shift )
#{ruby_command("%~dp0")} %1 %2 %3 %4 %5 %6 %7 %8 %9
#{pause_command}
endlocal
        EOF
      end
    end
create_datafile() click to toggle source
# File lib/neri/build.rb, line 533
def create_datafile()
  if @data_files.size > 1 || options[:encryption_key]
    options[:datafile] ||= basename + ".dat"
  end
  return unless options[:datafile]
  
  nputs "Creating datafile '#{datafile}'."
  data_files = @data_files.select { |file| File.file? file }
  @data_files.select { |file| File.directory? file }.each do |dir|
    data_files += Dir.glob(dir + "/**/*").select { |file| File.file? file }
  end
  if options[:encryption_key]
    require "digest/sha2"
    @encryption_key = Digest::SHA2.hexdigest(options[:encryption_key])
  end
  Neri.key = @encryption_key || "0" * 64
  open(datafile, "wb") do |f|
    pos = 0
    files_str = data_files.map{|file|
      filename = File.expand_path(file)
      filename = relative_path(filename, rubydir, "*neri*" + File::SEPARATOR)
      filename = relative_path(filename, Dir.pwd)
      filedata = [filename, File.size(file), pos]
      pos += File.size(file)
      pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
      nputs_v "  - #{filename}:#{File.size(file)} bytes"
      filedata.join("\t")
    }.join("\n").encode(Encoding::UTF_8)
    
    f.write(sprintf("%#{BLOCK_LENGTH}d", files_str.bytesize))
    f.write(xor(files_str))
    data_files.each do |file|
      f.write(xor(File.binread(file)))
    end
  end
end
create_exefile() click to toggle source
# File lib/neri/build.rb, line 600
    def create_exefile()
      unless system("gcc --version >nul 2>&1 && windres --version >nul 2>&1")
        error "gcc or windres not found !"
        create_batfile
        return
      end
      
      exe_file = to_winpath(basepath + ".exe"   )
      c_file   = to_winpath(basepath + "_tmp.c" )
      o_file   = to_winpath(basepath + "_tmp.o" )
      rc_file  = to_winpath(basepath + "_tmp.rc")
      system_dir = escape_cstr(to_winpath(File.join(options[:system_dir], "")))
      nputs "Creating exe_file '#{exe_file}'."
      open(c_file, "w:#{options[:external_encoding]}") do |f|
        f.puts <<-EOF
#include <stdio.h>
#include <windows.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    char exepath[_MAX_PATH  *  2 + 1], 
         drive  [_MAX_DRIVE      + 1],
         dir    [_MAX_DIR   *  2 + 1],
         fname  [_MAX_FNAME *  2 + 1],
         ext    [_MAX_EXT   *  2 + 1],
         paths  [_MAX_PATH  * 32 + 1],
         runruby[_MAX_PATH  * 32 + 1];
    PROCESS_INFORMATION pi; 
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    
    if(GetModuleFileName(NULL, exepath, MAX_PATH * 2) != 0){
        _splitpath_s(exepath, drive, _MAX_DRIVE, dir, _MAX_DIR * 2, fname, _MAX_FNAME * 2, ext, _MAX_EXT * 2);
    } else {
        exit(EXIT_FAILURE);
    }
    sprintf(paths, "PATH=%s%s#{system_dir}bin;%s", drive, dir, getenv("PATH"));
    putenv(paths);
    #{options[:chdir_first] ? 'sprintf(paths, "%s%s", drive, dir);chdir(paths);' : ''}
    sprintf(runruby, "#{escape_cstr(ruby_command("%s%s"))} %s %s %s %s %s %s %s %s %s",
        drive,
        dir,
        argc > 1 ? argv[1] : "",
        argc > 2 ? argv[2] : "",
        argc > 3 ? argv[3] : "",
        argc > 4 ? argv[4] : "",
        argc > 5 ? argv[5] : "",
        argc > 6 ? argv[6] : "",
        argc > 7 ? argv[7] : "",
        argc > 8 ? argv[8] : "",
        argc > 9 ? argv[9] : ""
        );
        EOF
        if options[:b2ec][:invisible]
          f.puts %[    CreateProcess(NULL, runruby, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);]
        else
          f.puts %[    system(runruby);]
        end
        if options[:pause_last]
          f.puts %[    system("echo.");]
          if options[:pause_text]
            f.puts %[    system("echo #{escape_cstr(options[:pause_text])}");]
            f.puts %[    system("pause >nul");]
          else
            f.puts %[    system("pause");]
          end
        end
        f.puts "    return 0;\n}"
      end
      
      open(rc_file, "w:#{options[:external_encoding]}") do |f|
        f.puts <<-EOF
#include <winver.h>

1 VERSIONINFO
#{options[:b2ec][:fileversion   ] ? "FILEVERSION     " + escape_cstr(options[:b2ec][:fileversion   ]) : ""}
#{options[:b2ec][:productversion] ? "PRODUCTVERSION  " + escape_cstr(options[:b2ec][:productversion]) : ""}
FILETYPE        VFT_APP
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "000004b0"
        BEGIN
            #{options[:b2ec][:fileversion     ] ? 'VALUE "FileVersion",      "' + escape_cstr(options[:b2ec][:fileversion     ]) + '\0"' : ''}
            #{options[:b2ec][:productversion  ] ? 'VALUE "ProductVersion",   "' + escape_cstr(options[:b2ec][:productversion  ]) + '\0"' : ''}
            #{options[:b2ec][:productname     ] ? 'VALUE "ProductName",      "' + escape_cstr(options[:b2ec][:productname     ]) + '\0"' : ''}
            #{options[:b2ec][:originalfilename] ? 'VALUE "OriginalFileName", "' + escape_cstr(options[:b2ec][:originalfilename]) + '\0"' : ''}
            #{options[:b2ec][:internalname    ] ? 'VALUE "InternalName",     "' + escape_cstr(options[:b2ec][:internalname    ]) + '\0"' : ''}
            #{options[:b2ec][:description     ] ? 'VALUE "FileDescription",  "' + escape_cstr(options[:b2ec][:description     ]) + '\0"' : ''}
            #{options[:b2ec][:company         ] ? 'VALUE "CompanyName",      "' + escape_cstr(options[:b2ec][:company         ]) + '\0"' : ''}
            #{options[:b2ec][:trademarks      ] ? 'VALUE "LegalTrademarks",  "' + escape_cstr(options[:b2ec][:trademarks      ]) + '\0"' : ''}
            #{options[:b2ec][:copyright       ] ? 'VALUE "LegalCopyright",   "' + escape_cstr(options[:b2ec][:copyright       ]) + '\0"' : ''}
            #{options[:b2ec][:privatebuild    ] ? 'VALUE "PrivateBuild",     "' + escape_cstr(options[:b2ec][:privatebuild    ]) + '\0"' : ''}
            #{options[:b2ec][:specialbuild    ] ? 'VALUE "SpecialBuild",     "' + escape_cstr(options[:b2ec][:specialbuild    ]) + '\0"' : ''}
            #{options[:b2ec][:comments        ] ? 'VALUE "Comments",         "' + escape_cstr(options[:b2ec][:comments        ]) + '\0"' : ''}
        END
    END

    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0, 0x4b0
    END
END

2 ICON "#{escape_cstr(options[:b2ec][:icon])}"
        EOF
      end
      nsystem(%[windres -o "#{o_file}" "#{rc_file}"])
      nsystem(%[gcc#{options[:b2ec][:invisible] ? " -mwindows" : ""} -o "#{exe_file}" "#{c_file}" "#{o_file}"])
      nsystem(%[strip "#{exe_file}"])
      File.delete(c_file, rc_file, o_file)
    end
create_recipe(file, hash = options, pre = "Neri.options") click to toggle source

–create-recipe

# File lib/neri/build.rb, line 169
def create_recipe(file, hash = options, pre = "Neri.options")
  hash.each_pair do |key, value|
    case value
    when Hash
      create_recipe(file, value, pre + "[:#{key}]")
    when Numeric, TrueClass, FalseClass
      file.puts "#{pre}[:#{key}] = #{value}"
    when NilClass
      file.puts "#{pre}[:#{key}] = nil"
    when String, Array
      file.puts "#{pre}[:#{key}] = " + JSON.generate(value)
    end
  end
end
create_zipfile() click to toggle source
# File lib/neri/build.rb, line 783
def create_zipfile()
  unless system("#{options[:sevenzip_path]} >nul 2>&1")
    error "7-Zip not found !"
    return
  end
  
  nputs "Creating zip_file '#{options[:zipfile]}'."
  File.delete(options[:zipfile]) if File.exist?(options[:zipfile])
  files = []
  if options[:output_dir] == "./"
    files.push(options[:system_dir])
    files.push(File.exist?(basepath + ".exe") ? basepath + ".exe" : basepath + ".bat")
  else
    files.push(options[:output_dir])
  end
  command = %("#{options[:sevenzip_path]}" a "#{options[:zipfile]}" "#{files.join('" "')}")
  nsystem command
end
datafile( ) click to toggle source
# File lib/neri/build.rb, line 92
def datafile(  ); File.join(options[:output_dir], options[:system_dir], options[:datafile]); end
datafile=(datafile) click to toggle source
# File lib/neri/runtime.rb, line 22
def datafile=(datafile)
  @datafile = datafile
  @system_dir = File.dirname(File.expand_path(datafile)) + File::SEPARATOR
  files_length = File.binread(@datafile, BLOCK_LENGTH).to_i
  files_str = read(files_length, BLOCK_LENGTH)
  pos = files_length + BLOCK_LENGTH
  pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
  files_str.force_encoding(Encoding::UTF_8)
  files_str.split("\n").each do |line|
    filename, length, offset = line.split("\t")
    @files[filename] = [length.to_i, offset.to_i + pos]
  end
end
dll_dependencies() click to toggle source
# File lib/neri/build.rb, line 331
def dll_dependencies()
  require "Win32API"
  
  enumprocessmodules = Win32API.new("psapi"   , "EnumProcessModules", ["L","P","L","P"], "L")
  getmodulefilename  = Win32API.new("kernel32", "GetModuleFileNameW", ["L","P","L"], "L")
  getcurrentprocess  = Win32API.new("kernel32", "GetCurrentProcess" , [], "L")
  
  bytes_needed = 4 * 32
  module_handle_buffer = nil
  process_handle = getcurrentprocess.call()
  loop do
    module_handle_buffer = "\x00" * bytes_needed
    bytes_needed_buffer = [0].pack("I")
    r = enumprocessmodules.call(process_handle, module_handle_buffer, module_handle_buffer.size, bytes_needed_buffer)
    bytes_needed = bytes_needed_buffer.unpack("I")[0]
    break if bytes_needed <= module_handle_buffer.size
  end
  
  handles = module_handle_buffer.unpack("I*")
  dependencies = handles.select { |handle| handle > 0 }.map do |handle|
    str = "\x00\x00" * 256
    modulefilename_length = getmodulefilename.call(handle, str, str.size)
    modulefilename = str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
  end
  
  dependencies.map!{|dep| dep.sub(/^\\\\\?\\/, "")}
  if File::ALT_SEPARATOR
    dependencies.map!{|dep| dep.tr(File::ALT_SEPARATOR, File::SEPARATOR)}
  end
  dependencies.delete(rubyexe)
  
  return dependencies.uniq
end
encoding_dependencies() click to toggle source
# File lib/neri/build.rb, line 410
def encoding_dependencies()
  return [] unless options[:encoding]
  dependencies = []
  enc_dir = Dir.glob(File.join(RbConfig::CONFIG["archdir"] || RbConfig::TOPDIR, "**", "enc")).first
  
  options[:encoding].split(",").map(&:strip).each do |enc|
    case enc
    when "ja"
      %w[windows_31j.so japanese_sjis.so encdb.so].each do |enc_name|
        dependencies += Dir.glob(File.join(enc_dir, "**", enc_name))
      end
    else
      dependencies += Dir.glob(File.join(enc_dir, "**", enc))
      dependencies += Dir.glob(File.join(enc_dir, "**", enc + ".*"))
    end
  end
  
  return dependencies.uniq
end
exist_in_datafile?(filename) click to toggle source
# File lib/neri/runtime.rb, line 98
def exist_in_datafile?(filename)
  return @files.has_key?(adjust_path(filename.encode(Encoding::UTF_8)))
end
file_exist?(filename) click to toggle source
# File lib/neri/runtime.rb, line 78
def file_exist?(filename)
  return exist_in_datafile?(filename) || File.exist?(filename)
end
file_read(filename, encoding = Encoding::BINARY) click to toggle source
# File lib/neri/runtime.rb, line 82
def file_read(filename, encoding = Encoding::BINARY)
  str = nil
  if exist_in_datafile?(filename)
    length, offset = @files[adjust_path(filename.encode(Encoding::UTF_8))]
    str = read(length, offset)
  else
    str = File.binread(filename)
  end
  str.force_encoding(encoding)
  return str
end
files() click to toggle source
# File lib/neri/runtime.rb, line 94
def files()
  return @files.keys
end
inno_setup() click to toggle source
# File lib/neri/build.rb, line 803
def inno_setup()
  unless system("#{options[:iscc_path]} /? >nul 2>&1")
    error("Inno Setup not found !")
    return
  end
  
  filename = options[:inno_script]
  nputs "Creating Installer '#{filename}'."
  script = "[Setup]\n"
  if File.exist?(filename)
    script = File.read(filename, encoding: Encoding::UTF_8)
    filename = File.basename(filename, ".*") + "_tmp" + File.extname(filename)
  end
  
  version = options[:b2ec][:productversion] || options[:b2ec][:fileversion]
  if !script.match(/^AppName=/) && options[:b2ec][:productname]
    script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppName=#{options[:b2ec][:productname]}#{$2}" }
  end
  if !script.match(/^AppVersion=/) && version
    script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppVersion=#{version}#{$2}" }
  end
  if !script.match(/^AppVerName=/) && options[:b2ec][:productname] && version
    script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppVerName=#{options[:b2ec][:productname]} #{version}#{$2}" }
  end
  if !script.match(/^AppPublisher=/) && options[:b2ec][:company]
    script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppPublisher=#{options[:b2ec][:company]}#{$2}" }
  end
  if !script.match(/^AppCopyright=/) && options[:b2ec][:copyright]
    script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppCopyright=#{options[:b2ec][:copyright]}#{$2}" }
  end
  
  script += "\n[Files]\n" unless script.match(/^\[Files\]/)
  dir = File.expand_path(options[:output_dir])
  files_str = ""
  Dir.glob(File.join(dir, "**", "*")).each do |file|
    next unless File.file? file
    dist_dir = to_winpath(File::SEPARATOR + File.dirname(relative_path(file, dir)))
    dist_dir = "" if dist_dir == "\\."
    files_str += "\nSource: \"#{to_winpath(file)}\"; DistDir: \"{app}#{dist_dir}"
    files_str += "; Flags: isreadme" if File.basename(file).match(/^readme/i)
  end
  script.sub!(/^(\[Files\])(\s*)/i){ "#{$1}#{files_str}#{$2}" }
  
  File.write(filename, script)
  command = %(#{options[:iscc_path]} "#{filename}")
  nsystem command
end
key=(key) click to toggle source
# File lib/neri/runtime.rb, line 36
def key=(key)
  @xor = key.scan(/../).map{|a| a.to_i(16)}.pack("c*")
end
load(file, priv = false) click to toggle source
# File lib/neri/runtime.rb, line 60
def load(file, priv = false)
  filepath = nil
  (load_path + [""]).each do |path|
    filepath = path + file if exist_in_datafile?(path + file)
  end
  
  if filepath
    code = load_code(filepath)
    if priv
      Module.new.module_eval(code, filepath)
    else
      eval(code, nil, filepath)
    end
  else
    _neri_orig_load(filepath || file, priv)
  end
end
output_help() click to toggle source

–help

# File lib/neri/build.rb, line 95
    def output_help
      puts <<-EOF
usage: neri [options] script.rb (other_files...) -- script_arguments

options:
  --help or -h
  --version or -v
  --quiet
  --verbose
  
  --external-encoding <encoding>
  
  --dll <dll1>,<dll2>,...
  --lib <lib1>,<lib2>,...
  --gem <gem1>,<gem2>,...
  
  --no-enc
  --encoding <enc1>,<enc2>,...
  
  --enable-gems
  --enable-did-you-mean
  --chdir-first
  --pause-last
  --no-pause-last
  --pause-text <text>
  
  --output-dir <dirname>
  --system-dir <dirname>
  --datafile <filename>
  --encryption-key <key>
  
  --no-exe
  --use-b2ec
  --b2ec-path <bat_to_exe_converter_path>
  --icon <iconfile>
  --windows or --invisible
  --console or --visible
  --x64
  --uac-admin
  --fileversion <string>     # ex) 1,2,3,4
  --productversion <string>  # ex) 1,2,3,4
  --productname <string>
  --originalfilename <string>
  --internalname <string>
  --description <string>
  --company <string>
  --trademarks <string>
  --copyright <string>
  --privatebuild <string>
  --specialbuild <string>
  --comments <string>
  
  --use-upx
  --upx-path <upx path>
  --upx_targets '<glob>'  # ex) 'bin/**/*.dll'
  --upx-options <options>
  
  --zipfile <filename>
  --7zip-path <7-zip path>
  
  --innosetup <inno_script>
  --iscc-path <iscc path>
  
  --create-recipe <recipefile>
  --recipe <recipefile>
      EOF
    end
output_version() click to toggle source

–version

# File lib/neri/build.rb, line 164
def output_version
  puts "Neri #{Neri::VERSION}"
end
rb_dependencies() click to toggle source

check dependencies

# File lib/neri/build.rb, line 327
def rb_dependencies()
  return $LOADED_FEATURES.uniq
end
relative_path(path, basedir=rubydir, prepath = "") click to toggle source
# File lib/neri/build.rb, line 77
def relative_path(path, basedir=rubydir, prepath = "")
  basedir.concat(File::SEPARATOR) unless basedir.end_with?(File::SEPARATOR)
  return path.start_with?(basedir) ? path.sub(basedir, prepath) : path
end
require(feature) click to toggle source
# File lib/neri/runtime.rb, line 40
def require(feature)
  filepath = nil
  load_path.each do |path|
    ["", ".rb"].each do |ext|
      next unless exist_in_datafile?(path + feature + ext)
      filepath = adjust_path(path + feature + ext)
    end
  end
  
  if filepath
    return false if $LOADED_FEATURES.index(filepath)
    code = load_code(filepath)
    eval(code, nil, filepath)
    $LOADED_FEATURES.push(filepath)
    return true
  else
    return _neri_orig_require(feature)
  end
end
ruby_command(path) click to toggle source
# File lib/neri/build.rb, line 714
def ruby_command(path)
  system_dir = "#{path}#{File.join(options[:system_dir], "")}"
  ruby_code = ""
  ruby_code = "Neri.key='#{@encryption_key}';" if @encryption_key
  if options[:datafile]
    ruby_code += "Neri.datafile='#{system_dir}' + #{unpack_filename(options[:datafile])};"
    ruby_code += "load File.expand_path(#{unpack_filename(File.basename(scriptfile))})"
  else
    ruby_code += "load File.expand_path('#{system_dir}' + #{unpack_filename(scriptfile)})"
  end
  
  r  = " -rneri"
  r += " -rneri/dxruby"       if @use_dxruby
  r += " -rneri/dxruby_tiled" if @use_dxruby_tiled
  r += " -rneri/ayame"        if @use_ayame
  
  ruby = to_winpath(relative_path(rubyexe, bindir))
  return %[#{ruby}#{r} #{@rubyopt} -e "# coding:utf-8" -e "#{ruby_code}" #{@args}]
end
ruby_dependencies() click to toggle source
# File lib/neri/build.rb, line 365
def ruby_dependencies()
  dependencies = Dir.glob(File.join(bindir, "**", "*.manifest"))
  dependencies.push(rubyexe)
  return dependencies.uniq
end
rubydir( ) click to toggle source
# File lib/neri/build.rb, line 87
def rubydir(   ); File.join(RbConfig::TOPDIR, ""); end
rubyexe( ) click to toggle source
# File lib/neri/build.rb, line 88
def rubyexe(   ); RbConfig.ruby; end
run() click to toggle source
# File lib/neri/build.rb, line 852
def run()
  check_options
  dependencies = check_dependencies
  copy_files(dependencies)
  create_datafile
  if options[:no_exe]
    create_batfile
  else
    options[:use_b2ec] ? bat_to_exe_converter : create_exefile
  end
  upx             if options[:use_upx]
  create_zipfile  if options[:zipfile]
  inno_setup      if options[:inno_script]
  nputs "Neri Finished."
end
scriptfile() click to toggle source
# File lib/neri/build.rb, line 89
def scriptfile(); @data_files.first; end
select_dependencies(dependencies) click to toggle source
# File lib/neri/build.rb, line 481
def select_dependencies(dependencies)
  dependencies.select! do |dependency|
    dependency.start_with?(rubydir)
  end
  
  @data_files.each do |file|
    dependencies.delete(File.expand_path(file))
  end
  
  unless options[:enable_gems]
    dependencies.delete_if do |dependency|
      File.basename(dependency) == "rubygems.rb" ||
      dependency.split(File::SEPARATOR).index("rubygems")
    end
  end
  unless options[:enable_did_you_mean]
    dependencies.delete_if do |dependency|
      File.basename(dependency) == "did_you_mean.rb" ||
      dependency.split(File::SEPARATOR).index("did_you_mean")
    end
  end
  
  return dependencies.uniq
end
to_winpath(path) click to toggle source
# File lib/neri/build.rb, line 82
def to_winpath(path)
  return File::ALT_SEPARATOR ? path.tr(File::SEPARATOR, File::ALT_SEPARATOR) : path
end
upx() click to toggle source
# File lib/neri/build.rb, line 767
def upx()
  unless system("#{options[:upx_path]} --version >nul 2>&1")
    error "UPX not found !"
    return
  end
  
  nputs "Compressing with UPX."
  options[:upx_targets].each do |target|
    Dir.glob(File.join(options[:output_dir], options[:system_dir], target)).each do |target_path|
      command = %("#{options[:upx_path]}" #{options[:upx_options]} "#{target_path}")
      nsystem command
    end
  end
end

Private Class Methods

adjust_path(path) click to toggle source
# File lib/neri/runtime.rb, line 118
def adjust_path(path)
  return path.sub(/^\.\//, "")
end
error(str) click to toggle source
# File lib/neri/build.rb, line 879
def error(str)
  puts "\e[31m#{str}\e[0m"
end
escape_cstr(str) click to toggle source
# File lib/neri/build.rb, line 887
def escape_cstr(str)
  str.gsub("\\"){ "\\\\" }.gsub('"'){ '\\"' }.gsub("'"){ "\\'" }
end
load_code(file) click to toggle source
# File lib/neri/runtime.rb, line 137
def load_code(file)
  code = file_read(file)
  encoding = "UTF-8"
  encoding = $1 if code.lines[0..2].join("\n").match(/coding:\s*(\S+)/)
  code.force_encoding(encoding)
  return code
end
load_path() click to toggle source
# File lib/neri/runtime.rb, line 132
def load_path()
  return $LOAD_PATH unless @system_dir
  return $LOAD_PATH.map{|path| path.sub(@system_dir, "*neri*#{File::SEPARATOR}") + File::SEPARATOR }
end
nputs(str) click to toggle source
# File lib/neri/build.rb, line 871
def nputs(str)
  puts "=== #{str}" unless options[:quiet]
end
nputs_v(str) click to toggle source
# File lib/neri/build.rb, line 875
def nputs_v(str)
  puts str if options[:verbose]
end
nsystem(str) click to toggle source
# File lib/neri/build.rb, line 891
def nsystem(str)
  nputs_v(str)
  command = str.encode(options[:external_encoding])
  return system(command + (options[:quiet] ? " >nul 2>&1" : ""))
end
read(length, offset) click to toggle source
# File lib/neri/runtime.rb, line 122
def read(length, offset)
  if @xor
    tmp_length = length
    tmp_length += BLOCK_LENGTH - length % BLOCK_LENGTH unless length % BLOCK_LENGTH == 0
    return xor(File.binread(@datafile, tmp_length, offset))[0, length]
  else
    return File.binread(@datafile, length, offset)
  end
end
unpack_filename(filename) click to toggle source
# File lib/neri/build.rb, line 883
def unpack_filename(filename)
  "[" + filename.unpack("U*").map { |u| u.to_s }.join(",") + "].pack('U*')"
end
xor(str) click to toggle source
# File lib/neri/runtime.rb, line 104
def xor(str)
  str.force_encoding(Encoding::BINARY)
  while str.bytesize % BLOCK_LENGTH != 0
    str << rand(256).chr
  end
  if defined?(Xorcist)
    return Xorcist.xor!(str, @xor * (str.bytesize / BLOCK_LENGTH))
  else
    s = []
    str.unpack("Q*").zip((@xor * (str.bytesize / BLOCK_LENGTH)).unpack("Q*")){|a, b| s.push(a ^ b)}
    return s.pack("Q*")
  end
end