crate 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +9 -0
- data/LICENSE +13 -0
- data/README +39 -0
- data/bin/crate +9 -0
- data/data/Makefile +5 -0
- data/data/Rakefile +77 -0
- data/data/application.rb +47 -0
- data/data/crate_boot.c +219 -0
- data/data/recipes/amalgalite/amalgalite.rake +7 -0
- data/data/recipes/arrayfields/arrayfields.rake +7 -0
- data/data/recipes/configuration/configuration.rake +7 -0
- data/data/recipes/openssl/openssl.rake +20 -0
- data/data/recipes/ruby/ext-extmk.rb.patch +33 -0
- data/data/recipes/ruby/ruby.rake +30 -0
- data/data/recipes/rubygems/rubygems.rake +19 -0
- data/data/recipes/zlib/zlib.rake +16 -0
- data/gemspec.rb +47 -0
- data/lib/crate.rb +85 -0
- data/lib/crate/dependency.rb +306 -0
- data/lib/crate/digest.rb +36 -0
- data/lib/crate/gem_integration.rb +91 -0
- data/lib/crate/main.rb +173 -0
- data/lib/crate/packing_list.rb +16 -0
- data/lib/crate/project.rb +255 -0
- data/lib/crate/ruby.rb +98 -0
- data/lib/crate/utils.rb +74 -0
- data/lib/crate/version.rb +26 -0
- data/spec/crate_spec.rb +16 -0
- data/spec/spec_helper.rb +5 -0
- data/tasks/announce.rake +38 -0
- data/tasks/config.rb +98 -0
- data/tasks/distribution.rake +46 -0
- data/tasks/documentation.rake +31 -0
- data/tasks/rspec.rake +29 -0
- data/tasks/rubyforge.rake +59 -0
- data/tasks/utils.rb +80 -0
- metadata +160 -0
data/HISTORY
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2008, Jeremy Hinegardner
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose
|
4
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
5
|
+
and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
9
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
11
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
12
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
13
|
+
THIS SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
== crate
|
2
|
+
|
3
|
+
* Homepage[http://copiousfreetime.rubyforge.org/crate]
|
4
|
+
* {Rubyforge Project}[http://rubyforge.org/projects/copiousfreetime/]
|
5
|
+
* email jeremy at copiousfreetime dot org
|
6
|
+
* git clone url git://github.com/copiousfreetime/crate.git
|
7
|
+
* {Packaging an Application With Crate}[http://copiousfreetime.org/articles/2008/11/30/package-an-application-with-crate.html
|
8
|
+
|
9
|
+
== DESCRIPTION
|
10
|
+
|
11
|
+
Crate is a developer tool to help package up your application as a custom static
|
12
|
+
build of the ruby interpreter plus all dependedent binary extensions. All the
|
13
|
+
pure ruby code (the ruby application, the ruby stdlib, etc ) is packed into one
|
14
|
+
or more SQLite databases.
|
15
|
+
|
16
|
+
The final distributable pieces are a single executable and a few SQLite
|
17
|
+
databases which can be then wrapped up appropriately as an OS X App; a self
|
18
|
+
extracting executable for Windows; a shar archive, rpm or tarball for Unixes.
|
19
|
+
|
20
|
+
== INSTALL
|
21
|
+
|
22
|
+
gem install crate
|
23
|
+
|
24
|
+
== LICENSE
|
25
|
+
|
26
|
+
Copyright (c) 2008, Jeremy Hinegardner
|
27
|
+
|
28
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose
|
29
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
30
|
+
and this permission notice appear in all copies.
|
31
|
+
|
32
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
33
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
34
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
35
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
36
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
37
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
38
|
+
THIS SOFTWARE.
|
39
|
+
|
data/bin/crate
ADDED
data/data/Makefile
ADDED
data/data/Rakefile
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#
|
2
|
+
# Top level Rakefile for building a custom static ruby based application
|
3
|
+
#
|
4
|
+
require 'crate'
|
5
|
+
|
6
|
+
#
|
7
|
+
# The name of your project. This will be the name of the final executable in
|
8
|
+
# the dist directory.
|
9
|
+
#
|
10
|
+
PROJ_NAME = "mycrateapp"
|
11
|
+
|
12
|
+
Crate::Project.new( PROJ_NAME ) do |crate|
|
13
|
+
|
14
|
+
# This is the configuration used to launch your program.
|
15
|
+
#
|
16
|
+
# main_file -> the file to 'require'
|
17
|
+
# main_class -> the Class in the main_file to instantiate
|
18
|
+
# run_method -> the instance method in main_class to invoke
|
19
|
+
#
|
20
|
+
#The new main of your program will essentially do:
|
21
|
+
#
|
22
|
+
# require 'application'
|
23
|
+
# app = App.new
|
24
|
+
# app.run( ARGV, ENV )
|
25
|
+
#
|
26
|
+
crate.main_file = "application"
|
27
|
+
crate.main_class = "App"
|
28
|
+
crate.run_method = "run"
|
29
|
+
|
30
|
+
|
31
|
+
# The list of extra files to include as packed into the app.db file
|
32
|
+
# This default one one will make sure to get any top level .rb files
|
33
|
+
# in the crate application directory.
|
34
|
+
#
|
35
|
+
crate.packing_lists << Crate::PackingList.new( Dir.glob("*.rb") )
|
36
|
+
|
37
|
+
|
38
|
+
# The extensions to compile into your project. Remove the ones you do not
|
39
|
+
# want or leave them commented out with a #
|
40
|
+
#
|
41
|
+
crate.extensions = %w[
|
42
|
+
#Win32API
|
43
|
+
bigdecimal
|
44
|
+
#curses
|
45
|
+
#dbm
|
46
|
+
digest
|
47
|
+
digest/md5
|
48
|
+
#digest/rmd160
|
49
|
+
digest/sha1
|
50
|
+
#digest/sha2
|
51
|
+
#dl
|
52
|
+
enumerator
|
53
|
+
etc
|
54
|
+
fcntl
|
55
|
+
#gdbm
|
56
|
+
#iconv
|
57
|
+
io/wait
|
58
|
+
nkf
|
59
|
+
#pty
|
60
|
+
openssl
|
61
|
+
#racc/cparse
|
62
|
+
#readline
|
63
|
+
#sdbm
|
64
|
+
socket
|
65
|
+
stringio
|
66
|
+
strscan
|
67
|
+
syck
|
68
|
+
#syslog
|
69
|
+
#tcltklib
|
70
|
+
thread
|
71
|
+
#tk
|
72
|
+
#win32ole
|
73
|
+
zlib
|
74
|
+
]
|
75
|
+
|
76
|
+
end
|
77
|
+
|
data/data/application.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
class App
|
2
|
+
def initialize
|
3
|
+
puts "initialized #{self.class}"
|
4
|
+
end
|
5
|
+
|
6
|
+
def run( argv, env )
|
7
|
+
puts "Executing : #{$0}"
|
8
|
+
puts "ARGV : #{argv.join(' ')}"
|
9
|
+
puts "ENV :"
|
10
|
+
env.keys.sort.each do |k|
|
11
|
+
puts " #{k} => #{env[k]}"
|
12
|
+
end
|
13
|
+
exit 42
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class App2 < App
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_me( argv, env )
|
23
|
+
run( argv, env )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class App3 < App
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
end
|
31
|
+
def b
|
32
|
+
raise NotImplementedError, "run has not been implemented"
|
33
|
+
end
|
34
|
+
|
35
|
+
def a
|
36
|
+
b
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def run( argv, env )
|
41
|
+
a
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if $0 == __FILE__ then
|
46
|
+
App3.new.run( nil, nil )
|
47
|
+
end
|
data/data/crate_boot.c
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2008, Jeremy Hinegardner
|
3
|
+
*
|
4
|
+
* Permission to use, copy, modify, and/or distribute this software for any
|
5
|
+
* purpose with or without fee is hereby granted, provided that the above
|
6
|
+
* copyright notice and this permission notice appear in all copies.
|
7
|
+
*
|
8
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
9
|
+
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
10
|
+
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
11
|
+
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
12
|
+
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
13
|
+
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
14
|
+
* PERFORMANCE OF THIS SOFTWARE.
|
15
|
+
*
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include <stdlib.h>
|
19
|
+
#include <getopt.h>
|
20
|
+
#include <ruby.h>
|
21
|
+
|
22
|
+
/** from ruby's original main.c **/
|
23
|
+
#if defined(__MACOS__) && defined(__MWERKS__)
|
24
|
+
#include <console.h>
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#include "crate_boot.h"
|
28
|
+
|
29
|
+
struct crate_app {
|
30
|
+
char *file_name;
|
31
|
+
char *class_name;
|
32
|
+
VALUE app_instance;
|
33
|
+
char *method_name;
|
34
|
+
ID run_method;
|
35
|
+
} ;
|
36
|
+
|
37
|
+
typedef struct crate_app crate_app;
|
38
|
+
|
39
|
+
/* crate 'secret' options */
|
40
|
+
static struct option longopts[] = {
|
41
|
+
{ "crate-file", required_argument, NULL, 1 },
|
42
|
+
{ "crate-class", required_argument, NULL, 2 },
|
43
|
+
{ "crate-method", required_argument, NULL, 3 },
|
44
|
+
{ NULL, 0, NULL, 0 }
|
45
|
+
};
|
46
|
+
|
47
|
+
int crate_init_from_options(crate_app *ca, int argc, char** argv )
|
48
|
+
{
|
49
|
+
int ch ;
|
50
|
+
int done = 0;
|
51
|
+
int old_opterr = opterr;
|
52
|
+
|
53
|
+
/* turn off printing to stderr */
|
54
|
+
opterr = 0;
|
55
|
+
|
56
|
+
ca->file_name = strdup( CRATE_MAIN_FILE );
|
57
|
+
ca->class_name = strdup( CRATE_MAIN_CLASS );
|
58
|
+
ca->method_name = strdup( CRATE_RUN_METHOD );
|
59
|
+
|
60
|
+
while ( !done && (ch = getopt_long( argc, argv, "", longopts, NULL ) ) != -1 ) {
|
61
|
+
switch ( ch ) {
|
62
|
+
case 1:
|
63
|
+
free( ca->file_name );
|
64
|
+
ca->file_name = strdup( optarg );
|
65
|
+
break;
|
66
|
+
|
67
|
+
case 2:
|
68
|
+
free( ca->class_name );
|
69
|
+
ca->class_name = strdup( optarg );
|
70
|
+
break;
|
71
|
+
|
72
|
+
case 3:
|
73
|
+
free( ca->method_name );
|
74
|
+
ca->method_name = strdup( optarg );
|
75
|
+
break;
|
76
|
+
|
77
|
+
default:
|
78
|
+
/* if we have a non-option then we are done and be sure to decrement
|
79
|
+
* optind so we keep the option that caused it to faile
|
80
|
+
*/
|
81
|
+
done = 1;
|
82
|
+
optind--;
|
83
|
+
break;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
opterr = old_opterr;
|
88
|
+
return optind;
|
89
|
+
}
|
90
|
+
|
91
|
+
/**
|
92
|
+
* Make the actual application call, we call the application instance with the
|
93
|
+
* method given and pass it ARGV and ENV in that order
|
94
|
+
*/
|
95
|
+
VALUE crate_wrap_app( VALUE arg )
|
96
|
+
{
|
97
|
+
crate_app *ca = (crate_app*)arg;
|
98
|
+
char *r = "Amalgalite::Requires.new( :dbfile_name => 'lib.db' )\n"\
|
99
|
+
"Amalgalite::Requires.new( :dbfile_name => 'app.db' )\n";
|
100
|
+
char buf[BUFSIZ];
|
101
|
+
char* dot ;
|
102
|
+
|
103
|
+
/* require the class file */
|
104
|
+
|
105
|
+
dot = strchr( ca->file_name, '.');
|
106
|
+
if ( NULL != dot ) { *dot = '\0' ; }
|
107
|
+
sprintf( buf,"%s\nrequire '%s'", r, ca->file_name);
|
108
|
+
rb_eval_string(buf);
|
109
|
+
|
110
|
+
/* get an instance of the application class and pack up the instance and the
|
111
|
+
* method
|
112
|
+
*/
|
113
|
+
ca->app_instance = rb_class_new_instance(0, 0, rb_const_get( rb_cObject, rb_intern( ca->class_name ) ) );
|
114
|
+
ca->run_method = rb_intern( ca->method_name );
|
115
|
+
|
116
|
+
return rb_funcall( ca->app_instance,
|
117
|
+
ca->run_method, 2,
|
118
|
+
rb_const_get_at( rb_cObject, rb_intern("ARGV") ),
|
119
|
+
rb_const_get_at( rb_cObject, rb_intern("ENV") ) );
|
120
|
+
}
|
121
|
+
|
122
|
+
static VALUE dump_backtrace( VALUE elem, VALUE n )
|
123
|
+
{
|
124
|
+
fprintf( stderr, "\tfrom %s\n", RSTRING(elem)->ptr );
|
125
|
+
}
|
126
|
+
|
127
|
+
/**
|
128
|
+
* ifdef items from ruby's original main.c
|
129
|
+
*/
|
130
|
+
|
131
|
+
/* to link startup code with ObjC support */
|
132
|
+
#if (defined(__APPLE__) || defined(__NeXT__)) && defined(__MACH__)
|
133
|
+
static void objcdummyfunction( void ) { objc_msgSend(); }
|
134
|
+
#endif
|
135
|
+
|
136
|
+
extern VALUE cARB;
|
137
|
+
|
138
|
+
int main( int argc, char** argv )
|
139
|
+
{
|
140
|
+
int state = 0;
|
141
|
+
int rc = 0;
|
142
|
+
int opt_mv = 0;
|
143
|
+
|
144
|
+
crate_app ca;
|
145
|
+
|
146
|
+
/** startup items from ruby's original main.c */
|
147
|
+
#ifdef _WIN32
|
148
|
+
NtInitialize(&argc, &argv);
|
149
|
+
#endif
|
150
|
+
#if defined(__MACOS__) && defined(__MWERKS__)
|
151
|
+
argc = ccommand(&argv);
|
152
|
+
#endif
|
153
|
+
|
154
|
+
/* setup ruby */
|
155
|
+
ruby_init();
|
156
|
+
ruby_script( argv[0] );
|
157
|
+
ruby_init_loadpath();
|
158
|
+
|
159
|
+
/* strip out the crate specific arguments from argv using --crate- */
|
160
|
+
opt_mv = crate_init_from_options( &ca, argc, argv );
|
161
|
+
argc -= opt_mv;
|
162
|
+
argv += opt_mv;
|
163
|
+
|
164
|
+
/* printf("crate file : %s\n", ca.file_name); */
|
165
|
+
/* printf("crate class : %s\n", ca.class_name); */
|
166
|
+
/* printf("crate method: %s\n", ca.method_name); */
|
167
|
+
|
168
|
+
/* make ARGV available */
|
169
|
+
ruby_set_argv( argc, argv );
|
170
|
+
|
171
|
+
/* initialize all extensions */
|
172
|
+
Init_ext();
|
173
|
+
|
174
|
+
/* load up the amalgalite libs */
|
175
|
+
am_bootstrap_lift( cARB, Qnil );
|
176
|
+
|
177
|
+
/* remove the current LOAD_PATH */
|
178
|
+
rb_ary_clear( rb_gv_get( "$LOAD_PATH" ) );
|
179
|
+
|
180
|
+
/* invoke the class / method passing in ARGV and ENV */
|
181
|
+
rb_protect( crate_wrap_app, (VALUE)&ca, &state );
|
182
|
+
|
183
|
+
/* check the results */
|
184
|
+
if ( state ) {
|
185
|
+
|
186
|
+
/* exception was raised, check the $! var */
|
187
|
+
VALUE lasterr = rb_gv_get("$!");
|
188
|
+
|
189
|
+
/* system exit was called so just propogate that up to our exit */
|
190
|
+
if ( rb_obj_is_instance_of( lasterr, rb_eSystemExit ) ) {
|
191
|
+
|
192
|
+
rc = NUM2INT( rb_attr_get( lasterr, rb_intern("status") ) );
|
193
|
+
/*printf(" Caught SystemExit -> $? will be %d\n", rc ); */
|
194
|
+
|
195
|
+
} else {
|
196
|
+
|
197
|
+
/* some other exception was raised so dump that out */
|
198
|
+
VALUE klass = rb_class_path( CLASS_OF( lasterr ) );
|
199
|
+
VALUE message = rb_obj_as_string( lasterr );
|
200
|
+
VALUE backtrace = rb_funcall( lasterr, rb_intern("backtrace"), 0 );
|
201
|
+
|
202
|
+
fprintf( stderr, "%s: %s\n", RSTRING( klass )->ptr, RSTRING( message )->ptr );
|
203
|
+
rb_iterate( rb_each, backtrace, dump_backtrace, Qnil );
|
204
|
+
|
205
|
+
rc = state;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
free( ca.file_name );
|
210
|
+
free( ca.class_name );
|
211
|
+
free( ca.method_name );
|
212
|
+
|
213
|
+
/* shut down ruby */
|
214
|
+
ruby_finalize();
|
215
|
+
|
216
|
+
/* exit the program */
|
217
|
+
exit( rc );
|
218
|
+
}
|
219
|
+
|
@@ -0,0 +1,7 @@
|
|
1
|
+
#
|
2
|
+
# The recipe for integrating amalgalite into the ruby build
|
3
|
+
#
|
4
|
+
Crate::GemIntegration.new("amalgalite", "0.5.1") do |t|
|
5
|
+
t.upstream_source = "http://rubyforge.org/frs/download.php/47660/amalgalite-0.5.1.gem"
|
6
|
+
t.upstream_sha1 = "fca93f2ab3abf46c86e78202d46489f25b7acb33"
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
#
|
2
|
+
# The recipe for integrating arrayfields into the ruby build
|
3
|
+
#
|
4
|
+
Crate::GemIntegration.new("arrayfields", "4.6.0") do |t|
|
5
|
+
t.upstream_source = "http://rubyforge.org/frs/download.php/39810/arrayfields-4.6.0.gem"
|
6
|
+
t.upstream_sha1 = "d1caaea59a6cd37efbf769f12bd3340bbd3104bb"
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
#
|
2
|
+
# The recipe for integrating configuration into the ruby build
|
3
|
+
#
|
4
|
+
Crate::GemIntegration.new("configuration", "0.0.5") do |t|
|
5
|
+
t.upstream_source = "http://rubyforge.org/frs/download.php/32720/configuration-0.0.5.gem"
|
6
|
+
t.upstream_sha1 = "ae65a38666706959aaaa034fb7cb3d0234349ecc"
|
7
|
+
end
|