ffi 0.6.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/History.txt +7 -0
- data/LICENSE +10 -21
- data/README.rdoc +70 -0
- data/Rakefile +56 -84
- data/ext/ffi_c/AbstractMemory.c +56 -38
- data/ext/ffi_c/AbstractMemory.h +15 -22
- data/ext/ffi_c/Buffer.c +61 -22
- data/ext/ffi_c/Call.c +52 -540
- data/ext/ffi_c/Call.h +1 -1
- data/ext/ffi_c/DataConverter.c +62 -0
- data/ext/ffi_c/DynamicLibrary.c +21 -1
- data/ext/ffi_c/Function.c +252 -30
- data/ext/ffi_c/MappedType.c +146 -0
- data/{libtest/FunctionTest.c → ext/ffi_c/MappedType.h} +32 -25
- data/ext/ffi_c/MemoryPointer.c +12 -33
- data/ext/ffi_c/Platform.c +2 -0
- data/ext/ffi_c/Pointer.c +66 -28
- data/ext/ffi_c/Struct.c +19 -306
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/{libtest/LastErrorTest.c → ext/ffi_c/StructByReference.h} +30 -21
- data/ext/ffi_c/StructLayout.c +26 -16
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +20 -5
- data/ext/ffi_c/Types.h +7 -7
- data/ext/ffi_c/Variadic.c +21 -17
- data/ext/ffi_c/extconf.rb +4 -0
- data/ext/ffi_c/ffi.c +8 -2
- data/ext/ffi_c/rbffi.h +1 -0
- data/lib/ffi/autopointer.rb +23 -22
- data/lib/ffi/enum.rb +36 -21
- data/lib/ffi/errno.rb +20 -0
- data/lib/ffi/ffi.rb +13 -80
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +109 -92
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +27 -33
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +98 -49
- data/lib/ffi/struct_layout_builder.rb +158 -0
- data/lib/ffi/types.rb +99 -128
- data/lib/ffi/union.rb +20 -0
- data/lib/ffi/variadic.rb +33 -22
- data/spec/ffi/async_callback_spec.rb +23 -0
- data/spec/ffi/callback_spec.rb +62 -0
- data/spec/ffi/custom_param_type.rb +31 -0
- data/spec/ffi/custom_type_spec.rb +73 -0
- data/spec/ffi/enum_spec.rb +19 -0
- data/spec/ffi/ffi_spec.rb +24 -0
- data/spec/ffi/pointer_spec.rb +15 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
- data/spec/ffi/strptr_spec.rb +36 -0
- data/spec/ffi/struct_packed_spec.rb +46 -0
- data/spec/ffi/struct_spec.rb +19 -5
- data/spec/ffi/typedef_spec.rb +14 -0
- data/tasks/ann.rake +80 -0
- data/tasks/extension.rake +25 -0
- data/tasks/gem.rake +200 -0
- data/tasks/git.rake +41 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +301 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +139 -131
- data/README.md +0 -109
- data/ext/ffi_c/AutoPointer.c +0 -60
- data/ext/ffi_c/AutoPointer.h +0 -18
- data/ext/ffi_c/Ffi_c.iml +0 -12
- data/ffi.gemspec +0 -18
- data/gen/log +0 -1
- data/lib/Lib.iml +0 -21
- data/libtest/Benchmark.c +0 -73
- data/libtest/BoolTest.c +0 -52
- data/libtest/BufferTest.c +0 -52
- data/libtest/ClosureTest.c +0 -173
- data/libtest/EnumTest.c +0 -55
- data/libtest/GNUmakefile +0 -141
- data/libtest/GlobalVariable.c +0 -56
- data/libtest/NumberTest.c +0 -145
- data/libtest/PointerTest.c +0 -84
- data/libtest/ReferenceTest.c +0 -44
- data/libtest/StringTest.c +0 -55
- data/libtest/StructTest.c +0 -247
- data/libtest/UnionTest.c +0 -64
- data/libtest/VariadicTest.c +0 -57
- data/spec/ffi/Ffi.iml +0 -12
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe "functions with custom parameter types" do
|
4
|
+
before :each do
|
5
|
+
|
6
|
+
Custom_enum = Class.new do
|
7
|
+
extend FFI::DataConverter
|
8
|
+
ToNativeMap= { :a => 1, :b => 2 }
|
9
|
+
FromNativeMap = { 1 => :a, 2 => :b }
|
10
|
+
|
11
|
+
def self.native_type
|
12
|
+
@native_type_called = true
|
13
|
+
FFI::Type::INT32
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.to_native(val, ctx)
|
17
|
+
@to_native_called = true
|
18
|
+
ToNativeMap[val]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_native(val, ctx)
|
22
|
+
@from_native_called = true
|
23
|
+
FromNativeMap[val]
|
24
|
+
end
|
25
|
+
def self.native_type_called?; @native_type_called; end
|
26
|
+
def self.from_native_called?; @from_native_called; end
|
27
|
+
def self.to_native_called?; @to_native_called; end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe "functions with custom types" do
|
4
|
+
before :each do
|
5
|
+
|
6
|
+
Custom_enum = Class.new do
|
7
|
+
extend FFI::DataConverter
|
8
|
+
ToNativeMap= { :a => 1, :b => 2, :c => 3 }
|
9
|
+
FromNativeMap = { 1 => :a, 2 => :b, 3 => :c }
|
10
|
+
|
11
|
+
def self.native_type
|
12
|
+
@native_type_called = true
|
13
|
+
FFI::Type::INT32
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.to_native(val, ctx)
|
17
|
+
@to_native_called = true
|
18
|
+
ToNativeMap[val]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_native(val, ctx)
|
22
|
+
@from_native_called = true
|
23
|
+
FromNativeMap[val]
|
24
|
+
end
|
25
|
+
def self.native_type_called?; @native_type_called; end
|
26
|
+
def self.from_native_called?; @from_native_called; end
|
27
|
+
def self.to_native_called?; @to_native_called; end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
it "can attach with custom return type" do
|
33
|
+
lambda do
|
34
|
+
m = Module.new do
|
35
|
+
extend FFI::Library
|
36
|
+
ffi_lib TestLibrary::PATH
|
37
|
+
attach_function :ret_s32, [ :int ], Custom_enum
|
38
|
+
end
|
39
|
+
end.should_not raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return object of correct type" do
|
43
|
+
|
44
|
+
m = Module.new do
|
45
|
+
|
46
|
+
extend FFI::Library
|
47
|
+
ffi_lib TestLibrary::PATH
|
48
|
+
attach_function :ret_s32, [ :int ], Custom_enum
|
49
|
+
end
|
50
|
+
|
51
|
+
m.ret_s32(1).is_a?(Symbol).should be_true
|
52
|
+
end
|
53
|
+
|
54
|
+
it "from_native should be called for result" do
|
55
|
+
m = Module.new do
|
56
|
+
extend FFI::Library
|
57
|
+
ffi_lib TestLibrary::PATH
|
58
|
+
attach_function :ret_s32, [ :int ], Custom_enum
|
59
|
+
end
|
60
|
+
m.ret_s32(1)
|
61
|
+
Custom_enum.from_native_called?.should be_true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "to_native should be called for parameter" do
|
65
|
+
m = Module.new do
|
66
|
+
extend FFI::Library
|
67
|
+
ffi_lib TestLibrary::PATH
|
68
|
+
attach_function :ret_s32, [ Custom_enum ], :int
|
69
|
+
end
|
70
|
+
m.ret_s32(:a)
|
71
|
+
Custom_enum.to_native_called?.should be_true
|
72
|
+
end
|
73
|
+
end
|
data/spec/ffi/enum_spec.rb
CHANGED
@@ -89,6 +89,25 @@ describe "A tagged typedef enum" do
|
|
89
89
|
TestEnum3.test_tagged_typedef_enum4(:c15).should == :c15
|
90
90
|
TestEnum3.test_tagged_typedef_enum4(:c16).should == :c16
|
91
91
|
end
|
92
|
+
|
93
|
+
it "integers can be used instead of constants" do
|
94
|
+
TestEnum3.test_tagged_typedef_enum1(0).should == :c1
|
95
|
+
TestEnum3.test_tagged_typedef_enum1(1).should == :c2
|
96
|
+
TestEnum3.test_tagged_typedef_enum1(2).should == :c3
|
97
|
+
TestEnum3.test_tagged_typedef_enum1(3).should == :c4
|
98
|
+
TestEnum3.test_tagged_typedef_enum2(42).should == :c5
|
99
|
+
TestEnum3.test_tagged_typedef_enum2(43).should == :c6
|
100
|
+
TestEnum3.test_tagged_typedef_enum2(44).should == :c7
|
101
|
+
TestEnum3.test_tagged_typedef_enum2(45).should == :c8
|
102
|
+
TestEnum3.test_tagged_typedef_enum3(42).should == :c9
|
103
|
+
TestEnum3.test_tagged_typedef_enum3(43).should == :c10
|
104
|
+
TestEnum3.test_tagged_typedef_enum3(4242).should == :c11
|
105
|
+
TestEnum3.test_tagged_typedef_enum3(4243).should == :c12
|
106
|
+
TestEnum3.test_tagged_typedef_enum4(42).should == :c13
|
107
|
+
TestEnum3.test_tagged_typedef_enum4(4242).should == :c14
|
108
|
+
TestEnum3.test_tagged_typedef_enum4(424242).should == :c15
|
109
|
+
TestEnum3.test_tagged_typedef_enum4(42424242).should == :c16
|
110
|
+
end
|
92
111
|
end
|
93
112
|
|
94
113
|
describe "All enums" do
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe "FFI" do
|
4
|
+
|
5
|
+
describe ".map_library_name" do
|
6
|
+
|
7
|
+
let(:prefix) { FFI::Platform::LIBPREFIX }
|
8
|
+
let(:suffix) { FFI::Platform::LIBSUFFIX }
|
9
|
+
|
10
|
+
it "should add platform library extension if not present" do
|
11
|
+
FFI.map_library_name("#{prefix}dummy").should == "#{prefix}dummy.#{suffix}"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should add platform library extension even if lib suffix is present in name" do
|
15
|
+
FFI.map_library_name("#{prefix}dummy_with_#{suffix}").should == "#{prefix}dummy_with_#{suffix}.#{suffix}"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return Platform::LIBC when called with 'c'" do
|
19
|
+
FFI.map_library_name('c').should == FFI::Library::LIBC
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/spec/ffi/pointer_spec.rb
CHANGED
@@ -177,7 +177,21 @@ describe "AutoPointer" do
|
|
177
177
|
end
|
178
178
|
AutoPointerTestHelper.gc_everything loop_count
|
179
179
|
end
|
180
|
+
|
181
|
+
it "can be used as the return type of a function" do
|
182
|
+
lambda do
|
183
|
+
Module.new do
|
184
|
+
extend FFI::Library
|
185
|
+
ffi_lib TestLibrary::PATH
|
186
|
+
class CustomAutoPointer < FFI::AutoPointer
|
187
|
+
def self.release(ptr); end
|
188
|
+
end
|
189
|
+
attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], CustomAutoPointer
|
190
|
+
end
|
191
|
+
end.should_not raise_error
|
192
|
+
end
|
180
193
|
end
|
194
|
+
|
181
195
|
describe "AutoPointer#new" do
|
182
196
|
class AutoPointerSubclass < FFI::AutoPointer
|
183
197
|
def self.release(ptr); end
|
@@ -193,3 +207,4 @@ describe "AutoPointer#new" do
|
|
193
207
|
end
|
194
208
|
|
195
209
|
end
|
210
|
+
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require "rubygems"
|
2
3
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
3
4
|
|
@@ -13,7 +14,12 @@ describe "MemoryPointer" do
|
|
13
14
|
m = FFI::MemoryPointer.from_string("FFI is Awesome")
|
14
15
|
m.type_size.should == 15
|
15
16
|
end
|
16
|
-
|
17
|
+
|
18
|
+
it "makes a pointer from a string with multibyte characters" do
|
19
|
+
m = FFI::MemoryPointer.from_string("ぱんだ")
|
20
|
+
m.type_size.should == 10
|
21
|
+
end
|
22
|
+
|
17
23
|
it "reads back a string" do
|
18
24
|
m = FFI::MemoryPointer.from_string("FFI is Awesome")
|
19
25
|
m.read_string.should == "FFI is Awesome"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe "functions returning :strptr" do
|
4
|
+
it "can attach function with :strptr return type" do
|
5
|
+
lambda do
|
6
|
+
m = Module.new do
|
7
|
+
extend FFI::Library
|
8
|
+
ffi_lib FFI::Library::LIBC
|
9
|
+
attach_function :strdup, [ :string ], :strptr
|
10
|
+
end
|
11
|
+
end.should_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
module StrPtr
|
15
|
+
extend FFI::Library
|
16
|
+
ffi_lib FFI::Library::LIBC
|
17
|
+
attach_function :strdup, [ :string ], :strptr
|
18
|
+
attach_function :free, [ :pointer ], :void
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return [ String, Pointer ]" do
|
22
|
+
result = StrPtr.strdup("test")
|
23
|
+
result[0].is_a?(String).should be_true
|
24
|
+
result[1].is_a?(FFI::Pointer).should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return the correct value" do
|
28
|
+
result = StrPtr.strdup("test")
|
29
|
+
result[0].should == "test"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return non-NULL pointer" do
|
33
|
+
result = StrPtr.strdup("test")
|
34
|
+
result[1].null?.should be_false
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe FFI::Struct do
|
4
|
+
it "packed :char followed by :int should have size of 5" do
|
5
|
+
Class.new(FFI::Struct) do
|
6
|
+
packed
|
7
|
+
layout :c, :char, :i, :int
|
8
|
+
end.size.should == 5
|
9
|
+
end
|
10
|
+
|
11
|
+
it "packed :char followed by :int should have alignment of 1" do
|
12
|
+
Class.new(FFI::Struct) do
|
13
|
+
packed
|
14
|
+
layout :c, :char, :i, :int
|
15
|
+
end.alignment.should == 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it "packed(2) :char followed by :int should have size of 6" do
|
19
|
+
Class.new(FFI::Struct) do
|
20
|
+
packed 2
|
21
|
+
layout :c, :char, :i, :int
|
22
|
+
end.size.should == 6
|
23
|
+
end
|
24
|
+
|
25
|
+
it "packed(2) :char followed by :int should have alignment of 2" do
|
26
|
+
Class.new(FFI::Struct) do
|
27
|
+
packed 2
|
28
|
+
layout :c, :char, :i, :int
|
29
|
+
end.alignment.should == 2
|
30
|
+
end
|
31
|
+
|
32
|
+
it "packed :short followed by int should have size of 6" do
|
33
|
+
Class.new(FFI::Struct) do
|
34
|
+
packed
|
35
|
+
layout :s, :short, :i, :int
|
36
|
+
end.size.should == 6
|
37
|
+
end
|
38
|
+
|
39
|
+
it "packed :short followed by int should have alignment of 1" do
|
40
|
+
Class.new(FFI::Struct) do
|
41
|
+
packed
|
42
|
+
layout :s, :short, :i, :int
|
43
|
+
end.alignment.should == 1
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/spec/ffi/struct_spec.rb
CHANGED
@@ -158,7 +158,7 @@ describe "Struct tests" do
|
|
158
158
|
class TestStruct < FFI::Struct
|
159
159
|
layout :c, :char
|
160
160
|
end
|
161
|
-
attach_function :struct_field_s8, [ TestStruct ], :char
|
161
|
+
attach_function :struct_field_s8, [ TestStruct.in ], :char
|
162
162
|
end
|
163
163
|
end
|
164
164
|
it "Can use Struct subclass as IN parameter type" do
|
@@ -327,8 +327,8 @@ describe "Struct tests" do
|
|
327
327
|
layout :add, :add,
|
328
328
|
:sub, :sub
|
329
329
|
end
|
330
|
-
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
331
|
-
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
330
|
+
attach_function :struct_call_add_cb, [TestStruct.in, :int, :int], :int
|
331
|
+
attach_function :struct_call_sub_cb, [TestStruct.in, :int, :int], :int
|
332
332
|
end
|
333
333
|
it "Can have CallbackInfo struct field" do
|
334
334
|
s = CallbackMember::TestStruct.new
|
@@ -336,8 +336,8 @@ describe "Struct tests" do
|
|
336
336
|
sub_proc = lambda { |a, b| a-b }
|
337
337
|
s[:add] = add_proc
|
338
338
|
s[:sub] = sub_proc
|
339
|
-
CallbackMember.struct_call_add_cb(s
|
340
|
-
CallbackMember.struct_call_sub_cb(s
|
339
|
+
CallbackMember.struct_call_add_cb(s, 40, 2).should == 42
|
340
|
+
CallbackMember.struct_call_sub_cb(s, 44, 2).should == 42
|
341
341
|
end
|
342
342
|
it "Can return its members as a list" do
|
343
343
|
class TestStruct < FFI::Struct
|
@@ -621,4 +621,18 @@ describe "Struct allocation" do
|
|
621
621
|
p.put_uint(4, 0xdeadbeef)
|
622
622
|
S.new(p[1])[:i].should == 0xdeadbeef
|
623
623
|
end
|
624
|
+
|
625
|
+
it "null? should be true when initialized with NULL pointer" do
|
626
|
+
class S < FFI::Struct
|
627
|
+
layout :i, :uint
|
628
|
+
end
|
629
|
+
S.new(Pointer::NULL).null?.should be_true
|
630
|
+
end
|
631
|
+
|
632
|
+
it "null? should be false when initialized with non-NULL pointer" do
|
633
|
+
class S < FFI::Struct
|
634
|
+
layout :i, :uint
|
635
|
+
end
|
636
|
+
S.new(MemoryPointer.new(S)).null?.should be_false
|
637
|
+
end
|
624
638
|
end
|
data/spec/ffi/typedef_spec.rb
CHANGED
@@ -45,4 +45,18 @@ describe "Custom type definitions" do
|
|
45
45
|
s[:a] = 0x12345678
|
46
46
|
s.pointer.get_uint(0).should == 0x12345678
|
47
47
|
end
|
48
|
+
|
49
|
+
it "attach_function after a typedef should not reject normal types" do
|
50
|
+
lambda do
|
51
|
+
Module.new do
|
52
|
+
extend FFI::Library
|
53
|
+
# enum() will insert a custom typedef called :foo for the enum
|
54
|
+
enum :foo, [ :a, :b ]
|
55
|
+
typedef :int, :bar
|
56
|
+
|
57
|
+
ffi_lib TestLibrary::PATH
|
58
|
+
attach_function :ptr_ret_int32_t, [ :string, :foo ], :bar
|
59
|
+
end
|
60
|
+
end.should_not raise_error
|
61
|
+
end
|
48
62
|
end
|
data/tasks/ann.rake
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require 'bones/smtp_tls'
|
4
|
+
rescue LoadError
|
5
|
+
require 'net/smtp'
|
6
|
+
end
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
namespace :ann do
|
10
|
+
|
11
|
+
# A prerequisites task that all other tasks depend upon
|
12
|
+
task :prereqs
|
13
|
+
|
14
|
+
file PROJ.ann.file do
|
15
|
+
ann = PROJ.ann
|
16
|
+
puts "Generating #{ann.file}"
|
17
|
+
File.open(ann.file,'w') do |fd|
|
18
|
+
fd.puts("#{PROJ.name} version #{PROJ.version}")
|
19
|
+
fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
|
20
|
+
fd.puts(" #{PROJ.url}") if PROJ.url.valid?
|
21
|
+
fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
|
22
|
+
fd.puts
|
23
|
+
fd.puts("== DESCRIPTION")
|
24
|
+
fd.puts
|
25
|
+
fd.puts(PROJ.description)
|
26
|
+
fd.puts
|
27
|
+
fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
|
28
|
+
fd.puts
|
29
|
+
ann.paragraphs.each do |p|
|
30
|
+
fd.puts "== #{p.upcase}"
|
31
|
+
fd.puts
|
32
|
+
fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
|
33
|
+
fd.puts
|
34
|
+
end
|
35
|
+
fd.puts ann.text if ann.text
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Create an announcement file"
|
40
|
+
task :announcement => ['ann:prereqs', PROJ.ann.file]
|
41
|
+
|
42
|
+
desc "Send an email announcement"
|
43
|
+
task :email => ['ann:prereqs', PROJ.ann.file] do
|
44
|
+
ann = PROJ.ann
|
45
|
+
from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
|
46
|
+
to = Array(ann.email[:to])
|
47
|
+
|
48
|
+
### build a mail header for RFC 822
|
49
|
+
rfc822msg = "From: #{from}\n"
|
50
|
+
rfc822msg << "To: #{to.join(',')}\n"
|
51
|
+
rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
|
52
|
+
rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
|
53
|
+
rfc822msg << "\n"
|
54
|
+
rfc822msg << "Date: #{Time.new.rfc822}\n"
|
55
|
+
rfc822msg << "Message-Id: "
|
56
|
+
rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
|
57
|
+
rfc822msg << File.read(ann.file)
|
58
|
+
|
59
|
+
params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
|
60
|
+
ann.email[key]
|
61
|
+
end
|
62
|
+
|
63
|
+
params[3] = (PROJ.ann.email[:from] || PROJ.email) if params[3].nil?
|
64
|
+
|
65
|
+
if params[4].nil?
|
66
|
+
STDOUT.write "Please enter your e-mail password (#{params[3]}): "
|
67
|
+
params[4] = STDIN.gets.chomp
|
68
|
+
end
|
69
|
+
|
70
|
+
### send email
|
71
|
+
Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
|
72
|
+
end
|
73
|
+
end # namespace :ann
|
74
|
+
|
75
|
+
desc 'Alias to ann:announcement'
|
76
|
+
task :ann => 'ann:announcement'
|
77
|
+
|
78
|
+
CLOBBER << PROJ.ann.file
|
79
|
+
|
80
|
+
# EOF
|
@@ -0,0 +1,25 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = PROJ.name
|
3
|
+
s.version = PROJ.version
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.has_rdoc = true
|
6
|
+
s.extra_rdoc_files = ["README.rdoc", "LICENSE"]
|
7
|
+
s.summary = PROJ.summary
|
8
|
+
s.description = PROJ.description
|
9
|
+
s.authors = Array(PROJ.authors)
|
10
|
+
s.email = PROJ.email
|
11
|
+
s.homepage = Array(PROJ.url).first
|
12
|
+
s.rubyforge_project = PROJ.rubyforge.name
|
13
|
+
s.extensions = %w(ext/ffi_c/extconf.rb gen/Rakefile)
|
14
|
+
s.require_path = 'lib'
|
15
|
+
s.files = PROJ.gem.files
|
16
|
+
s.add_dependency *PROJ.gem.dependencies.flatten
|
17
|
+
end
|
18
|
+
|
19
|
+
Rake::ExtensionTask.new('ffi_c', spec) do |ext|
|
20
|
+
ext.name = 'ffi_c' # indicate the name of the extension.
|
21
|
+
# ext.lib_dir = BUILD_DIR # put binaries into this folder.
|
22
|
+
ext.tmp_dir = BUILD_DIR # temporary folder used during compilation.
|
23
|
+
ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
|
24
|
+
ext.cross_platform = ['i386-mingw32', 'i386-mswin32'] # forces the Windows platform instead of the default one
|
25
|
+
end if USE_RAKE_COMPILER
|