irpack 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ir
2
+
3
+ =begin
4
+ Copyright (c) 2010 Ryuichi Sakamoto.
5
+
6
+ This software is provided 'as-is', without any express or implied
7
+ warranty. In no event will the authors be held liable for any damages
8
+ arising from the use of this software.
9
+
10
+ Permission is granted to anyone to use this software for any purpose,
11
+ including commercial applications, and to alter it and redistribute it
12
+ freely, subject to the following restrictions:
13
+
14
+ 1. The origin of this software must not be misrepresented; you must not
15
+ claim that you wrote the original software. If you use this software
16
+ in a product, an acknowledgment in the product documentation would be
17
+ appreciated but is not required.
18
+
19
+ 2. Altered source versions must be plainly marked as such, and must not be
20
+ misrepresented as being the original software.
21
+
22
+ 3. This notice may not be removed or altered from any source
23
+ distribution.
24
+ =end
25
+
26
+ require 'irpack'
27
+ require 'optparse'
28
+
29
+ packdir = nil
30
+ output_file = nil
31
+ target = :exe
32
+ compress = false
33
+ stdlib = true
34
+ opt = OptionParser.new
35
+ opt.on('-d SOURCEDIR', 'Specify pack directory. [base of ENTRYFILE]') {|v| packdir = v }
36
+ opt.on('-o OUTPUTFILE', 'Specify output file name.') {|v| output_file = v }
37
+ opt.on('-w', 'Generate window app.') { target = :winexe }
38
+ opt.on('-W', 'Generate console app.[default]') { target = :exe }
39
+ opt.on('--compress', 'Compress package.') { compress = true }
40
+ opt.on('--no-stdlib', 'Do not include IronRuby assemblies.') {|v| stdlib = v }
41
+ opt.banner = "Usage: #{$0} [options] ENTRYFILE"
42
+ opt.parse!(ARGV)
43
+
44
+ if ARGV.size<1 then
45
+ $stderr.puts opt.help
46
+ exit 1
47
+ end
48
+
49
+ entry_file = ARGV[0]
50
+ packdir ||= File.dirname(entry_file)
51
+ output_file ||= File.join(File.dirname(entry_file), File.basename(entry_file, '.*')+'.exe')
52
+ IRPack.pack_dir(packdir, entry_file, output_file,
53
+ :target => target,
54
+ :compress => compress,
55
+ :stdlib => stdlib)
56
+
@@ -0,0 +1,504 @@
1
+ =begin
2
+ Copyright (c) 2010 Ryuichi Sakamoto.
3
+
4
+ This software is provided 'as-is', without any express or implied
5
+ warranty. In no event will the authors be held liable for any damages
6
+ arising from the use of this software.
7
+
8
+ Permission is granted to anyone to use this software for any purpose,
9
+ including commercial applications, and to alter it and redistribute it
10
+ freely, subject to the following restrictions:
11
+
12
+ 1. The origin of this software must not be misrepresented; you must not
13
+ claim that you wrote the original software. If you use this software
14
+ in a product, an acknowledgment in the product documentation would be
15
+ appreciated but is not required.
16
+
17
+ 2. Altered source versions must be plainly marked as such, and must not be
18
+ misrepresented as being the original software.
19
+
20
+ 3. This notice may not be removed or altered from any source
21
+ distribution.
22
+ =end
23
+
24
+ require 'erb'
25
+ require 'fileutils'
26
+ require 'tmpdir'
27
+ require 'pathname'
28
+ require 'WindowsBase'
29
+
30
+ unless Dir.respond_to?(:mktmpdir) then
31
+ def Dir.mktmpdir(prefix_suffix=['d',''], tmpdir=Dir.tmpdir, &block)
32
+ if prefix_suffix.kind_of?(String) then
33
+ prefix = prefix_suffix
34
+ suffix = ''
35
+ else
36
+ prefix = prefix_suffix[0]
37
+ suffix = prefix_suffix[1]
38
+ end
39
+ n = 0
40
+ begin
41
+ path = File.join(tmpdir, "#{prefix}-#{Time.now.to_i}-#{$$}-#{rand(0x100000000).to_s(36)}-#{suffix}-#{n}")
42
+ Dir.mkdir(path, 0700)
43
+ rescue Errno::EEXIST
44
+ n += 1
45
+ retry
46
+ end
47
+
48
+ if block then
49
+ begin
50
+ block.call(path)
51
+ ensure
52
+ FileUtils.remove_entry_secure(path)
53
+ end
54
+ else
55
+ path
56
+ end
57
+ end
58
+ end
59
+
60
+ module IRPack
61
+ include System
62
+ include System::Reflection
63
+
64
+ module CSCompiler
65
+ include Microsoft::CSharp
66
+ include System::CodeDom::Compiler
67
+ include System::Reflection
68
+
69
+ module_function
70
+ def compiler_version
71
+ case System::Environment.version.major
72
+ when 4
73
+ 'v4.0'
74
+ when 2
75
+ 'v3.5'
76
+ end
77
+ end
78
+
79
+ def system_assemblies
80
+ case compiler_version
81
+ when 'v4.0'
82
+ [
83
+ 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
84
+ 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
85
+ 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
86
+ ]
87
+ when 'v3.5'
88
+ [
89
+ 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
90
+ 'WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
91
+ 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
92
+ ]
93
+ end
94
+ end
95
+
96
+ def system_assembly_files
97
+ system_assemblies.collect {|name|
98
+ Assembly.reflection_only_load(name.to_clr_string).location
99
+ }
100
+ end
101
+
102
+ def find_assembly(paths, file)
103
+ path = paths.find {|path| File.exist?(File.join(path, file)) }
104
+ if path then
105
+ File.join(path, file)
106
+ else
107
+ file
108
+ end
109
+ end
110
+
111
+ class CompileError < RuntimeError; end
112
+ def compile(target, srcs, references, resources, output_name)
113
+ opts = System::Collections::Generic::Dictionary[System::String,System::String].new
114
+ opts['CompilerVersion'] = compiler_version
115
+ @compiler = CSharpCodeProvider.new(opts)
116
+ srcs = srcs.kind_of?(Array) ? srcs : [srcs]
117
+ refs = system_assembly_files + references
118
+ refs = System::Array[System::String].new(refs.size) {|i| refs[i] }
119
+ icon = resources.find {|rc| File.extname(rc)=='.ico' }
120
+
121
+ params = CompilerParameters.new(refs, output_name, false)
122
+ params.generate_in_memory = false
123
+ compiler_options = ['/optimize+']
124
+ case target
125
+ when :exe, 'exe'
126
+ params.generate_executable = true
127
+ compiler_options << '/target:exe'
128
+ compiler_options << "/win32icon:#{icon}" if icon
129
+ when :winexe, 'winexe'
130
+ params.generate_executable = true
131
+ compiler_options << '/target:winexe'
132
+ compiler_options << "/win32icon:#{icon}" if icon
133
+ else
134
+ params.generate_executable = false
135
+ compiler_options << '/target:library'
136
+ end
137
+ params.compiler_options = compiler_options.join(' ')
138
+ resources.each do |rc|
139
+ params.embedded_resources.add(rc)
140
+ end
141
+ srcs = System::Array[System::String].new(srcs.size) {|i| srcs[i] }
142
+ result = @compiler.compile_assembly_from_source(params, srcs)
143
+ result.errors.each do |err|
144
+ if err.is_warning then
145
+ $stderr.puts(err.to_s)
146
+ else
147
+ raise CompileError, err.to_s
148
+ end
149
+ end
150
+ result.path_to_assembly
151
+ end
152
+ end
153
+ end
154
+
155
+ module IRPack
156
+ BootLoaderSource = <<CS
157
+ using System;
158
+ using System.IO;
159
+ using System.IO.Packaging;
160
+ using System.Reflection;
161
+
162
+ namespace <%= module_name %> {
163
+ public class BootLoader
164
+ {
165
+ private static Assembly LoadAssemblyFromPackage(AppDomain domain, Package package, string file)
166
+ {
167
+ var uri = PackUriHelper.CreatePartUri(new Uri(file, UriKind.Relative));
168
+ if (package.PartExists(uri)) {
169
+ var stream = package.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
170
+ var raw = new byte[stream.Length];
171
+ stream.Read(raw, 0, (int)stream.Length);
172
+ stream.Close();
173
+ return domain.Load(raw);
174
+ }
175
+ else {
176
+ return null;
177
+ }
178
+ }
179
+
180
+ private static Assembly LoadAssembly(AppDomain domain, Package package, string file)
181
+ {
182
+ try {
183
+ return domain.Load(file);
184
+ }
185
+ catch (FileNotFoundException)
186
+ {
187
+ return LoadAssemblyFromPackage(domain, package, file);
188
+ }
189
+ }
190
+
191
+ public static int Main(string[] args)
192
+ {
193
+ AppDomain domain = AppDomain.CurrentDomain;
194
+ domain.AssemblyResolve += new ResolveEventHandler(delegate (object sender, ResolveEventArgs e) {
195
+ foreach (var asm in domain.GetAssemblies()) {
196
+ if (e.Name==asm.FullName) {
197
+ return asm;
198
+ }
199
+ }
200
+ throw new FileNotFoundException(e.Name);
201
+ });
202
+ var stream = Assembly.GetEntryAssembly().GetManifestResourceStream(@"<%= package_file %>");
203
+ var package = Package.Open(stream, FileMode.Open, FileAccess.Read);
204
+ <% preload_assemblies.each do |asm| %>
205
+ LoadAssembly(domain, package, @"<%= asm %>");
206
+ <% end %>
207
+ var entry_point = LoadAssemblyFromPackage(domain, package, @"<%= module_name %>.EntryPoint.dll");
208
+ var main = entry_point.GetType(@"<%= module_name %>.EntryPoint").GetMethod("Main");
209
+ int result = (int)(main.Invoke(null, new object[] { package, args }));
210
+ package.Close();
211
+ return result;
212
+ }
213
+ }
214
+ }
215
+ CS
216
+
217
+ EntryPointSource = <<CS
218
+ using System;
219
+ using System.IO;
220
+ using System.IO.Packaging;
221
+ using System.Reflection;
222
+ using Microsoft.Scripting;
223
+ using Microsoft.Scripting.Hosting;
224
+
225
+ namespace <%= module_name %> {
226
+ public class EntryPoint
227
+ {
228
+ public class PackagePAL : PlatformAdaptationLayer
229
+ {
230
+ public Package CurrentPackage { get; set; }
231
+ public PackagePAL(Package pkg)
232
+ {
233
+ CurrentPackage = pkg;
234
+ }
235
+
236
+ private Uri ToPackageLoadPath(string path)
237
+ {
238
+ var domain = AppDomain.CurrentDomain;
239
+ var fullpath = Path.GetFullPath(path);
240
+ var searchpath = Path.GetFullPath(
241
+ domain.RelativeSearchPath!=null ?
242
+ Path.Combine(domain.BaseDirectory, domain.RelativeSearchPath) :
243
+ domain.BaseDirectory);
244
+ if (fullpath.StartsWith(searchpath)) {
245
+ var relpath = fullpath.Substring(searchpath.Length, fullpath.Length-searchpath.Length);
246
+ return PackUriHelper.CreatePartUri(new Uri(relpath, UriKind.Relative));
247
+ }
248
+ else {
249
+ return PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative));
250
+ }
251
+ }
252
+
253
+ private Uri ToPackagePath(string path)
254
+ {
255
+ var fullpath = Path.GetFullPath(path);
256
+ var searchpath = Path.GetDirectoryName(Path.GetFullPath(Assembly.GetEntryAssembly().Location));
257
+ if (fullpath.StartsWith(searchpath)) {
258
+ var relpath = fullpath.Substring(searchpath.Length, fullpath.Length-searchpath.Length);
259
+ return PackUriHelper.CreatePartUri(new Uri(relpath, UriKind.Relative));
260
+ }
261
+ else {
262
+ return PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative));
263
+ }
264
+ }
265
+
266
+ public override Assembly LoadAssembly(string name)
267
+ {
268
+ foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
269
+ if (asm.FullName==name) {
270
+ return asm;
271
+ }
272
+ }
273
+ return Assembly.Load(name);
274
+ }
275
+
276
+ public override Assembly LoadAssemblyFromPath(string path)
277
+ {
278
+ try {
279
+ return Assembly.LoadFile(path);
280
+ }
281
+ catch (FileNotFoundException e) {
282
+ var uri = ToPackageLoadPath(path);
283
+ if (CurrentPackage.PartExists(uri)) {
284
+ var stream = CurrentPackage.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
285
+ var raw = new byte[stream.Length];
286
+ stream.Read(raw, 0, (int)stream.Length);
287
+ stream.Close();
288
+ return Assembly.Load(raw);
289
+ }
290
+ else {
291
+ throw e;
292
+ }
293
+ }
294
+ }
295
+
296
+ public override bool FileExists(string path)
297
+ {
298
+ if (File.Exists(path)) {
299
+ return true;
300
+ }
301
+ else {
302
+ var uri = ToPackagePath(path);
303
+ return CurrentPackage.PartExists(uri);
304
+ }
305
+ }
306
+
307
+ public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share)
308
+ {
309
+ if (mode==FileMode.Open && access==FileAccess.Read) {
310
+ var uri = ToPackagePath(path);
311
+ if (CurrentPackage.PartExists(uri)) {
312
+ return CurrentPackage.GetPart(uri).GetStream(mode, access);
313
+ }
314
+ else {
315
+ return new FileStream(path, mode, access, share);
316
+ }
317
+ }
318
+ else {
319
+ return new FileStream(path, mode, access, share);
320
+ }
321
+ }
322
+
323
+ public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
324
+ {
325
+ if (mode==FileMode.Open && access==FileAccess.Read) {
326
+ var uri = ToPackagePath(path);
327
+ if (CurrentPackage.PartExists(uri)) {
328
+ return CurrentPackage.GetPart(uri).GetStream(mode, access);
329
+ }
330
+ else {
331
+ return new FileStream(path, mode, access, share, bufferSize);
332
+ }
333
+ }
334
+ else {
335
+ return new FileStream(path, mode, access, share, bufferSize);
336
+ }
337
+ }
338
+
339
+ public override Stream OpenInputFileStream(string path)
340
+ {
341
+ var uri = ToPackagePath(path);
342
+ if (CurrentPackage.PartExists(uri)) {
343
+ return CurrentPackage.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
344
+ }
345
+ else {
346
+ return new FileStream(path, FileMode.Open, FileAccess.Read);
347
+ }
348
+ }
349
+ }
350
+
351
+ public class IRHost : ScriptHost
352
+ {
353
+ private PlatformAdaptationLayer PAL_;
354
+ public override PlatformAdaptationLayer PlatformAdaptationLayer { get { return PAL_; } }
355
+ public IRHost(Package pkg)
356
+ {
357
+ PAL_ = new PackagePAL(pkg);
358
+ }
359
+ }
360
+
361
+ public static int Main(Package package, string[] args)
362
+ {
363
+ var runtime_setup = new ScriptRuntimeSetup();
364
+ runtime_setup.LanguageSetups.Add(IronRuby.Ruby.CreateRubySetup());
365
+ runtime_setup.Options["MainFile"] = "<%= entry_file %>";
366
+ runtime_setup.Options["Arguments"] = args;
367
+ runtime_setup.HostType = typeof(IRHost);
368
+ runtime_setup.HostArguments = new object[] { package };
369
+ var engine = IronRuby.Ruby.GetEngine(IronRuby.Ruby.CreateRuntime(runtime_setup));
370
+ try {
371
+ engine.ExecuteFile("<%= entry_file %>");
372
+ return 0;
373
+ }
374
+ catch (IronRuby.Builtins.SystemExit e) {
375
+ return e.Status;
376
+ }
377
+ }
378
+ }
379
+ }
380
+ CS
381
+ module_function
382
+ def bootloader_source(module_name, package_file, preload_assemblies)
383
+ ERB.new(BootLoaderSource).result(binding)
384
+ end
385
+
386
+ def entrypoint_source(module_name, entry_file)
387
+ ERB.new(EntryPointSource).result(binding)
388
+ end
389
+ end
390
+
391
+ module IRPack
392
+ module Packager
393
+ include System
394
+ include System::IO::Packaging
395
+
396
+ RelType = 'http://schemas.openxmlformats.org/package/2006/relationships/meta data/core-properties'
397
+ module_function
398
+ def pack(files, package_file, compress=false)
399
+ compress_option = compress ? CompressionOption.normal : CompressionOption.not_compressed
400
+ package = Package.open(package_file, System::IO::FileMode.create)
401
+ files.each do |src, dest|
402
+ uri = PackUriHelper.create_part_uri(Uri.new(dest, UriKind.relative))
403
+ part = package.create_part(uri, 'application/octet-stream', compress_option)
404
+ stream = part.get_stream
405
+ File.open(src, 'rb') do |f|
406
+ data = f.read
407
+ stream.write(data, 0, data.size)
408
+ end
409
+ stream.close
410
+ package.create_relationship(uri, TargetMode.internal, RelType)
411
+ end
412
+ package.close
413
+ end
414
+
415
+ def pack_dir(dir_name, package_file)
416
+ files = {}
417
+ base = Pathname.new(dir_name)
418
+ Dir.glob(base.join('**', '*')) do |fn|
419
+ files[fn] = Pathname.new(fn).relative_path_from(base)
420
+ end
421
+ pack(files, package_file)
422
+ end
423
+ end
424
+
425
+ AssemblyPath = ::File.dirname(Assembly.get_entry_assembly.location.to_s)
426
+ PreloadAssemblies = %w[
427
+ Microsoft.Dynamic.dll
428
+ Microsoft.Scripting.dll
429
+ Microsoft.Scripting.Core.dll
430
+ IronRuby.dll
431
+ IronRuby.Libraries.dll
432
+ IronRuby.Libraries.Yaml.dll
433
+ ]
434
+
435
+ module_function
436
+ def path_to_module_name(filename)
437
+ name = File.basename(filename, '.*')
438
+ name.gsub!(/[^A-Za-z0-9_]/, '_')
439
+ /^[A-Za-z]/=~name ? name : ('M'+name)
440
+ end
441
+
442
+ def pack(files, entry_file, output_file, options={})
443
+ preload_assemblies = PreloadAssemblies.collect {|fn|
444
+ File.join(AssemblyPath, fn)
445
+ }.select {|fn|
446
+ File.exist?(fn)
447
+ }
448
+ basename = File.basename(output_file, '.*')
449
+ module_name = path_to_module_name(output_file)
450
+ resources = options[:resources] || []
451
+ target = options[:target] || :exe
452
+ stdlib = options.include?(:stdlib) ? options[:stdlib] : true
453
+ compress = options.include?(:compress) ? options[:compress] : false
454
+ pack_files = files.dup
455
+
456
+ Dir.mktmpdir(File.basename($0,'.*')) do |tmp_path|
457
+ entry_src = entrypoint_source(module_name, entry_file)
458
+ entry_dll = File.join(tmp_path, module_name+'.EntryPoint.dll')
459
+ CSCompiler.compile(:dll, entry_src, preload_assemblies, [], entry_dll)
460
+ pack_files[entry_dll] = File.basename(entry_dll)
461
+ if stdlib then
462
+ preload_assemblies.each do |asm|
463
+ pack_files[asm] = File.basename(asm)
464
+ end
465
+ end
466
+ package_file = File.join(tmp_path, basename+'.pkg')
467
+ Packager.pack(pack_files, package_file, compress)
468
+
469
+ target_src = bootloader_source(
470
+ module_name,
471
+ File.basename(package_file),
472
+ preload_assemblies.collect {|fn| File.basename(fn) }
473
+ )
474
+ Dir.chdir(tmp_path) do
475
+ CSCompiler.compile(target, target_src, [], [File.basename(package_file)], output_file)
476
+ end
477
+ end
478
+ end
479
+
480
+ def pack_dir(pack_dir, entry_file, output_file, options={})
481
+ output_file = File.expand_path(output_file)
482
+ entry_packed = nil
483
+ pack_files = {}
484
+ resources = []
485
+ base = Pathname.new(pack_dir).expand_path
486
+ Dir.glob(base.join('**', '*')) do |fn|
487
+ path = Pathname.new(File.expand_path(fn))
488
+ next if path==output_file
489
+ relpath = path.relative_path_from(base)
490
+ pack_files[path] = relpath
491
+ if not entry_packed and
492
+ (path.to_s==File.expand_path(entry_file) or
493
+ path.basename.to_s==entry_file or
494
+ relpath.to_s==entry_file) then
495
+ entry_packed = relpath
496
+ end
497
+ resources << path.to_s if path.extname=='.ico'
498
+ end
499
+ raise ArgumentError, "Entry file `#{entry_file}' is not in packed directory."unless entry_packed
500
+ options = options.merge(:resources => resources)
501
+ pack(pack_files, entry_packed, output_file, options)
502
+ end
503
+ end
504
+
@@ -0,0 +1,48 @@
1
+
2
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'test/unit'
4
+ require 'tempfile'
5
+ require 'tmpdir'
6
+ require 'fileutils'
7
+ require 'irpack'
8
+
9
+ require 'WindowsBase'
10
+ include System
11
+ include System::IO
12
+ include System::IO::Packaging
13
+
14
+ class TC_CSCompiler < Test::Unit::TestCase
15
+ def test_compile_dll
16
+ src = <<-CS
17
+ using System;
18
+ namespace hoge {
19
+ class Hoge {
20
+ public static int Main(string[] args) {
21
+ System.Console.WriteLine("hoge");
22
+ return 0;
23
+ }
24
+ }
25
+ }
26
+ CS
27
+ references = []
28
+ resources = []
29
+ output_file = Tempfile.new(File.basename(__FILE__))
30
+ output_file.close
31
+ result = IRPack::CSCompiler.compile(
32
+ :dll,
33
+ src,
34
+ references,
35
+ resources,
36
+ output_file.path
37
+ )
38
+ assert_equal(output_file.path, result)
39
+ asm = nil
40
+ assert_nothing_raised do
41
+ asm = System::Reflection::Assembly.load_from(output_file.path)
42
+ end
43
+ assert(asm.get_type('hoge.Hoge'))
44
+ assert_nil(asm.entry_point)
45
+ assert_equal(System::Reflection::Assembly.get_entry_assembly.image_runtime_version, asm.image_runtime_version)
46
+ end
47
+ end
48
+
@@ -0,0 +1,56 @@
1
+
2
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'test/unit'
4
+ require 'tempfile'
5
+ require 'tmpdir'
6
+ require 'fileutils'
7
+ require 'irpack'
8
+
9
+ require 'WindowsBase'
10
+ include System
11
+ include System::IO
12
+ include System::IO::Packaging
13
+
14
+ class TC_Packager < Test::Unit::TestCase
15
+ SrcFiles = {
16
+ File.join(File.dirname(__FILE__), 'test_packager.rb') => 'foo.rb',
17
+ File.join(File.dirname(__FILE__), 'test_cscompiler.rb') => 'bar.rb',
18
+ }
19
+
20
+ def test_pack
21
+ target = Tempfile.new(File.basename(__FILE__))
22
+ target.close
23
+ IRPack::Packager.pack(SrcFiles, target.path)
24
+ package = Package.open(target.path, FileMode.open)
25
+ SrcFiles.each do |src, dest|
26
+ uri = Uri.new(File.join('/', dest), UriKind.relative)
27
+ assert(package.part_exists(uri))
28
+ stream = package.get_part(uri).get_stream
29
+ bytes = System::Array[System::Byte].new(stream.length)
30
+ stream.read(bytes, 0, stream.length)
31
+ assert_equal(File.open(src, 'rb'){|f|f.read}, bytes.to_a.pack('C*'))
32
+ end
33
+ end
34
+
35
+ def test_pack_dir
36
+ Dir.mktmpdir do |src_path|
37
+ SrcFiles.each do |src, dest|
38
+ FileUtils.mkdir_p(File.join(src_path, File.dirname(dest)))
39
+ FileUtils.copy(src, File.join(src_path, dest))
40
+ end
41
+ target = Tempfile.new(File.basename(__FILE__))
42
+ target.close
43
+ IRPack::Packager.pack_dir(src_path, target.path)
44
+ package = Package.open(target.path, FileMode.open)
45
+ SrcFiles.each do |src, dest|
46
+ uri = Uri.new(File.join('/', dest), UriKind.relative)
47
+ assert(package.part_exists(uri))
48
+ stream = package.get_part(uri).get_stream
49
+ bytes = System::Array[System::Byte].new(stream.length)
50
+ stream.read(bytes, 0, stream.length)
51
+ assert_equal(File.open(src, 'rb'){|f|f.read}, bytes.to_a.pack('C*'))
52
+ end
53
+ end
54
+ end
55
+ end
56
+
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: irpack
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - kumaryu
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-11 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: |
22
+ IRPack converts your IronRuby scripts to a standalone .exe file.
23
+ Generated executable does not require IronRuby, but only .NET Framework or mono.
24
+
25
+ email: kumaryu@kumayu.net
26
+ executables:
27
+ - irpack
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - bin/irpack
34
+ - lib/irpack.rb
35
+ - test/test_cscompiler.rb
36
+ - test/test_packager.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/kumaryu/irpack
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements:
63
+ - none
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.7
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Generate a standalone executable file from IronRuby scripts.
69
+ test_files: []
70
+