mkmf-lite 0.7.3 → 0.7.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 726b5a45c22c5700645950241fabc40621f7a1ec9f57a20fffd212623a41acd0
4
- data.tar.gz: 34bc9e1d6d1c3bba0a9c73cfd7d899fda171054c73dfaaeec6305f246f0fe497
3
+ metadata.gz: 83a4d986b70bc7bcd5c5787245bd5b76f335dc6079124d6bdd18847b128dcb3c
4
+ data.tar.gz: c688342d4e86a77221dbbd2dd12fc3c3a77ac92892bb4aab230af11bc50ff5ec
5
5
  SHA512:
6
- metadata.gz: b5e4afd22216317af2dbb01ea8ead2339976c00276774b1a9e6b5a72e04e6d6ecb097863f6366ce7de93628299440a44b0663db245964d8c30bc310f72d14021
7
- data.tar.gz: 0d132571eb8b470886c5e2bce7c5b80b0de36ffe563dd929d7ba479173125827a643b8d63584d7b76a6d05c8db72dd1f5c35b095f38cad707d06d29541c4103c
6
+ metadata.gz: c36047013680595f8776cd8e87813ccf4fdf2aac43056d6ffc676c61c262f502e8c3114b3a09ca6b1610eede8ea6c3b59bce4e8631e0e785afd385c789d61aad
7
+ data.tar.gz: 0ef5c1481603d4ffdc840d6f468f4ddcaa0e03b81f2648e6395f48df72b21d772c24ff17638db365d2c1316f57e24cff8ac6880b7895b5710178625df43bf4be
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,5 +1,8 @@
1
+ ## 0.7.4 - 23-Dec-2025
2
+ * Added have_library method.
3
+
1
4
  ## 0.7.3 - 21-Mar-2025
2
- * Add check_offsetof method.
5
+ * Added check_offsetof method.
3
6
 
4
7
  ## 0.7.2 - 13-Mar-2025
5
8
  * Allow option of adding directories to check_sizeof and check_valueof methods.
data/README.md CHANGED
@@ -54,7 +54,7 @@ JRuby may emit warnings on some platforms.
54
54
  Apache-2.0
55
55
 
56
56
  ## Copyright
57
- (C) 2010-2024 Daniel J. Berger
57
+ (C) 2010-2025 Daniel J. Berger
58
58
  All Rights Reserved
59
59
 
60
60
  ## Warranty
data/Rakefile CHANGED
@@ -24,7 +24,10 @@ end
24
24
  RuboCop::RakeTask.new
25
25
 
26
26
  desc "Run the test suite"
27
- RSpec::Core::RakeTask.new(:spec)
27
+ RSpec::Core::RakeTask.new(:spec) do |t|
28
+ t.verbose = false
29
+ t.rspec_opts = '-f documentation -w'
30
+ end
28
31
 
29
32
  # Clean up afterwards
30
33
  Rake::Task[:spec].enhance do
data/conftest.c ADDED
@@ -0,0 +1,5 @@
1
+ #include <foobar.h>
2
+
3
+ int main(){
4
+ return 0;
5
+ }
data/conftest.exe ADDED
Binary file
data/lib/mkmf/lite.rb CHANGED
@@ -16,7 +16,7 @@ module Mkmf
16
16
  extend Memoist
17
17
 
18
18
  # The version of the mkmf-lite library
19
- MKMF_LITE_VERSION = '0.7.3'
19
+ MKMF_LITE_VERSION = '0.7.4'
20
20
 
21
21
  private
22
22
 
@@ -25,15 +25,22 @@ module Mkmf
25
25
  end
26
26
 
27
27
  def jruby?
28
- defined?(JRUBY_VERSION) ? true : false
28
+ defined?(JRUBY_VERSION)
29
29
  end
30
30
 
31
31
  memoize :jruby?
32
32
 
33
+ def windows_with_cl_compiler?
34
+ File::ALT_SEPARATOR && RbConfig::CONFIG['CPP']&.match?(/^cl/)
35
+ end
36
+
37
+ memoize :windows_with_cl_compiler?
38
+
33
39
  # rubocop:disable Layout/LineLength
