mkmf-lite 0.8.1 → 0.9.0

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: b780dd7e2e0e1b2be89941ce19c6cd891de5318b53cb199e6b3cbfead5c174be
4
- data.tar.gz: 7b8afafe384f433f17b309416b24a467c488696b6b2e98560c4f2e545bfd9c77
3
+ metadata.gz: f47fa10fbba01d8138ccf00130db6de0a655ade9160bbf1f63c66a49f0180a85
4
+ data.tar.gz: 89ebf0df0a2ba2763f288f063766f886050e6cec2320875429499aeeb5f6697c
5
5
  SHA512:
6
- metadata.gz: 1a80776330561d06936541572c984baec486bbacce69fa15bf07c3e8578981791a2769e17d94e793781f5203339b037860a5ba7d86bed1d67b65216885cde910
7
- data.tar.gz: 98dc7c4df08d005d8628b4509f1b58059a2995bc321798138315d794d98ffadad2ef48b383afe5374ac66b162e8c5c9108376ceb6e2d33701e89cf596b8731ae
6
+ metadata.gz: 5941960fbc5d1adbeda16c00cb056d75c816b07d5d9a361f62457dec029fe8bbb096957a7ce5b63ccf7220f12f0d97550e39a018e013c7d7309fbfe12cc8f020
7
+ data.tar.gz: aaf1b5436a3949512180a187909273fbf8c8738cb3f6bf46dad9c9e9b5707584b3db7a9ea9fceaba77384a2a904e58488f3621887f42ecdd848937ce3a8c134f
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.9.0 - 5-Jul-2026
2
+ * Added `Mkmf::Lite.configure` for process-wide compiler, include directory,
3
+ library directory, compile flag, and link flag defaults.
4
+ * Configuration changes now clear memoized probe results on existing
5
+ `Mkmf::Lite` extenders.
6
+
1
7
  ## 0.8.1 - 30-Jun-2026
2
8
  * Improved generated C formatting for size, offset, and constant probes.
3
9
  * Simplified struct member probes to use a compile-only member check.
data/README.md CHANGED
@@ -109,6 +109,23 @@ class LocalHeader
109
109
  end
