hubris 0.0.2 → 0.0.3

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/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/