34
40
  def cpp_command
35
41
  command = RbConfig::CONFIG['CC'] || RbConfig::CONFIG['CPP'] || File.which('cc') || File.which('gcc') || File.which('cl')
36
- raise 'Compiler not found' unless command
42
+ raise StandardError, 'Compiler not found' unless command
43
+
37
44
  command
38
45
  end
39
46
  # rubocop:enable Layout/LineLength
@@ -45,7 +52,7 @@ module Mkmf
45
52
  end
46
53
 
47
54
  def cpp_out_file
48
- if File::ALT_SEPARATOR && RbConfig::CONFIG['CPP'] =~ /^cl/
55
+ if windows_with_cl_compiler?
49
56
  '/Feconftest.exe'
50
57
  else
51
58
  '-o conftest.exe'
@@ -55,10 +62,9 @@ module Mkmf
55
62
  memoize :cpp_out_file
56
63
 
57
64
  def cpp_libraries
58
- return if File::ALT_SEPARATOR && RbConfig::CONFIG['CPP'] =~ /^cl/
59
- return if jruby?
65
+ return nil if windows_with_cl_compiler? || jruby?
60
66
 
61
- if cpp_command =~ /clang/i
67
+ if cpp_command.match?(/clang/i)
62
68
  '-Lrt -Ldl -Lcrypt -Lm'
63
69
  else
64
70
  '-lrt -ldl -lcrypt -lm'
@@ -77,14 +83,7 @@ module Mkmf
77
83
  def have_header(header, *directories)
78
84
  erb = ERB.new(read_template('have_header.erb'))
79
85
  code = erb.result(binding)
80
-
81
- if directories.empty?
82
- options = nil
83
- else
84
- options = ''
85
- directories.each{ |dir| options += "-I#{dir} " }
86
- options.rstrip!
87
- end
86
+ options = build_directory_options(directories)
88
87
 
89
88
  try_to_compile(code, options)
90
89
  end
@@ -112,6 +111,25 @@ module Mkmf
112
111
 
113
112
  memoize :have_func
114
113
 
114
+ # Check for the presence of the given +library+. You may optionally
115
+ # provide a +function+ name to check for within that library, as well
116
+ # as any additional +headers+.
117
+ #
118
+ # Returns true if the library can be linked, or false otherwise.
119
+ #
120
+ def have_library(library, function = nil, headers = [])
121
+ headers = get_header_string(headers)
122
+ erb = ERB.new(read_template('have_library.erb'))
123
+ code = erb.result(binding)
124
+
125
+ # Build link options with the library
126
+ link_options = windows_with_cl_compiler? ? "#{library}.lib" : "-l#{library}"
127
+
128
+ try_to_compile(code, nil, link_options)
129
+ end
130
+
131
+ memoize :have_library
132
+
115
133
  # Checks whether or not the struct of type +struct_type+ contains the
116
134
  # +struct_member+. If it does not, or the struct type cannot be found,
117
135
  # then false is returned.
@@ -139,14 +157,7 @@ module Mkmf
139
157
  headers = get_header_string(headers)
140
158
  erb = ERB.new(read_template('check_valueof.erb'))
141
159
  code = erb.result(binding)
142
-
143
- if directories.empty?
144
- options = nil
145
- else
146
- options = ''
147
- directories.each{ |dir| options += "-I#{dir} " }
148
- options.rstrip!
149
- end
160
+ options = build_directory_options(directories)
150
161
 
151
162
  try_to_execute(code, options)
152
163
  end
@@ -170,14 +181,7 @@ module Mkmf
170
181
  headers = get_header_string(headers)
171
182
  erb = ERB.new(read_template('check_sizeof.erb'))
172
183
  code = erb.result(binding)
173
-
174
- if directories.empty?
175
- options = nil
176
- else
177
- options = ''
178
- directories.each{ |dir| options += "-I#{dir} " }
179
- options.rstrip!
180
- end
184
+ options = build_directory_options(directories)
181
185
 
182
186
  try_to_execute(code, options)
183
187
  end
@@ -202,14 +206,7 @@ module Mkmf
202
206
  headers = get_header_string(headers)