110
110
  ```
111
111
 
112
+ ## Configuration
113
+ Use `Mkmf::Lite.configure` to set process-wide defaults that should apply to
114
+ all probes:
115
+
116
+ ```ruby
117
+ Mkmf::Lite.configure do |config|
118
+ config.compiler = 'clang'
119
+ config.include_dirs = ['/opt/local/include']
120
+ config.lib_dirs = ['/opt/local/lib']
121
+ config.cflags = ['-D_GNU_SOURCE']
122
+ config.ldflags = ['-Wl,-rpath,/opt/local/lib']
123
+ end
124
+ ```
125
+
126
+ The same configuration object is available from any object that extends
127
+ `Mkmf::Lite`, so local setup code can call `configure` there as well.
128
+
112
129
  ## Memoization
113
130
  As of version 0.6.0, public probe results are memoized for the lifetime of the
114
131
  object that extends `Mkmf::Lite`. The method arguments are part of the cache
@@ -116,9 +133,9 @@ key, so `have_header('foo.h')` and `have_header('foo.h', '/usr/local/include')`
116
133
  are distinct checks.
117
134
 
118
135
  This fits the normal use case where compiler configuration, headers, and system
119
- libraries do not change while the Ruby process is running. If you need to probe
120
- again after changing the environment, create a new object or restart the
121
- process.
136
+ libraries do not change while the Ruby process is running. Calling
137
+ `Mkmf::Lite.configure` clears memoized probe results on objects that already
138
+ extended `Mkmf::Lite`, so repeated checks use the updated defaults.
122
139
 
123
140
  ## Known Issues
124
141
  JRuby may emit warnings on some platforms.
data/ROADMAP.md CHANGED
@@ -123,10 +123,12 @@ have_library(
123
123
 
124
124
  Consider a small configuration API if repeated keyword arguments become noisy.
125
125
 
126
- * Evaluate `Mkmf::Lite.configure` for global defaults.
127
- * Support compiler, include directories, library directories, compile flags,
126
+ Status: Done.
127
+
128
+ * [x] Evaluate `Mkmf::Lite.configure` for global defaults.
129
+ * [x] Support compiler, include directories, library directories, compile flags,
128
130
  and link flags as possible defaults.
129
- * Make configuration interaction with memoized probe results explicit.
131
+ * [x] Make configuration interaction with memoized probe results explicit.
130
132
 
131
133
  ### 1.0.0 - Stable Contract
132
134
 
data/lib/mkmf/lite.rb CHANGED
@@ -15,8 +15,74 @@ module Mkmf
15
15
  module Lite
16
16
  extend Memoist
17
17
 
18
+ # Stores process-wide defaults for compiler probe commands.
19
+ class Configuration
20
+ attr_accessor :compiler
21
+ attr_reader :include_dirs, :lib_dirs, :cflags, :ldflags
22
+
23
+ def initialize
24
+ @compiler = nil
25
+ @include_dirs = []
26
+ @lib_dirs = []
27
+ @cflags = []
28
+ @ldflags = []
29
+ end
30
+
31
+ def include_dirs=(dirs)
32
+ @include_dirs = normalize_options(dirs)
33
+ end
34
+
35
+ def lib_dirs=(dirs)
36
+ @lib_dirs = normalize_options(dirs)
37
+ end
38
+
39
+ def cflags=(flags)
40
+ @cflags = normalize_options(flags)
41
+ end
42
+
43
+ def ldflags=(flags)
44
+ @ldflags = normalize_options(flags)
45
+ end
46
+
47
+ private
48
+
49
+ def normalize_options(options)
50
+ Array(options).flatten.compact.map(&:to_s)
51
+ end
52
+ end
53
+
18
54
  # The version of the mkmf-lite library
19
- MKMF_LITE_VERSION = '0.8.1'
55
+ MKMF_LITE_VERSION = '0.9.0'
56
+
57
+ class << self
58
+ def configuration
59
+ @configuration ||= Configuration.new
60
+ end
61
+
62
+ def configure
63
+ yield configuration
64
+ reset_memoized_results
65
+ configuration
66
+ end
67
+
68
+ def extended(object)
69
+ configured_objects << object
70
+ end
71
+
72
+ private
73
+
74
+ def configured_objects
75
+ @configured_objects ||= []
76
+ end
77
+
78
+ def reset_memoized_results
79
+ ([self] + configured_objects).each do |object|
80
+ object.instance_variables.grep(/^@_memoized_/).each do |ivar|
81
+ object.remove_instance_variable(ivar)
82
+ end
83
+ end
84
+ end
85
+ end
20
86
 
21
87
  private
22
88
 
@@ -38,7 +104,7 @@ module Mkmf
38
104
 
39
105
  # rubocop:disable Layout/LineLength
40
106
  def cpp_command
41
- command = RbConfig::CONFIG['CC'] || RbConfig::CONFIG['CPP'] || File.which('cc') || File.which('gcc') || File.which('cl')
107
+ command = configuration.compiler || RbConfig::CONFIG['CC'] || RbConfig::CONFIG['CPP'] || File.which('cc') || File.which('gcc') || File.which('cl')
42
108
  raise StandardError, 'Compiler not found' unless command
43
109
 
44
110
  command
@@ -68,6 +134,8 @@ module Mkmf
68
134
  def cpp_library_paths
69
135
  paths = []
70
136
 
137
+ paths.concat(build_library_directory_options(configuration.lib_dirs))
138
+
71
139
  # Add Homebrew library paths on macOS
72
140
  if RbConfig::CONFIG['host_os'].match?(/darwin/)
73
141
  # Apple Silicon Macs
@@ -83,6 +151,14 @@ module Mkmf
83
151
 
84
152
  public
85
153
 
154
+ def configure(&block)
155
+ Mkmf::Lite.configure(&block)
156
+ end
157
+
158
+ def configuration
159
+ Mkmf::Lite.configuration
160
+ end
161
+
86
162
  # Check for the presence of the given +header+ file. You may optionally
87
163
  # provide a list of directories to search.
88
164
  #
@@ -236,18 +312,34 @@ module Mkmf
236
312
  directories.flatten.map { |dir| "-I#{dir}" }
237
313
  end
238
314
 
315
+ def build_configured_compile_options(command_options)
316
+ [
317
+ build_directory_options(configuration.include_dirs),
318
+ configuration.cflags,
319
+ command_options
320
+ ].flatten.compact
321
+ end
322
+
323
+ def build_configured_link_options(library_options)
324
+ [library_options, configuration.ldflags].flatten.compact
325
+ end
326
+
327
+ def build_library_directory_options(directories)
328
+ directories.flatten.map { |dir| "-L#{dir}" }
329
+ end
330
+
239
331
  def build_compile_command(command_options = nil, library_options = nil, paths = {})
240
332
  source_file = paths.fetch(:source_file, cpp_source_file)
241
333
  output_file = paths.fetch(:output_file, 'conftest.exe')
242
334
 
243
335
  command_parts = shellwords(cpp_command)
244
- command_parts.concat(shellwords(command_options))
336
+ command_parts.concat(shellwords(build_configured_compile_options(command_options)))
245
337
  command_parts.concat(shellwords(cpp_library_paths))
246
338
  command_parts.concat(shellwords(cpp_libraries))
247
339
  command_parts.concat(shellwords(cpp_defs))
248
340
  command_parts.concat(shellwords(cpp_out_file(output_file)))
249
341
  command_parts << source_file
250
- command_parts.concat(shellwords(library_options))
342
+ command_parts.concat(shellwords(build_configured_link_options(library_options)))
251
343
 
252
344
  command_parts
253
345
  end
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.8.1'
6
+ spec.version = '0.9.0'
7
7
  spec.author = 'Daniel J. Berger'
8
8
  spec.license = 'Apache-2.0'
9
9
  spec.email = 'djberg96@gmail.com'
@@ -14,6 +14,16 @@ require 'tmpdir'
14
14
  RSpec.describe Mkmf::Lite do
15
15
  subject { Class.new{ |obj| obj.extend Mkmf::Lite } }
16
16
 
17
+ after do
18
+ described_class.configure do |config|
19
+ config.compiler = nil
20
+ config.include_dirs = []
21
+ config.lib_dirs = []
22
+ config.cflags = []
23
+ config.ldflags = []
24
+ end
25
+ end
26
+
17
27
  def new_probe
18
28
  Class.new{ |obj| obj.extend Mkmf::Lite }
19
29
  end
@@ -32,6 +42,57 @@ RSpec.describe Mkmf::Lite do
32
42
  probe.send(:build_compile_command, nil, ['-L/tmp/lib dir', '-lfoo'])
33
43
  end
34
44
 
45
+ def configured_compile_command(probe)
46
+ probe.send(
47
+ :build_compile_command,
48
+ nil,
49
+ ['-lfoo'],
50
+ :source_file => 'source.c',
51
+ :output_file => 'output file'
52
+ )
53
+ end
54
+
55
+ def configure_compiler_defaults
56
+ described_class.configure do |config|
57
+ config.compiler = 'custom-cc'
58
+ config.include_dirs = ['/tmp/include dir']
59
+ config.lib_dirs = ['/tmp/lib dir']
60
+ config.cflags = ['-DLOCAL_BUILD=1']
61
+ config.ldflags = ['-Wl,-rpath,/tmp/lib dir']
62
+ end
63
+ end
64
+
65
+ def write_configured_header(dir, header)
66
+ File.write(File.join(dir, header), "#define MKMF_LITE_CONFIGURED_HEADER 1\n")
67
+ end
68
+
69
+ def expect_configured_command_defaults(command)
70
+ expect(command).to include(
71
+ 'custom-cc',
72
+ '-I/tmp/include dir',
73
+ '-L/tmp/lib dir',
74
+ '-DLOCAL_BUILD=1',
75
+ '-lfoo',
76
+ '-Wl,-rpath,/tmp/lib dir'
77
+ )
78
+ end
79
+
80
+ def expect_configured_command_order(command)
81
+ expect(command.index('-DLOCAL_BUILD=1')).to be < command.index('source.c')
82
+ expect(command.index('-Wl,-rpath,/tmp/lib dir')).to be > command.index('source.c')
83
+ end
84
+
85
+ def expect_probe_to_refresh_with_configured_header(probe)
86
+ header = 'mkmf_lite_configured_header.h'
87
+
88
+ Dir.mktmpdir('mkmf lite configured') do |dir|
89
+ write_configured_header(dir, header)
90
+ expect(probe.have_header(header)).to be(false)
91
+ described_class.configure { |config| config.include_dirs = [dir] }
92
+ expect(probe.have_header(header)).to be(true)
93
+ end
94
+ end
95
+
35
96
  let(:st_type) { 'struct stat' }
36
97
  let(:st_member) { 'st_uid' }
37
98
  let(:st_header) { 'sys/stat.h' }
@@ -39,7 +100,7 @@ RSpec.describe Mkmf::Lite do
39
100
 
40
101
  describe 'constants' do
41
102
  example 'version information' do
42
- expect(described_class::MKMF_LITE_VERSION).to eq('0.8.1')
103
+ expect(described_class::MKMF_LITE_VERSION).to eq('0.9.0')
43
104
  expect(described_class::MKMF_LITE_VERSION).to be_frozen
44
105
  end
45
106
  end
@@ -302,6 +363,27 @@ RSpec.describe Mkmf::Lite do
302
363
  end
303
364
  end
304
365
 
366
+ describe 'configuration' do
367
+ example 'exposes global compiler and flag defaults' do
368
+ configure_compiler_defaults
369
+
370
+ command = configured_compile_command(subject)
371
+
372
+ expect_configured_command_defaults(command)
373
+ expect_configured_command_order(command)
374
+ end
375
+
376
+ example 'configuration can be set from an object that extends Mkmf::Lite' do
377
+ subject.configure { |config| config.cflags = '-DMKMF_LITE_CONFIGURED=1' }
378
+
379
+ expect(subject.configuration.cflags).to eq(['-DMKMF_LITE_CONFIGURED=1'])
380
+ end
381
+
382
+ example 'configuration changes clear memoized probe results' do
383
+ expect_probe_to_refresh_with_configured_header(new_probe)
384
+ end
385
+ end
386
+
305
387
  describe 'parallel probe invocations' do
306
388
  example 'run independently without temporary file collisions' do
307
389
  results = Array.new(6) { Thread.new { parallel_probe_result } }.map(&:value)
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mkmf-lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -178,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
178
  - !ruby/object:Gem::Version
179
179
  version: '0'
180
180
  requirements: []
181
- rubygems_version: 4.0.12
181
+ rubygems_version: 4.0.15
182
182
  specification_version: 4
183
183
  summary: A lighter version of mkmf designed for use as a library
184
184
  test_files:
metadata.gz.sig CHANGED
Binary file