mkmf-lite 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,2 @@
1
+ = 0.1.0 - 24-May-2010
2
+ * Initial release.
data/MANIFEST ADDED
@@ -0,0 +1,7 @@
1
+ * CHANGES
2
+ * MANIFEST
3
+ * Rakefile
4
+ * mkmf-lite.gemspec
5
+ * lib/mkmf/lite.rb
6
+ * lib/mkmf/templates/have_header.erb
7
+ * test/test_mkmf_lite.rb
data/README ADDED
@@ -0,0 +1,45 @@
1
+ = Summary
2
+ A light version of mkmf designed for use within programs.
3
+
4
+ = Synopsis
5
+ require 'mkmf/lite'
6
+
7
+ class System
8
+ include Mkmf::Lite
9
+
10
+ HAVE_PW_NAME = have_struct_member('struct passwd', 'pw_name', 'pwd.h')
11
+
12
+ def some_method
13
+ if HAVE_PW_NAME
14
+ # Do something
15
+ end
16
+ end
17
+ end
18
+
19
+ = Description
20
+ The mkmf library that ships as part of the Ruby standard library is not
21
+ meant for use as an internal library. It's strictly designed for building
22
+ C extensions. It's huge, its methods sit in a global namespace, it contains
23
+ many methods you don't care about, and emits output to $stdout that cannot
24
+ easily be disabled. Also, the source code is monstrous.
25
+
26
+ The mkmf-lite is a module, it's small, and it's designed to be mixed into
27
+ classes. It contains a handful of methods that, most likely, will be used
28
+ in conjunction with FFI. Also, the source code is quite readable.
29
+
30
+ It does not package C extensions, nor generate a log file or a Makefile.
31
+
32
+ == License
33
+ Artistic 2.0
34
+
35
+ == Copyright
36
+ (C) 2010 Daniel J. Berger
37
+ All Rights Reserved
38
+
39
+ == Warranty
40
+ This library is provided "as is" and without any express or
41
+ implied warranties, including, without limitation, the implied
42
+ warranties of merchantability and fitness for a particular purpose.
43
+
44
+ = Author
45
+ Daniel Berger
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rbconfig'
4
+
5
+
6
+ namespace 'gem' do
7
+ desc 'Remove any existing .gem files'
8
+ task :clean do
9
+ Dir['**/*.gem'].each{ |f| File.delete(f) }
10
+ end
11
+
12
+ desc 'Create the mkmf-lite gem.'
13
+ task :create => [:clean] do
14
+ spec = eval(IO.read('mkmf-lite.gemspec'))
15
+ Gem::Builder.new(spec).build
16
+ end
17
+
18
+ desc 'Install the mkmf-lite gem.'
19
+ task :install => [:create] do
20
+ file = Dir["*.gem"].first
21
+ sh "gem install #{file}"
22
+ end
23
+ end
24
+
25
+ Rake::TestTask.new do |t|
26
+ t.verbose = true
27
+ t.warning = true
28
+ end
data/lib/mkmf/lite.rb ADDED
@@ -0,0 +1,127 @@
1
+ require 'erb'
2
+ require 'rbconfig'
3
+ require 'tmpdir'
4
+ require 'ptools'
5
+
6
+ module Mkmf
7
+ module Lite
8
+ # The version of the mkmf-lite library
9
+ MKMF_LITE_VERSION = '0.1.0'
10
+
11
+ @@cpp_command = Config::CONFIG['CC'] || Config::CONFIG['CPP']
12
+ @@cpp_outfile = Config::CONFIG['CPPOUTFILE'] # -o conftest.i
13
+ @@cpp_libraries = Config::CONFIG['LIBS'] + Config::CONFIG['LIBRUBYARG']
14
+ @@cpp_srcfile = 'conftest.c'
15
+
16
+ # Check for the presence of the given +header+ file.
17
+ #
18
+ # Returns true if found, or false if not found.
19
+ #
20
+ def have_header(header)
21
+ erb = ERB.new(read_template('have_header.erb'))
22
+ code = erb.result(binding)
23
+ try_to_compile(code)
24
+ end
25
+
26
+ # Check for the presence of the given +function+ in the common header
27
+ # files, or within any +headers+ that you provide.
28
+ #
29
+ # Returns true if found, or false if not found.
30
+ #
31
+ def have_func(function, headers = [])
32
+ headers = get_header_string(headers)
33
+
34
+ erb_ptr = ERB.new(read_template('have_func_pointer.erb'))
35
+ erb_std = ERB.new(read_template('have_func.erb'))
36
+
37
+ ptr_code = erb_ptr.result(binding)
38
+ std_code = erb_std.result(binding)
39
+
40
+ # Check for just the function pointer first. If that fails, then try
41
+ # to compile with the function declaration.
42
+ try_to_compile(ptr_code) || try_to_compile(std_code)
43
+ end
44
+
45
+ # Checks whether or not the struct of type +struct_type+ contains the
46
+ # +struct_member+. If it does not, or the struct type cannot be found,
47
+ # then false is returned.
48
+ #
49
+ # An optional list of +headers+ may be specified, in addition to the
50
+ # common header files that are already searched.
51
+ #
52
+ def have_struct_member(struct_type, struct_member, headers = [])
53
+ headers = get_header_string(headers)
54
+ erb = ERB.new(read_template('have_struct_member.erb'))
55
+ code = erb.result(binding)
56
+
57
+ try_to_compile(code)
58
+ end
59
+
60
+ private
61
+
62
+ # Take an array of header file names (or convert it to an array if it's a
63
+ # single argument), add the COMMON_HEADERS, flatten it out and remove any
64
+ # duplicates.
65
+ #
66
+ # Finally, convert the result into a single string of '#include'
67
+ # directives, each separated by a newline.
68
+ #
69
+ # This string is then to be used at the top of the ERB templates.
70
+ #
71
+ def get_header_string(headers)
72
+ headers = [headers] unless headers.is_a?(Array)
73
+
74
+ unless Config::CONFIG['COMMON_HEADERS'].empty?
75
+ headers += Config::CONFIG['COMMON_HEADERS'].split
76
+ end
77
+
78
+ headers = headers.flatten.uniq
79
+ headers = headers.map{ |h| "#include <#{h}>" }.join("\n")
80
+
81
+ headers
82
+ end
83
+
84
+ # Create a temporary bit of C source code in the temp directory, and
85
+ # try to compile it. If it succeeds, return true. Otherwise, return
86
+ # false.
87
+ #
88
+ # Note that $stderr is temporarily redirected to the null device because
89
+ # we don't actually care about the reason for failure.
90
+ #
91
+ def try_to_compile(code)
92
+ begin
93
+ bool = false
94
+ stderr_orig = $stderr.dup
95
+
96
+ Dir.chdir(Dir.tmpdir){
97
+ File.open(@@cpp_srcfile, 'w'){ |fh| fh.write(code) }
98
+
99
+ command = @@cpp_command + ' '
100
+ command += @@cpp_outfile + ' '
101
+ command += @@cpp_srcfile
102
+
103
+ $stderr.reopen(File.null)
104
+ bool = system(command)
105
+ }
106
+ ensure
107
+ File.delete(@@cpp_srcfile) if File.exists?(@@cpp_srcfile)
108
+ File.delete(@@cpp_outfile) if File.exists?(@@cpp_outfile)
109
+ $stderr.reopen(stderr_orig)
110
+ end
111
+
112
+ bool
113
+ end
114
+
115
+ # Slurp the contents of the template file for evaluation later.
116
+ #
117
+ def read_template(file)
118
+ IO.read(get_template_file(file))
119
+ end
120
+
121
+ # Retrieve the path to the template +file+ name.
122
+ #
123
+ def get_template_file(file)
124
+ File.join(File.dirname(__FILE__), 'templates', file)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,10 @@
1
+ <%= headers %>
2
+
3
+ int try_func(){
4
+ <%= function %>();
5
+ return 0;
6
+ }
7
+
8
+ int main(){
9
+ return 0;
10
+ }
@@ -0,0 +1,11 @@
1
+ <%= headers %>
2
+
3
+ int check_for_function(){
4
+ void ((*volatile p)());
5
+ p = (void ((*)()))<%= function %>;
6
+ return 0;
7
+ }
8
+
9
+ int main(){
10
+ return 0;
11
+ }
@@ -0,0 +1,5 @@
1
+ #include <<%= header %>>
2
+
3
+ int main(){
4
+ return 0;
5
+ }
@@ -0,0 +1,6 @@
1
+ <%= headers %>
2
+
3
+ int main(){
4
+ int s = (char *)&((<%= struct_type %>*)0)-><%= struct_member %> - (char *)0;
5
+ return 0;
6
+ }
data/mkmf-lite.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'mkmf-lite'
5
+ spec.summary = 'A lighter version of mkmf designed for use as a library'
6
+ spec.version = '0.1.0'
7
+ spec.author = 'Daniel J. Berger'
8
+ spec.license = 'Artistic 2.0'
9
+ spec.email = 'djberg96@gmail.com'
10
+ spec.homepage = 'http://www.rubyforge.org/projects/shards'
11
+ spec.test_file = 'test/test_mkmf_lite.rb'
12
+ spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
13
+
14
+ spec.extra_rdoc_files = ['CHANGES', 'README', 'MANIFEST']
15
+ spec.rubyforge_project = 'shards'
16
+
17
+ spec.add_dependency('ptools')
18
+ spec.add_development_dependency('test-unit', '>= 2.0.7')
19
+
20
+ spec.description = <<-EOF
21
+ The mkmf-lite library is a light version of the the mkmf library
22
+ designed for use as a library. It does not create packages, builds,
23
+ or log files of any kind. Instead, it provides mixin methods that you
24
+ can use in FFI or tests to check for the presence of header files,
25
+ constants, and so on.
26
+ EOF
27
+ end
@@ -0,0 +1,94 @@
1
+ ########################################################################
2
+ # test_mkmf_lite.rb
3
+ #
4
+ # Tests for the mkmf-lite library.
5
+ ########################################################################
6
+ require 'rubygems'
7
+ gem 'test-unit'
8
+ require 'test/unit'
9
+ require 'mkmf/lite'
10
+
11
+ class TC_Mkmf_Lite < Test::Unit::TestCase
12
+ include Mkmf::Lite
13
+
14
+ def self.startup
15
+ @@windows = Config::CONFIG['host_os'] =~ /mswin|msdos|win32|mingw|cygwin/i
16
+ end
17
+
18
+ def setup
19
+ @st_type = 'struct stat'
20
+ @st_member = 'st_uid'
21
+ @st_header = 'sys/stat.h'
22
+ end
23
+
24
+ test "version information" do
25
+ assert_equal('0.1.0', MKMF_LITE_VERSION)
26
+ end
27
+
28
+ test "have_header basic functionality" do
29
+ assert_respond_to(self, :have_header)
30
+ end
31
+
32
+ test "have_header returns expected boolean value" do
33
+ assert_true(have_header('stdio.h'))
34
+ assert_false(have_header('foobar.h'))
35
+ end
36
+
37
+ test "have_header requires one argument only" do
38
+ assert_raise(ArgumentError){ have_header }
39
+ assert_raise(ArgumentError){ have_header('stdio.h', 'stdlib.h') }
40
+ end
41
+
42
+ test "have_func basic functionality" do
43
+ assert_respond_to(self, :have_func)
44
+ end
45
+
46
+ test "have_func with no arguments returns expected boolean value" do
47
+ assert_true(have_func('abort'))
48
+ assert_false(have_header('abortxyz'))
49
+ end
50
+
51
+ test "have_func with arguments returns expected boolean value" do
52
+ assert_true(have_func('printf', 'stdio.h'))
53
+ assert_false(have_func('printfx', 'stdio.h'))
54
+ end
55
+
56
+ test "have_func requires at least one argument" do
57
+ assert_raise(ArgumentError){ have_func }
58
+ end
59
+
60
+ test "have_func accepts a maximum of two arguments" do
61
+ assert_raise(ArgumentError){ have_func('printf', 'stdio.h', 'bogus') }
62
+ end
63
+
64
+ test "have_struct_member basic functionality" do
65
+ assert_respond_to(self, :have_struct_member)
66
+ end
67
+
68
+ test "have_struct_member returns expected boolean value" do
69
+ assert_true(have_struct_member(@st_type, @st_member, @st_header))
70
+ assert_false(have_struct_member(@st_type, 'pw_bogus', @st_header))
71
+ assert_false(have_struct_member(@st_type, @st_member))
72
+ end
73
+
74
+ test "have_struct_member requires at least two arguments" do
75
+ assert_raise(ArgumentError){ have_struct_member() }
76
+ assert_raise(ArgumentError){ have_struct_member('struct passwd') }
77
+ end
78
+
79
+ test "have_struct_member accepts a maximum of three arguments" do
80
+ assert_raise(ArgumentError){
81
+ have_struct_member('struct passwd', 'pw_name', 'pwd.h', true)
82
+ }
83
+ end
84
+
85
+ def teardown
86
+ @st_type = nil
87
+ @st_member = nil
88
+ @st_header = nil
89
+ end
90
+
91
+ def self.shutdown
92
+ @@windows = nil
93
+ end
94
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mkmf-lite
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Daniel J. Berger
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-24 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: ptools
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: test-unit
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 2
41
+ - 0
42
+ - 7
43
+ version: 2.0.7
44
+ type: :development
45
+ version_requirements: *id002
46
+ description: " The mkmf-lite library is a light version of the the mkmf library\n designed for use as a library. It does not create packages, builds,\n or log files of any kind. Instead, it provides mixin methods that you\n can use in FFI or tests to check for the presence of header files,\n constants, and so on.\n"
47
+ email: djberg96@gmail.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - CHANGES
54
+ - README
55
+ - MANIFEST
56
+ files:
57
+ - CHANGES
58
+ - lib/mkmf/lite.rb
59
+ - lib/mkmf/templates/have_func.erb
60
+ - lib/mkmf/templates/have_func_pointer.erb
61
+ - lib/mkmf/templates/have_header.erb
62
+ - lib/mkmf/templates/have_struct_member.erb
63
+ - MANIFEST
64
+ - mkmf-lite.gemspec
65
+ - Rakefile
66
+ - README
67
+ - test/test_mkmf_lite.rb
68
+ has_rdoc: true
69
+ homepage: http://www.rubyforge.org/projects/shards
70
+ licenses:
71
+ - Artistic 2.0
72
+ post_install_message:
73
+ rdoc_options: []
74
+
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ requirements: []
92
+
93
+ rubyforge_project: shards
94
+ rubygems_version: 1.3.6
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: A lighter version of mkmf designed for use as a library
98
+ test_files:
99
+ - test/test_mkmf_lite.rb