203
207
  erb = ERB.new(read_template('check_offsetof.erb'))
204
208
  code = erb.result(binding)
205
-
206
- if directories.empty?
207
- options = nil
208
- else
209
- options = ''
210
- directories.each{ |dir| options += "-I#{dir} " }
211
- options.rstrip!
212
- end
209
+ options = build_directory_options(directories)
213
210
 
214
211
  try_to_execute(code, options)
215
212
  end
@@ -218,6 +215,39 @@ module Mkmf
218
215
 
219
216
  private
220
217
 
218
+ def build_directory_options(directories)
219
+ return nil if directories.empty?
220
+
221
+ directories.map { |dir| "-I#{dir}" }.join(' ')
222
+ end
223
+
224
+ def build_compile_command(command_options = nil, library_options = nil)
225
+ command_parts = [cpp_command]
226
+ command_parts << command_options if command_options
227
+ command_parts << cpp_libraries if cpp_libraries
228
+ command_parts << cpp_defs
229
+ command_parts << cpp_out_file
230
+ command_parts << cpp_source_file
231
+ command_parts << library_options if library_options
232
+
233
+ command_parts.compact.join(' ')
234
+ end
235
+
236
+ def with_suppressed_output
237
+ stderr_orig = $stderr.dup
238
+ stdout_orig = $stdout.dup
239
+
240
+ $stderr.reopen(IO::NULL)
241
+ $stdout.reopen(IO::NULL)
242
+
243
+ yield
244
+ ensure
245
+ $stderr.reopen(stderr_orig)
246
+ $stdout.reopen(stdout_orig)
247
+ stderr_orig.close
248
+ stdout_orig.close
249
+ end
250
+
221
251
  # Take an array of header file names (or convert it to an array if it's a
222
252
  # single argument), add the COMMON_HEADERS, flatten it out and remove any
223
253
  # duplicates.
@@ -228,21 +258,20 @@ module Mkmf
228
258
  # This string is then to be used at the top of the ERB templates.
229
259
  #
230
260
  def get_header_string(headers)
231
- headers = [headers] unless headers.is_a?(Array)
261
+ headers = Array(headers)
232
262
 
233
263
  common_headers = RbConfig::CONFIG['COMMON_HEADERS']
234
264
 
235
265
  if common_headers.nil? || common_headers.empty?
236
266
  if headers.empty?
237
267
  headers = ['stdio.h', 'stdlib.h']
238
- headers += 'windows.h' if File::ALT_SEPARATOR
268
+ headers << 'windows.h' if File::ALT_SEPARATOR
239
269
  end
240
270
  else
241
271
  headers += common_headers.split
242
272
  end
243
273
 
244
- headers = headers.flatten.uniq
245
- headers.map{ |h| "#include <#{h}>" }.join("\n")
274
+ headers.flatten.uniq.map { |h| "#include <#{h}>" }.join("\n")
246
275
  end
247
276
 
248
277
  # Create a temporary bit of C source code in the temp directory, and
@@ -255,50 +284,32 @@ module Mkmf
255
284
  # error is raised if the compilation step fails.
256
285
  #
257
286
  def try_to_execute(code, command_options = nil)
258
- begin
259
- result = 0
260
-
261
- stderr_orig = $stderr.dup
262
- stdout_orig = $stdout.dup
263
-
264
- Dir.chdir(Dir.tmpdir) do
265
- File.write(cpp_source_file, code)
266
-
267
- if command_options
268
- command = "#{cpp_command} #{command_options} #{cpp_libraries} #{cpp_defs} "
269
- else
270
- command = "#{cpp_command} #{cpp_libraries} #{cpp_defs} "
271
- end
287
+ result = 0
272
288
 
273
- command += "#{cpp_out_file} "
274
- command += cpp_source_file
289
+ Dir.chdir(Dir.tmpdir) do
290
+ File.write(cpp_source_file, code)
291
+ command = build_compile_command(command_options)
275
292
 
276
- # Temporarily close these
277
- $stderr.reopen(IO::NULL)
278
- $stdout.reopen(IO::NULL)
293
+ compilation_successful = with_suppressed_output { system(command) }
279
294
 
