hubris 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
- gem 'hoe', '>= 2.1.0'
3
- require 'hoe'
2
+ #gem 'hoe', '>= 2.1.0'
3
+ #require 'hoe'
4
4
  require 'fileutils'
5
5
  require './lib/hubris'
6
6
 
@@ -10,14 +10,14 @@ require './lib/hubris'
10
10
 
11
11
  # Generate all the Rake tasks
12
12
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
- $hoe = Hoe.spec 'hubris' do
14
- self.developer 'Mark Wotton', 'mwotton@gmail.com'
15
- self.rubyforge_name = "hubris"
16
- self.summary = 'tool to help build .so files from haskell code for use in Ruby via dl'
17
- self.post_install_message = 'PostInstall.txt'
18
- self.readme_file = "README.markdown"
19
- self.history_file = "HISTORY.markdown"
20
- end
13
+ #$hoe = Hoe.spec 'hubris' do
14
+ # self.developer 'Mark Wotton', 'mwotton@gmail.com'
15
+ # self.rubyforge_name = "hubris"
16
+ # self.summary = 'tool to help build .so files from haskell code for use in Ruby via dl'
17
+ # self.post_install_message = 'PostInstall.txt'
18
+ # self.readme_file = "README.markdown"
19
+ # self.history_file = "HISTORY.markdown"
20
+ #end
21
21
 
22
22
  #require 'newgem/tasks'
23
23
  # Dir['tasks/**/*.rake'].each { |t| load t }
