Skip to content

Commit 74ac5a1

Browse files
committed
feat: integrate better with MakeMakefile
If MakeMakefile is loaded, assume we're in an `extconf.rb` and: - prepend a `-L lib_path` and `-l lib_name` to $LDFLAGS - prepend `-I include_path` to $CPPFLAGS This should mean we don't need to use the pkgconf trick in extconf.rb anymore, which completely avoids the behavior of Fedora's pkgconf described in #118. I'm a little worried that this might break packages in some subtle way, so it can be turned off by passing `mkmf: false` to `MiniPortile#activate` also: - fix up the windows paths in the the LDFLAGS env var and the tests - use assert_includes for better failure messages - extract public class methods MiniPortile.native_path and .posix_path
1 parent 62b9a6e commit 74ac5a1

File tree

3 files changed

+129
-58
lines changed

3 files changed

+129
-58
lines changed

examples/Rakefile

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
require 'rbconfig'
2-
require 'mkmf'
32

43
$: << File.expand_path(File.join(File.dirname(__FILE__), "../lib"))
54
require "mini_portile2"
65

6+
$LDFLAGS = "-mimic-being-in-extconf" # mimic being in an extconf (mkmf.rb sets this global variable)
77
recipes = []
88
recipe_hooks = {}
99

@@ -131,12 +131,7 @@ yaml.files = [{
131131
}]
132132
recipes.push(yaml)
133133
recipe_hooks["yaml"] = lambda do |recipe|
134-
expected = "-L" + File.join(recipe.path, "lib")
135-
!$LDFLAGS.split.include?(expected) or raise "assertion failed on setup"
136-
137-
conf = pkg_config(File.join(recipe.path, "lib", "pkgconfig", "yaml-0.1.pc"))
138-
puts "pkg_config: #{conf.inspect}"
139-
134+
expected = "-L" + MiniPortile.native_path(File.join(recipe.path, "lib"))
140135
$LDFLAGS.split.include?(expected) or raise(<<~MSG)
141136
assertion failed: LDFLAGS not updated correctly:
142137
#{$LDFLAGS}
@@ -173,6 +168,7 @@ namespace :ports do
173168
recipes.each do |recipe|
174169
puts "Artifacts of '#{recipe.name}' in '#{recipe.path}'"
175170
end
171+
puts "LIBRARY_PATH: #{ENV['LIBRARY_PATH'].inspect}"
176172
puts "LDFLAGS: #{ENV['LDFLAGS'].inspect}, #{$LDFLAGS.inspect}"
177173
end
178174
end

lib/mini_portile2/mini_portile.rb

+50-31
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,24 @@ def self.target_cpu
7676
RbConfig::CONFIG['target_cpu']
7777
end
7878

79+
def self.native_path(path)
80+
path = File.expand_path(path)
81+
if File::ALT_SEPARATOR
82+
path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
83+
else
84+
path
85+
end
86+
end
87+
88+
def self.posix_path(path)
89+
path = File.expand_path(path)
90+
if File::ALT_SEPARATOR
91+
"/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR)
92+
else
93+
path
94+
end
95+
end
96+
7997
def initialize(name, version, **kwargs)
8098
@name = name
8199
@version = version
@@ -218,34 +236,45 @@ def cook
218236
return true
219237
end
220238

221-
def activate
239+
def activate(mkmf: defined?(MakeMakefile))
240+
output "Activating #{@name} #{@version} (from #{port_path})..."
241+
242+
bin_path = File.join(port_path, 'bin')
243+
include_path = File.join(port_path, 'include')
222244
lib_path = File.join(port_path, "lib")
223-
vars = {
224-
'PATH' => File.join(port_path, 'bin'),
225-
'CPATH' => File.join(port_path, 'include'),
226-
'LIBRARY_PATH' => lib_path
227-
}.reject { |env, path| !File.directory?(path) }
228245

229-
output "Activating #{@name} #{@version} (from #{port_path})..."
230-
vars.each do |var, path|
231-
full_path = native_path(path)
246+
if Dir.exist?(bin_path)
247+
ENV["PATH"] = ENV.fetch("PATH", "").split(File::PATH_SEPARATOR)
248+
.unshift(native_path(bin_path)).join(File::PATH_SEPARATOR)
249+
end
232250

233-
# save current variable value
234-
old_value = ENV[var] || ''
251+
if Dir.exist?(include_path)
252+
ENV["CPATH"] = ENV.fetch("CPATH", "").split(File::PATH_SEPARATOR)
253+
.unshift(native_path(include_path)).join(File::PATH_SEPARATOR)
235254

