ocra 1.0.3 → 1.1.0
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.
- data/History.txt +12 -1
- data/Manifest.txt +1 -0
- data/README.txt +93 -16
- data/Rakefile +18 -4
- data/bin/ocra.rb +138 -8
- data/lib/ocra.rb +1 -1
- data/share/ocra/edicon.exe +0 -0
- data/share/ocra/stub.exe +0 -0
- data/share/ocra/stubw.exe +0 -0
- data/test/test_ocra.rb +199 -123
- metadata +3 -2
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 1.1.0
|
2
|
+
|
3
|
+
* Added an icon to the executable. Can be replaced from a .ico file
|
4
|
+
using the --icon <ico> option.
|
5
|
+
|
6
|
+
* Improved handling of load paths added either from the command line
|
7
|
+
(ruby -I), RUBYLIB environment variable or during the script (by
|
8
|
+
modifying $: or $LOAD_PATH).
|
9
|
+
|
10
|
+
* Now automatically detects loaded DLLs through Win32::API. Disable
|
11
|
+
with --no-autodll.
|
12
|
+
|
1
13
|
=== 1.0.3 / 2009-05-25
|
2
14
|
|
3
15
|
* Fixed invokation of executables with spaces in path names (#25966).
|
@@ -21,4 +33,3 @@
|
|
21
33
|
* 1 major enhancement
|
22
34
|
|
23
35
|
* Birthday!
|
24
|
-
|
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
@@ -18,6 +18,11 @@ any additionally needed ruby libraries or DLL.
|
|
18
18
|
* Both console programs and desktop programs supported (no console will
|
19
19
|
pop up with .rbw files).
|
20
20
|
|
21
|
+
If you experience problems with Ocra or have found a bug, please use
|
22
|
+
the tracker on the RubyForge project page
|
23
|
+
http://rubyforge.org/projects/ocra/. You are welcome to ask questions
|
24
|
+
in the forums there aswell.
|
25
|
+
|
21
26
|
== TODO:
|
22
27
|
|
23
28
|
* Clean up using manual recursive deletion (not SHop).
|
@@ -32,16 +37,18 @@ ocra.rb [option] your/script.rb
|
|
32
37
|
* Your program should 'require' all necessary files when invoked without
|
33
38
|
arguments, so ocra can detect all dependencies.
|
34
39
|
|
35
|
-
*
|
36
|
-
|
40
|
+
* Ocra executables clear the RUBYLIB environment variable but set
|
41
|
+
RUBYOPT to whatever value it had when you invoked Ocra.
|
37
42
|
|
38
43
|
* Ocra does not set up the include path. Use "$:.unshift
|
39
44
|
File.dirname(__FILE__)" at the start of your script if you need to
|
40
45
|
'require' additional source files in the same directory no matter
|
41
46
|
what the user's current working directory is.
|
42
47
|
|
43
|
-
* DLLs
|
44
|
-
|
48
|
+
* Loaded DLLs are detected automatically but only those located in
|
49
|
+
your Ruby installation are included. Automatic detection can be
|
50
|
+
disabled using --no-autodll. DLLs can be manually added using the
|
51
|
+
--dll option.
|
45
52
|
|
46
53
|
== REQUIREMENTS:
|
47
54
|
|
@@ -57,29 +64,96 @@ ocra.rb [option] your/script.rb
|
|
57
64
|
|
58
65
|
Can also be downloaded from http://rubyforge.org/frs/?group_id=8185
|
59
66
|
|
60
|
-
|
67
|
+
=== Stand-alone
|
61
68
|
|
62
69
|
Get ocrasa.rb from http://rubyforge.org/frs/?group_id=8185. Requires
|
63
70
|
nothing but a working Ruby installation on Windows.
|
64
71
|
|
65
72
|
== TECHNICAL DETAILS
|
66
73
|
|
67
|
-
The Ocra stub extracts the
|
68
|
-
|
69
|
-
|
70
|
-
|
74
|
+
The Ocra stub extracts the Ruby interpreter and your scripts into a
|
75
|
+
temporary directory. The directory will contains the same directory
|
76
|
+
layout as your Ruby installlation. The source files for your
|
77
|
+
application will be put in the 'src' subdirectory.
|
78
|
+
|
79
|
+
=== Libraries
|
80
|
+
|
81
|
+
Rubygems will be automatically included in the Ocra executable.
|
71
82
|
|
72
83
|
Libraries found in non-standard path (for example, if you invoke Ocra
|
73
84
|
with "ruby -I some/path") will be placed into the site dir
|
74
|
-
(lib/ruby/site_ruby).
|
85
|
+
(lib/ruby/site_ruby). Avoid changing $LOAD_PATH / $: from your script
|
86
|
+
to include paths outside your source tree.
|
75
87
|
|
76
|
-
|
77
|
-
launched by the executable in order not to interfere with any Ruby
|
78
|
-
installation on the end user's installation.
|
79
|
-
|
80
|
-
Autoloaded constants will be attempted loaded when building the
|
88
|
+
Autoloaded libraries will be attempted loaded when building the
|
81
89
|
executable. Modules that doesn't exist will be ignore (but a warning
|
82
|
-
will be logged.
|
90
|
+
will be logged).
|
91
|
+
|
92
|
+
=== Environment variables
|
93
|
+
|
94
|
+
Ocra executables clear the RUBYLIB environment variable before your
|
95
|
+
script is launched. This is done to ensure that your script does not
|
96
|
+
use load paths from the end user's Ruby installation.
|
97
|
+
|
98
|
+
Ocra executables set the RUBYOPT environment variable to the value it
|
99
|
+
had when you invoked Ocra. For example, if you had "RUBYOPT=rubygems"
|
100
|
+
on your build PC, Ocra ensures that it is also set on PC's running the
|
101
|
+
executables.
|
102
|
+
|
103
|
+
=== Working directory
|
104
|
+
|
105
|
+
You should not assume that the current working directory when invoking
|
106
|
+
an executable built with .exe is the location of the source script. It
|
107
|
+
can be the directory where the executable is placed (when invoked
|
108
|
+
through the Windows Explorer), the users' current working directory
|
109
|
+
(when invoking from the Command Prompt), or even C:\WINDOWS\SYSTEM32
|
110
|
+
when the executable is invoked through a file association. You can
|
111
|
+
optionally change the directory yourself:
|
112
|
+
|
113
|
+
Dir.chdir File.dirname(__FILE__)
|
114
|
+
|
115
|
+
If you wish to maintain the user's working directory, but need to
|
116
|
+
'require' additional Ruby scripts from the source directory, you can
|
117
|
+
add the following line to your script:
|
118
|
+
|
119
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
120
|
+
|
121
|
+
=== $LOAD_PATH/$: mangling
|
122
|
+
|
123
|
+
Adding paths to $LOAD_PATH or $: at runtime is not recommended. Adding
|
124
|
+
relative load paths depends on the working directory being the same as
|
125
|
+
where the script is located (See above). If you have additional
|
126
|
+
library files in directories below the directory containing your
|
127
|
+
source script you can use this idiom:
|
128
|
+
|
129
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'path/to/script')
|
130
|
+
|
131
|
+
=== Detecting OCRA
|
132
|
+
|
133
|
+
You can detect whether Ocra is currently building your script by
|
134
|
+
looking for the 'Ocra' constant. If it is defined, Ocra is currenly
|
135
|
+
building the executable from your script. For example, you can use
|
136
|
+
this to avoid opening a GUI window when compiling executables:
|
137
|
+
|
138
|
+
app = MyApp.new
|
139
|
+
if not defined?(Ocra)
|
140
|
+
app.main_loop
|
141
|
+
end
|
142
|
+
|
143
|
+
=== Additional files and resources
|
144
|
+
|
145
|
+
You can add additional files to the Ocra executable (for example
|
146
|
+
images) by appending them to the command line. They should be placed
|
147
|
+
in the source directory with your main script (or a subdirectory).
|
148
|
+
|
149
|
+
ocra.rb mainscript.rb someimage.jpeg docs/document.txt
|
150
|
+
|
151
|
+
This will create the following layout in the temporary directory when
|
152
|
+
your program is executed:
|
153
|
+
|
154
|
+
src/mainscript.rb
|
155
|
+
src/someimage.jpeg
|
156
|
+
src/docs/document.txt
|
83
157
|
|
84
158
|
== CREDITS:
|
85
159
|
|
@@ -88,6 +162,9 @@ source code used was place into Public Domain by Igor Pavlov.
|
|
88
162
|
|
89
163
|
Erik Veenstra for rubyscript2exe which provided inspiration.
|
90
164
|
|
165
|
+
Dice for the default .exe icon (vit-ruby.ico,
|
166
|
+
http://ruby.morphball.net/vit-ruby-ico_en.html)
|
167
|
+
|
91
168
|
== LICENSE:
|
92
169
|
|
93
170
|
(The MIT License)
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
|
-
require '
|
5
|
+
require 'bin/ocra'
|
6
6
|
|
7
7
|
Hoe.new('ocra', Ocra::VERSION) do |p|
|
8
8
|
p.developer('Lars Christensen', 'larsch@belunktum.dk')
|
@@ -12,17 +12,26 @@ task :stub do
|
|
12
12
|
sh "mingw32-make -C src"
|
13
13
|
cp 'src/stub.exe', 'share/ocra/stub.exe'
|
14
14
|
cp 'src/stubw.exe', 'share/ocra/stubw.exe'
|
15
|
+
cp 'src/edicon.exe', 'share/ocra/edicon.exe'
|
15
16
|
end
|
16
17
|
|
17
18
|
task :test => :stub
|
18
19
|
|
19
20
|
task :standalone => [ 'bin/ocrasa.rb' ]
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
standalone_zip = "bin/ocrasa-#{ENV['VERSION']}.zip"
|
23
|
+
|
24
|
+
file standalone_zip => 'bin/ocrasa.rb' do
|
25
|
+
chdir('bin') do
|
26
|
+
system("zip ocrasa-#{ENV['VERSION']}.zip ocrasa.rb")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
task :release_standalone => standalone_zip do
|
31
|
+
sh "rubyforge add_release ocra ocra-standalone #{Ocra::VERSION} #{standalone_zip}"
|
23
32
|
end
|
24
33
|
|
25
|
-
file 'bin/ocrasa.rb' => [ 'bin/ocra.rb', 'share/ocra/stub.exe', 'share/ocra/stubw.exe', 'share/ocra/lzma.exe' ] do
|
34
|
+
file 'bin/ocrasa.rb' => [ 'bin/ocra.rb', 'share/ocra/stub.exe', 'share/ocra/stubw.exe', 'share/ocra/lzma.exe', 'share/ocra/edicon.exe' ] do
|
26
35
|
cp 'bin/ocra.rb', 'bin/ocrasa.rb'
|
27
36
|
File.open("bin/ocrasa.rb", "a") do |f|
|
28
37
|
f.puts "__END__"
|
@@ -41,6 +50,11 @@ file 'bin/ocrasa.rb' => [ 'bin/ocra.rb', 'share/ocra/stub.exe', 'share/ocra/stub
|
|
41
50
|
lzma64 = [lzma].pack("m")
|
42
51
|
f.puts lzma64.size
|
43
52
|
f.puts lzma64
|
53
|
+
|
54
|
+
lzma = File.open("share/ocra/edicon.exe", "rb") {|g| g.read}
|
55
|
+
lzma64 = [lzma].pack("m")
|
56
|
+
f.puts lzma64.size
|
57
|
+
f.puts lzma64
|
44
58
|
end
|
45
59
|
end
|
46
60
|
|
data/bin/ocra.rb
CHANGED
@@ -10,6 +10,10 @@ module Ocra
|
|
10
10
|
OP_DECOMPRESS_LZMA = 4
|
11
11
|
OP_SETENV = 5
|
12
12
|
|
13
|
+
VERSION = "1.1.0"
|
14
|
+
|
15
|
+
IGNORE_MODULES = /^enumerator.so$/
|
16
|
+
|
13
17
|
class << self
|
14
18
|
attr_accessor :lzma_mode
|
15
19
|
attr_accessor :extra_dlls
|
@@ -17,8 +21,11 @@ module Ocra
|
|
17
21
|
attr_accessor :load_autoload
|
18
22
|
attr_accessor :force_windows
|
19
23
|
attr_accessor :force_console
|
24
|
+
attr_accessor :icon_filename
|
20
25
|
attr_accessor :quiet
|
26
|
+
attr_accessor :autodll
|
21
27
|
attr_reader :lzmapath
|
28
|
+
attr_reader :ediconpath
|
22
29
|
attr_reader :stubimage
|
23
30
|
attr_reader :stubwimage
|
24
31
|
|
@@ -28,18 +35,23 @@ module Ocra
|
|
28
35
|
end
|
29
36
|
|
30
37
|
def Ocra.initialize_ocra
|
38
|
+
@load_path_before = $LOAD_PATH.dup
|
39
|
+
|
31
40
|
if defined?(DATA)
|
32
41
|
@stubimage = get_next_embedded_image
|
33
42
|
@stubwimage = get_next_embedded_image
|
34
43
|
lzmaimage = get_next_embedded_image
|
35
44
|
@lzmapath = File.join(ENV['TEMP'], 'lzma.exe').tr('/','\\')
|
36
45
|
File.open(@lzmapath, "wb") { |file| file << lzmaimage }
|
46
|
+
ediconimage = get_next_embedded_image
|
47
|
+
@ediconpath = File.join(ENV['TEMP'], 'edicon.exe').tr('/','\\')
|
48
|
+
File.open(@ediconpath, "wb") { |file| file << ediconimage }
|
37
49
|
else
|
38
50
|
ocrapath = File.dirname(__FILE__)
|
39
51
|
@stubimage = File.open(File.join(ocrapath, '../share/ocra/stub.exe'), "rb") { |file| file.read }
|
40
52
|
@stubwimage = File.open(File.join(ocrapath, '../share/ocra/stubw.exe'), "rb") { |file| file.read }
|
41
53
|
@lzmapath = File.expand_path('../share/ocra/lzma.exe', ocrapath).tr('/','\\')
|
42
|
-
|
54
|
+
@ediconpath = File.expand_path('../share/ocra/edicon.exe', ocrapath).tr('/','\\')
|
43
55
|
end
|
44
56
|
end
|
45
57
|
|
@@ -50,7 +62,9 @@ module Ocra
|
|
50
62
|
load_autoload = true
|
51
63
|
force_windows = false
|
52
64
|
force_console = false
|
65
|
+
icon_filename = nil
|
53
66
|
quiet = false
|
67
|
+
autodll = true
|
54
68
|
|
55
69
|
usage = <<EOF
|
56
70
|
ocra [options] script.rb
|
@@ -62,6 +76,8 @@ ocra [options] script.rb
|
|
62
76
|
--windows Force Windows application (rubyw.exe)
|
63
77
|
--console Force console application (ruby.exe)
|
64
78
|
--no-autoload Don't load/include script.rb's autoloads
|
79
|
+
--icon <ico> Replace icon with a custom one
|
80
|
+
--version Display version number
|
65
81
|
EOF
|
66
82
|
|
67
83
|
while arg = argv.shift
|
@@ -78,6 +94,14 @@ EOF
|
|
78
94
|
force_console = true
|
79
95
|
when /\A--no-autoload\z/
|
80
96
|
load_autoload = false
|
97
|
+
when /\A--icon\z/
|
98
|
+
icon_filename = argv.shift
|
99
|
+
raise "Icon file #{icon_filename} not found.\n" unless File.exist?(icon_filename)
|
100
|
+
when /\A--no-autodll\z/
|
101
|
+
autodll = false
|
102
|
+
when /\A--version\z/
|
103
|
+
puts "Ocra #{VERSION}"
|
104
|
+
exit
|
81
105
|
when /\A--help\z/, /\A--/
|
82
106
|
puts usage
|
83
107
|
exit
|
@@ -97,6 +121,8 @@ EOF
|
|
97
121
|
@force_windows = force_windows
|
98
122
|
@force_console = force_console
|
99
123
|
@load_autoload = load_autoload
|
124
|
+
@icon_filename = icon_filename
|
125
|
+
@autodll = autodll
|
100
126
|
@files = files
|
101
127
|
end
|
102
128
|
|
@@ -130,8 +156,32 @@ EOF
|
|
130
156
|
end
|
131
157
|
end
|
132
158
|
end
|
159
|
+
|
160
|
+
def Ocra.relative_path(src, tgt)
|
161
|
+
a = src.split('/')
|
162
|
+
b = tgt.split('/')
|
163
|
+
while a.first && a.first.downcase == b.first.downcase
|
164
|
+
a.shift
|
165
|
+
b.shift
|
166
|
+
end
|
167
|
+
return tgt if b.first =~ /^[a-z]:/i
|
168
|
+
a.size.times { b.unshift '..' }
|
169
|
+
return b.join('/')
|
170
|
+
end
|
171
|
+
|
172
|
+
def Ocra.find_load_path(paths, path)
|
173
|
+
if path[1,1] == ":"
|
174
|
+
rps = paths.map {|p| relative_path(p, path) }
|
175
|
+
rps.zip(paths).sort_by {|x| x[0].size }.first[1]
|
176
|
+
else
|
177
|
+
candidates = paths.select { |p| File.exist?(File.expand_path(path, p)) }
|
178
|
+
candidates.sort_by {|p| p.size}.last
|
179
|
+
end
|
180
|
+
end
|
133
181
|
|
134
182
|
def Ocra.build_exe
|
183
|
+
@added_load_paths = $LOAD_PATH - @load_path_before
|
184
|
+
|
135
185
|
# Attempt to autoload libraries before doing anything else.
|
136
186
|
attempt_load_autoload if Ocra.load_autoload
|
137
187
|
|
@@ -154,25 +204,40 @@ EOF
|
|
154
204
|
libruby_so = RbConfig::CONFIG['LIBRUBY_SO']
|
155
205
|
|
156
206
|
instsitelibdir = sitelibdir[exec_prefix.size+1..-1]
|
207
|
+
|
208
|
+
load_path = []
|
157
209
|
|
158
210
|
# Find loaded files
|
159
211
|
libs = []
|
160
212
|
features.each do |filename|
|
161
|
-
path =
|
213
|
+
path = find_load_path($:, filename)
|
162
214
|
if path
|
215
|
+
if filename[1,1] == ":"
|
216
|
+
filename = relative_path(File.expand_path(path), filename)
|
217
|
+
end
|
218
|
+
if filename =~ /^\.\.\//
|
219
|
+
puts "=== WARNING: Detected a relative require (#{filename}). This is not recommended."
|
220
|
+
end
|
163
221
|
fullpath = File.expand_path(filename, path)
|
164
222
|
if fullpath.index(exec_prefix) == 0
|
165
223
|
libs << [ fullpath, fullpath[exec_prefix.size+1..-1] ]
|
166
224
|
elsif fullpath.index(src_prefix) == 0
|
167
|
-
|
225
|
+
targetpath = "src/" + fullpath[src_prefix.size+1..-1]
|
226
|
+
libs << [ fullpath, targetpath ]
|
227
|
+
if not @added_load_paths.include?(path) and not load_path.include?(path)
|
228
|
+
load_path << File.join("\xFF", File.dirname(targetpath))
|
229
|
+
end
|
168
230
|
else
|
169
231
|
libs << [ fullpath, File.join(instsitelibdir, filename) ]
|
170
232
|
end
|
171
233
|
else
|
172
|
-
puts "=== WARNING: Couldn't find #{filename}"
|
234
|
+
puts "=== WARNING: Couldn't find #{filename}" unless filename =~ IGNORE_MODULES
|
173
235
|
end
|
174
236
|
end
|
175
237
|
|
238
|
+
# Detect additional DLLs
|
239
|
+
dlls = Ocra.autodll ? LibraryDetector.detect_dlls : []
|
240
|
+
|
176
241
|
executable = Ocra.files[0].sub(/(\.rbw?)?$/, '.exe')
|
177
242
|
|
178
243
|
windowed = (Ocra.files[0] =~ /\.rbw$/ || Ocra.force_windows) && !Ocra.force_console
|
@@ -196,6 +261,16 @@ EOF
|
|
196
261
|
sb.createfile(File.join(bindir, libruby_so), "bin\\#{libruby_so}")
|
197
262
|
end
|
198
263
|
|
264
|
+
# Add detected DLLs
|
265
|
+
dlls.each do |dll|
|
266
|
+
if dll.tr('\\','/').index(exec_prefix) == 0
|
267
|
+
target = dll[exec_prefix.size+1..-1]
|
268
|
+
else
|
269
|
+
target = File.join('bin', File.basename(dll))
|
270
|
+
end
|
271
|
+
sb.createfile(dll, target)
|
272
|
+
end
|
273
|
+
|
199
274
|
# Add extra DLLs
|
200
275
|
Ocra.extra_dlls.each do |dll|
|
201
276
|
sb.createfile(File.join(bindir, dll), File.join("bin", dll).tr('/','\\'))
|
@@ -218,7 +293,7 @@ EOF
|
|
218
293
|
|
219
294
|
# Set environment variable
|
220
295
|
sb.setenv('RUBYOPT', '')
|
221
|
-
sb.setenv('RUBYLIB', '')
|
296
|
+
sb.setenv('RUBYLIB', load_path.join(';'))
|
222
297
|
|
223
298
|
# Launch the script
|
224
299
|
sb.createprocess("bin\\" + rubyexe, "#{rubyexe} \xff\\src\\" + Ocra.files[0])
|
@@ -227,6 +302,52 @@ EOF
|
|
227
302
|
end
|
228
303
|
puts "=== Finished (Final size was #{File.size(executable)})" unless Ocra.quiet
|
229
304
|
end
|
305
|
+
|
306
|
+
module LibraryDetector
|
307
|
+
def LibraryDetector.loaded_dlls
|
308
|
+
begin
|
309
|
+
require 'rubygems'
|
310
|
+
gem 'win32-api', '>=1.4.0'
|
311
|
+
require 'win32/api'
|
312
|
+
rescue Exception => e
|
313
|
+
puts "=== ERROR: Failed to load the win32-api gem. Install win32-api or use --no-autodll."
|
314
|
+
puts "=== CAUSE: #{e.class.name}: #{e.message.chomp}"
|
315
|
+
exit
|
316
|
+
end
|
317
|
+
|
318
|
+
enumprocessmodules = Win32::API.new('EnumProcessModules', 'LPLP', 'B', 'psapi')
|
319
|
+
getmodulefilename = Win32::API.new('GetModuleFileName', 'LPL', 'L')
|
320
|
+
getcurrentprocess = Win32::API.new('GetCurrentProcess', 'V', 'L')
|
321
|
+
|
322
|
+
bytes_needed = 4 * 32
|
323
|
+
module_handle_buffer = nil
|
324
|
+
process_handle = getcurrentprocess.call()
|
325
|
+
loop do
|
326
|
+
module_handle_buffer = "\x00" * bytes_needed
|
327
|
+
bytes_needed_buffer = [0].pack("I")
|
328
|
+
r = enumprocessmodules.call(process_handle, module_handle_buffer, module_handle_buffer.size, bytes_needed_buffer)
|
329
|
+
bytes_needed = bytes_needed_buffer.unpack("I")[0]
|
330
|
+
break if bytes_needed <= module_handle_buffer.size
|
331
|
+
end
|
332
|
+
|
333
|
+
handles = module_handle_buffer.unpack("I*")
|
334
|
+
handles.select{|x|x>0}.map do |h|
|
335
|
+
str = "\x00" * 256
|
336
|
+
r = getmodulefilename.call(h, str, str.size)
|
337
|
+
str[0,r]
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def LibraryDetector.detect_dlls
|
342
|
+
loaded = loaded_dlls
|
343
|
+
exec_prefix = RbConfig::CONFIG['exec_prefix']
|
344
|
+
loaded.select do |path|
|
345
|
+
path.tr('\\','/').index(exec_prefix) == 0 and
|
346
|
+
File.basename(path) =~ /\.dll$/ and
|
347
|
+
File.basename(path).downcase != RbConfig::CONFIG['LIBRUBY_SO'].downcase
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
230
351
|
|
231
352
|
class OcraBuilder
|
232
353
|
def initialize(path, windowed)
|
@@ -238,7 +359,16 @@ EOF
|
|
238
359
|
else
|
239
360
|
ocrafile.write(Ocra.stubimage)
|
240
361
|
end
|
241
|
-
|
362
|
+
end
|
363
|
+
|
364
|
+
if Ocra.icon_filename
|
365
|
+
system("#{Ocra.ediconpath} #{path} #{Ocra.icon_filename}")
|
366
|
+
end
|
367
|
+
|
368
|
+
opcode_offset = File.size(path)
|
369
|
+
|
370
|
+
File.open(path, "ab") do |ocrafile|
|
371
|
+
|
242
372
|
if Ocra.lzma_mode
|
243
373
|
@of = ""
|
244
374
|
else
|
@@ -263,7 +393,7 @@ EOF
|
|
263
393
|
end
|
264
394
|
|
265
395
|
ocrafile.write([OP_END].pack("V"))
|
266
|
-
ocrafile.write([
|
396
|
+
ocrafile.write([opcode_offset].pack("V")) # Pointer to start of opcodes
|
267
397
|
ocrafile.write(Signature.pack("C*"))
|
268
398
|
end
|
269
399
|
end
|
@@ -308,7 +438,7 @@ if File.basename(__FILE__) == File.basename($0)
|
|
308
438
|
Ocra.build_exe
|
309
439
|
exit(0)
|
310
440
|
end
|
311
|
-
|
441
|
+
|
312
442
|
puts "=== Loading script to check dependencies" unless Ocra.quiet
|
313
443
|
$0 = Ocra.files[0]
|
314
444
|
load Ocra.files[0]
|
data/lib/ocra.rb
CHANGED
Binary file
|
data/share/ocra/stub.exe
CHANGED
Binary file
|
data/share/ocra/stubw.exe
CHANGED
Binary file
|
data/test/test_ocra.rb
CHANGED
@@ -3,9 +3,12 @@ require "ocra"
|
|
3
3
|
require "tmpdir"
|
4
4
|
require "fileutils"
|
5
5
|
require "rbconfig"
|
6
|
+
include FileUtils
|
6
7
|
|
7
8
|
class TestOcra < Test::Unit::TestCase
|
8
9
|
|
10
|
+
DefaultArgs = [ '--quiet', '--no-lzma' ]
|
11
|
+
|
9
12
|
TESTED_OCRA = ENV['TESTED_OCRA'] || 'ocra.rb'
|
10
13
|
|
11
14
|
def initialize(*args)
|
@@ -18,6 +21,41 @@ class TestOcra < Test::Unit::TestCase
|
|
18
21
|
def ocra
|
19
22
|
@ocra
|
20
23
|
end
|
24
|
+
|
25
|
+
OcraRoot = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
26
|
+
|
27
|
+
FixturePath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
28
|
+
|
29
|
+
# Sets up an directory with a copy of a fixture and yields to the
|
30
|
+
# block, then cleans up everything. A fixture here is a hierachy of
|
31
|
+
# files located in test/fixtures.
|
32
|
+
def with_fixture(name)
|
33
|
+
path = File.join(FixturePath, name)
|
34
|
+
FileUtils.cp_r path, '.'
|
35
|
+
begin
|
36
|
+
cd name do
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
rm_rf 'name'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sets up temporary environment variable and yields to the block.
|
45
|
+
def with_env(hash)
|
46
|
+
old = {}
|
47
|
+
hash.each do |k,v|
|
48
|
+
old[k] = ENV[k]
|
49
|
+
ENV[k] = v
|
50
|
+
end
|
51
|
+
begin
|
52
|
+
yield
|
53
|
+
ensure
|
54
|
+
hash.each do |k,v|
|
55
|
+
ENV[k] = old[k]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
21
59
|
|
22
60
|
def setup
|
23
61
|
@testnum += 1
|
@@ -32,168 +70,206 @@ class TestOcra < Test::Unit::TestCase
|
|
32
70
|
end
|
33
71
|
|
34
72
|
def test_helloworld
|
35
|
-
|
36
|
-
|
73
|
+
with_fixture 'helloworld' do
|
74
|
+
assert system("ruby", ocra, "helloworld.rb", *DefaultArgs)
|
75
|
+
assert File.exist?("helloworld.exe")
|
76
|
+
assert system("helloworld.exe")
|
37
77
|
end
|
38
|
-
assert system("ruby", ocra, "--quiet", "helloworld.rb")
|
39
|
-
assert File.exist?("helloworld.exe")
|
40
|
-
assert system("helloworld.exe")
|
41
78
|
end
|
42
79
|
|
43
80
|
def test_writefile
|
44
|
-
|
45
|
-
|
81
|
+
with_fixture 'writefile' do
|
82
|
+
assert system("ruby", ocra, "writefile.rb", *DefaultArgs)
|
83
|
+
assert File.exist?("writefile.exe")
|
84
|
+
assert system("writefile.exe")
|
85
|
+
assert File.exist?("output.txt")
|
86
|
+
assert "output", File.read("output.txt")
|
46
87
|
end
|
47
|
-
assert system("ruby", ocra, "--quiet", "writefile.rb")
|
48
|
-
assert File.exist?("writefile.exe")
|
49
|
-
assert system("writefile.exe")
|
50
|
-
assert File.exist?("output.txt")
|
51
|
-
assert "output", File.read("output.txt")
|
52
88
|
end
|
53
89
|
|
54
90
|
def test_exitstatus
|
55
|
-
|
56
|
-
|
91
|
+
with_fixture 'exitstatus' do
|
92
|
+
assert system("ruby", ocra, "exitstatus.rb", *DefaultArgs)
|
93
|
+
system("exitstatus.exe")
|
94
|
+
assert_equal 167, $?.exitstatus
|
57
95
|
end
|
58
|
-
assert system("ruby", ocra, "--quiet", "exitstatus.rb")
|
59
|
-
system("exitstatus.exe")
|
60
|
-
assert_equal 167, $?.exitstatus
|
61
96
|
end
|
62
97
|
|
63
98
|
def test_arguments
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
f << "exit(5)\n"
|
71
|
-
f << "end"
|
72
|
-
end
|
73
|
-
assert system("ruby", ocra, "--quiet", "arguments.rb")
|
74
|
-
assert File.exist?("arguments.exe")
|
75
|
-
# system(File.expand_path("arguments.exe"), "foo", "bar baz", "\"smile\"")
|
76
|
-
system("arguments.exe foo \"bar baz\"")
|
77
|
-
assert_equal 5, $?.exitstatus
|
99
|
+
with_fixture 'arguments' do
|
100
|
+
assert system("ruby", ocra, "arguments.rb", *DefaultArgs)
|
101
|
+
assert File.exist?("arguments.exe")
|
102
|
+
system("arguments.exe foo \"bar baz\"")
|
103
|
+
assert_equal 5, $?.exitstatus
|
104
|
+
end
|
78
105
|
end
|
79
106
|
|
80
107
|
def test_stdout_redir
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
108
|
+
with_fixture 'stdoutredir' do
|
109
|
+
assert system("ruby", ocra, "stdoutredir.rb", *DefaultArgs)
|
110
|
+
assert File.exist?("stdoutredir.exe")
|
111
|
+
system("stdoutredir.exe > output.txt")
|
112
|
+
assert File.exist?("output.txt")
|
113
|
+
assert_equal "Hello, World!\n", File.read("output.txt")
|
85
114
|
end
|
86
|
-
assert system("ruby", ocra, "--quiet", "stdoutredir.rb")
|
87
|
-
assert File.exist?("stdoutredir.exe")
|
88
|
-
system("stdoutredir.exe > output.txt")
|
89
|
-
assert File.exist?("output.txt")
|
90
|
-
assert_equal "Hello, World!\n", File.read("output.txt")
|
91
115
|
end
|
92
116
|
|
93
117
|
def test_stdin_redir
|
94
|
-
|
95
|
-
|
118
|
+
with_fixture 'stdinredir' do
|
119
|
+
assert system("ruby", ocra, "stdinredir.rb", *DefaultArgs)
|
120
|
+
assert File.exist?("stdinredir.exe")
|
121
|
+
system("stdinredir.exe < input.txt")
|
122
|
+
assert 104, $?.exitstatus
|
96
123
|
end
|
97
|
-
File.open("stdinredir.rb", "w") do |f|
|
98
|
-
f << "if $0 == __FILE__\n"
|
99
|
-
f << " exit 104 if gets == \"Hello, World!\\n\""
|
100
|
-
f << "end\n"
|
101
|
-
end
|
102
|
-
assert system("ruby", ocra, "--quiet", "stdinredir.rb")
|
103
|
-
assert File.exist?("stdinredir.exe")
|
104
|
-
system("stdinredir.exe < input.txt")
|
105
|
-
assert 104, $?.exitstatus
|
106
124
|
end
|
107
125
|
|
108
126
|
def test_gdbmdll
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
gdbmdllpath = Dir[File.join(bindir, 'gdbm*.dll')][0]
|
116
|
-
raise "gdbm dll was not found" unless gdbmdllpath
|
117
|
-
gdbmdll = File.basename(gdbmdllpath)
|
118
|
-
assert system("ruby", ocra, "--quiet", "--dll", gdbmdll, "gdbmdll.rb")
|
119
|
-
path = ENV['PATH']
|
120
|
-
ENV['PATH'] = "."
|
121
|
-
begin
|
122
|
-
system("gdbmdll.exe")
|
123
|
-
ensure
|
124
|
-
ENV['PATH'] = path
|
127
|
+
with_fixture 'gdbmdll' do
|
128
|
+
assert system("ruby", ocra, "gdbmdll.rb", *DefaultArgs)
|
129
|
+
with_env 'PATH' => '.' do
|
130
|
+
system("gdbmdll.exe")
|
131
|
+
assert_equal 104, $?.exitstatus
|
132
|
+
end
|
125
133
|
end
|
126
|
-
assert_equal 104, $?.exitstatus
|
127
134
|
end
|
128
135
|
|
129
136
|
def test_relative_require
|
130
|
-
|
131
|
-
|
132
|
-
|
137
|
+
with_fixture 'relativerequire' do
|
138
|
+
assert system("ruby", ocra, "relativerequire.rb", *DefaultArgs)
|
139
|
+
assert File.exist?("relativerequire.exe")
|
140
|
+
system("relativerequire.exe")
|
141
|
+
assert_equal 160, $?.exitstatus
|
133
142
|
end
|
134
|
-
|
135
|
-
|
136
|
-
|
143
|
+
end
|
144
|
+
|
145
|
+
# Test that autoloaded files which are not actually loaded while
|
146
|
+
# running the script through Ocra are included in the resulting
|
147
|
+
# executable.
|
148
|
+
def test_autoload
|
149
|
+
with_fixture 'autoload' do
|
150
|
+
assert system("ruby", ocra, "autoload.rb", *DefaultArgs)
|
151
|
+
assert File.exist?("autoload.exe")
|
152
|
+
File.unlink('foo.rb')
|
153
|
+
assert system("autoload.exe")
|
137
154
|
end
|
138
|
-
assert system("ruby", ocra, "--quiet", "relativerequire.rb")
|
139
|
-
assert File.exist?("relativerequire.exe")
|
140
|
-
system("relativerequire.exe")
|
141
|
-
assert_equal 160, $?.exitstatus
|
142
155
|
end
|
143
156
|
|
144
|
-
|
145
|
-
|
146
|
-
|
157
|
+
# Test that autoload statement which point to non-existing files are
|
158
|
+
# ignored by Ocra (a warning may be logged).
|
159
|
+
def test_autoload_missing
|
160
|
+
with_fixture 'autoloadmissing' do
|
161
|
+
assert system("ruby", ocra, "autoloadmissing.rb", *DefaultArgs)
|
162
|
+
assert File.exist?("autoloadmissing.exe")
|
163
|
+
assert system("autoloadmissing.exe")
|
147
164
|
end
|
148
|
-
assert system("ruby", ocra, "--quiet", "exiting.rb")
|
149
|
-
assert File.exist?("exiting.exe")
|
150
|
-
system("exiting.exe")
|
151
|
-
assert_equal 214, $?.exitstatus
|
152
165
|
end
|
153
166
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
167
|
+
# Test that Ocra picks up autoload statement nested in modules.
|
168
|
+
def test_autoload_nested
|
169
|
+
with_fixture 'autoloadnested' do
|
170
|
+
assert system("ruby", ocra, "autoloadnested.rb", *DefaultArgs)
|
171
|
+
assert File.exist?("autoloadnested.exe")
|
172
|
+
File.unlink('foo.rb')
|
173
|
+
assert system("autoloadnested.exe")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Test that we can use custom include paths when invoking Ocra (ruby
|
178
|
+
# -I somepath). In this case the lib scripts are put in the src/
|
179
|
+
# directory.
|
180
|
+
def test_relative_loadpath1_ilib
|
181
|
+
with_fixture 'relloadpath1' do
|
182
|
+
assert system('ruby', '-I', 'lib', ocra, 'relloadpath1.rb', *DefaultArgs)
|
183
|
+
assert File.exist?('relloadpath1.exe')
|
184
|
+
assert system('relloadpath1.exe')
|
159
185
|
end
|
160
|
-
|
161
|
-
|
186
|
+
end
|
187
|
+
|
188
|
+
# Same as above with './lib'
|
189
|
+
def test_relative_loadpath_idotlib
|
190
|
+
with_fixture 'relloadpath1' do
|
191
|
+
assert system('ruby', '-I', './lib', ocra, 'relloadpath1.rb', *DefaultArgs)
|
192
|
+
assert File.exist?('relloadpath1.exe')
|
193
|
+
assert system('relloadpath1.exe')
|
162
194
|
end
|
163
|
-
assert system("ruby", ocra, "--quiet", "autoload.rb")
|
164
|
-
assert File.exist?("autoload.exe")
|
165
|
-
File.unlink('foo.rb')
|
166
|
-
assert system("autoload.exe")
|
167
|
-
# assert_equal 214, $?.exitstatus
|
168
195
|
end
|
169
196
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
197
|
+
# Test that we can use custom include paths when invoking Ocra (env
|
198
|
+
# RUBYLIB=lib). In this case the lib scripts are put in the src/
|
199
|
+
# directory.
|
200
|
+
def test_relative_loadpath_rubyliblib
|
201
|
+
with_fixture 'relloadpath1' do
|
202
|
+
with_env 'RUBYLIB' => 'lib' do
|
203
|
+
assert system('ruby', ocra, 'relloadpath1.rb', *DefaultArgs)
|
204
|
+
assert File.exist?('relloadpath1.exe')
|
205
|
+
assert system('relloadpath1.exe')
|
206
|
+
end
|
174
207
|
end
|
175
|
-
assert system("ruby", ocra, "--quiet", "autoloadmissing.rb")
|
176
|
-
assert File.exist?("autoloadmissing.exe")
|
177
|
-
assert system("autoloadmissing.exe")
|
178
208
|
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
209
|
+
|
210
|
+
# Same as above with './lib'
|
211
|
+
def test_relative_loadpath_rubylibdotlib
|
212
|
+
with_fixture 'relloadpath1' do
|
213
|
+
with_env 'RUBYLIB' => './lib' do
|
214
|
+
assert system('ruby', ocra, 'relloadpath1.rb', *DefaultArgs)
|
215
|
+
assert File.exist?('relloadpath1.exe')
|
216
|
+
assert system('relloadpath1.exe')
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Relative path with .. prefix (../lib).
|
222
|
+
def test_relative_loadpath2_idotdotlib
|
223
|
+
with_fixture 'relloadpath2' do
|
224
|
+
cd 'src' do
|
225
|
+
assert system('ruby', '-I', '../lib', ocra, 'relloadpath2.rb', *DefaultArgs)
|
226
|
+
assert File.exist?('relloadpath2.exe')
|
227
|
+
assert system('relloadpath2.exe')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Test that scripts which modify $LOAD_PATH with a relative path
|
233
|
+
# (./lib) work correctly.
|
234
|
+
def test_relloadpath3
|
235
|
+
with_fixture 'relloadpath3' do
|
236
|
+
assert system('ruby', ocra, 'relloadpath3.rb', *DefaultArgs)
|
237
|
+
assert File.exist?('relloadpath3.exe')
|
238
|
+
assert system('relloadpath3.exe')
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Test that scripts which modify $LOAD_PATH with a relative path
|
243
|
+
# (../lib) work correctly.
|
244
|
+
def test_relloadpath4
|
245
|
+
with_fixture 'relloadpath4' do
|
246
|
+
cd 'src' do
|
247
|
+
assert system('ruby', ocra, 'relloadpath4.rb', *DefaultArgs)
|
248
|
+
assert File.exist?('relloadpath4.exe')
|
249
|
+
assert system('relloadpath4.exe')
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_version
|
255
|
+
assert_match(/^Ocra \d+(\.\d)+$/, `ruby #{ocra} --version`)
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_icon
|
259
|
+
with_fixture 'helloworld' do
|
260
|
+
icofile = File.join(OcraRoot, 'src', 'vit-ruby.ico')
|
261
|
+
assert system("ruby", ocra, '--icon', icofile, "helloworld.rb", *DefaultArgs)
|
262
|
+
assert File.exist?("helloworld.exe")
|
263
|
+
assert system("helloworld.exe")
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_resource
|
268
|
+
with_fixture 'resource' do
|
269
|
+
assert system("ruby", ocra, "resource.rb", "resource.txt", "res/resource.txt", *DefaultArgs)
|
270
|
+
assert File.exist?("resource.exe")
|
271
|
+
assert system("resource.exe")
|
272
|
+
end
|
198
273
|
end
|
199
274
|
end
|
275
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ocra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Christensen
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-27 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -46,6 +46,7 @@ files:
|
|
46
46
|
- share/ocra/lzma.exe
|
47
47
|
- share/ocra/stub.exe
|
48
48
|
- share/ocra/stubw.exe
|
49
|
+
- share/ocra/edicon.exe
|
49
50
|
- test/test_ocra.rb
|
50
51
|
- lib/ocra.rb
|
51
52
|
has_rdoc: true
|