neri 0.9.1 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/neri/ayame.rb +3 -6
- data/lib/neri/build.rb +279 -243
- data/lib/neri/dxruby.rb +18 -28
- data/lib/neri/dxruby_tiled.rb +1 -1
- data/lib/neri/runtime.rb +113 -95
- data/lib/neri/version.rb +1 -1
- data/neri.gemspec +3 -5
- metadata +5 -19
data/lib/neri/build.rb
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
2
|
|
4
3
|
require "neri"
|
5
4
|
|
6
5
|
module Neri
|
7
6
|
@data_files = []
|
8
|
-
|
7
|
+
|
9
8
|
@options = {
|
10
9
|
quiet: false,
|
11
10
|
verbose: false,
|
12
|
-
|
11
|
+
|
13
12
|
external_encoding: nil,
|
14
|
-
|
13
|
+
|
15
14
|
dlls: [],
|
16
15
|
libs: [],
|
17
16
|
gems: [],
|
18
17
|
encoding: "*",
|
19
|
-
|
18
|
+
|
20
19
|
enable_gems: false,
|
21
20
|
enable_did_you_mean: false,
|
22
|
-
chdir_first:
|
21
|
+
chdir_first: true,
|
23
22
|
pause_last: nil,
|
24
23
|
pause_text: nil,
|
25
|
-
|
24
|
+
|
26
25
|
output_dir: "./",
|
27
26
|
system_dir: "system",
|
28
|
-
|
27
|
+
|
29
28
|
datafile: nil,
|
30
29
|
encryption_key: nil,
|
31
|
-
|
30
|
+
virtual_directory: nil,
|
31
|
+
|
32
32
|
no_exe: false,
|
33
33
|
use_b2ec: false,
|
34
34
|
b2ec_path: "Bat_To_Exe_Converter",
|
35
35
|
b2ec: {
|
36
|
-
icon:
|
36
|
+
icon: File.expand_path("#{File.dirname(__FILE__)}/../../share/default.ico"),
|
37
37
|
invisible: nil,
|
38
38
|
x64: nil,
|
39
39
|
uac_admin: nil,
|
@@ -50,50 +50,49 @@ module Neri
|
|
50
50
|
specialbuild: nil,
|
51
51
|
comments: nil
|
52
52
|
},
|
53
|
-
|
53
|
+
|
54
54
|
use_upx: false,
|
55
55
|
upx_path: "upx",
|
56
56
|
upx_targets: ["bin/**/*.dll"],
|
57
57
|
upx_options: "",
|
58
|
-
|
58
|
+
|
59
59
|
zipfile: nil,
|
60
60
|
sevenzip_path: "7z",
|
61
|
-
|
61
|
+
|
62
62
|
inno_script: nil,
|
63
|
-
iscc_path: "iscc"
|
63
|
+
iscc_path: "iscc"
|
64
64
|
}
|
65
65
|
@rubyopt = ENV["RUBYOPT"].to_s
|
66
66
|
@args = ""
|
67
67
|
@encryption_key = nil
|
68
|
-
|
68
|
+
|
69
69
|
@use_dxruby = false
|
70
70
|
@use_dxruby_tiled = false
|
71
71
|
@use_ayame = false
|
72
|
-
|
72
|
+
|
73
73
|
class << self
|
74
|
-
|
75
74
|
attr_reader :options
|
76
|
-
|
77
|
-
def relative_path(path, basedir=rubydir, prepath = "")
|
75
|
+
|
76
|
+
def relative_path(path, basedir = rubydir, prepath = "")
|
78
77
|
basedir.concat(File::SEPARATOR) unless basedir.end_with?(File::SEPARATOR)
|
79
|
-
|
78
|
+
path.start_with?(basedir) ? path.sub(basedir, prepath) : path
|
80
79
|
end
|
81
|
-
|
80
|
+
|
82
81
|
def to_winpath(path)
|
83
|
-
|
82
|
+
File::ALT_SEPARATOR ? path.tr(File::SEPARATOR, File::ALT_SEPARATOR) : path
|
84
83
|
end
|
85
|
-
|
86
|
-
def bindir
|
87
|
-
def rubydir
|
88
|
-
def rubyexe
|
89
|
-
def scriptfile
|
90
|
-
def basename
|
91
|
-
def basepath
|
92
|
-
def datafile
|
93
|
-
|
84
|
+
|
85
|
+
def bindir ; RbConfig::CONFIG["bindir"] || File.join(rubydir, "bin"); end
|
86
|
+
def rubydir ; File.join(RbConfig::TOPDIR, ""); end
|
87
|
+
def rubyexe ; RbConfig.ruby; end
|
88
|
+
def scriptfile; @data_files.first; end
|
89
|
+
def basename ; File.basename(scriptfile, ".*"); end
|
90
|
+
def basepath ; File.join(options[:output_dir], basename); end
|
91
|
+
def datafile ; File.join(options[:output_dir], options[:system_dir], options[:datafile]); end
|
92
|
+
|
94
93
|
# --help
|
95
94
|
def output_help
|
96
|
-
puts <<-
|
95
|
+
puts <<-HELP_MESSAGE
|
97
96
|
usage: neri [options] script.rb (other_files...) -- script_arguments
|
98
97
|
|
99
98
|
options:
|
@@ -101,28 +100,28 @@ options:
|
|
101
100
|
--version or -v
|
102
101
|
--quiet
|
103
102
|
--verbose
|
104
|
-
|
103
|
+
|
105
104
|
--external-encoding <encoding>
|
106
|
-
|
105
|
+
|
107
106
|
--dll <dll1>,<dll2>,...
|
108
107
|
--lib <lib1>,<lib2>,...
|
109
108
|
--gem <gem1>,<gem2>,...
|
110
|
-
|
109
|
+
|
111
110
|
--no-enc
|
112
111
|
--encoding <enc1>,<enc2>,...
|
113
|
-
|
112
|
+
|
114
113
|
--enable-gems
|
115
114
|
--enable-did-you-mean
|
116
|
-
--chdir
|
115
|
+
--no-chdir
|
117
116
|
--pause-last
|
118
117
|
--no-pause-last
|
119
118
|
--pause-text <text>
|
120
|
-
|
119
|
+
|
121
120
|
--output-dir <dirname>
|
122
121
|
--system-dir <dirname>
|
123
122
|
--datafile <filename>
|
124
123
|
--encryption-key <key>
|
125
|
-
|
124
|
+
|
126
125
|
--no-exe
|
127
126
|
--use-b2ec
|
128
127
|
--b2ec-path <bat_to_exe_converter_path>
|
@@ -143,28 +142,29 @@ options:
|
|
143
142
|
--privatebuild <string>
|
144
143
|
--specialbuild <string>
|
145
144
|
--comments <string>
|
146
|
-
|
145
|
+
|
147
146
|
--use-upx
|
148
147
|
--upx-path <upx path>
|
149
148
|
--upx_targets '<glob>' # ex) 'bin/**/*.dll'
|
150
149
|
--upx-options <options>
|
151
|
-
|
150
|
+
|
152
151
|
--zipfile <filename>
|
153
152
|
--7zip-path <7-zip path>
|
154
|
-
|
153
|
+
|
155
154
|
--innosetup <inno_script>
|
156
155
|
--iscc-path <iscc path>
|
157
|
-
|
156
|
+
|
158
157
|
--create-recipe <recipefile>
|
159
158
|
--recipe <recipefile>
|
160
|
-
|
159
|
+
--virtual-directory <string>
|
160
|
+
HELP_MESSAGE
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
# --version
|
164
164
|
def output_version
|
165
165
|
puts "Neri #{Neri::VERSION}"
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
# --create-recipe
|
169
169
|
def create_recipe(file, hash = options, pre = "Neri.options")
|
170
170
|
hash.each_pair do |key, value|
|
@@ -180,8 +180,7 @@ options:
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
183
|
-
|
184
|
-
|
183
|
+
|
185
184
|
def check_options
|
186
185
|
nputs_v "Checking Neri options."
|
187
186
|
while arg = ARGV.shift
|
@@ -194,7 +193,7 @@ options:
|
|
194
193
|
exit
|
195
194
|
when "--quiet", "-q"
|
196
195
|
options[:quiet] = true
|
197
|
-
when "--verbose"
|
196
|
+
when "--verbose"
|
198
197
|
options[:verbose] = true
|
199
198
|
when "--external_encoding"
|
200
199
|
options[:external_encoding] = ARGV.shift
|
@@ -212,7 +211,9 @@ options:
|
|
212
211
|
options[:enable_gems] = true
|
213
212
|
when "--enable-did-you-mean"
|
214
213
|
options[:enable_did_you_mean] = true
|
215
|
-
when "--chdir
|
214
|
+
when "--no-chdir"
|
215
|
+
options[:chdir_first] = false
|
216
|
+
when "--chdir-first" # deprecated
|
216
217
|
options[:chdir_first] = true
|
217
218
|
when "--pause-last"
|
218
219
|
options[:pause_last] = true
|
@@ -278,7 +279,7 @@ options:
|
|
278
279
|
when "--upx-options"
|
279
280
|
options[:upx_options] = ARGV.shift
|
280
281
|
when "--zipfile"
|
281
|
-
options[:zipfile] = ARGV.shift.encode(
|
282
|
+
options[:zipfile] = "#{ARGV.shift.encode('utf-8').sub(/\.zip$/, '')}.zip"
|
282
283
|
when "--7zip-path"
|
283
284
|
options[:sevenzip_path] = ARGV.shift.encode("utf-8")
|
284
285
|
when "--innosetup"
|
@@ -289,12 +290,14 @@ options:
|
|
289
290
|
require "json"
|
290
291
|
filename = ARGV.shift.encode("utf-8")
|
291
292
|
nputs "Creating recipe_file '#{filename}'."
|
292
|
-
open(filename, "w:utf-8"){ |file| create_recipe(file) }
|
293
|
+
File.open(filename, "w:utf-8") { |file| create_recipe(file) }
|
293
294
|
exit
|
294
295
|
when "--recipe"
|
295
296
|
filename = ARGV.shift.encode("utf-8")
|
296
297
|
nputs_v "Loading recipe_file '#{filename}'."
|
297
298
|
load File.expand_path(filename)
|
299
|
+
when "--virtual-directory"
|
300
|
+
options[:virtual_directory] = ARGV.shift.encode("utf-8")
|
298
301
|
when "--"
|
299
302
|
break
|
300
303
|
when /^(--.+)/
|
@@ -305,116 +308,142 @@ options:
|
|
305
308
|
@data_files.push(arg.encode("utf-8"))
|
306
309
|
end
|
307
310
|
end
|
308
|
-
|
311
|
+
|
309
312
|
if @data_files.empty?
|
310
313
|
error "No Script File!"
|
311
314
|
output_help
|
312
315
|
exit
|
313
316
|
end
|
314
|
-
|
315
|
-
@args = ARGV.map{ |
|
316
|
-
@options[:external_encoding] ||= Encoding
|
317
|
-
unless options[:enable_gems]
|
318
|
-
@rubyopt += " --disable-gems"
|
317
|
+
|
318
|
+
@args = ARGV.map { |a| %( "#{a}") }.join("")
|
319
|
+
@options[:external_encoding] ||= Encoding.default_external.name
|
320
|
+
unless options[:enable_gems] || @rubyopt.index("--disable-gems")
|
321
|
+
@rubyopt += " --disable-gems"
|
319
322
|
end
|
320
|
-
unless options[:enable_did_you_mean]
|
321
|
-
@rubyopt += " --disable-did_you_mean"
|
323
|
+
unless options[:enable_did_you_mean] || @rubyopt.index("--disable-did_you_mean")
|
324
|
+
@rubyopt += " --disable-did_you_mean"
|
322
325
|
end
|
323
326
|
if @data_files.size > 1 || options[:encryption_key]
|
324
|
-
options[:datafile] ||= basename
|
327
|
+
options[:datafile] ||= "#{basename}.dat"
|
325
328
|
end
|
326
329
|
end
|
327
|
-
|
328
|
-
|
330
|
+
|
329
331
|
# check dependencies
|
330
|
-
def rb_dependencies
|
331
|
-
|
332
|
+
def rb_dependencies
|
333
|
+
$LOADED_FEATURES.uniq
|
332
334
|
end
|
333
|
-
|
334
|
-
def dll_dependencies
|
335
|
-
require "
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
335
|
+
|
336
|
+
def dll_dependencies
|
337
|
+
require "fiddle/import"
|
338
|
+
|
339
|
+
pointer_type = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
|
340
|
+
psapi = Fiddle.dlopen("psapi.dll")
|
341
|
+
kernel32 = Fiddle.dlopen("kernel32.dll")
|
342
|
+
enumprocessmodules = Fiddle::Function.new(
|
343
|
+
psapi["EnumProcessModules"],
|
344
|
+
[Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP],
|
345
|
+
Fiddle::TYPE_LONG,
|
346
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
347
|
+
)
|
348
|
+
getmodulefilename = Fiddle::Function.new(
|
349
|
+
kernel32["GetModuleFileNameW"],
|
350
|
+
[Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG],
|
351
|
+
Fiddle::TYPE_LONG,
|
352
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
353
|
+
)
|
354
|
+
getcurrentprocess = Fiddle::Function.new(
|
355
|
+
kernel32["GetCurrentProcess"],
|
356
|
+
[],
|
357
|
+
Fiddle::TYPE_LONG,
|
358
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
359
|
+
)
|
340
360
|
|
341
361
|
bytes_needed = 4 * 32
|
342
362
|
module_handle_buffer = nil
|
343
|
-
process_handle = getcurrentprocess.call
|
363
|
+
process_handle = getcurrentprocess.call
|
344
364
|
loop do
|
345
365
|
module_handle_buffer = "\x00" * bytes_needed
|
346
366
|
bytes_needed_buffer = [0].pack("I")
|
347
|
-
|
348
|
-
|
367
|
+
enumprocessmodules.call(
|
368
|
+
[process_handle].pack("I").unpack1("i"),
|
369
|
+
[module_handle_buffer].pack("p").unpack1(pointer_type),
|
370
|
+
[module_handle_buffer.size].pack("I").unpack1("i"),
|
371
|
+
[bytes_needed_buffer].pack("p").unpack1(pointer_type)
|
372
|
+
)
|
373
|
+
bytes_needed = bytes_needed_buffer.unpack1("I")
|
349
374
|
break if bytes_needed <= module_handle_buffer.size
|
350
375
|
end
|
351
376
|
|
352
377
|
handles = module_handle_buffer.unpack("I*")
|
353
378
|
dependencies = handles.select { |handle| handle > 0 }.map do |handle|
|
354
379
|
str = "\x00\x00" * 256
|
355
|
-
modulefilename_length = getmodulefilename.call(
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
dependencies.map!{|dep| dep.tr(File::ALT_SEPARATOR, File::SEPARATOR)}
|
380
|
+
modulefilename_length = getmodulefilename.call(
|
381
|
+
[handle].pack("I").unpack1("i"),
|
382
|
+
[str].pack("p").unpack1(pointer_type),
|
383
|
+
[str.size].pack("I").unpack1("i")
|
384
|
+
)
|
385
|
+
str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
|
362
386
|
end
|
387
|
+
|
388
|
+
dependencies.map! { |dep| dep.sub(/^\\\\\?\\/, "") }
|
389
|
+
dependencies.map! { |dep| dep.tr(File::ALT_SEPARATOR, File::SEPARATOR) } if File::ALT_SEPARATOR
|
363
390
|
dependencies.delete(rubyexe)
|
364
|
-
|
365
|
-
|
391
|
+
|
392
|
+
dependencies.uniq
|
366
393
|
end
|
367
|
-
|
368
|
-
def ruby_dependencies
|
394
|
+
|
395
|
+
def ruby_dependencies
|
369
396
|
dependencies = Dir.glob(File.join(bindir, "**", "*.manifest"))
|
370
397
|
dependencies.push(rubyexe)
|
371
|
-
|
398
|
+
dependencies.uniq
|
372
399
|
end
|
373
|
-
|
374
|
-
def additional_dlls_dependencies
|
400
|
+
|
401
|
+
def additional_dlls_dependencies
|
375
402
|
dependencies = []
|
376
403
|
options[:dlls].each do |dll|
|
377
404
|
dependencies += Dir.glob(File.join(bindir, "**", dll))
|
378
|
-
dependencies += Dir.glob(File.join(bindir, "**", dll
|
405
|
+
dependencies += Dir.glob(File.join(bindir, "**", "#{dll}.*"))
|
379
406
|
end
|
380
|
-
|
407
|
+
dependencies.uniq
|
381
408
|
end
|
382
|
-
|
383
|
-
def additional_libs_dependencies
|
409
|
+
|
410
|
+
def additional_libs_dependencies
|
384
411
|
dependencies = []
|
385
412
|
options[:libs].each do |lib|
|
386
413
|
$LOAD_PATH.each do |path|
|
387
414
|
dependencies += Dir.glob(File.join(path, lib))
|
388
|
-
dependencies += Dir.glob(File.join(path, lib
|
415
|
+
dependencies += Dir.glob(File.join(path, "#{lib}.*"))
|
389
416
|
dependencies += Dir.glob(File.join(path, lib, "**", "*"))
|
390
417
|
end
|
391
418
|
end
|
392
|
-
|
419
|
+
dependencies.uniq
|
393
420
|
end
|
394
|
-
|
395
|
-
def additional_gems_dependencies
|
421
|
+
|
422
|
+
def additional_gems_dependencies
|
396
423
|
require "rubygems"
|
397
424
|
dependencies = []
|
398
425
|
rubygems_dir = File.join(Gem.dir, "gems")
|
399
426
|
options[:gems].each do |gem|
|
400
|
-
gem.sub!(
|
401
|
-
targets =
|
427
|
+
gem.sub!(/:(.+)/, "")
|
428
|
+
targets = Regexp.last_match(1).to_s.split("|")
|
402
429
|
targets.push("lib/**/*")
|
403
430
|
gem += "-*" unless gem.match("-")
|
404
|
-
gemdir = Dir.glob(File.join(rubygems_dir, gem)).
|
431
|
+
gemdir = Dir.glob(File.join(rubygems_dir, gem)).max
|
405
432
|
next unless gemdir
|
433
|
+
|
406
434
|
targets.each do |target|
|
407
435
|
dependencies += Dir.glob(File.join(gemdir, target))
|
408
436
|
end
|
409
437
|
end
|
410
|
-
|
438
|
+
dependencies.uniq
|
411
439
|
end
|
412
|
-
|
413
|
-
def encoding_dependencies
|
440
|
+
|
441
|
+
def encoding_dependencies
|
414
442
|
return [] unless options[:encoding]
|
443
|
+
|
415
444
|
dependencies = []
|
416
445
|
enc_dir = Dir.glob(File.join(RbConfig::CONFIG["archdir"] || RbConfig::TOPDIR, "**", "enc")).first
|
417
|
-
|
446
|
+
|
418
447
|
options[:encoding].split(",").map(&:strip).each do |enc|
|
419
448
|
case enc
|
420
449
|
when "ja"
|
@@ -423,21 +452,21 @@ options:
|
|
423
452
|
end
|
424
453
|
else
|
425
454
|
dependencies += Dir.glob(File.join(enc_dir, "**", enc))
|
426
|
-
dependencies += Dir.glob(File.join(enc_dir, "**", enc
|
455
|
+
dependencies += Dir.glob(File.join(enc_dir, "**", "#{enc}.*"))
|
427
456
|
end
|
428
457
|
end
|
429
|
-
|
430
|
-
|
458
|
+
|
459
|
+
dependencies.uniq
|
431
460
|
end
|
432
|
-
|
433
|
-
def check_dependencies
|
461
|
+
|
462
|
+
def check_dependencies
|
434
463
|
nputs "Running script '#{scriptfile}' to check dependencies."
|
435
464
|
begin
|
436
465
|
load File.expand_path(scriptfile)
|
437
466
|
rescue SystemExit, Interrupt
|
438
467
|
end
|
439
468
|
nputs "Script '#{scriptfile}' end."
|
440
|
-
|
469
|
+
|
441
470
|
if defined? DXRuby
|
442
471
|
require "neri/dxruby"
|
443
472
|
@use_dxruby = true
|
@@ -450,15 +479,15 @@ options:
|
|
450
479
|
require "neri/ayame"
|
451
480
|
@use_ayame = true
|
452
481
|
end
|
453
|
-
|
454
|
-
if options[:b2ec][:invisible]
|
482
|
+
|
483
|
+
if options[:b2ec][:invisible].nil? &&
|
455
484
|
(File.extname(scriptfile) == ".rbw" || @use_dxruby)
|
456
485
|
options[:b2ec][:invisible] = true
|
457
486
|
end
|
458
|
-
if options[:pause_last]
|
459
|
-
options[:pause_last] = true
|
487
|
+
if options[:pause_last].nil? && !options[:b2ec][:invisible]
|
488
|
+
options[:pause_last] = true
|
460
489
|
end
|
461
|
-
|
490
|
+
|
462
491
|
require "rbconfig"
|
463
492
|
dependencies = []
|
464
493
|
dependencies += rb_dependencies
|
@@ -469,59 +498,58 @@ options:
|
|
469
498
|
dependencies += additional_gems_dependencies
|
470
499
|
dependencies += encoding_dependencies
|
471
500
|
dependencies = select_dependencies(dependencies)
|
472
|
-
|
473
|
-
size = dependencies.map{|d| File.size(d)}.inject(&:+)
|
501
|
+
|
502
|
+
size = dependencies.map { |d| File.size(d) }.inject(&:+)
|
474
503
|
nputs "#{dependencies.size} files, #{size} bytes dependencies."
|
475
504
|
if options[:verbose]
|
476
505
|
dependencies.each do |dependency|
|
477
506
|
nputs_v " - #{dependency}"
|
478
507
|
end
|
479
508
|
end
|
480
|
-
|
481
|
-
|
509
|
+
|
510
|
+
dependencies
|
482
511
|
end
|
483
|
-
|
512
|
+
|
484
513
|
def select_dependencies(dependencies)
|
485
514
|
dependencies.select! do |dependency|
|
486
515
|
dependency.start_with?(rubydir)
|
487
516
|
end
|
488
|
-
|
517
|
+
|
489
518
|
@data_files.each do |file|
|
490
519
|
dependencies.delete(File.expand_path(file))
|
491
520
|
end
|
492
|
-
|
521
|
+
|
493
522
|
unless options[:enable_gems]
|
494
523
|
dependencies.delete_if do |dependency|
|
495
524
|
File.basename(dependency) == "rubygems.rb" ||
|
496
|
-
|
525
|
+
dependency.split(File::SEPARATOR).index("rubygems")
|
497
526
|
end
|
498
527
|
end
|
499
528
|
unless options[:enable_did_you_mean]
|
500
529
|
dependencies.delete_if do |dependency|
|
501
530
|
File.basename(dependency) == "did_you_mean.rb" ||
|
502
|
-
|
531
|
+
dependency.split(File::SEPARATOR).index("did_you_mean")
|
503
532
|
end
|
504
533
|
end
|
505
|
-
|
506
|
-
|
534
|
+
|
535
|
+
dependencies.uniq
|
507
536
|
end
|
508
|
-
|
509
|
-
|
537
|
+
|
510
538
|
def copy_files(dependencies)
|
511
539
|
nputs "Copying dependencies."
|
512
540
|
require "fileutils"
|
513
541
|
src_dir = rubydir
|
514
542
|
desc_dir = File.join(options[:output_dir], options[:system_dir], "")
|
515
|
-
|
543
|
+
|
516
544
|
system_files = dependencies.map do |file|
|
517
545
|
[file, file.sub(src_dir, desc_dir)]
|
518
546
|
end
|
519
547
|
unless options[:enable_gems]
|
520
|
-
system_files.each do |
|
521
|
-
desc.sub!(
|
548
|
+
system_files.each do |_src, desc|
|
549
|
+
desc.sub!(%r{/gems(/\d+\.\d+\.\d+/)gems/(.+?)-[^/]+/lib/}, "/vendor_ruby\\1")
|
522
550
|
end
|
523
551
|
end
|
524
|
-
|
552
|
+
|
525
553
|
system_files.each do |src, desc|
|
526
554
|
FileUtils.makedirs(File.dirname(desc))
|
527
555
|
if File.file?(src)
|
@@ -531,49 +559,62 @@ options:
|
|
531
559
|
end
|
532
560
|
FileUtils.copy(scriptfile, desc_dir) unless options[:datafile]
|
533
561
|
end
|
534
|
-
|
535
|
-
|
536
|
-
def create_datafile()
|
537
|
-
if @data_files.size > 1 || options[:encryption_key]
|
538
|
-
options[:datafile] ||= basename + ".dat"
|
539
|
-
end
|
562
|
+
|
563
|
+
def create_datafile
|
540
564
|
return unless options[:datafile]
|
541
|
-
|
565
|
+
|
542
566
|
nputs "Creating datafile '#{datafile}'."
|
543
567
|
data_files = @data_files.select { |file| File.file? file }
|
544
568
|
@data_files.select { |file| File.directory? file }.each do |dir|
|
545
|
-
data_files += Dir.glob(dir
|
569
|
+
data_files += Dir.glob("#{dir}/**/*").select { |file| File.file? file }
|
546
570
|
end
|
571
|
+
data_files.uniq! { |file| File.expand_path(file) }
|
572
|
+
|
573
|
+
unless options[:virtual_directory]
|
574
|
+
dir_pwd = Dir.pwd.encode(Encoding::UTF_8)
|
575
|
+
virtual_directories = Pathname.new(dir_pwd).ascend.to_a.map(&:to_s)
|
576
|
+
data_files.each do |file|
|
577
|
+
fullpath = File.expand_path(file)
|
578
|
+
next if fullpath.start_with?(rubydir) || Pathname.new(file).absolute?
|
579
|
+
virtual_directories.shift until fullpath.start_with?(virtual_directories.first)
|
580
|
+
end
|
581
|
+
options[:virtual_directory] = relative_path(dir_pwd, virtual_directories.first, "/_neri_virtual_directory_/")
|
582
|
+
puts "virtual_directory: #{options[:virtual_directory]}"
|
583
|
+
end
|
584
|
+
|
547
585
|
if options[:encryption_key]
|
548
586
|
require "digest/sha2"
|
549
587
|
@encryption_key = Digest::SHA2.hexdigest(options[:encryption_key])
|
550
588
|
end
|
551
589
|
Neri.key = @encryption_key || "0" * 64
|
552
|
-
open(datafile, "wb") do |f|
|
590
|
+
File.open(datafile, "wb") do |f|
|
553
591
|
pos = 0
|
554
|
-
|
555
|
-
|
556
|
-
filename =
|
557
|
-
|
558
|
-
|
592
|
+
file_informations = data_files.map do |file|
|
593
|
+
fullpath = File.expand_path(file)
|
594
|
+
filename = if fullpath.start_with?(rubydir)
|
595
|
+
relative_path(fullpath, rubydir, "#{options[:system_dir]}#{File::SEPARATOR}")
|
596
|
+
else
|
597
|
+
file
|
598
|
+
end
|
599
|
+
filedata = [filename, File.size(file), pos].join("\t")
|
600
|
+
nputs_v " - #{filename}:#{File.size(file)} bytes"
|
559
601
|
pos += File.size(file)
|
560
602
|
pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
f.write(
|
603
|
+
filedata
|
604
|
+
end
|
605
|
+
files_str = file_informations.join("\n").encode(Encoding::UTF_8)
|
606
|
+
|
607
|
+
f.write(format("%#{BLOCK_LENGTH}d", files_str.bytesize))
|
566
608
|
f.write(xor(files_str))
|
567
609
|
data_files.each do |file|
|
568
610
|
f.write(xor(File.binread(file)))
|
569
611
|
end
|
570
612
|
end
|
571
613
|
end
|
572
|
-
|
573
|
-
|
574
|
-
def create_batfile()
|
614
|
+
|
615
|
+
def create_batfile
|
575
616
|
nputs "Creating batch_file '#{basepath}.bat'."
|
576
|
-
|
617
|
+
|
577
618
|
pause_command = ""
|
578
619
|
if options[:pause_last]
|
579
620
|
pause_command += "echo.\n"
|
@@ -585,37 +626,37 @@ options:
|
|
585
626
|
end
|
586
627
|
end
|
587
628
|
chdir = options[:chdir_first] ? 'cd /d "%~dp0"' : ""
|
588
|
-
|
589
|
-
open(basepath
|
590
|
-
f.puts <<-
|
629
|
+
|
630
|
+
File.open("#{basepath}.bat", "w:#{options[:external_encoding]}") do |f|
|
631
|
+
f.puts <<-BATCH
|
591
632
|
@echo off
|
592
633
|
setlocal
|
593
634
|
set PATH=%~dp0#{options[:system_dir]}\\#{relative_path(bindir)};%PATH%
|
594
635
|
set NERI_EXECUTABLE=%~0
|
595
636
|
#{chdir}
|
596
637
|
if %~x0 == .exe ( shift )
|
597
|
-
#{ruby_command(options[:chdir_first] ?
|
638
|
+
#{ruby_command(options[:chdir_first] ? '' : '%~dp0')} %1 %2 %3 %4 %5 %6 %7 %8 %9
|
598
639
|
#{pause_command}
|
599
640
|
endlocal
|
600
|
-
|
641
|
+
BATCH
|
601
642
|
end
|
602
643
|
end
|
603
|
-
|
604
|
-
def create_exefile
|
644
|
+
|
645
|
+
def create_exefile
|
605
646
|
unless system("gcc --version >nul 2>&1 && windres --version >nul 2>&1")
|
606
647
|
error "gcc or windres not found !"
|
607
648
|
create_batfile
|
608
649
|
return
|
609
650
|
end
|
610
|
-
|
611
|
-
exe_file = to_winpath(basepath
|
612
|
-
c_file = to_winpath(basepath
|
613
|
-
o_file = to_winpath(basepath
|
614
|
-
rc_file = to_winpath(basepath
|
651
|
+
|
652
|
+
exe_file = to_winpath("#{basepath}.exe" )
|
653
|
+
c_file = to_winpath("#{basepath}_tmp.c" )
|
654
|
+
o_file = to_winpath("#{basepath}_tmp.o" )
|
655
|
+
rc_file = to_winpath("#{basepath}_tmp.rc")
|
615
656
|
system_dir = escape_cstr(to_winpath(File.join(options[:system_dir], "")))
|
616
657
|
nputs "Creating exe_file '#{exe_file}'."
|
617
|
-
open(c_file, "w:#{options[:external_encoding]}") do |f|
|
618
|
-
f.puts <<-
|
658
|
+
File.open(c_file, "w:#{options[:external_encoding]}") do |f|
|
659
|
+
f.puts <<-CFILE
|
619
660
|
#include <stdio.h>
|
620
661
|
#include <stdlib.h>
|
621
662
|
#include <windows.h>
|
@@ -623,17 +664,17 @@ endlocal
|
|
623
664
|
|
624
665
|
int main(int argc, char *argv[])
|
625
666
|
{
|
626
|
-
char exepath[_MAX_PATH * 2 + 1],
|
667
|
+
char exepath[_MAX_PATH * 2 + 1],
|
627
668
|
drive [_MAX_DRIVE + 1],
|
628
669
|
dir [_MAX_DIR * 2 + 1],
|
629
670
|
fname [_MAX_FNAME * 2 + 1],
|
630
671
|
ext [_MAX_EXT * 2 + 1],
|
631
672
|
paths [_MAX_PATH * 32 + 1],
|
632
673
|
runruby[_MAX_PATH * 32 + 1];
|
633
|
-
PROCESS_INFORMATION pi;
|
674
|
+
PROCESS_INFORMATION pi;
|
634
675
|
STARTUPINFO si;
|
635
676
|
ZeroMemory(&si, sizeof(STARTUPINFO));
|
636
|
-
|
677
|
+
|
637
678
|
if(GetModuleFileName(NULL, exepath, MAX_PATH * 2) != 0){
|
638
679
|
_splitpath_s(exepath, drive, _MAX_DRIVE, dir, _MAX_DIR * 2, fname, _MAX_FNAME * 2, ext, _MAX_EXT * 2);
|
639
680
|
} else {
|
@@ -644,8 +685,8 @@ int main(int argc, char *argv[])
|
|
644
685
|
snprintf(paths, sizeof(paths), "PATH=%s%s#{system_dir}bin;%s", drive, dir, getenv("PATH"));
|
645
686
|
putenv(paths);
|
646
687
|
#{options[:chdir_first] ? 'snprintf(paths, sizeof(paths), "%s%s", drive, dir);chdir(paths);' : ''}
|
647
|
-
snprintf(runruby, sizeof(runruby), "#{escape_cstr(ruby_command(options[:chdir_first] ?
|
648
|
-
#{options[:chdir_first] ?
|
688
|
+
snprintf(runruby, sizeof(runruby), "#{escape_cstr(ruby_command(options[:chdir_first] ? '' : '%s%s'))} %s %s %s %s %s %s %s %s %s",
|
689
|
+
#{options[:chdir_first] ? '' : 'drive, dir,'}
|
649
690
|
argc > 1 ? argv[1] : "",
|
650
691
|
argc > 2 ? argv[2] : "",
|
651
692
|
argc > 3 ? argv[3] : "",
|
@@ -656,7 +697,7 @@ int main(int argc, char *argv[])
|
|
656
697
|
argc > 8 ? argv[8] : "",
|
657
698
|
argc > 9 ? argv[9] : ""
|
658
699
|
);
|
659
|
-
|
700
|
+
CFILE
|
660
701
|
if options[:b2ec][:invisible]
|
661
702
|
f.puts %[ CreateProcess(NULL, runruby, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);]
|
662
703
|
else
|
@@ -673,14 +714,14 @@ int main(int argc, char *argv[])
|
|
673
714
|
end
|
674
715
|
f.puts " return 0;\n}"
|
675
716
|
end
|
676
|
-
|
677
|
-
open(rc_file, "w:#{options[:external_encoding]}") do |f|
|
678
|
-
f.puts <<-
|
717
|
+
|
718
|
+
File.open(rc_file, "w:#{options[:external_encoding]}") do |f|
|
719
|
+
f.puts <<-RCFILE
|
679
720
|
#include <winver.h>
|
680
721
|
|
681
722
|
1 VERSIONINFO
|
682
|
-
#{options[:b2ec][:fileversion ] ? "FILEVERSION
|
683
|
-
#{options[:b2ec][:productversion] ? "PRODUCTVERSION
|
723
|
+
#{options[:b2ec][:fileversion ] ? "FILEVERSION #{escape_cstr(options[:b2ec][:fileversion ])}" : ""}
|
724
|
+
#{options[:b2ec][:productversion] ? "PRODUCTVERSION #{escape_cstr(options[:b2ec][:productversion])}" : ""}
|
684
725
|
FILETYPE VFT_APP
|
685
726
|
BEGIN
|
686
727
|
BLOCK "StringFileInfo"
|
@@ -709,36 +750,38 @@ BEGIN
|
|
709
750
|
END
|
710
751
|
|
711
752
|
2 ICON "#{escape_cstr(options[:b2ec][:icon])}"
|
712
|
-
|
753
|
+
RCFILE
|
713
754
|
end
|
714
|
-
nsystem(%
|
715
|
-
nsystem(%
|
716
|
-
nsystem(%
|
755
|
+
nsystem(%(windres -o "#{o_file}" "#{rc_file}"))
|
756
|
+
nsystem(%(gcc#{options[:b2ec][:invisible] ? ' -mwindows' : ''} -o "#{exe_file}" "#{c_file}" "#{o_file}"))
|
757
|
+
nsystem(%(strip "#{exe_file}"))
|
717
758
|
File.delete(c_file, rc_file, o_file)
|
718
759
|
end
|
719
|
-
|
760
|
+
|
720
761
|
def ruby_command(path)
|
721
|
-
system_dir = "#{path}#{File.join(options[:system_dir],
|
762
|
+
system_dir = "#{path}#{File.join(options[:system_dir], '')}"
|
722
763
|
ruby_code = ""
|
723
764
|
ruby_code = "Neri.key='#{@encryption_key}';" if @encryption_key
|
724
765
|
if options[:datafile]
|
725
766
|
ruby_code += "Neri.datafile='#{system_dir}' + #{unpack_filename(options[:datafile])};"
|
767
|
+
if options[:virtual_directory]
|
768
|
+
ruby_code += "Neri.virtual_directory=#{unpack_filename(options[:virtual_directory])};"
|
769
|
+
end
|
726
770
|
ruby_code += "load #{unpack_filename(File.basename(scriptfile))}"
|
727
771
|
else
|
728
772
|
ruby_code += "load File.expand_path('#{system_dir}' + #{unpack_filename(scriptfile)})"
|
729
773
|
end
|
730
|
-
|
774
|
+
|
731
775
|
r = " -rneri"
|
732
776
|
r += " -rneri/dxruby" if @use_dxruby
|
733
777
|
r += " -rneri/dxruby_tiled" if @use_dxruby_tiled
|
734
778
|
r += " -rneri/ayame" if @use_ayame
|
735
|
-
|
779
|
+
|
736
780
|
ruby = to_winpath(relative_path(rubyexe, bindir))
|
737
|
-
|
781
|
+
%(#{ruby}#{r} #{@rubyopt} -e "# coding:utf-8" -e "#{ruby_code}" #{@args})
|
738
782
|
end
|
739
|
-
|
740
|
-
|
741
|
-
def bat_to_exe_converter()
|
783
|
+
|
784
|
+
def bat_to_exe_converter
|
742
785
|
create_batfile
|
743
786
|
begin
|
744
787
|
`#{options[:b2ec_path]} /help`
|
@@ -746,36 +789,32 @@ END
|
|
746
789
|
error "Bat To Exe Converter not found !"
|
747
790
|
return
|
748
791
|
end
|
749
|
-
|
750
|
-
batch_file = basepath
|
751
|
-
exe_file = basepath
|
792
|
+
|
793
|
+
batch_file = "#{basepath}.bat"
|
794
|
+
exe_file = "#{basepath}.exe"
|
752
795
|
nputs "Creating exe_file '#{exe_file}' with Bat To Exe Converter."
|
753
796
|
File.delete(exe_file) if File.exist?(exe_file)
|
754
|
-
if options[:b2ec][:x64]
|
755
|
-
options[:b2ec][:x64] = true
|
797
|
+
if options[:b2ec][:x64].nil? && RbConfig::CONFIG["target"].to_s.index("64")
|
798
|
+
options[:b2ec][:x64] = true
|
756
799
|
end
|
757
|
-
args = %
|
758
|
-
args += options[:b2ec].map{|key, value|
|
800
|
+
args = %( /bat "#{batch_file}" /exe "#{exe_file}")
|
801
|
+
args += options[:b2ec].map { |key, value|
|
759
802
|
case value
|
760
|
-
when String
|
761
|
-
when true
|
762
|
-
else;
|
803
|
+
when String then %( /#{key.to_s.tr('_', '-')} "#{value}")
|
804
|
+
when true then %( /#{key.to_s.tr('_', '-')})
|
805
|
+
else; %()
|
763
806
|
end
|
764
807
|
}.join("")
|
765
|
-
|
766
|
-
|
767
|
-
unless nsystem "#{options[:b2ec_path]}#{args}"
|
768
|
-
error "Failed to create exe_file !"
|
769
|
-
end
|
808
|
+
|
809
|
+
error "Failed to create exe_file !" unless nsystem "#{options[:b2ec_path]}#{args}"
|
770
810
|
end
|
771
|
-
|
772
|
-
|
773
|
-
def upx()
|
811
|
+
|
812
|
+
def upx
|
774
813
|
unless system("#{options[:upx_path]} --version >nul 2>&1")
|
775
814
|
error "UPX not found !"
|
776
815
|
return
|
777
816
|
end
|
778
|
-
|
817
|
+
|
779
818
|
nputs "Compressing with UPX."
|
780
819
|
options[:upx_targets].each do |target|
|
781
820
|
Dir.glob(File.join(options[:output_dir], options[:system_dir], target)).each do |target_path|
|
@@ -784,78 +823,76 @@ END
|
|
784
823
|
end
|
785
824
|
end
|
786
825
|
end
|
787
|
-
|
788
|
-
|
789
|
-
def create_zipfile()
|
826
|
+
|
827
|
+
def create_zipfile
|
790
828
|
unless system("#{options[:sevenzip_path]} >nul 2>&1")
|
791
829
|
error "7-Zip not found !"
|
792
830
|
return
|
793
831
|
end
|
794
|
-
|
832
|
+
|
795
833
|
nputs "Creating zip_file '#{options[:zipfile]}'."
|
796
834
|
File.delete(options[:zipfile]) if File.exist?(options[:zipfile])
|
797
835
|
files = []
|
798
836
|
if options[:output_dir] == "./"
|
799
837
|
files.push(options[:system_dir])
|
800
|
-
files.push(File.exist?(basepath
|
838
|
+
files.push(File.exist?("#{basepath}.exe") ? "#{basepath}.exe" : "#{basepath}.bat")
|
801
839
|
else
|
802
840
|
files.push(options[:output_dir])
|
803
841
|
end
|
804
842
|
command = %("#{options[:sevenzip_path]}" a "#{options[:zipfile]}" "#{files.join('" "')}")
|
805
843
|
nsystem command
|
806
844
|
end
|
807
|
-
|
808
|
-
|
809
|
-
def inno_setup()
|
845
|
+
|
846
|
+
def inno_setup
|
810
847
|
unless system("#{options[:iscc_path]} /? >nul 2>&1")
|
811
848
|
error("Inno Setup not found !")
|
812
849
|
return
|
813
850
|
end
|
814
|
-
|
851
|
+
|
815
852
|
filename = options[:inno_script]
|
816
853
|
nputs "Creating Installer '#{filename}'."
|
817
854
|
script = "[Setup]\n"
|
818
855
|
if File.exist?(filename)
|
819
856
|
script = File.read(filename, encoding: Encoding::UTF_8)
|
820
|
-
filename = File.basename(filename,
|
857
|
+
filename = "#{File.basename(filename, '.*')}_tmp#{File.extname(filename)}"
|
821
858
|
end
|
822
|
-
|
859
|
+
|
823
860
|
version = options[:b2ec][:productversion] || options[:b2ec][:fileversion]
|
824
861
|
if !script.match(/^AppName=/) && options[:b2ec][:productname]
|
825
|
-
script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppName=#{options[:b2ec][:productname]}#{$2}" }
|
862
|
+
script.sub!(/^(\[Setup\])(\s+)/i) { "#{$1}\nAppName=#{options[:b2ec][:productname]}#{$2}" }
|
826
863
|
end
|
827
864
|
if !script.match(/^AppVersion=/) && version
|
828
|
-
script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppVersion=#{version}#{$2}" }
|
865
|
+
script.sub!(/^(\[Setup\])(\s+)/i) { "#{$1}\nAppVersion=#{version}#{$2}" }
|
829
866
|
end
|
830
867
|
if !script.match(/^AppVerName=/) && options[:b2ec][:productname] && version
|
831
|
-
script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppVerName=#{options[:b2ec][:productname]} #{version}#{$2}" }
|
868
|
+
script.sub!(/^(\[Setup\])(\s+)/i) { "#{$1}\nAppVerName=#{options[:b2ec][:productname]} #{version}#{$2}" }
|
832
869
|
end
|
833
870
|
if !script.match(/^AppPublisher=/) && options[:b2ec][:company]
|
834
|
-
script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppPublisher=#{options[:b2ec][:company]}#{$2}" }
|
871
|
+
script.sub!(/^(\[Setup\])(\s+)/i) { "#{$1}\nAppPublisher=#{options[:b2ec][:company]}#{$2}" }
|
835
872
|
end
|
836
873
|
if !script.match(/^AppCopyright=/) && options[:b2ec][:copyright]
|
837
|
-
script.sub!(/^(\[Setup\])(\s+)/i){ "#{$1}\nAppCopyright=#{options[:b2ec][:copyright]}#{$2}" }
|
874
|
+
script.sub!(/^(\[Setup\])(\s+)/i) { "#{$1}\nAppCopyright=#{options[:b2ec][:copyright]}#{$2}" }
|
838
875
|
end
|
839
|
-
|
876
|
+
|
840
877
|
script += "\n[Files]\n" unless script.match(/^\[Files\]/)
|
841
878
|
dir = File.expand_path(options[:output_dir])
|
842
879
|
files_str = ""
|
843
880
|
Dir.glob(File.join(dir, "**", "*")).each do |file|
|
844
881
|
next unless File.file? file
|
882
|
+
|
845
883
|
dist_dir = to_winpath(File::SEPARATOR + File.dirname(relative_path(file, dir)))
|
846
884
|
dist_dir = "" if dist_dir == "\\."
|
847
885
|
files_str += "\nSource: \"#{to_winpath(file)}\"; DistDir: \"{app}#{dist_dir}"
|
848
886
|
files_str += "; Flags: isreadme" if File.basename(file).match(/^readme/i)
|
849
887
|
end
|
850
|
-
script.sub!(/^(\[Files\])(\s*)/i){ "#{$1}#{files_str}#{$2}" }
|
851
|
-
|
888
|
+
script.sub!(/^(\[Files\])(\s*)/i) { "#{$1}#{files_str}#{$2}" }
|
889
|
+
|
852
890
|
File.write(filename, script)
|
853
891
|
command = %(#{options[:iscc_path]} "#{filename}")
|
854
892
|
nsystem command
|
855
893
|
end
|
856
|
-
|
857
|
-
|
858
|
-
def run()
|
894
|
+
|
895
|
+
def run
|
859
896
|
check_options
|
860
897
|
dependencies = check_dependencies
|
861
898
|
copy_files(dependencies)
|
@@ -870,34 +907,33 @@ END
|
|
870
907
|
inno_setup if options[:inno_script]
|
871
908
|
nputs "Neri Finished."
|
872
909
|
end
|
873
|
-
|
874
910
|
|
875
911
|
private
|
876
|
-
|
912
|
+
|
877
913
|
def nputs(str)
|
878
914
|
puts "=== #{str}" unless options[:quiet]
|
879
915
|
end
|
880
|
-
|
916
|
+
|
881
917
|
def nputs_v(str)
|
882
918
|
puts str if options[:verbose]
|
883
919
|
end
|
884
|
-
|
920
|
+
|
885
921
|
def error(str)
|
886
922
|
puts "\e[31m#{str}\e[0m"
|
887
923
|
end
|
888
|
-
|
924
|
+
|
889
925
|
def unpack_filename(filename)
|
890
|
-
"[
|
926
|
+
"[#{filename.unpack('U*').map(&:to_s).join(',')}].pack('U*')"
|
891
927
|
end
|
892
|
-
|
928
|
+
|
893
929
|
def escape_cstr(str)
|
894
|
-
str.gsub("\\"){ "\\\\" }.gsub('"'){ '\\"' }.gsub("'"){ "\\'" }
|
930
|
+
str.gsub("\\") { "\\\\" }.gsub('"') { '\\"' }.gsub("'") { "\\'" }
|
895
931
|
end
|
896
|
-
|
932
|
+
|
897
933
|
def nsystem(str)
|
898
934
|
nputs_v(str)
|
899
935
|
command = str.encode(options[:external_encoding])
|
900
|
-
|
936
|
+
system(command + (options[:quiet] ? " >nul 2>&1" : ""))
|
901
937
|
end
|
902
938
|
end
|
903
939
|
end
|