280
- if system(command)
281
- $stdout.reopen(stdout_orig) # We need this back for open3 to work.
295
+ if compilation_successful
296
+ conftest = File::ALT_SEPARATOR ? 'conftest.exe' : './conftest.exe'
282
297
 
283
- conftest = File::ALT_SEPARATOR ? 'conftest.exe' : './conftest.exe'
284
-
285
- Open3.popen3(conftest) do |stdin, stdout, stderr|
286
- stdin.close
287
- stderr.close
288
- result = stdout.gets.chomp.to_i
289
- end
290
- else
291
- raise "Failed to compile source code with command '#{command}':\n===\n#{code}==="
298
+ Open3.popen3(conftest) do |stdin, stdout, stderr|
299
+ stdin.close
300
+ stderr.close
301
+ output = stdout.gets
302
+ result = output&.chomp&.to_i || 0
292
303
  end
304
+ else
305
+ raise StandardError, "Failed to compile source code with command '#{command}':\n===\n#{code}==="
293
306
  end
294
- ensure
295
- FileUtils.rm_f(cpp_source_file)
296
- FileUtils.rm_f(cpp_out_file)
297
- $stderr.reopen(stderr_orig)
298
- $stdout.reopen(stdout_orig)
299
307
  end
300
308
 
301
309
  result
310
+ ensure
311
+ FileUtils.rm_f(File.join(Dir.tmpdir, cpp_source_file))
312
+ FileUtils.rm_f(File.join(Dir.tmpdir, 'conftest.exe'))
302
313
  end
303
314
 
304
315
  # Create a temporary bit of C source code in the temp directory, and
@@ -308,36 +319,16 @@ module Mkmf
308
319
  # Note that $stderr is temporarily redirected to the null device because
309
320
  # we don't actually care about the reason for failure.
310
321
  #
311
- def try_to_compile(code, command_options = nil)
312
- begin
313
- boolean = false
314
- stderr_orig = $stderr.dup
315
- stdout_orig = $stdout.dup
316
-
317
- Dir.chdir(Dir.tmpdir) do
318
- File.write(cpp_source_file, code)
319
-
320
- if command_options
321
- command = "#{cpp_command} #{command_options} #{cpp_libraries} #{cpp_defs} "
322
- else
323
- command = "#{cpp_command} #{cpp_libraries} #{cpp_defs} "
324
- end
325
-
326
- command += "#{cpp_out_file} "
327
- command += cpp_source_file
322
+ def try_to_compile(code, command_options = nil, library_options = nil)
323
+ Dir.chdir(Dir.tmpdir) do
324
+ File.write(cpp_source_file, code)
325
+ command = build_compile_command(command_options, library_options)
328
326
 
329
- $stderr.reopen(IO::NULL)
330
- $stdout.reopen(IO::NULL)
331
- boolean = system(command)
332
- end
333
- ensure
334
- FileUtils.rm_f(cpp_source_file)
335
- FileUtils.rm_f(cpp_out_file)
336
- $stdout.reopen(stdout_orig)
337
- $stderr.reopen(stderr_orig)
327
+ with_suppressed_output { system(command) }
338
328
  end
339
-
340
- boolean
329
+ ensure
330
+ FileUtils.rm_f(File.join(Dir.tmpdir, cpp_source_file))
331
+ FileUtils.rm_f(File.join(Dir.tmpdir, 'conftest.exe'))
341
332
  end
342
333
 
343
334
  # Slurp the contents of the template file for evaluation later.
@@ -0,0 +1,10 @@
1
+ <%= headers %>
2
+
3
+ int main(){
4
+ <% if function %>
5
+ void *p = (void *)&<%= function %>;
6
+ return !p;
7
+ <% else %>
8
+ return 0;
9
+ <% end %>
10
+ }
data/mkmf-lite.gemspec CHANGED
@@ -3,7 +3,7 @@ require 'rubygems'
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'mkmf-lite'
5
5
  spec.summary = 'A lighter version of mkmf designed for use as a library'
6
- spec.version = '0.7.3'
6
+ spec.version = '0.7.4'
7
7
  spec.author = 'Daniel J. Berger'
