irpack 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+