ocran 1.3.14 → 1.3.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/ocran +185 -161
- data/lib/ocran/version.rb +2 -2
- data/share/ocran/edicon.exe +0 -0
- data/share/ocran/empty-msys-2.0.dll +0 -0
- data/share/ocran/stub.exe +0 -0
- data/share/ocran/stubw.exe +0 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a782f6a9d0c148e6270aa19573c86e5f6518e9511bcfda3aec59de84a1291e41
|
4
|
+
data.tar.gz: 4eff772bc2997a4a99d08ea925c9e9d2eb0e8a1da48c687588dbf7c46d3d3453
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f94bc970689b64b199584baa2ee27f5f371ba6220b3fd736ef24314ab49644eb21932ba2e9397add861bfc609da6b5e4d0be5e45a6804a8bcf64057a1c51978
|
7
|
+
data.tar.gz: b881a6a9f0832490a5875360531e367b0f6efb008b2c8f94c54815fb63885f5350a19c40800f13da70fe714607ee774fd2a4e598373318d2b15a2b4b6fb9fc75
|
data/bin/ocran
CHANGED
@@ -15,6 +15,16 @@ module Ocran
|
|
15
15
|
a.downcase == b.downcase
|
16
16
|
end
|
17
17
|
|
18
|
+
def Pathname.glob(pattern, flags = 0)
|
19
|
+
if block_given?
|
20
|
+
Dir.glob(pattern, flags) { |s| yield Pathname.new(s) }
|
21
|
+
else
|
22
|
+
ary = Dir.glob(pattern, flags)
|
23
|
+
ary.map! { |s| Pathname.new(s) }
|
24
|
+
ary
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
18
28
|
attr_reader :path
|
19
29
|
if File::ALT_SEPARATOR.nil?
|
20
30
|
File::ALT_SEPARATOR = "\\"
|
@@ -23,7 +33,7 @@ module Ocran
|
|
23
33
|
ABSOLUTE_PAT = /\A([A-Z]:)?#{SEPARATOR_PAT}/i
|
24
34
|
|
25
35
|
def initialize(path)
|
26
|
-
@path = path
|
36
|
+
@path = path.encode("UTF-8")
|
27
37
|
end
|
28
38
|
|
29
39
|
def to_native
|
@@ -39,20 +49,20 @@ module Ocran
|
|
39
49
|
# be reached from 'src'.
|
40
50
|
def relative_path_from(other)
|
41
51
|
a = @path.split(SEPARATOR_PAT)
|
42
|
-
b = other.
|
52
|
+
b = other.to_s.split(SEPARATOR_PAT)
|
43
53
|
while a.first && b.first && Pathname.pathequal(a.first, b.first)
|
44
54
|
a.shift
|
45
55
|
b.shift
|
46
56
|
end
|
47
|
-
return other if Pathname.new(b.first).absolute?
|
57
|
+
return other if b.first && Pathname.new(b.first).absolute?
|
48
58
|
b.size.times { a.unshift ".." }
|
49
|
-
|
59
|
+
Pathname.new(File.join(*a))
|
50
60
|
end
|
51
61
|
|
52
62
|
# Determines if 'src' is contained in 'tgt' (i.e. it is a subpath of
|
53
63
|
# 'tgt'). Both must be absolute paths and not contain '..'
|
54
64
|
def subpath?(other)
|
55
|
-
other =
|
65
|
+
other = Pathname.new(other)
|
56
66
|
src_normalized = to_posix.downcase
|
57
67
|
tgt_normalized = other.to_posix.downcase
|
58
68
|
src_normalized =~ /^#{Regexp.escape tgt_normalized}#{SEPARATOR_PAT}/i
|
@@ -62,37 +72,49 @@ module Ocran
|
|
62
72
|
# is an absolute path. Otherwise, returns the full path of the
|
63
73
|
# left + right.
|
64
74
|
def /(other)
|
65
|
-
other =
|
75
|
+
other = Pathname.new(other)
|
66
76
|
if other.absolute?
|
67
77
|
other
|
68
78
|
else
|
69
|
-
|
79
|
+
Pathname.new(File.join(@path, other.to_s))
|
70
80
|
end
|
71
81
|
end
|
72
82
|
|
73
83
|
def append_to_filename!(s)
|
74
|
-
@path
|
84
|
+
@path = sub(/(\.[^.]*?|)$/) { s.to_s + $1 }
|
85
|
+
end
|
86
|
+
|
87
|
+
def sub(*a, &b)
|
88
|
+
Pathname.new(@path.sub(*a, &b))
|
89
|
+
end
|
90
|
+
|
91
|
+
def sub_ext(new_ext)
|
92
|
+
sub(/(\.[^.]*?)?$/, new_ext)
|
93
|
+
end
|
94
|
+
|
95
|
+
def extname
|
96
|
+
File.extname(@path)
|
75
97
|
end
|
76
98
|
|
77
99
|
def ext(new_ext = nil)
|
78
100
|
if new_ext
|
79
|
-
|
101
|
+
sub_ext(new_ext)
|
80
102
|
else
|
81
|
-
|
103
|
+
extname
|
82
104
|
end
|
83
105
|
end
|
84
106
|
|
85
107
|
def ext?(expected_ext)
|
86
|
-
Pathname.pathequal(
|
108
|
+
Pathname.pathequal(extname, expected_ext)
|
87
109
|
end
|
88
110
|
|
89
111
|
def entries
|
90
|
-
Dir.entries(@path).map { |e| self / e
|
112
|
+
Dir.entries(@path, encoding: "UTF-8").map { |e| self / e }
|
91
113
|
end
|
92
114
|
|
93
115
|
# Recursively find all files which match a specified regular
|
94
116
|
# expression.
|
95
|
-
def find_all_files(re)
|
117
|
+
def find_all_files(re = //)
|
96
118
|
entries.map do |pn|
|
97
119
|
if pn.directory?
|
98
120
|
if pn.basename =~ /^\.\.?$/
|
@@ -111,18 +133,35 @@ module Ocran
|
|
111
133
|
end
|
112
134
|
|
113
135
|
def ==(other); to_posix.downcase == other.to_posix.downcase; end
|
136
|
+
alias === ==
|
137
|
+
alias eql? ==
|
114
138
|
def =~(o); @path =~ o; end
|
115
|
-
def <=>(other); @path.casecmp(other.
|
139
|
+
def <=>(other); @path.casecmp(other.to_s); end
|
116
140
|
def exist?; File.exist?(@path); end
|
117
141
|
def file?; File.file?(@path); end
|
118
142
|
def directory?; File.directory?(@path); end
|
119
143
|
def absolute?; @path =~ ABSOLUTE_PAT; end
|
120
144
|
def dirname; Pathname.new(File.dirname(@path)); end
|
121
145
|
def basename; Pathname.new(File.basename(@path)); end
|
122
|
-
|
146
|
+
|
147
|
+
def expand_path(dir = ".")
|
148
|
+
Pathname.new(File.expand_path(@path, dir))
|
149
|
+
end
|
150
|
+
|
151
|
+
def expand(dir = nil); dir ? expand_path(dir) : expand_path; end
|
123
152
|
def size; File.size(@path); end
|
124
153
|
def encode(e); to_posix.encode(e); end # called when creating an installer with innosetup
|
125
154
|
|
155
|
+
def binread(*args)
|
156
|
+
File.binread(@path, *args)
|
157
|
+
end
|
158
|
+
|
159
|
+
def parent
|
160
|
+
Pathname.new(File.basename(File.dirname(@path)))
|
161
|
+
end
|
162
|
+
|
163
|
+
alias to_path to_posix
|
164
|
+
|
126
165
|
alias to_s to_posix
|
127
166
|
alias to_str to_posix
|
128
167
|
end
|
@@ -187,7 +226,7 @@ module Ocran
|
|
187
226
|
a.sort.inject([]) { |r, e| r.last == e ? r : r << e }
|
188
227
|
end
|
189
228
|
|
190
|
-
VERSION = "1.3.
|
229
|
+
VERSION = "1.3.15"
|
191
230
|
|
192
231
|
IGNORE_MODULE_NAMES = /\/(enumerator.so|rational.so|complex.so|fiber.so|thread.rb|ruby2_keywords.rb)$/
|
193
232
|
|
@@ -202,7 +241,7 @@ module Ocran
|
|
202
241
|
# Directories anywhere
|
203
242
|
(^|\/)(\.autotest|\.svn|\.cvs|\.git)(\/|$) |
|
204
243
|
# Unlikely extensions
|
205
|
-
\.(rdoc|c|cpp|c\+\+|cxx|h|hxx|hpp|obj|o|a)
|
244
|
+
\.(rdoc|c|cpp|c\+\+|cxx|h|hxx|hpp|obj|o|a)$
|
206
245
|
)}xi
|
207
246
|
|
208
247
|
GEM_NON_FILE_RE = /(#{GEM_EXTRA_RE}|#{GEM_SCRIPT_RE})/
|
@@ -270,40 +309,23 @@ module Ocran
|
|
270
309
|
exit 1
|
271
310
|
end
|
272
311
|
|
273
|
-
# Returns a binary blob store embedded in the current Ruby script.
|
274
|
-
def Ocran.get_next_embedded_image
|
275
|
-
DATA.read(DATA.readline.to_i).unpack("m")[0]
|
276
|
-
end
|
277
|
-
|
278
312
|
def Ocran.save_environment
|
279
313
|
@load_path_before = $LOAD_PATH.dup
|
280
314
|
@pwd_before = Dir.pwd
|
281
|
-
@env_before =
|
315
|
+
@env_before = ENV.to_hash
|
282
316
|
end
|
283
317
|
|
284
318
|
def Ocran.restore_environment
|
285
|
-
@env_before
|
286
|
-
ENV.each_key { |key| ENV.delete(key) unless @env_before.has_key?(key) }
|
319
|
+
ENV.clear.update(@env_before)
|
287
320
|
Dir.chdir @pwd_before
|
288
321
|
end
|
289
322
|
|
290
323
|
def Ocran.find_stubs
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
File.open(@lzmapath, "wb") { |file| file << lzmaimage }
|
297
|
-
ediconimage = get_next_embedded_image
|
298
|
-
@ediconpath = Host.tempdir / "edicon.exe"
|
299
|
-
File.open(@ediconpath, "wb") { |file| file << ediconimage }
|
300
|
-
else
|
301
|
-
ocranpath = Pathname(File.dirname(__FILE__))
|
302
|
-
@stubimage = File.open(ocranpath / "../share/ocran/stub.exe", "rb") { |file| file.read }
|
303
|
-
@stubwimage = File.open(ocranpath / "../share/ocran/stubw.exe", "rb") { |file| file.read }
|
304
|
-
@lzmapath = (ocranpath / "../share/ocran/lzma.exe").expand
|
305
|
-
@ediconpath = (ocranpath / "../share/ocran/edicon.exe").expand
|
306
|
-
end
|
324
|
+
ocranpath = Pathname(File.dirname(__FILE__))
|
325
|
+
@stubimage = (ocranpath / "../share/ocran/stub.exe").binread
|
326
|
+
@stubwimage = (ocranpath / "../share/ocran/stubw.exe").binread
|
327
|
+
@lzmapath = (ocranpath / "../share/ocran/lzma.exe").expand_path
|
328
|
+
@ediconpath = (ocranpath / "../share/ocran/edicon.exe").expand_path
|
307
329
|
end
|
308
330
|
|
309
331
|
def Ocran.parseargs(argv)
|
@@ -377,9 +399,11 @@ EOF
|
|
377
399
|
when /\A--add-all-core\z/
|
378
400
|
@options[:add_all_core] = true
|
379
401
|
when /\A--output\z/
|
380
|
-
|
402
|
+
path = argv.shift
|
403
|
+
@options[:output_override] = Pathname.new(path) if path
|
381
404
|
when /\A--dll\z/
|
382
|
-
|
405
|
+
path = argv.shift
|
406
|
+
@options[:extra_dlls] << path if path
|
383
407
|
when /\A--quiet\z/
|
384
408
|
@options[:quiet] = true
|
385
409
|
when /\A--verbose\z/
|
@@ -393,16 +417,19 @@ EOF
|
|
393
417
|
when /\A--chdir-first\z/
|
394
418
|
@options[:chdir_first] = true
|
395
419
|
when /\A--icon\z/
|
396
|
-
|
397
|
-
Ocran.fatal_error "Icon file #{
|
420
|
+
path = argv.shift
|
421
|
+
Ocran.fatal_error "Icon file #{path} not found.\n" unless path && File.exist?(path)
|
422
|
+
@options[:icon_filename] = Pathname.new(path)
|
398
423
|
when /\A--rubyopt\z/
|
399
424
|
@options[:rubyopt] = argv.shift
|
400
425
|
when /\A--gemfile\z/
|
401
|
-
|
402
|
-
Ocran.fatal_error "Gemfile #{
|
426
|
+
path = argv.shift
|
427
|
+
Ocran.fatal_error "Gemfile #{path} not found.\n" unless path && File.exist?(path)
|
428
|
+
@options[:gemfile] = Pathname.new(path)
|
403
429
|
when /\A--innosetup\z/
|
404
|
-
|
405
|
-
Ocran.fatal_error "Inno Script #{
|
430
|
+
path = argv.shift
|
431
|
+
Ocran.fatal_error "Inno Script #{path} not found.\n" unless path && File.exist?(path)
|
432
|
+
@options[:inno_script] = Pathname.new(path)
|
406
433
|
when /\A--no-autodll\z/
|
407
434
|
@options[:autodll] = false
|
408
435
|
when /\A--version\z/
|
@@ -421,17 +448,18 @@ EOF
|
|
421
448
|
@options[:enc] = !$1
|
422
449
|
when /\A--(no-)?gem-(\w+)(?:=(.*))?$/
|
423
450
|
negate, group, list = $1, $2, $3
|
424
|
-
@options[:gem]
|
425
|
-
@options[:gem] << [negate, group.to_sym, list && list.split(",")]
|
451
|
+
@options[:gem] << [negate, group.to_sym, list&.split(",")] if group
|
426
452
|
when /\A--help\z/, /\A--./
|
427
453
|
puts usage
|
428
454
|
exit 0
|
429
455
|
else
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
456
|
+
path = arg.dup
|
457
|
+
|
458
|
+
if !File.exist?(path) || Dir.empty?(path)
|
459
|
+
Ocran.fatal_error "#{path} not found!"
|
434
460
|
end
|
461
|
+
|
462
|
+
@options[:files] << path
|
435
463
|
end
|
436
464
|
end
|
437
465
|
|
@@ -453,14 +481,12 @@ EOF
|
|
453
481
|
end
|
454
482
|
|
455
483
|
@options[:files].map! { |path|
|
456
|
-
path = path.encode("UTF-8").tr(
|
484
|
+
path = path.encode("UTF-8").tr("\\", "/")
|
457
485
|
if File.directory?(path)
|
458
486
|
# If a directory is passed, we want all files under that directory
|
459
487
|
path = "#{path}/**/*"
|
460
488
|
end
|
461
|
-
|
462
|
-
Ocran.fatal_error "#{path} not found!" if files.empty?
|
463
|
-
files.map { |path| Pathname(path).expand }
|
489
|
+
Pathname.glob(path).map!(&:expand_path)
|
464
490
|
}.flatten!
|
465
491
|
end
|
466
492
|
|
@@ -486,8 +512,6 @@ EOF
|
|
486
512
|
modules_to_check.each do |mod|
|
487
513
|
modules_checked[mod] = true
|
488
514
|
mod.constants.each do |const|
|
489
|
-
# Module::Config causes warning on Ruby 1.9.3 - prevent autoloading
|
490
|
-
next if Module === mod && const == :Config
|
491
515
|
if mod.autoload?(const)
|
492
516
|
Ocran.msg "Attempting to trigger autoload of #{mod}::#{const}"
|
493
517
|
begin
|
@@ -509,26 +533,26 @@ EOF
|
|
509
533
|
def Ocran.find_load_path(loadpaths, feature)
|
510
534
|
if feature.absolute?
|
511
535
|
# Choose those loadpaths which contain the feature
|
512
|
-
candidate_loadpaths = loadpaths.select { |loadpath| feature.subpath?(loadpath.
|
536
|
+
candidate_loadpaths = loadpaths.select { |loadpath| feature.subpath?(loadpath.expand_path) }
|
513
537
|
# Guess the require'd feature
|
514
|
-
feature_pairs = candidate_loadpaths.map { |loadpath| [loadpath, feature.relative_path_from(loadpath.
|
538
|
+
feature_pairs = candidate_loadpaths.map { |loadpath| [loadpath, feature.relative_path_from(loadpath.expand_path)] }
|
515
539
|
# Select the shortest possible require-path (longest load-path)
|
516
540
|
if feature_pairs.empty?
|
517
541
|
nil
|
518
542
|
else
|
519
|
-
feature_pairs.sort_by { |loadpath, feature| feature.
|
543
|
+
feature_pairs.sort_by { |loadpath, feature| feature.to_s.size }.first[0]
|
520
544
|
end
|
521
545
|
else
|
522
546
|
# Select the loadpaths that contain 'feature' and select the shortest
|
523
|
-
candidates = loadpaths.select { |loadpath| feature.
|
524
|
-
candidates.sort_by { |loadpath| loadpath.
|
547
|
+
candidates = loadpaths.select { |loadpath| feature.expand_path(loadpath).exist? }
|
548
|
+
candidates.sort_by { |loadpath| loadpath.to_s.size }.last
|
525
549
|
end
|
526
550
|
end
|
527
551
|
|
528
552
|
# Find the root of all files specified on the command line and use
|
529
553
|
# it as the "src" of the output.
|
530
554
|
def Ocran.find_src_root(files)
|
531
|
-
src_files = files.map { |file| file.
|
555
|
+
src_files = files.map { |file| file.expand_path }
|
532
556
|
src_prefix = src_files.inject(src_files.first.dirname) do |srcroot, path|
|
533
557
|
if path.subpath?(Host.exec_prefix)
|
534
558
|
srcroot
|
@@ -579,18 +603,19 @@ EOF
|
|
579
603
|
end
|
580
604
|
end
|
581
605
|
|
582
|
-
ENV["BUNDLE_GEMFILE"] = Ocran.gemfile
|
606
|
+
ENV["BUNDLE_GEMFILE"] = Ocran.gemfile.to_s
|
583
607
|
Bundler.load.specs.each do |spec|
|
584
608
|
Ocran.verbose_msg "From Gemfile, adding gem #{spec.full_name}"
|
585
609
|
gems[spec.name] ||= spec
|
586
610
|
end
|
587
611
|
|
612
|
+
# This code is implemented for compatibility with older Bundler versions (< v1.16.0.pre.1).
|
588
613
|
unless gems.any? { |name, spec| name == "bundler" }
|
589
614
|
# Bundler itself wasn't added for some reason, let's put it in directly
|
590
615
|
Ocran.verbose_msg "From Gemfile, forcing inclusion of bundler gem itself"
|
591
616
|
bundler_spec = Gem.loaded_specs["bundler"]
|
592
617
|
bundler_spec or Ocran.fatal_error "Unable to locate bundler gem"
|
593
|
-
gems["bundler"] ||=
|
618
|
+
gems["bundler"] ||= bundler_spec
|
594
619
|
end
|
595
620
|
end
|
596
621
|
|
@@ -610,12 +635,12 @@ EOF
|
|
610
635
|
features_from_gems << feature
|
611
636
|
next
|
612
637
|
end
|
613
|
-
gempaths =
|
638
|
+
gempaths = Gem.path
|
614
639
|
gempaths.each do |gempath|
|
615
640
|
geminstallpath = Pathname(gempath) / "gems"
|
616
641
|
if feature.subpath?(geminstallpath)
|
617
642
|
gemlocalpath = feature.relative_path_from(geminstallpath)
|
618
|
-
fullgemname = gemlocalpath.
|
643
|
+
fullgemname = gemlocalpath.to_s.split("/").first
|
619
644
|
gemspecpath = gempath / "specifications" / "#{fullgemname}.gemspec"
|
620
645
|
if spec = Gem::Specification.load(gemspecpath)
|
621
646
|
gems[spec.name] ||= spec
|
@@ -682,9 +707,9 @@ EOF
|
|
682
707
|
Ocran.msg "Detected gem #{spec.full_name} (#{include.join(", ")})"
|
683
708
|
|
684
709
|
gem_root = Pathname(spec.gem_dir)
|
685
|
-
gem_extension = (gem_root / ".." / ".." / "extensions").
|
710
|
+
gem_extension = (gem_root / ".." / ".." / "extensions").expand_path
|
686
711
|
if gem_extension.exist?
|
687
|
-
build_complete = gem_extension.find_all_files(/gem.build_complete/).select { |p| p.
|
712
|
+
build_complete = gem_extension.find_all_files(/gem.build_complete/).select { |p| p.parent.to_s == spec.full_name }
|
688
713
|
else
|
689
714
|
build_complete = nil
|
690
715
|
end
|
@@ -704,14 +729,14 @@ EOF
|
|
704
729
|
when :loaded
|
705
730
|
files << features_from_gems.select { |feature| feature.subpath?(gem_root) }
|
706
731
|
when :files
|
707
|
-
gem_root_files ||= gem_root.find_all_files
|
732
|
+
gem_root_files ||= gem_root.find_all_files
|
708
733
|
files << gem_root_files.select { |path| path.relative_path_from(gem_root) !~ GEM_NON_FILE_RE }
|
709
734
|
files << build_complete if build_complete
|
710
735
|
when :extras
|
711
|
-
gem_root_files ||= gem_root.find_all_files
|
736
|
+
gem_root_files ||= gem_root.find_all_files
|
712
737
|
files << gem_root_files.select { |path| path.relative_path_from(gem_root) =~ GEM_EXTRA_RE }
|
713
738
|
when :scripts
|
714
|
-
gem_root_files ||= gem_root.find_all_files
|
739
|
+
gem_root_files ||= gem_root.find_all_files
|
715
740
|
files << gem_root_files.select { |path| path.relative_path_from(gem_root) =~ GEM_SCRIPT_RE }
|
716
741
|
end
|
717
742
|
end
|
@@ -723,7 +748,7 @@ EOF
|
|
723
748
|
Ocran.warn "#{missing_file} was not found"
|
724
749
|
end
|
725
750
|
|
726
|
-
total_size = actual_files.
|
751
|
+
total_size = actual_files.sum(0, &:size)
|
727
752
|
Ocran.msg "\t#{actual_files.size} files, #{total_size} bytes"
|
728
753
|
|
729
754
|
gem_files += actual_files
|
@@ -737,9 +762,9 @@ EOF
|
|
737
762
|
end
|
738
763
|
|
739
764
|
def Ocran.build_exe
|
740
|
-
all_load_paths = $LOAD_PATH.map { |loadpath| Pathname(loadpath).
|
741
|
-
@added_load_paths = ($LOAD_PATH - @load_path_before).map { |loadpath| Pathname(loadpath).
|
742
|
-
working_directory = Pathname.pwd
|
765
|
+
all_load_paths = $LOAD_PATH.map { |loadpath| Pathname(loadpath).expand_path }
|
766
|
+
@added_load_paths = ($LOAD_PATH - @load_path_before).map { |loadpath| Pathname(loadpath).expand_path }
|
767
|
+
working_directory = Pathname.pwd
|
743
768
|
|
744
769
|
restore_environment
|
745
770
|
|
@@ -784,7 +809,7 @@ EOF
|
|
784
809
|
encpath = path / "enc"
|
785
810
|
if encpath.exist?
|
786
811
|
encfiles = encpath.find_all_files(/\.so$/)
|
787
|
-
size = encfiles.
|
812
|
+
size = encfiles.sum(0, &:size)
|
788
813
|
Ocran.msg "Including #{encfiles.size} encoding support files (#{size} bytes, use --no-enc to exclude)"
|
789
814
|
features.push(*encfiles)
|
790
815
|
end
|
@@ -799,13 +824,13 @@ EOF
|
|
799
824
|
libs = []
|
800
825
|
features.each do |feature|
|
801
826
|
path = find_load_path(all_load_paths, feature)
|
802
|
-
if path.nil? || path.
|
827
|
+
if path.nil? || path.expand_path == Pathname.pwd
|
803
828
|
Ocran.files << feature
|
804
829
|
else
|
805
830
|
if feature.absolute?
|
806
|
-
feature = feature.relative_path_from(path.
|
831
|
+
feature = feature.relative_path_from(path.expand_path)
|
807
832
|
end
|
808
|
-
fullpath = feature.
|
833
|
+
fullpath = feature.expand_path(path)
|
809
834
|
|
810
835
|
if fullpath.subpath?(Host.exec_prefix)
|
811
836
|
# Features found in the Ruby installation are put in the
|
@@ -868,11 +893,10 @@ EOF
|
|
868
893
|
next unless path.to_posix =~
|
869
894
|
/\/(ruby\/(?:site_ruby\/|vendor_ruby\/)?[0-9.]+)\/?$/i
|
870
895
|
subdir = $1
|
871
|
-
|
872
|
-
fpath = Pathname.new(f)
|
896
|
+
Pathname.glob("#{lp}/**/*").each do |fpath|
|
873
897
|
next if fpath.directory?
|
874
898
|
tgt = "lib/#{subdir}/#{fpath.relative_path_from(path).to_posix}"
|
875
|
-
libs << [
|
899
|
+
libs << [fpath, tgt]
|
876
900
|
end
|
877
901
|
end
|
878
902
|
end
|
@@ -881,13 +905,19 @@ EOF
|
|
881
905
|
dlls = Ocran.autodll ? LibraryDetector.detect_dlls : []
|
882
906
|
|
883
907
|
# Detect external manifests
|
884
|
-
|
908
|
+
# For RubyInstaller environments supporting Ruby 2.4 and above,
|
909
|
+
# a manifest file is required.
|
910
|
+
if (manifest = Host.exec_prefix / "bin/ruby_builtin_dlls/ruby_builtin_dlls.manifest").exist?
|
911
|
+
manifests = [manifest]
|
912
|
+
else
|
913
|
+
manifests = []
|
914
|
+
end
|
885
915
|
|
886
916
|
executable = nil
|
887
917
|
if Ocran.output_override
|
888
918
|
executable = Ocran.output_override
|
889
919
|
else
|
890
|
-
executable = Ocran.files.first.basename.
|
920
|
+
executable = Ocran.files.first.basename.sub_ext(".exe")
|
891
921
|
executable.append_to_filename!("-debug") if Ocran.debug
|
892
922
|
end
|
893
923
|
|
@@ -963,8 +993,8 @@ EOF
|
|
963
993
|
if gemspec.subpath?(Host.exec_prefix)
|
964
994
|
path = gemspec.relative_path_from(Host.exec_prefix)
|
965
995
|
sb.createfile(gemspec, path)
|
966
|
-
elsif defined?(Gem) and gemhome =
|
967
|
-
path = GEMHOMEDIR / gemspec.relative_path_from(gemhome)
|
996
|
+
elsif defined?(Gem) and gemhome = Gem.path.find { |pth| gemspec.subpath?(pth) }
|
997
|
+
path = GEMHOMEDIR / gemspec.relative_path_from(Pathname(gemhome))
|
968
998
|
sb.createfile(gemspec, path)
|
969
999
|
else
|
970
1000
|
Ocran.fatal_error "Gem spec #{gemspec} does not exist in the Ruby installation. Don't know where to put it."
|
@@ -979,8 +1009,9 @@ EOF
|
|
979
1009
|
|
980
1010
|
# Workaround: RubyInstaller cannot find the msys folder if ../msys64/usr/bin/msys-2.0.dll is not present (since RubyInstaller-2.4.1 rubyinstaller 2 issue 23)
|
981
1011
|
# Add an empty file to /msys64/usr/bin/msys-2.0.dll if the dll was not required otherwise
|
982
|
-
|
983
|
-
|
1012
|
+
unless sb.files.keys.any? { |entry| entry.to_s.include?("msys-2.0.dll") }
|
1013
|
+
sb.createfile(Pathname(File.dirname(__FILE__)) / "../share/ocran/empty-msys-2.0.dll".to_s, 'msys64/usr/bin/msys-2.0.dll')
|
1014
|
+
end
|
984
1015
|
|
985
1016
|
# Set environment variable
|
986
1017
|
sb.setenv("RUBYOPT", Ocran.rubyopt || ENV["RUBYOPT"] || "")
|
@@ -1002,71 +1033,64 @@ EOF
|
|
1002
1033
|
end
|
1003
1034
|
|
1004
1035
|
module LibraryDetector
|
1036
|
+
# Windows API functions for handling files may return long paths,
|
1037
|
+
# with a maximum character limit of 32,767.
|
1038
|
+
# "\\?\" prefix(4 characters) + long path(32762 characters) + NULL = 32767 characters
|
1039
|
+
# https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
|
1040
|
+
MAX_PATH = 32767
|
1041
|
+
|
1042
|
+
# The byte size of the buffer given as an argument to the EnumProcessModules function.
|
1043
|
+
# This buffer is used to store the handles of the loaded modules.
|
1044
|
+
# If the buffer size is smaller than the number of loaded modules,
|
1045
|
+
# it will automatically increase the buffer size and call the EnumProcessModules function again.
|
1046
|
+
# Increasing the initial buffer size can reduce the number of iterations required.
|
1047
|
+
# https://learn.microsoft.com/en-us/windows/win32/psapi/enumerating-all-modules-for-a-process
|
1048
|
+
DEFAULT_HMODULE_BUFFER_SIZE = 1024
|
1049
|
+
|
1005
1050
|
def LibraryDetector.init_fiddle
|
1006
|
-
require "fiddle"
|
1051
|
+
require "fiddle/import"
|
1007
1052
|
require "fiddle/types"
|
1008
|
-
module_eval {
|
1009
|
-
extend Fiddle::Importer
|
1010
|
-
dlload "psapi.dll"
|
1011
|
-
include Fiddle::Win32Types
|
1012
|
-
extern "BOOL EnumProcessModules(HANDLE, HMODULE*, DWORD, DWORD*)"
|
1013
|
-
extend Fiddle::Importer
|
1014
|
-
dlload "kernel32.dll"
|
1015
|
-
include Fiddle::Win32Types
|
1016
|
-
|
1017
|
-
# https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
|
1018
|
-
# typedef PVOID HANDLE
|
1019
|
-
# typedef HINSTANCE HMODULE;
|
1020
|
-
|
1021
|
-
typealias "HMODULE", "voidp"
|
1022
|
-
typealias "HANDLE", "voidp"
|
1023
|
-
typealias "LPWSTR", "char*"
|
1024
|
-
|
1025
|
-
extern "DWORD GetModuleFileNameW(HMODULE, LPWSTR, DWORD)"
|
1026
|
-
extern "HANDLE GetCurrentProcess(void)"
|
1027
|
-
extern "DWORD GetLastError(void)"
|
1028
|
-
}
|
1029
|
-
end
|
1030
1053
|
|
1031
|
-
|
1032
|
-
|
1033
|
-
psapi = Fiddle.dlopen("psapi")
|
1034
|
-
enumprocessmodules = Fiddle::Function.new(psapi["EnumProcessModules"], [Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP], Fiddle::TYPE_LONG)
|
1035
|
-
kernel32 = Fiddle.dlopen("kernel32")
|
1036
|
-
getcurrentprocess = Fiddle::Function.new(kernel32["GetCurrentProcess"], [], Fiddle::TYPE_LONG)
|
1037
|
-
getmodulefilename = Fiddle::Function.new(kernel32["GetModuleFileNameW"], [Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG], Fiddle::TYPE_LONG)
|
1038
|
-
getlasterror = Fiddle::Function.new(kernel32["GetLastError"], [], Fiddle::TYPE_LONG)
|
1039
|
-
|
1040
|
-
# Different packing/unpacking for 64/32 bits systems
|
1041
|
-
if Fiddle::SIZEOF_VOIDP == 8 then
|
1042
|
-
f_single = "Q"
|
1043
|
-
f_array = "Q*"
|
1044
|
-
else
|
1045
|
-
f_single = "I"
|
1046
|
-
f_array = "I*"
|
1047
|
-
end
|
1054
|
+
extend Fiddle::Importer
|
1055
|
+
dlload "kernel32.dll", "psapi.dll"
|
1048
1056
|
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1057
|
+
include Fiddle::Win32Types
|
1058
|
+
# https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
|
1059
|
+
typealias "HINSTANCE", "HANDLE" # for Ruby2.6 only
|
1060
|
+
typealias "HMODULE", "HINSTANCE"
|
1061
|
+
typealias "LPDWORD", "PDWORD"
|
1062
|
+
typealias "LPWSTR", "char*"
|
1063
|
+
|
1064
|
+
extern "BOOL EnumProcessModules(HANDLE, HMODULE*, DWORD, LPDWORD)"
|
1065
|
+
extern "DWORD GetModuleFileNameW(HMODULE, LPWSTR, DWORD)"
|
1066
|
+
extern "HANDLE GetCurrentProcess()"
|
1067
|
+
extern "DWORD GetLastError()"
|
1068
|
+
end
|
1059
1069
|
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1070
|
+
def LibraryDetector.loaded_dlls
|
1071
|
+
init_fiddle
|
1072
|
+
|
1073
|
+
dword = "L" # A DWORD is a 32-bit unsigned integer.
|
1074
|
+
bytes_needed = [0].pack(dword)
|
1075
|
+
bytes = DEFAULT_HMODULE_BUFFER_SIZE
|
1076
|
+
process_handle = GetCurrentProcess()
|
1077
|
+
handles = while true
|
1078
|
+
buffer = "\x00" * bytes
|
1079
|
+
if EnumProcessModules(process_handle, buffer, buffer.bytesize, bytes_needed) == 0
|
1080
|
+
Ocran.fatal_error "LibraryDetector: EnumProcessModules failed with error code %#010x" % GetLastError()
|
1081
|
+
end
|
1082
|
+
bytes = bytes_needed.unpack1(dword)
|
1083
|
+
if bytes <= buffer.bytesize
|
1084
|
+
break buffer.unpack("J#{bytes / Fiddle::SIZEOF_VOIDP}")
|
1085
|
+
end
|
1086
|
+
end
|
1087
|
+
str = "\x00".encode("UTF-16LE") * MAX_PATH
|
1088
|
+
handles.map do |handle|
|
1089
|
+
length = GetModuleFileNameW(handle, str, str.bytesize)
|
1090
|
+
if length == 0
|
1091
|
+
Ocran.fatal_error "LibraryDetector: GetModuleFileNameW failed with error code %#010x" % GetLastError()
|
1067
1092
|
end
|
1068
|
-
|
1069
|
-
Ocran.Pathname(modulefilename)
|
1093
|
+
Ocran.Pathname(str[0, length])
|
1070
1094
|
end
|
1071
1095
|
end
|
1072
1096
|
|
@@ -1112,7 +1136,7 @@ EOF
|
|
1112
1136
|
end
|
1113
1137
|
|
1114
1138
|
if Ocran.icon_filename
|
1115
|
-
system Ocran.ediconpath, path, Ocran.icon_filename
|
1139
|
+
system Ocran.ediconpath.to_s, path.to_s, Ocran.icon_filename.to_s
|
1116
1140
|
end
|
1117
1141
|
|
1118
1142
|
opcode_offset = File.size(path)
|
@@ -1142,7 +1166,7 @@ EOF
|
|
1142
1166
|
begin
|
1143
1167
|
data_size = File.size(tmpinpath)
|
1144
1168
|
Ocran.msg "Compressing #{data_size} bytes"
|
1145
|
-
system(Ocran.lzmapath, "e", tmpinpath, tmpoutpath) or fail
|
1169
|
+
system(Ocran.lzmapath.to_s, "e", tmpinpath, tmpoutpath) or fail
|
1146
1170
|
compressed_data_size = File.size?(tmpoutpath)
|
1147
1171
|
ocranfile.write([OP_DECOMPRESS_LZMA, compressed_data_size].pack("VV"))
|
1148
1172
|
IO.copy_stream(tmpoutpath, ocranfile)
|
@@ -1189,7 +1213,7 @@ EOF
|
|
1189
1213
|
Ocran.msg "Running InnoSetup compiler ISCC"
|
1190
1214
|
result = system(*iscc_cmd)
|
1191
1215
|
if not result
|
1192
|
-
case
|
1216
|
+
case $?.exitstatus
|
1193
1217
|
when 0 then raise RuntimeError.new("ISCC reported success, but system reported error?")
|
1194
1218
|
when 1 then raise RuntimeError.new("ISCC reports invalid command line parameters")
|
1195
1219
|
when 2 then raise RuntimeError.new("ISCC reports that compilation failed")
|
@@ -1206,8 +1230,8 @@ EOF
|
|
1206
1230
|
end
|
1207
1231
|
|
1208
1232
|
def mkdir(path)
|
1209
|
-
return if @paths[path.
|
1210
|
-
@paths[path.
|
1233
|
+
return if @paths[path.to_s.downcase]
|
1234
|
+
@paths[path.to_posix.downcase] = true
|
1211
1235
|
Ocran.verbose_msg "m #{showtempdir path}"
|
1212
1236
|
unless Ocran.inno_script # The directory will be created by InnoSetup with a [Dirs] statement
|
1213
1237
|
@of << [OP_CREATE_DIRECTORY, path.to_native].pack("VZ*")
|
@@ -1216,7 +1240,7 @@ EOF
|
|
1216
1240
|
|
1217
1241
|
def ensuremkdir(tgt)
|
1218
1242
|
tgt = Ocran.Pathname(tgt)
|
1219
|
-
return if tgt.
|
1243
|
+
return if tgt.to_s == "."
|
1220
1244
|
if not @paths[tgt.to_posix.downcase]
|
1221
1245
|
ensuremkdir(tgt.dirname)
|
1222
1246
|
mkdir(tgt)
|
@@ -1234,7 +1258,7 @@ EOF
|
|
1234
1258
|
@files[tgt] = src
|
1235
1259
|
src, tgt = Ocran.Pathname(src), Ocran.Pathname(tgt)
|
1236
1260
|
ensuremkdir(tgt.dirname)
|
1237
|
-
str =
|
1261
|
+
str = src.binread
|
1238
1262
|
Ocran.verbose_msg "a #{showtempdir tgt}"
|
1239
1263
|
unless Ocran.inno_script # InnoSetup will install the file with a [Files] statement
|
1240
1264
|
@of << [OP_CREATE_FILE, tgt.to_native, str.size].pack("VZ*V")
|
@@ -1265,7 +1289,7 @@ EOF
|
|
1265
1289
|
end
|
1266
1290
|
|
1267
1291
|
def showtempdir(x)
|
1268
|
-
x.to_s.gsub(TEMPDIR_ROOT, "<tempdir>")
|
1292
|
+
x.to_s.gsub(TEMPDIR_ROOT.to_s, "<tempdir>")
|
1269
1293
|
end
|
1270
1294
|
end # class OcranBuilder
|
1271
1295
|
end # module Ocran
|
@@ -1287,7 +1311,7 @@ if File.basename(__FILE__) == File.basename($0)
|
|
1287
1311
|
|
1288
1312
|
if Ocran.run_script
|
1289
1313
|
Ocran.msg "Loading script to check dependencies"
|
1290
|
-
$0 = Ocran.files.first
|
1314
|
+
$0 = Ocran.files.first.to_s
|
1291
1315
|
load Ocran.files.first
|
1292
1316
|
end
|
1293
1317
|
end
|
data/lib/ocran/version.rb
CHANGED
data/share/ocran/edicon.exe
CHANGED
Binary file
|
File without changes
|
data/share/ocran/stub.exe
CHANGED
Binary file
|
data/share/ocran/stubw.exe
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ocran
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andi Idogawa
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-11-30 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: "OCRAN (One-Click Ruby Application Next) builds Windows executables from
|
15
15
|
Ruby source code. \n The executable is a self-extracting, self-running executable
|
@@ -31,6 +31,7 @@ files:
|
|
31
31
|
- lib/ocran.rb
|
32
32
|
- lib/ocran/version.rb
|
33
33
|
- share/ocran/edicon.exe
|
34
|
+
- share/ocran/empty-msys-2.0.dll
|
34
35
|
- share/ocran/lzma.exe
|
35
36
|
- share/ocran/stub.exe
|
36
37
|
- share/ocran/stubw.exe
|
@@ -49,7 +50,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
50
|
requirements:
|
50
51
|
- - ">="
|
51
52
|
- !ruby/object:Gem::Version
|
52
|
-
version: 2.
|
53
|
+
version: 2.6.0
|
53
54
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
55
|
requirements:
|
55
56
|
- - ">="
|