@@ -0,0 +1,29 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <ruby.h>
4
+
5
+ int loaded = 0;
6
+ VALUE Exports = Qnil;
7
+ extern void hs_init(int * argc, char ** argv[]);
8
+ void safe_hs_init() {
9
+ char ** argv = malloc(sizeof(char**) * 1);
10
+ int argc = 1;
11
+
12
+ argv[0]="haskell_extension";
13
+ if (! loaded) {
14
+ loaded=1;
15
+ // printf("really loading haskell runtime\n");
16
+ hs_init(&argc, &argv);
17
+ }
18
+ }
19
+
20
+ void Init_HubrisStubLoader() {
21
+ // don't do anything, we just want to make
22
+ // sure that the other objects can see the
23
+ // safe_hs_init symbols at the C level
24
+
25
+ // so, ok. we do do some stuff here.:) but it's really two separate things.
26
+ VALUE Hubris = rb_define_module("Hubris");
27
+ Exports = rb_define_module_under(Hubris, "Exports");
28
+
29
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ # dir_config("HubrisStubLoader")
4
+ have_header('ruby.h')
5
+ create_makefile 'HubrisStubLoader'
data/lib/hubris.rb CHANGED
@@ -26,7 +26,7 @@ class File
26
26
  end
27
27
 
28
28
  module Hubris
29
- VERSION = '0.0.2'
29
+ VERSION = '0.0.3'
30
30
  SO_CACHE = File.expand_path("/var/hubris/cache")
31
31
  HS_CACHE = File.expand_path("/var/hubris/source")
32
32
  require 'HubrisStubLoader'
@@ -0,0 +1,350 @@
1
+ # encoding: ASCII-8BIT
2
+ load File.dirname(__FILE__) + '/spec_helper.rb'
3
+ require "hubris"
4
+ Hubris.add_packages %w(base)
5
+
6
+ # # just want to check it's actually possible to load a library dynamically
7
+ # describe "dlload" do
8
+ # it "actually builds and loads a C level dylib stupidly" do
9
+ # system "cd sample; make"
10
+ # `cd sample; ruby hsload.rb`.chomp.should eql("144")
11
+ # end
12
+ # end
13
+
14
+ class Target
15
+ def foo_local
16
+ 14
17
+ end
18
+ end
19
+
20
+ Signal.trap("INT", 'EXIT');
21
+
22
+ describe "Target" do
23
+ it "whines like a little baby when you pass it bad haskell" do
24
+ lambda{ class Foo; hubris :inline => "broken _ = (1 + \"a string\")", :no_strict => true; end}.should raise_error(HaskellError)
25
+ end
26
+
27
+ it "ignores a comment" do
28
+ lambda {
29
+ class Foo; hubris :inline => "--blah blah blah
30
+ {- another silly comment -}
31
+ foo :: Bool -> Bool
32
+ foo True = False
33
+ foo False = True"; end
34
+ }.should_not raise_error
35
+ end
36
+
37
+ it "sings like a golden bird when you treat it right, aw yeah" do
38
+ # t = Target.new
39
+ # lambda { t.inline("working _ = T_FIXNUM (1+2)", { :no_strict => true }) }.should_not raise_error
40
+ lambda { class Foo; hubris :inline => "working :: Integer -> Integer; working a = 2*a"; end}.should_not raise_error
41
+ end
42
+
43
+
44
+ # it "handles booleans" do
45
+ # class Bar
46
+ # hubris :inline => "my_negate True = False;my_negate False = True", :no_strict => true
47
+ # end
48
+ # t = Bar.new
49
+ # # puts t.methods
50
+ # t.my_negate(false).should eql(true)
51
+ # t.my_negate(true).should eql(false)
52
+ # lambda{ t.my_negate("Banana")}.should raise_error
53
+ # end
54
+
55
+ it "handles doubles" do
56
+ class Doubler
57
+ hubris :inline => "triple :: Double -> Double; triple a = a*3.0", :no_strict => true
58
+ end
59
+ d = Doubler.new
60
+
61
+ d.triple(3.4).should eql(10.2)
62
+ end
63
+ end
64
+
65
+ describe "Strings" do
66
+ it "can reverse a string" do
67
+ class Stringer
68
+ hubris :inline => "import Data.ByteString; my_reverse::ByteString->ByteString; my_reverse s = Data.ByteString.reverse s", :no_strict => true
69
+ end
70
+ Stringer.new.my_reverse("foot").should eql("toof")
71
+ end
72
+ end
73
+
74
+ describe "BigInt" do
75
+ it "handles BigInts" do
76
+ class Bigint
77
+ hubris :inline => "big_inc :: Integer -> Integer; big_inc i = i + 1"
78
+ end
79
+ b = Bigint.new
80
+ b.big_inc(10000000000000000).should eql(10000000000000001)
81
+ b.big_inc(1).should eql(2)
82
+ end
83
+ end
84
+
85
+ describe 'Multiple' do
86
+ # this one requires multiple lib linking
87
+ it "can load multiple libs" do
88
+ class Multiple
89
+ def foo_local
90
+ 14
91
+ end
92
+ hubris :inline => "mydouble::Int->Int; mydouble i =(i + i)"
93
+ hubris :inline => "incr::Int->Int;incr i = 1+i"
94
+ end
95
+ t=Multiple.new
96
+ t.mydouble(1).should eql(2)
97
+ # and it doesn't wipe out other methods on the class
98
+ t.foo_local.should eql(14)
99
+ t.incr(3).should eql(4)
100
+ # FIXME this one is waiting for support of Control.Exception in
101
+ # JHC
102
+ # lambda { t.mydouble(2.3)}.should raise_error(HaskellError)
103
+ # Fooclever.mydouble(2.3).should raise_error(RuntimeError)
104
+ end
105
+ end
106
+
107
+ describe 'Arrays' do
108
+ it "can use arrays sensibly" do
109
+ class ArrayTest
110
+ hubris :inline => "mylength :: [Int] -> Int; mylength [] = 0; mylength (_:xs) = 1 + mylength xs"
111
+ end
112
+
113
+ ArrayTest.new.mylength([1,2,3,4]).should eql(4)
114
+ end
115
+ it "returns a haskell list as an array" do
116
+ class ArrayTest2
117
+ hubris :inline => "elts :: Int -> [Int]; elts i = take i [1..]"
118
+ end
119
+ t=ArrayTest2.new
120
+ t.elts(5).should eql([1,2,3,4,5])
121
+ lambda { t.elts("A Banana")}.should raise_error(HaskellError)
122
+ end
123
+ it "uses a Haskell array" do
124
+ class ArrayTest3
125
+ hubris :inline => "import Data.Array.IArray; larr :: Int -> Array Int Int; larr x = listArray (0,x-1) [1..x]"
126
+ end
127
+ ArrayTest3.new.larr(7).should == [1,2,3,4,5,6,7]
128
+ end
129
+ end
130
+
131
+ describe 'MaybeOut' do
132
+ it "passes back maybes" do
133
+ class Maybe
134
+ hubris :inline => "foo:: Int -> Maybe Int; foo 1 = Just 1; foo _ = Nothing"
135
+ end
136
+ m=Maybe.new
137
+ m.foo(1).should == 1
138
+ m.foo(2).should == nil
139
+ lambda{ m.foo("blah") }.should raise_error(HaskellError)
140
+ end
141
+ end
142
+ describe "MaybeIn" do
143
+ it "takes in Maybes" do
144
+ class MaybeIn
145
+ hubris :inline => "foo:: Maybe Int -> Int; foo (Just n) = 2*n; foo Nothing = 0"
146
+ end
147
+ class MaybeLazy
148
+ hubris :inline => "foo:: Maybe Int -> Int; foo (Just _) = 1; foo Nothing = 0"
149
+ end
150
+ m=MaybeIn.new
151
+ # m.foo(1).should == 1
152
+ # m.foo(20).should == 1
153
+ # m.foo(nil).should == 2
154
+ lambda{ m.foo("blah") }.should raise_error(HaskellError)
155
+ # here's a tricky bit: in the previous example, we had to look at the value of the
156
+ # Maybe, so the exception got triggered.
157
+ # Here, however, we're not passing in a nil, so we get a "Just 'something'", and never
158
+ # deeply examine the something. Arguably, it would be less surprising if we always looked
159
+ # deeply into it, but it's up for debate. TODO
160
+
161
+ lazy = MaybeLazy.new
162
+ lazy.foo("blah").should == 1
163
+ end
164
+ end
165
+
166
+ describe 'Hashes' do
167
+ it "can move a Haskell map to ruby" do
168
+ class HaskellMap
169
+ hubris :inline => "import Data.Map ; h :: Int -> Map Int Int; h n = Data.Map.fromList $ zip [1..n] [n, n-1 .. 1]"
170
+ end
171
+ rh=HaskellMap.new.h(3)
172
+ rh[3].should == 1
173
+ rh[2].should == 2
174
+ rh[1].should == 3
175
+ end
176
+
177
+ it "can move a ruby map to haskell" do
178
+ class RubyMap
179
+ hubris :inline => "import Data.Map; h :: Map Int Int -> Maybe Int; h m = Data.Map.lookup 10 m"
180
+ end
181
+ rb = RubyMap.new
182
+ rb.h({8 => 100, 2 => 7}).should eql(nil)
183
+ rb.h({10 => 100, 2 => 7}).should eql(100)
184
+ end
185
+
186
+ end
187
+
188
+
189
+
190
+ describe "Blocks" do
191
+
192
+ it "can be called in a block" do
193
+ class T2
194
+ hubris :inline => "foo::Integer->Integer;foo i = -i"
195
+ end
196
+ t = T2.new
197
+ (1..2).each do |x|
198
+ t.foo(x).should eql(0-x)
199
+ end
200
+ end
201
+ end
202
+
203
+ describe "Overwrite" do
204
+ it "can overwrite old functions" do
205
+ class Overlapping
206
+ hubris :inline => "myid::Int -> Int; myid i = i"
207
+ hubris :inline => "myid::Int -> Int; myid i = i+1"
208
+ end
209
+ t=Overlapping.new
210
+ t.myid(1).should eql(2)
211
+ end
212
+
213
+
214
+ end
215
+
216
+ describe "Exceptions" do
217
+ it "throws an exception on partial match" do
218
+ class BoolFunc
219
+ hubris :inline => "mynot :: Bool -> Bool; mynot True = False; mynot False = True"
220
+ end
221
+ t=BoolFunc.new
222
+ lambda{ t.mynot(true) }.should_not raise_error(HaskellError)
223
+ lambda{ puts t.mynot("blah") }.should raise_error(HaskellError)
224
+ end
225
+
226
+ it "catches incomplete code unless you turn no_strict on" do
227
+ lambda {
228
+ class Incomplete
229
+ hubris :inline => "incomplete :: Int -> Bool; incomplete 1 = True"
230
+ end
231
+ }.should raise_error(HaskellError)
232
+ lambda {
233
+ class IncompleteButOk
234
+ hubris :inline => "incomplete :: Int -> Bool; incomplete 1 = True" , :no_strict => true
235
+ end
236
+ }.should_not raise_error()
237
+
238
+ end
239
+
240
+ end
241
+
242
+ describe 'Idempotence' do
243
+ it "doesn't affect other modules" do
244
+ class Existing
245
+ end
246
+
247
+ class Target
248
+ hubris :inline => "fun :: Int -> Int; fun x = x+1"
249
+ end
250
+ e=Existing.new
251
+ t=Target.new
252
+ lambda{ e.fun(10)}.should raise_error(NoMethodError)
253
+ lambda{ t.fun(10)}.should_not raise_error(NoMethodError)
254
+ t.fun(10).should eql(11)
255
+ end
256
+
257
+ it "can insert the same code into two ruby modules" do
258
+ class Foo10
259
+ hubris :inline => "foobar::Double -> Double;foobar n = n+1.0"
260
+ end
261
+ class Foo11
262
+ hubris :inline => "foobar::Double -> Double;foobar n = n+1.0"
263
+ end
264
+
265
+ Foo10.new.foobar(1.0).should eql(2.0)
266
+ Foo11.new.foobar(1.0).should eql(2.0)
267
+
268
+ end
269
+ end
270
+
271
+ describe 'Realworld' do
272
+ it "can handle the bytestring lib" do
273
+
274
+ class ByteString
275
+ hubris :module => "Data.ByteString"
276
+ end
277
+
278
+ b = ByteString.new
279
+ b.sort("zabcdfg").should == "abcdfgz"
280
+ end
281
+
282
+ it "can import zlib" do
283
+ pending "Not doing the right thing with embedded nulls yet"
284
+ class ZLib
285
+ hubris :module => 'Codec.Compression.GZip', :packages => ['zlib', 'bytestring']
286
+ end
287
+ z=ZLib.new
288
+ w="osatnoensauhoestnuhoastuhoeatnuhosnueohnsauostneo"
289
+ puts w.encoding
290
+ x=z.compress(w)
291
+ x.each_byte {|c| print c, ' ' }
292
+ puts "length|#{x.length}|"
293
+ puts "second"
294
+ z.decompress(z.compress(w)).should eql(w)
295
+ end
296
+
297
+ end
298
+
299
+ describe 'Performance' do
300
+ def be_quick
301
+ simple_matcher("a small duration") { |given| given < 0.1 }
302
+ end
303
+
304
+ it "caches its output" do
305
+ # only relevant for inlining
306
+
307
+ t=Target.new
308
+ class First
309
+ hubris :inline => "foobar::Int->Int; foobar a = a"
310
+ end
311
+ before = Time.now
312
+ class Second
313
+ hubris :inline => "foobar::Int->Int; foobar a = a"
314
+ end
315
+ after = Time.now
316
+
317
+ (after-before).should be_quick
318
+ end
319
+
320
+ it "behaves memory-wise" do
321
+ # so, how on earth do we do this? Conceptually, we want to bind a function,
322
+ # call it many times, and assert that memory use is (eventually) constant
323
+ # possible approaches
324
+ # - caveman: ps, grep etc.
325
+ # - galois style (is that haskell-dtrace?)
326
+ end
327
+
328
+ it "behaves concurrently" do
329
+ # create a bunch of ruby threads which all call a given Haskell function
330
+ # repeatedly. Checks that we get the right result, and that we don't crash.
331
+ pending "Don't wanna run this every time"
332
+ no_threads = 10
333
+ reps=1000
334
+ class ConcTest
335
+ hubris :inline => "sumInts :: Int -> Int; sumInts n = sum [0..n]"
336
+ end
337
+ t = ConcTest.new
338
+
339
+ res = (0..no_threads).map { |n| (0..n).inject { |sum,n| sum+n } }
340
+ threads = []
341
+ lambda {
342
+ (0..no_threads).each { |n|
343
+ threads << Thread.start(n) { |x|
344
+ reps.times { t.sumInts(x).should eql(res[x]) }
345
+ }
346
+ }
347
+ threads.each { |t| t.join }
348
+ }.should_not raise_error
349
+ end
350
+ end
metadata CHANGED
@@ -1,10 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Wotton
8
+ - James Britt
9
+ - Josh Price
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
@@ -13,55 +15,55 @@ date: 2009-11-30 00:00:00 +11:00
13
15
  default_executable:
14
16
  dependencies:
15
17
  - !ruby/object:Gem::Dependency
16
- name: hoe
17
- type: :development
18
+ name: rspec
19
+ type: :runtime
18
20
  version_requirement:
19
21
  version_requirements: !ruby/object:Gem::Requirement
20
22
  requirements:
21
23
  - - ">="
22
24
  - !ruby/object:Gem::Version
23
- version: 2.3.3
25
+ version: "0"
24
26
  version:
25
- description: |-
26
- Hubris is a bridge between Ruby and Haskell, between love and bondage,
27
- between slothful indolence and raw, blazing speed. Hubris will wash
28
- your car, lie to your boss, and salvage your love life. If you are
29
- very, very lucky, it might also let you get some functional goodness
30
- into your ruby programs through the back door.
31
-
32
- I probably don't have to say this, but patches are very much
33
- welcome. If you have trouble installing it, tell me, and help me
34
- improve the docs.
35
- email:
36
- - mwotton@gmail.com
27
+ - !ruby/object:Gem::Dependency
28
+ name: open4
29
+ type: :runtime
30
+ version_requirement:
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ version:
37
+ description: A Ruby Haskell bridge
38
+ email: mwotton@gmail.com
37
39
  executables: []
38
40
 
39
- extensions: []
41
+ extensions:
42
+ - ext/extconf.rb
43
+ extra_rdoc_files: []
40
44
 
41
- extra_rdoc_files:
42
- - Manifest.txt
43
- - PostInstall.txt
44
45
  files:
45
46
  - HISTORY.markdown
46
- - Manifest.txt
47
- - PostInstall.txt
48
- - README.markdown
49
- - Rakefile
47
+ - ext/extconf.rb
48
+ - ext/HubrisStubLoader.c
50
49
  - lib/hubris.rb
51
- - sample/Fibonacci.hs
50
+ - Rakefile
52
51
  - sample/config.ru
52
+ - sample/Fibonacci.hs
53
+ - spec/hubris_spec.rb
53
54
  - spec/spec.opts
54
55
  - spec/spec_helper.rb
55
56
  has_rdoc: true
56
- homepage:
57
+ homepage: http://github.com/mwotton/hubris
57
58
  licenses: []
58
59
 
59
- post_install_message: PostInstall.txt
60
+ post_install_message:
60
61
  rdoc_options:
61
- - --main
62
- - README.markdown
62
+ - --inline-source
63
+ - --charset=UTF-8
63
64
  require_paths:
64
65
  - lib
66
+ - ext
65
67
  required_ruby_version: !ruby/object:Gem::Requirement
66
68
  requirements:
67
69
  - - ">="
@@ -80,6 +82,6 @@ rubyforge_project: hubris
80
82
  rubygems_version: 1.3.5
81
83
  signing_key:
82
84
  specification_version: 3
83
- summary: tool to help build .so files from haskell code for use in Ruby via dl
85
+ summary: Hubris is a Ruby Haskell bridge allowing you to call Haskell functions from your Ruby code.
84
86
  test_files: []
85
87
 
data/Manifest.txt DELETED
@@ -1,10 +0,0 @@
1
- HISTORY.markdown
2
- Manifest.txt
3
- PostInstall.txt
4
- README.markdown
5
- Rakefile
6
- lib/hubris.rb
7
- sample/Fibonacci.hs
8
- sample/config.ru
9
- spec/spec.opts
10
- spec/spec_helper.rb
data/PostInstall.txt DELETED
@@ -1,3 +0,0 @@
1
- For more information on Hubris, see http://github.com/mwotton/Hubris/tree/master
2
-
3
- You should now have a bin file named jhc_builder that you can use to compile Haskell files into .so files
data/README.markdown DELETED
@@ -1,142 +0,0 @@
1
- # Hubris
2
-
3
- ## Description
4
-
5
- Hubris is a bridge between Ruby and Haskell, between love and bondage,
6
- between slothful indolence and raw, blazing speed. Hubris will wash
7
- your car, lie to your boss, and salvage your love life. If you are
8
- very, very lucky, it might also let you get some functional goodness
9
- into your ruby programs through the back door.
10
-
11
- I probably don't have to say this, but patches are very much
12
- welcome. If you have trouble installing it, tell me, and help me
13
- improve the docs.
14
-
15
- ## Synopsis
16
-
17
- The best docs, as ever, are in the tests, but as a quick precis, you
18
- can use it a little like this:
19
-
20
- require 'hubris' # best line ever
21
-
22
- class Target
23
- hubris :inline =>"triple::Int->Int; triple n = 3*n"
24
- end
25
-
26
- t = Target.new
27
- puts t.triple(10)
28
- => 30
29
-
30
- There are a few restrictions. All functions take one argument and
31
- return one value: this shouldn't be a major problem because you can
32
- pass arrays of arguments in if you need more. Hubris can currently
33
- handle numbers, strings, basic types (like nil, true and false),
34
- arrays and hashes. There will probably be some Ruby structures
35
- (modules, regular expressions, etc) that won't ever be handled
36
- natively unless someone can convince me it's a sensible thing to do.
37
-
38
- Hubris will refuse to compile Haskell code that produces any
39
- warnings. You can suppress this admittedly fairly strict behaviour by
40
- passing the ":no_strict => true" flag, but in your heart of hearts
41
- you'll know you've done the wrong thing.
42
-
43
- There are also two other modes:
44
-
45
- hubris :source => "MyCoolModule.hs"
46
-
47
- which loads a source file on disk (in the same directory as your ruby),
48
- and
49
-
50
- hubris :module => "Data.ByteString", :packages => ["bytestring"]
51
-
52
- which will load the Data.ByteString module which is installed on the
53
- system. In this case, we also need to let the Haskell side know that
54
- we'll be using the "bytestring" package, so we pass that too: You may
55
- need to load extra packages with :inline and :source as well, and
56
- that's supported.
57
-
58
-
59
- ## Requirements
60
-
61
- * ghc 6.10 (to bootstrap 6.12) and cabal-install. This comes with the
62
- Haskell Platform
63
- * ruby 1.8.6 or higher (most heavily tested on 1.9.1)
64
- * Linux or Mac. See
65
- <http://www.shimweasel.com/2009/09/14/unprincipled-skulduggery-with-ghc-6-12-dylibs-on-mac-os-x>
66
- and the following entry for more info on the Mac build.
67
- * zsh or bash
68
- * git
69
-
70
- ## Install
71
-
72
- First, we install GHC 6.12 RC2 (living on the cutting edge is fun,
73
- right?)
74
-
75
- wget http://www.haskell.org/ghc/dist/6.12.1-rc2/ghc-6.12.0.20091121-src.tar.bz2
76
- tar -jxvf ghc-6.12.0.20091121-src.tar.bz2
77
- cd ghc-6.12.0.20091121-src
78
- # adjust the argument to -j to your number of cores, and the prefix if you need to install somewhere else
79
- sh boot && ./configure --enable-shared --prefix=/usr/local && make -j 4 && sudo make install
80
- # check ghc --version at the prompt tells you you're running 6.12
81
-
82
- Then get the Haskell support libraries installed
83
-
84
- cabal install c2hs
85
- # probably a better way of doing this, but this is how i build it.
86
- cabal unpack hubris
87
- cd hubris-0.0.2
88
- # edit the --extra-include-dirs and --extra-lib-dirs to reflect
89
- # your installation. You'll need the ruby headers installed -
90
- # they're installed already in ports, and it's ruby1.9.dev on Ubuntu.
91
- runhaskell Setup configure --enable-shared --user --ghc-options=-dynamic --extra-include-dirs=/usr/local/include/ruby-1.9.1/ --extra-lib-dirs=/usr/local/lib/
92
- runhaskell Setup build
93
- runhaskell Setup install
94
- # check that Hubrify is now in your path.
95
-
96
- Then the Ruby side
97
-
98
- sudo gem install rake open4 rspec hubris
99
-
100
- git clone git://github.com/mwotton/Hubris.git
101
- cd Hubris/lib
102
- ruby extconf.rb && make
103
- cd ..
104
- spec .
105
-
106
- I'll gemify this soon too.
107
-
108
-
109
- ## Contributors
110
-
111
- * Mark Wotton
112
- * James Britt
113
- * Josh Price
114
- * Tatsuhiro Ujihisa
115
-
116
- ## License
117
-
118
- (The MIT License)
119
-
120
- Copyright (c) 2009 Mark Wotton
121
-
122
- Permission is hereby granted, free of charge, to any person obtaining
123
- a copy of this software and associated documentation files (the
124
- 'Software'), to deal in the Software without restriction, including
125
- without limitation the rights to use, copy, modify, merge, publish,
126
- distribute, sublicense, and/or sell copies of the Software, and to
127
- permit persons to whom the Software is furnished to do so, subject to
128
- the following conditions:
129
-
130
- The above copyright notice and this permission notice shall be
131
- included in all copies or substantial portions of the Software.
132
-
133
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
134
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
135
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
136
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
137
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
138
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
139
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
140
-
141
-
142
- [haskell_platform]: http://hackage.haskell.org/platform/