irpack 0.1.0 → 0.2.1

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.
@@ -0,0 +1,87 @@
1
+ =begin
2
+ Copyright (c) 2010-2011 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 'irpack'
25
+ require 'optparse'
26
+ require 'pathname'
27
+
28
+ module IRPack
29
+ module Application
30
+ Arguments = Struct.new(
31
+ :output_file,
32
+ :target,
33
+ :compress,
34
+ :embed_references,
35
+ :entry_file,
36
+ :files) do
37
+ def self.parse!(argv)
38
+ args = self.new
39
+ basedir = nil
40
+ args.output_file = nil
41
+ args.target = :exe
42
+ args.compress = false
43
+ args.embed_references = true
44
+ args.entry_file = nil
45
+ args.files = {}
46
+ opt = OptionParser.new
47
+ opt.on('-b BASEDIR', 'Specify base directory. [base of ENTRYFILE]') {|v| basedir = v }
48
+ opt.on('-o OUTPUTFILE', 'Specify output file name.') {|v| args.output_file = v }
49
+ opt.on('--window', 'Generate window app.') { args.target = :winexe }
50
+ opt.on('--console', 'Generate console app.[default]') { args.target = :exe }
51
+ opt.on('--compress', 'Compress package.') { args.compress = true }
52
+ opt.on('--no-embed', 'Do not embed IronRuby assemblies.') {|v| args.embed_references = v }
53
+ opt.banner = "Usage: #{$0} [options] ENTRYFILE [EMBEDFILES...]"
54
+ opt.parse!(argv)
55
+
56
+ if argv.size<1 then
57
+ $stderr.puts opt.help
58
+ nil
59
+ else
60
+ basedir = Pathname.new(File.expand_path(basedir || File.dirname(argv[0])).gsub(/\\/, '/'))
61
+ args.output_file ||= File.join(File.dirname(argv[0]), File.basename(argv[0], '.*')+'.exe')
62
+ args.entry_file = argv[0]
63
+ argv.each_with_index do |file, i|
64
+ fullpath = Pathname.new(file.gsub(/\\/, '/')).expand_path
65
+ relpath = fullpath.relative_path_from(basedir)
66
+ args.files[fullpath.to_s] = relpath.to_s
67
+ args.entry_file = relpath.to_s if i==0
68
+ end
69
+ args
70
+ end
71
+ end
72
+ end
73
+
74
+ def self.run(args)
75
+ return 1 unless args
76
+ IRPack.pack(
77
+ args.output_file,
78
+ args.files,
79
+ args.entry_file,
80
+ :target => args.target,
81
+ :compress => args.compress,
82
+ :embed_references => args.embed)
83
+ return 0
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,110 @@
1
+ =begin
2
+ Copyright (c) 2011 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 'irpack/cscompiler'
26
+
27
+ module IRPack
28
+ module BootLoader
29
+ Source = <<CS
30
+ using System;
31
+ using System.IO;
32
+ using System.IO.Packaging;
33
+ using System.Reflection;
34
+
35
+ namespace <%= module_name %> {
36
+ public class BootLoader
37
+ {
38
+ private static Assembly LoadAssemblyFromPackage(AppDomain domain, Package package, string file)
39
+ {
40
+ var uri = PackUriHelper.CreatePartUri(new Uri(file, UriKind.Relative));
41
+ if (package.PartExists(uri)) {
42
+ var stream = package.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
43
+ var raw = new byte[stream.Length];
44
+ stream.Read(raw, 0, (int)stream.Length);
45
+ stream.Close();
46
+ return domain.Load(raw);
47
+ }
48
+ else {
49
+ return null;
50
+ }
51
+ }
52
+
53
+ private static Assembly LoadAssembly(AppDomain domain, Package package, string file)
54
+ {
55
+ try {
56
+ return domain.Load(file);
57
+ }
58
+ catch (FileNotFoundException)
59
+ {
60
+ return LoadAssemblyFromPackage(domain, package, file);
61
+ }
62
+ }
63
+
64
+ public static int Main(string[] args)
65
+ {
66
+ AppDomain domain = AppDomain.CurrentDomain;
67
+ domain.AssemblyResolve += new ResolveEventHandler(delegate (object sender, ResolveEventArgs e) {
68
+ foreach (var asm in domain.GetAssemblies()) {
69
+ if (e.Name==asm.FullName) {
70
+ return asm;
71
+ }
72
+ }
73
+ throw new FileNotFoundException(e.Name);
74
+ });
75
+ var stream = Assembly.GetEntryAssembly().GetManifestResourceStream(@"<%= package_file %>");
76
+ var package = Package.Open(stream, FileMode.Open, FileAccess.Read);
77
+ <% preload_assemblies.each do |asm| %>
78
+ LoadAssembly(domain, package, @"<%= asm %>");
79
+ <% end %>
80
+ var entry_point = LoadAssemblyFromPackage(domain, package, @"<%= module_name %>.EntryPoint.dll");
81
+ var main = entry_point.GetType(@"<%= module_name %>.EntryPoint").GetMethod("Main");
82
+ int result = (int)(main.Invoke(null, new object[] { package, args }));
83
+ package.Close();
84
+ return result;
85
+ }
86
+ }
87
+ }
88
+ CS
89
+ module_function
90
+ def source(module_name, package_file, preload_assemblies)
91
+ ERB.new(Source).result(binding)
92
+ end
93
+
94
+ def compile(target, output_file, module_name, references, package_file)
95
+ boot_src = source(
96
+ module_name,
97
+ File.basename(package_file),
98
+ references.collect {|fn| File.basename(fn) }
99
+ )
100
+ sysasm = IRPack::CSCompiler.system_assemblies.collect {|asm|
101
+ IRPack::CSCompiler.assembly_location(asm)
102
+ }
103
+ Dir.chdir(File.dirname(package_file)) do
104
+ IRPack::CSCompiler.compile(target, output_file, boot_src, references+sysasm, [File.basename(package_file)])
105
+ end
106
+ output_file
107
+ end
108
+ end
109
+ end
110
+
@@ -0,0 +1,115 @@
1
+ =begin
2
+ Copyright (c) 2011 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
+ module IRPack
25
+ include System
26
+ include System::Reflection
27
+
28
+ module CSCompiler
29
+ include Microsoft::CSharp
30
+ include System::CodeDom::Compiler
31
+ include System::Reflection
32
+
33
+ class CompileError < RuntimeError
34
+ end
35
+
36
+ module_function
37
+ def compiler_version(target_version=System::Environment.version.major)
38
+ case target_version
39
+ when 4
40
+ 'v4.0'
41
+ when 2...4
42
+ 'v3.5'
43
+ else
44
+ raise ArgumentError, "Unsupported version #{target_version}"
45
+ end
46
+ end
47
+
48
+ def system_assemblies(target_version=System::Environment.version.major)
49
+ case compiler_version(target_version)
50
+ when 'v4.0'
51
+ [
52
+ 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
53
+ 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
54
+ 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
55
+ ]
56
+ when 'v3.5'
57
+ [
58
+ 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
59
+ 'WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
60
+ 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
61
+ ]
62
+ end
63
+ end
64
+
65
+ def assembly_location(sig)
66
+ Assembly.reflection_only_load(sig.to_clr_string).location
67
+ end
68
+
69
+ def compile(target, output_name, srcs, references, resources)
70
+ opts = System::Collections::Generic::Dictionary[System::String,System::String].new
71
+ opts['CompilerVersion'] = compiler_version
72
+ @compiler = CSharpCodeProvider.new(opts)
73
+ srcs = srcs.kind_of?(Array) ? srcs : [srcs]
74
+ icon = resources.find {|rc| File.extname(rc)=='.ico' }
75
+
76
+ params = CompilerParameters.new(
77
+ System::Array[System::String].new(references),
78
+ output_name,
79
+ false)
80
+ params.generate_in_memory = false
81
+ compiler_options = ['/optimize+']
82
+ case target
83
+ when :exe, 'exe'
84
+ params.generate_executable = true
85
+ compiler_options << '/target:exe'
86
+ compiler_options << "/win32icon:#{icon}" if icon
87
+ when :winexe, 'winexe'
88
+ params.generate_executable = true
89
+ compiler_options << '/target:winexe'
90
+ compiler_options << "/win32icon:#{icon}" if icon
91
+ when :dll, 'dll', :library, 'library'
92
+ params.generate_executable = false
93
+ compiler_options << '/target:library'
94
+ else
95
+ raise ArgumentError, "target must be :exe, :winexe or :library"
96
+ end
97
+ params.compiler_options = compiler_options.join(' ')
98
+ resources.each do |rc|
99
+ params.embedded_resources.add(rc)
100
+ end
101
+ result = @compiler.compile_assembly_from_source(
102
+ params,
103
+ System::Array[System::String].new(srcs))
104
+ result.errors.each do |err|
105
+ if err.is_warning then
106
+ $stderr.puts(err.to_s)
107
+ else
108
+ raise CompileError, err.to_s
109
+ end
110
+ end
111
+ result.path_to_assembly
112
+ end
113
+ end
114
+ end
115
+
@@ -0,0 +1,217 @@
1
+ =begin
2
+ Copyright (c) 2011 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 'irpack/cscompiler'
26
+
27
+ module IRPack
28
+ module EntryPoint
29
+ Source = <<CS
30
+ using System;
31
+ using System.IO;
32
+ using System.IO.Packaging;
33
+ using System.Reflection;
34
+ using Microsoft.Scripting;
35
+ using Microsoft.Scripting.Hosting;
36
+
37
+ namespace <%= module_name %> {
38
+ public class EntryPoint
39
+ {
40
+ public class PackagePAL : PlatformAdaptationLayer
41
+ {
42
+ public Package CurrentPackage { get; set; }
43
+ public PackagePAL(Package pkg)
44
+ {
45
+ CurrentPackage = pkg;
46
+ }
47
+
48
+ private Uri ToPackageLoadPath(string path)
49
+ {
50
+ var domain = AppDomain.CurrentDomain;
51
+ var fullpath = Path.GetFullPath(path);
52
+ var searchpath = Path.GetFullPath(
53
+ domain.RelativeSearchPath!=null ?
54
+ Path.Combine(domain.BaseDirectory, domain.RelativeSearchPath) :
55
+ domain.BaseDirectory);
56
+ if (fullpath.StartsWith(searchpath)) {
57
+ var relpath = fullpath.Substring(searchpath.Length, fullpath.Length-searchpath.Length);
58
+ return PackUriHelper.CreatePartUri(new Uri(relpath, UriKind.Relative));
59
+ }
60
+ else {
61
+ return PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative));
62
+ }
63
+ }
64
+
65
+ private Uri ToPackagePath(string path)
66
+ {
67
+ var fullpath = Path.GetFullPath(path);
68
+ var searchpath = Path.GetDirectoryName(Path.GetFullPath(Assembly.GetEntryAssembly().Location));
69
+ if (fullpath.StartsWith(searchpath)) {
70
+ var relpath = fullpath.Substring(searchpath.Length, fullpath.Length-searchpath.Length);
71
+ return PackUriHelper.CreatePartUri(new Uri(relpath, UriKind.Relative));
72
+ }
73
+ else {
74
+ return PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative));
75
+ }
76
+ }
77
+
78
+ public override Assembly LoadAssembly(string name)
79
+ {
80
+ foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
81
+ if (asm.FullName==name) {
82
+ return asm;
83
+ }
84
+ }
85
+ return Assembly.Load(name);
86
+ }
87
+
88
+ public override Assembly LoadAssemblyFromPath(string path)
89
+ {
90
+ try {
91
+ return Assembly.LoadFile(path);
92
+ }
93
+ catch (FileNotFoundException e) {
94
+ var uri = ToPackageLoadPath(path);
95
+ if (CurrentPackage.PartExists(uri)) {
96
+ var stream = CurrentPackage.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
97
+ var raw = new byte[stream.Length];
98
+ stream.Read(raw, 0, (int)stream.Length);
99
+ stream.Close();
100
+ return Assembly.Load(raw);
101
+ }
102
+ else {
103
+ throw;
104
+ }
105
+ }
106
+ }
107
+
108
+ public override bool FileExists(string path)
109
+ {
110
+ if (File.Exists(path)) {
111
+ return true;
112
+ }
113
+ else {
114
+ var uri = ToPackagePath(path);
115
+ return CurrentPackage.PartExists(uri);
116
+ }
117
+ }
118
+
119
+ public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share)
120
+ {
121
+ if (mode==FileMode.Open && access==FileAccess.Read) {
122
+ var uri = ToPackagePath(path);
123
+ if (CurrentPackage.PartExists(uri)) {
124
+ return CurrentPackage.GetPart(uri).GetStream(mode, access);
125
+ }
126
+ else {
127
+ return new FileStream(path, mode, access, share);
128
+ }
129
+ }
130
+ else {
131
+ return new FileStream(path, mode, access, share);
132
+ }
133
+ }
134
+
135
+ public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
136
+ {
137
+ if (mode==FileMode.Open && access==FileAccess.Read) {
138
+ var uri = ToPackagePath(path);
139
+ if (CurrentPackage.PartExists(uri)) {
140
+ return CurrentPackage.GetPart(uri).GetStream(mode, access);
141
+ }
142
+ else {
143
+ return new FileStream(path, mode, access, share, bufferSize);
144
+ }
145
+ }
146
+ else {
147
+ return new FileStream(path, mode, access, share, bufferSize);
148
+ }
149
+ }
150
+
151
+ public override Stream OpenInputFileStream(string path)
152
+ {
153
+ var uri = ToPackagePath(path);
154
+ if (CurrentPackage.PartExists(uri)) {
155
+ return CurrentPackage.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
156
+ }
157
+ else {
158
+ return new FileStream(path, FileMode.Open, FileAccess.Read);
159
+ }
160
+ }
161
+ }
162
+
163
+ public class IRHost : ScriptHost
164
+ {
165
+ private PlatformAdaptationLayer PAL_;
166
+ public override PlatformAdaptationLayer PlatformAdaptationLayer { get { return PAL_; } }
167
+ public IRHost(Package pkg)
168
+ {
169
+ PAL_ = new PackagePAL(pkg);
170
+ }
171
+ }
172
+
173
+ public static int Main(Package package, string[] args)
174
+ {
175
+ var entry_path = Path.GetDirectoryName(Path.GetFullPath(Assembly.GetEntryAssembly().Location));
176
+ var entry_file = Path.Combine(entry_path, "<%= entry_file %>");
177
+ var runtime_setup = new ScriptRuntimeSetup();
178
+ runtime_setup.LanguageSetups.Add(IronRuby.Ruby.CreateRubySetup());
179
+ runtime_setup.Options["MainFile"] = entry_file;
180
+ runtime_setup.Options["Arguments"] = args;
181
+ runtime_setup.HostType = typeof(IRHost);
182
+ runtime_setup.HostArguments = new object[] { package };
183
+ var engine = IronRuby.Ruby.GetEngine(IronRuby.Ruby.CreateRuntime(runtime_setup));
184
+ try {
185
+ engine.ExecuteFile(entry_file);
186
+ return 0;
187
+ }
188
+ catch (IronRuby.Builtins.SystemExit e) {
189
+ return e.Status;
190
+ }
191
+ catch (Exception e) {
192
+ var thread_abort = e as System.Threading.ThreadAbortException;
193
+ if (thread_abort==null || !(thread_abort.ExceptionState is KeyboardInterruptException)) {
194
+ Console.Error.WriteLine(engine.GetService<ExceptionOperations>().FormatException(e));
195
+ }
196
+ return -1;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ CS
202
+ module_function
203
+ def source(module_name, entry_file)
204
+ ERB.new(Source).result(binding)
205
+ end
206
+
207
+ def compile(output_file, module_name, entry_file, references)
208
+ src = source(module_name, entry_file)
209
+ sysasm = IRPack::CSCompiler.system_assemblies.collect {|asm|
210
+ IRPack::CSCompiler.assembly_location(asm)
211
+ }
212
+ IRPack::CSCompiler.compile(:dll, output_file, src, references+sysasm, [])
213
+ output_file
214
+ end
215
+ end
216
+ end
217
+