236-
unless old_value.include?(full_path)
237-
ENV[var] = "#{full_path}#{File::PATH_SEPARATOR}#{old_value}"
255+
if mkmf
256+
$CPPFLAGS = ($CPPFLAGS || "").split
257+
.unshift("-I#{native_path(include_path)}")
258+
.join(" ")
238259
end
239260
end
240261

241-
# rely on LDFLAGS when cross-compiling
242-
if File.exist?(lib_path) && (@host != @original_host)
243-
full_path = File.expand_path(lib_path)
262+
if Dir.exist?(lib_path)
263+
ENV["LIBRARY_PATH"] = ENV.fetch("LIBRARY_PATH", "").split(File::PATH_SEPARATOR)
264+
.unshift(native_path(lib_path)).join(File::PATH_SEPARATOR)
244265

245-
old_value = ENV.fetch("LDFLAGS", "")
266+
ldflag ="-L#{native_path(lib_path)}"
267+
268+
if (@host != @original_host)
269+
# rely on LDFLAGS when cross-compiling
270+
ENV["LDFLAGS"] = ENV.fetch("LDFLAGS", "").split.unshift(ldflag).join(" ")
271+
end
246272

247-
unless old_value.include?(full_path)
248-
ENV["LDFLAGS"] = "-L#{full_path} #{old_value}".strip
273+
if mkmf
274+
$LDFLAGS = ($LDFLAGS || "").split
275+
.unshift("-l#{name}")
276+
.unshift(ldflag)
277+
.join(" ")
249278
end
250279
end
251280
end
@@ -265,21 +294,11 @@ def make_cmd
265294
private
266295

267296
def native_path(path)
268-
path = File.expand_path(path)
269-
if File::ALT_SEPARATOR
270-
path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
271-
else
272-
path
273-
end
297+
MiniPortile.native_path(path)
274298
end
275299

276300
def posix_path(path)
277-
path = File.expand_path(path)
278-
if File::ALT_SEPARATOR
279-
"/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR)
280-
else
281-
path
282-
end
301+
MiniPortile.posix_path(path)
283302
end
284303

285304
def tmp_path

test/test_activate.rb

+76-20
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ class TestActivate < TestCase
66
def setup
77
super
88

9-
@save_env = %w[PATH CPATH LIBRARY_PATH].inject({}) do |env, var|
9+
@save_env = %w[PATH CPATH LIBRARY_PATH LDFLAGS].inject({}) do |env, var|
1010
env.update(var => ENV[var])
1111
end
12+
$LDFLAGS = nil
13+
$CPPFLAGS = nil
1214

1315
FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
1416

@@ -20,6 +22,8 @@ def setup
2022
def teardown
2123
FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
2224

25+
$LDFLAGS = nil
26+
$CPPFLAGS = nil
2327
@save_env.each do |var, val|
2428
ENV[var] = val
2529
end
@@ -28,79 +32,131 @@ def teardown
2832
end
2933

3034
def test_PATH_env_var_when_bin_does_not_exist
35+
ENV["PATH"] = "foo"
3136
refute(Dir.exist?(bin_path))
32-
refute(path_elements('PATH').include?(bin_path))
37+
refute_includes(path_elements('PATH'), bin_path)
3338

3439
recipe.activate
3540

36-
refute(path_elements('PATH').include?(bin_path))
41+
refute_includes(path_elements('PATH'), bin_path)
3742
end
3843

3944
def test_PATH_env_var_when_bin_exists
45+
ENV["PATH"] = "foo"
4046
FileUtils.mkdir_p(bin_path)
41-
refute(path_elements('PATH').include?(bin_path))
47+
refute_includes(path_elements('PATH'), bin_path)
4248

4349
recipe.activate
4450

45-
assert(path_elements('PATH').include?(bin_path))
51+
assert_includes(path_elements('PATH'), bin_path)
52+
assert_equal(path_elements('PATH').first, bin_path)
4653
end
4754

4855
def test_CPATH_env_var_when_include_does_not_exist
56+
ENV["CPATH"] = "foo"
4957
refute(Dir.exist?(include_path))
50-
refute(path_elements('CPATH').include?(include_path))
58+
refute_includes(path_elements('CPATH'), include_path)
5159

5260
recipe.activate
5361

54-
refute(path_elements('CPATH').include?(include_path))
62+
refute_includes(path_elements('CPATH'), include_path)
5563
end
5664

5765
def test_CPATH_env_var_when_include_exists
66+
ENV["CPATH"] = "foo"
5867
FileUtils.mkdir_p(include_path)
59-
refute(path_elements('CPATH').include?(include_path))
68+
refute_includes(path_elements('CPATH'), include_path)
6069

6170
recipe.activate
6271

63-
assert(path_elements('CPATH').include?(include_path))
72+
assert_includes(path_elements('CPATH'), include_path)
73+
assert_equal(path_elements('CPATH').first, include_path)
6474
end
6575

