ocran 1.3.15 → 1.3.16
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/bin/ocran +2 -1314
- data/lib/ocran/build_constants.rb +16 -0
- data/lib/ocran/build_facade.rb +17 -0
- data/lib/ocran/build_helper.rb +105 -0
- data/lib/ocran/command_output.rb +22 -0
- data/lib/ocran/direction.rb +386 -0
- data/lib/ocran/file_path_set.rb +69 -0
- data/lib/ocran/gem_spec_queryable.rb +172 -0
- data/lib/ocran/host_config_helper.rb +37 -0
- data/lib/ocran/inno_setup_script_builder.rb +111 -0
- data/lib/ocran/launcher_batch_builder.rb +85 -0
- data/lib/ocran/library_detector.rb +61 -0
- data/lib/ocran/option.rb +273 -0
- data/lib/ocran/refine_pathname.rb +104 -0
- data/lib/ocran/runner.rb +105 -0
- data/lib/ocran/runtime_environment.rb +46 -0
- data/lib/ocran/stub_builder.rb +224 -0
- data/lib/ocran/version.rb +1 -1
- data/lib/ocran/windows_command_escaping.rb +15 -0
- data/lib/ocran.rb +3 -2
- data/share/ocran/edicon.exe +0 -0
- data/share/ocran/stub.exe +0 -0
- data/share/ocran/stubw.exe +0 -0
- metadata +23 -6
- /data/{share/ocran/empty-msys-2.0.dll → lib/ocran/empty_source} +0 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "tempfile"
|
3
|
+
require_relative "file_path_set"
|
4
|
+
|
5
|
+
module Ocran
|
6
|
+
# Utility class that produces the actual executable. Opcodes
|
7
|
+
# (create_file, mkdir etc) are added by invoking methods on an
|
8
|
+
# instance of OcranBuilder.
|
9
|
+
class StubBuilder
|
10
|
+
Signature = [0x41, 0xb6, 0xba, 0x4e].freeze
|
11
|
+
OP_END = 0
|
12
|
+
OP_CREATE_DIRECTORY = 1
|
13
|
+
OP_CREATE_FILE = 2
|
14
|
+
OP_SETENV = 3
|
15
|
+
OP_SET_SCRIPT = 4
|
16
|
+
|
17
|
+
DEBUG_MODE = 0x01
|
18
|
+
EXTRACT_TO_EXE_DIR = 0x02
|
19
|
+
AUTO_CLEAN_INST_DIR = 0x04
|
20
|
+
CHDIR_BEFORE_SCRIPT = 0x08
|
21
|
+
DATA_COMPRESSED = 0x10
|
22
|
+
|
23
|
+
base_dir = File.expand_path("../../share/ocran", File.dirname(__FILE__))
|
24
|
+
STUB_PATH = File.expand_path("stub.exe", base_dir)
|
25
|
+
STUBW_PATH = File.expand_path("stubw.exe", base_dir)
|
26
|
+
LZMA_PATH = File.expand_path("lzma.exe", base_dir)
|
27
|
+
EDICON_PATH = File.expand_path("edicon.exe", base_dir)
|
28
|
+
|
29
|
+
attr_reader :data_size
|
30
|
+
|
31
|
+
# chdir_before:
|
32
|
+
# When set to true, the working directory is changed to the application's
|
33
|
+
# deployment location at runtime.
|
34
|
+
#
|
35
|
+
# debug_mode:
|
36
|
+
# When the debug_mode option is set to true, the stub will output debug information
|
37
|
+
# when the exe file is executed. Debug mode can also be enabled within the directive
|
38
|
+
# code using the enable_debug_mode method. This option is provided to transition to
|
39
|
+
# debug mode from the initialization point of the stub.
|
40
|
+
#
|
41
|
+
# debug_extract:
|
42
|
+
# When set to true, the runtime file is extracted to the directory where the executable resides,
|
43
|
+
# and the extracted files remain even after the application exits.
|
44
|
+
# When set to false, the runtime file is extracted to the system's temporary directory,
|
45
|
+
# and the extracted files are deleted after the application exits.
|
46
|
+
#
|
47
|
+
# gui_mode:
|
48
|
+
# When set to true, the stub does not display a console window at startup. Errors are shown in a dialog window.
|
49
|
+
# When set to false, the stub reports errors through the console window.
|
50
|
+
#
|
51
|
+
# icon_path:
|
52
|
+
# Specifies the path to the icon file to be embedded in the stub's resources.
|
53
|
+
#
|
54
|
+
def initialize(path, chdir_before: nil, debug_extract: nil, debug_mode: nil,
|
55
|
+
enable_compression: nil, gui_mode: nil, icon_path: nil)
|
56
|
+
@dirs = FilePathSet.new
|
57
|
+
@files = FilePathSet.new
|
58
|
+
@data_size = 0
|
59
|
+
|
60
|
+
if icon_path && !File.exist?(icon_path)
|
61
|
+
raise "Icon file #{icon_path} not found"
|
62
|
+
end
|
63
|
+
|
64
|
+
stub = Tempfile.new("", File.dirname(path))
|
65
|
+
IO.copy_stream(gui_mode ? STUBW_PATH : STUB_PATH, stub)
|
66
|
+
stub.close
|
67
|
+
|
68
|
+
if icon_path
|
69
|
+
system(EDICON_PATH, stub.path, icon_path.to_s, exception: true)
|
70
|
+
end
|
71
|
+
|
72
|
+
File.open(stub, "ab") do |of|
|
73
|
+
@of = of
|
74
|
+
@opcode_offset = @of.size
|
75
|
+
|
76
|
+
write_header(debug_mode, debug_extract, chdir_before, enable_compression)
|
77
|
+
|
78
|
+
b = proc {
|
79
|
+
yield(self)
|
80
|
+
write_opcode(OP_END)
|
81
|
+
}
|
82
|
+
|
83
|
+
if enable_compression
|
84
|
+
compress(&b)
|
85
|
+
else
|
86
|
+
b.yield
|
87
|
+
end
|
88
|
+
|
89
|
+
write_footer
|
90
|
+
end
|
91
|
+
|
92
|
+
File.rename(stub, path)
|
93
|
+
end
|
94
|
+
|
95
|
+
def mkdir(target)
|
96
|
+
return unless @dirs.add?("/", target)
|
97
|
+
|
98
|
+
write_opcode(OP_CREATE_DIRECTORY)
|
99
|
+
write_path(target)
|
100
|
+
end
|
101
|
+
|
102
|
+
def cp(source, target)
|
103
|
+
unless File.exist?(source)
|
104
|
+
raise "The file does not exist (#{source})"
|
105
|
+
end
|
106
|
+
|
107
|
+
return unless @files.add?(source, target)
|
108
|
+
|
109
|
+
write_opcode(OP_CREATE_FILE)
|
110
|
+
write_path(target)
|
111
|
+
write_file(source)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Specifies the final application script to be launched, which can be called
|
115
|
+
# from any position in the data stream. It cannot be specified more than once.
|
116
|
+
#
|
117
|
+
# You can omit setting OP_SET_SCRIPT without issues, in which case
|
118
|
+
# the stub terminates without launching anything after performing other
|
119
|
+
# runtime operations.
|
120
|
+
def exec(image, script, *argv)
|
121
|
+
if @script_set
|
122
|
+
raise "Script is already set"
|
123
|
+
end
|
124
|
+
@script_set = true
|
125
|
+
|
126
|
+
write_opcode(OP_SET_SCRIPT)
|
127
|
+
write_string_array(convert_to_native(image), convert_to_native(script), *argv)
|
128
|
+
end
|
129
|
+
|
130
|
+
def export(name, value)
|
131
|
+
write_opcode(OP_SETENV)
|
132
|
+
write_string(name.to_s)
|
133
|
+
write_string(value.to_s)
|
134
|
+
end
|
135
|
+
|
136
|
+
def compress
|
137
|
+
IO.popen([LZMA_PATH, "e", "-si", "-so"], "r+b") do |lzma|
|
138
|
+
_of, @of = @of, lzma
|
139
|
+
Thread.new { yield(self); lzma.close_write }
|
140
|
+
IO.copy_stream(lzma, _of)
|
141
|
+
@of = _of
|
142
|
+
end
|
143
|
+
|
144
|
+
# Calculate the position to write the LZMA decompressed size (64-bit unsigned integer)
|
145
|
+
# @opcode_offset: start position of the data section
|
146
|
+
# 1: size of the header byte
|
147
|
+
# 5: size of the LZMA header in bytes
|
148
|
+
File.binwrite(@of.path, [@data_size].pack("Q<"), @opcode_offset + 1 + 5)
|
149
|
+
end
|
150
|
+
private :compress
|
151
|
+
|
152
|
+
def write_header(debug_mode, debug_extract, chdir_before, compressed)
|
153
|
+
next_to_exe, delete_after = debug_extract, !debug_extract
|
154
|
+
@of << [0 |
|
155
|
+
(debug_mode ? DEBUG_MODE : 0) |
|
156
|
+
(next_to_exe ? EXTRACT_TO_EXE_DIR : 0) |
|
157
|
+
(delete_after ? AUTO_CLEAN_INST_DIR : 0) |
|
158
|
+
(chdir_before ? CHDIR_BEFORE_SCRIPT : 0) |
|
159
|
+
(compressed ? DATA_COMPRESSED : 0)
|
160
|
+
].pack("C")
|
161
|
+
end
|
162
|
+
private :write_header
|
163
|
+
|
164
|
+
def write_opcode(op)
|
165
|
+
@of << [op].pack("C")
|
166
|
+
@data_size += 1
|
167
|
+
end
|
168
|
+
private :write_opcode
|
169
|
+
|
170
|
+
def write_size(i)
|
171
|
+
if i > 0xFFFF_FFFF
|
172
|
+
raise ArgumentError, "Size #{i} is too large: must be 32-bit unsigned integer (0 to 4294967295)"
|
173
|
+
end
|
174
|
+
|
175
|
+
@of << [i].pack("V")
|
176
|
+
@data_size += 4
|
177
|
+
end
|
178
|
+
private :write_size
|
179
|
+
|
180
|
+
def write_string(str)
|
181
|
+
len = str.bytesize + 1 # +1 to account for the null terminator
|
182
|
+
|
183
|
+
if len > 0xFFFF
|
184
|
+
raise ArgumentError, "String length #{len} is too large: must be less than or equal to 65535 bytes including null terminator"
|
185
|
+
end
|
186
|
+
|
187
|
+
@of << [len, str].pack("vZ*")
|
188
|
+
@data_size += 2 + len
|
189
|
+
end
|
190
|
+
private :write_string
|
191
|
+
|
192
|
+
def write_string_array(*str_array)
|
193
|
+
ary = str_array.map(&:to_s)
|
194
|
+
size = ary.sum(0) { |s| s.bytesize + 1 }
|
195
|
+
write_size(size)
|
196
|
+
ary.each_slice(1) { |a| @of << a.pack("Z*") }
|
197
|
+
@data_size += size
|
198
|
+
end
|
199
|
+
private :write_string_array
|
200
|
+
|
201
|
+
def write_file(src)
|
202
|
+
size = File.size(src)
|
203
|
+
write_size(size)
|
204
|
+
IO.copy_stream(src, @of)
|
205
|
+
@data_size += size
|
206
|
+
end
|
207
|
+
private :write_file
|
208
|
+
|
209
|
+
def write_path(path)
|
210
|
+
write_string(convert_to_native(path))
|
211
|
+
end
|
212
|
+
private :write_path
|
213
|
+
|
214
|
+
def write_footer
|
215
|
+
@of << ([@opcode_offset] + Signature).pack("VC*")
|
216
|
+
end
|
217
|
+
private :write_footer
|
218
|
+
|
219
|
+
def convert_to_native(path)
|
220
|
+
path.to_s.tr(File::SEPARATOR, "\\")
|
221
|
+
end
|
222
|
+
private :convert_to_native
|
223
|
+
end
|
224
|
+
end
|
data/lib/ocran/version.rb
CHANGED
data/lib/ocran.rb
CHANGED
data/share/ocran/edicon.exe
CHANGED
Binary file
|
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.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andi Idogawa
|
@@ -9,13 +9,13 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-08-05 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
|
16
16
|
that contains the Ruby interpreter, your source code and any additionally needed
|
17
17
|
ruby libraries or DLL.\n \n This is a fork of OCRA that is compatible with ruby
|
18
|
-
version after
|
18
|
+
version after 3.0.\n Migration guide: make sure to write ocran instead of ocra
|
19
19
|
in your code. For instance: OCRAN_EXECUTABLE\n\n usage: \n ocra helloworld.rb\n
|
20
20
|
\ helloworld.exe\n\n See readme at https://github.com/largo/ocran\n Report problems
|
21
21
|
in the github issues. Contributions welcome.\n This gem contains executables. We
|
@@ -29,9 +29,26 @@ extra_rdoc_files: []
|
|
29
29
|
files:
|
30
30
|
- bin/ocran
|
31
31
|
- lib/ocran.rb
|
32
|
+
- lib/ocran/build_constants.rb
|
33
|
+
- lib/ocran/build_facade.rb
|
34
|
+
- lib/ocran/build_helper.rb
|
35
|
+
- lib/ocran/command_output.rb
|
36
|
+
- lib/ocran/direction.rb
|
37
|
+
- lib/ocran/empty_source
|
38
|
+
- lib/ocran/file_path_set.rb
|
39
|
+
- lib/ocran/gem_spec_queryable.rb
|
40
|
+
- lib/ocran/host_config_helper.rb
|
41
|
+
- lib/ocran/inno_setup_script_builder.rb
|
42
|
+
- lib/ocran/launcher_batch_builder.rb
|
43
|
+
- lib/ocran/library_detector.rb
|
44
|
+
- lib/ocran/option.rb
|
45
|
+
- lib/ocran/refine_pathname.rb
|
46
|
+
- lib/ocran/runner.rb
|
47
|
+
- lib/ocran/runtime_environment.rb
|
48
|
+
- lib/ocran/stub_builder.rb
|
32
49
|
- lib/ocran/version.rb
|
50
|
+
- lib/ocran/windows_command_escaping.rb
|
33
51
|
- share/ocran/edicon.exe
|
34
|
-
- share/ocran/empty-msys-2.0.dll
|
35
52
|
- share/ocran/lzma.exe
|
36
53
|
- share/ocran/stub.exe
|
37
54
|
- share/ocran/stubw.exe
|
@@ -50,14 +67,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
67
|
requirements:
|
51
68
|
- - ">="
|
52
69
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
70
|
+
version: 3.0.0
|
54
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
72
|
requirements:
|
56
73
|
- - ">="
|
57
74
|
- !ruby/object:Gem::Version
|
58
75
|
version: '0'
|
59
76
|
requirements: []
|
60
|
-
rubygems_version: 3.
|
77
|
+
rubygems_version: 3.5.3
|
61
78
|
signing_key:
|
62
79
|
specification_version: 4
|
63
80
|
summary: OCRAN (One-Click Ruby Application Next) builds Windows executables from Ruby
|
File without changes
|