8
8
  spec.license = 'Apache-2.0'
9
9
  spec.email = 'djberg96@gmail.com'
@@ -20,7 +20,7 @@ RSpec.describe Mkmf::Lite do
20
20
 
21
21
  describe 'constants' do
22
22
  example 'version information' do
23
- expect(described_class::MKMF_LITE_VERSION).to eq('0.7.3')
23
+ expect(described_class::MKMF_LITE_VERSION).to eq('0.7.4')
24
24
  expect(described_class::MKMF_LITE_VERSION).to be_frozen
25
25
  end
26
26
  end
@@ -164,4 +164,34 @@ RSpec.describe Mkmf::Lite do
164
164
  expect(size).to be > 0
165
165
  end
166
166
  end
167
+
168
+ context 'have_library' do
169
+ example 'have_library basic functionality' do
170
+ expect(subject).to respond_to(:have_library)
171
+ end
172
+
173
+ example 'have_library returns expected boolean value' do
174
+ expect(subject.have_library('c')).to be(true)
175
+ expect(subject.have_library('m')).to be(true)
176
+ expect(subject.have_library('nonexistent_library_xyz')).to be(false)
177
+ end
178
+
179
+ example 'have_library with function argument returns expected boolean value' do
180
+ expect(subject.have_library('m', 'sqrt', 'math.h')).to be(true)
181
+ expect(subject.have_library('m', 'nonexistent_function_xyz', 'math.h')).to be(false)
182
+ end
183
+
184
+ example 'have_library with headers argument works correctly' do
185
+ expect{ subject.have_library('m', 'sqrt', 'math.h') }.not_to raise_error
186
+ expect(subject.have_library('m', 'sqrt', 'math.h')).to be(true)
187
+ end
188
+
189
+ example 'have_library requires at least one argument' do
190
+ expect{ subject.have_library }.to raise_error(ArgumentError)
191
+ end
192
+
193
+ example 'have_library accepts a maximum of three arguments' do
194
+ expect{ subject.have_library('m', 'sqrt', 'math.h', 'bogus') }.to raise_error(ArgumentError)
195
+ end
196
+ end
167
197
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mkmf-lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -35,7 +34,7 @@ cert_chain:
35
34
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
35
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
36
  -----END CERTIFICATE-----
38
- date: 2025-03-22 00:00:00.000000000 Z
37
+ date: 1980-01-02 00:00:00.000000000 Z
39
38
  dependencies:
40
39
  - !ruby/object:Gem::Dependency
41
40
  name: ptools
@@ -139,6 +138,8 @@ files:
139
138
  - README.md
140
139
  - Rakefile
141
140
  - certs/djberg96_pub.pem
141
+ - conftest.c
142
+ - conftest.exe
142
143
  - lib/mkmf-lite.rb
143
144
  - lib/mkmf/lite.rb
144
145
  - lib/mkmf/templates/check_offsetof.erb
@@ -147,6 +148,7 @@ files:
147
148
  - lib/mkmf/templates/have_func.erb
148
149
  - lib/mkmf/templates/have_func_pointer.erb
149
150
  - lib/mkmf/templates/have_header.erb
151
+ - lib/mkmf/templates/have_library.erb
150
152
  - lib/mkmf/templates/have_struct_member.erb
151
153
  - mkmf-lite.gemspec
152
154
  - spec/mkmf_lite_spec.rb
@@ -163,7 +165,6 @@ metadata:
163
165
  rubygems_mfa_required: 'true'
164
166
  github_repo: https://github.com/djberg96/mkmf-lite
165
167
  funding_uri: https://github.com/sponsors/djberg96
166
- post_install_message:
167
168
  rdoc_options: []
168
169
  require_paths:
169
170
  - lib
@@ -178,8 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
179
  - !ruby/object:Gem::Version
179
180
  version: '0'
180
181
  requirements: []
181
- rubygems_version: 3.5.22
182
- signing_key:
182
+ rubygems_version: 3.7.2
183
183
  specification_version: 4
184
184
  summary: A lighter version of mkmf designed for use as a library
185
185
  test_files:
metadata.gz.sig CHANGED
Binary file