crate 0.1.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.
- 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
|