6676
def test_LIBRARY_PATH_env_var_when_lib_does_not_exist
77+
ENV["LIBRARY_PATH"] = "foo"
6778
refute(Dir.exist?(lib_path))
68-
refute(path_elements('LIBRARY_PATH').include?(lib_path))
79+
refute_includes(path_elements('LIBRARY_PATH'), lib_path)
6980

7081
recipe.activate
7182

72-
refute(path_elements('LIBRARY_PATH').include?(lib_path))
83+
refute_includes(path_elements('LIBRARY_PATH'), lib_path)
7384
end
7485

7586
def test_LIBRARY_PATH_env_var_when_lib_exists
87+
ENV["LIBRARY_PATH"] = "foo"
7688
FileUtils.mkdir_p(lib_path)
77-
refute(path_elements('LIBRARY_PATH').include?(lib_path))
89+
refute_includes(path_elements('LIBRARY_PATH'), lib_path)
7890

7991
recipe.activate
8092

81-
assert(path_elements('LIBRARY_PATH').include?(lib_path))
93+
assert_includes(path_elements('LIBRARY_PATH'), lib_path)
94+
assert_equal(path_elements('LIBRARY_PATH').first, lib_path)
8295
end
8396

8497
def test_LDFLAGS_env_var_when_not_cross_compiling
98+
ENV["LDFLAGS"] = "-lfoo"
8599
FileUtils.mkdir_p(lib_path)
86100
assert_equal(recipe.host, recipe.original_host) # assert on setup)
87101

88-
refute(flag_elements('LDFLAGS').include?("-L#{lib_path}"))
102+
refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
89103

90104
recipe.activate
91105

92-
refute(flag_elements('LDFLAGS').include?("-L#{lib_path}"))
106+
refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
93107
end
94108

95109
def test_LDFLAGS_env_var_when_cross_compiling
110+
ENV["LDFLAGS"] = "-lfoo"
96111
recipe.host = recipe.original_host + "-x" # make them not-equal
97112
FileUtils.mkdir_p(lib_path)
98113

99-
refute(flag_elements('LDFLAGS').include?("-L#{lib_path}"))
114+
refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
100115

101116
recipe.activate
102117

103-
assert(flag_elements('LDFLAGS').include?("-L#{lib_path}"))
118+
assert_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
119+
assert_equal(flag_elements('LDFLAGS').first, "-L#{lib_path}")
120+
end
121+
122+
def test_LDFLAGS_global_not_set_when_mkmf_is_false
123+
$LDFLAGS = "-lm"
124+
FileUtils.mkdir_p(lib_path)
125+
126+
recipe.activate(mkmf: false)
127+
128+
refute_includes($LDFLAGS.split, "-l#{recipe.name}")
129+
refute_includes($LDFLAGS.split, "-L#{lib_path}")
130+
end
131+
132+
def test_LDFLAGS_global_set_in_mkmf
133+
$LDFLAGS = '-lm'
134+
FileUtils.mkdir_p(lib_path)
135+
136+
recipe.activate(mkmf: true)
137+
138+
assert_includes($LDFLAGS.split, "-l#{recipe.name}")
139+
assert_includes($LDFLAGS.split, "-L#{lib_path}")
140+
assert_equal($LDFLAGS.split.first, "-L#{lib_path}")
141+
end
142+
143+
def test_CPPFLAGS_global_not_set_when_mkmf_is_false
144+
$CPPFLAGS = "-Ifoo"
145+
FileUtils.mkdir_p(include_path)
146+
147+
recipe.activate(mkmf: false)
148+
149+
refute_includes($CPPFLAGS.split, "-I#{include_path}")
150+
end
151+
152+
def test_CPPFLAGS_global_set_in_mkmf
153+
$CPPFLAGS = '-Ifoo'
154+
FileUtils.mkdir_p(include_path)
155+
156+
recipe.activate(mkmf: true)
157+
158+
assert_includes($CPPFLAGS.split, "-I#{include_path}")
159+
assert_equal($CPPFLAGS.split.first, "-I#{include_path}")
104160
end
105161

106162
private
@@ -114,14 +170,14 @@ def flag_elements(varname)
114170
end
115171

116172
def bin_path
117-
File.join(recipe.path, "bin")
173+
MiniPortile.native_path(File.join(recipe.path, "bin"))
118174
end
119175

120176
def include_path
121-
File.join(recipe.path, "include")
177+
MiniPortile.native_path(File.join(recipe.path, "include"))
122178
end
123179

124180
def lib_path
125-
File.join(recipe.path, "lib")
181+
MiniPortile.native_path(File.join(recipe.path, "lib"))
126182
end
127183
end

0 commit comments

Comments
 (0)