mini_portile2 2.8.0 → 2.8.9
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 +4 -4
- data/.github/workflows/ci.yml +101 -7
- data/.github/workflows/downstream.yml +66 -0
- data/.github/workflows/upstream.yml +39 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +80 -0
- data/Gemfile +15 -3
- data/README.md +29 -7
- data/Rakefile +3 -5
- data/lib/mini_portile2/mini_portile.rb +265 -72
- data/lib/mini_portile2/mini_portile_cmake.rb +75 -7
- data/lib/mini_portile2/version.rb +1 -1
- data/mini_portile2.gemspec +8 -12
- data/test/assets/pkgconf/libxml2/libxml-2.0.pc +13 -0
- data/test/assets/pkgconf/libxslt/libexslt.pc +13 -0
- data/test/assets/pkgconf/libxslt/libxslt.pc +13 -0
- data/test/assets/test-cmake-1.0/CMakeLists.txt +1 -1
- data/test/helper.rb +12 -1
- data/test/test_activate.rb +139 -0
- data/test/test_cmake.rb +184 -8
- data/test/test_cook.rb +30 -1
- data/test/test_digest.rb +75 -77
- data/test/test_download.rb +5 -4
- data/test/test_execute.rb +4 -3
- data/test/test_mkmf_config.rb +202 -0
- data/test/test_proxy.rb +7 -6
- data/test/test_recipe.rb +18 -0
- metadata +25 -96
|
@@ -5,9 +5,11 @@ require 'fileutils'
|
|
|
5
5
|
require 'tempfile'
|
|
6
6
|
require 'digest'
|
|
7
7
|
require 'open-uri'
|
|
8
|
-
require
|
|
8
|
+
require "cgi/escape"
|
|
9
|
+
require "cgi/util" if RUBY_VERSION < "3.5"
|
|
9
10
|
require 'rbconfig'
|
|
10
11
|
require 'shellwords'
|
|
12
|
+
require 'open3'
|
|
11
13
|
|
|
12
14
|
# Monkey patch for Net::HTTP by ruby open-uri fix:
|
|
13
15
|
# https://github.com/ruby/ruby/commit/58835a9
|
|
@@ -27,25 +29,73 @@ class Net::HTTP
|
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
32
|
+
$MINI_PORTILE_STATIC_LIBS = {}
|
|
33
|
+
|
|
30
34
|
class MiniPortile
|
|
31
35
|
DEFAULT_TIMEOUT = 10
|
|
32
36
|
|
|
33
|
-
attr_reader :name, :version, :original_host
|
|
37
|
+
attr_reader :name, :version, :original_host, :source_directory
|
|
34
38
|
attr_writer :configure_options
|
|
35
|
-
attr_accessor :host, :files, :patch_files, :target, :logger
|
|
39
|
+
attr_accessor :host, :files, :patch_files, :target, :logger
|
|
36
40
|
|
|
37
41
|
def self.windows?
|
|
38
|
-
|
|
42
|
+
target_os =~ /mswin|mingw/
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# GNU MinGW compiled Ruby?
|
|
42
46
|
def self.mingw?
|
|
43
|
-
|
|
47
|
+
target_os =~ /mingw/
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
# MS Visual-C compiled Ruby?
|
|
47
51
|
def self.mswin?
|
|
48
|
-
|
|
52
|
+
target_os =~ /mswin/
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.darwin?
|
|
56
|
+
target_os =~ /darwin/
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.freebsd?
|
|
60
|
+
target_os =~ /freebsd/
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.openbsd?
|
|
64
|
+
target_os =~ /openbsd/
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.linux?
|
|
68
|
+
target_os =~ /linux/
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.solaris?
|
|
72
|
+
target_os =~ /solaris/
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.target_os
|
|
76
|
+
RbConfig::CONFIG['target_os']
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.target_cpu
|
|
80
|
+
RbConfig::CONFIG['target_cpu']
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.native_path(path)
|
|
84
|
+
path = File.expand_path(path)
|
|
85
|
+
if File::ALT_SEPARATOR
|
|
86
|
+
path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
|
|
87
|
+
else
|
|
88
|
+
path
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.posix_path(path)
|
|
93
|
+
path = File.expand_path(path)
|
|
94
|
+
if File::ALT_SEPARATOR
|
|
95
|
+
"/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR)
|
|
96
|
+
else
|
|
97
|
+
path
|
|
98
|
+
end
|
|
49
99
|
end
|
|
50
100
|
|
|
51
101
|
def initialize(name, version, **kwargs)
|
|
@@ -55,24 +105,25 @@ class MiniPortile
|
|
|
55
105
|
@files = []
|
|
56
106
|
@patch_files = []
|
|
57
107
|
@log_files = {}
|
|
58
|
-
@logger = STDOUT
|
|
108
|
+
@logger = kwargs[:logger] || STDOUT
|
|
59
109
|
@source_directory = nil
|
|
60
110
|
|
|
61
|
-
@
|
|
62
|
-
|
|
63
|
-
@gcc_command = kwargs[:gcc_command]
|
|
111
|
+
@cc_command = kwargs[:cc_command] || kwargs[:gcc_command]
|
|
112
|
+
@cxx_command = kwargs[:cxx_command]
|
|
64
113
|
@make_command = kwargs[:make_command]
|
|
65
114
|
@open_timeout = kwargs[:open_timeout] || DEFAULT_TIMEOUT
|
|
66
115
|
@read_timeout = kwargs[:read_timeout] || DEFAULT_TIMEOUT
|
|
116
|
+
|
|
117
|
+
@original_host = @host = detect_host
|
|
67
118
|
end
|
|
68
119
|
|
|
69
120
|
def source_directory=(path)
|
|
70
|
-
@source_directory =
|
|
121
|
+
@source_directory = posix_path(path)
|
|
71
122
|
end
|
|
72
123
|
|
|
73
124
|
def prepare_build_directory
|
|
74
125
|
raise "source_directory is not set" if source_directory.nil?
|
|
75
|
-
output "Building #{@name}
|
|
126
|
+
output "Building #{@name} from source at '#{source_directory}'"
|
|
76
127
|
FileUtils.mkdir_p(File.join(tmp_path, [name, version].join("-")))
|
|
77
128
|
FileUtils.rm_rf(port_path) # make sure we always re-install
|
|
78
129
|
end
|
|
@@ -99,9 +150,9 @@ class MiniPortile
|
|
|
99
150
|
when which('git')
|
|
100
151
|
lambda { |file|
|
|
101
152
|
message "Running git apply with #{file}... "
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
153
|
+
Dir.mktmpdir do |tmp_git_dir|
|
|
154
|
+
execute('patch', ["git", "--git-dir=#{tmp_git_dir}", "--work-tree=.", "apply", "--whitespace=warn", file], :initial_message => false)
|
|
155
|
+
end
|
|
105
156
|
}
|
|
106
157
|
when which('patch')
|
|
107
158
|
lambda { |file|
|
|
@@ -137,7 +188,7 @@ class MiniPortile
|
|
|
137
188
|
# Windows doesn't recognize the shebang.
|
|
138
189
|
command.unshift("sh")
|
|
139
190
|
end
|
|
140
|
-
execute('configure', command + computed_options)
|
|
191
|
+
execute('configure', command + computed_options, altlog: "config.log")
|
|
141
192
|
end
|
|
142
193
|
|
|
143
194
|
def compile
|
|
@@ -191,19 +242,15 @@ class MiniPortile
|
|
|
191
242
|
end
|
|
192
243
|
|
|
193
244
|
def activate
|
|
194
|
-
lib_path = File.join(port_path, "lib")
|
|
195
245
|
vars = {
|
|
196
246
|
'PATH' => File.join(port_path, 'bin'),
|
|
197
|
-
'CPATH' =>
|
|
198
|
-
'LIBRARY_PATH' => lib_path
|
|
247
|
+
'CPATH' => include_path,
|
|
248
|
+
'LIBRARY_PATH' => lib_path,
|
|
199
249
|
}.reject { |env, path| !File.directory?(path) }
|
|
200
250
|
|
|
201
251
|
output "Activating #{@name} #{@version} (from #{port_path})..."
|
|
202
252
|
vars.each do |var, path|
|
|
203
|
-
full_path =
|
|
204
|
-
|
|
205
|
-
# turn into a valid Windows path (if required)
|
|
206
|
-
full_path.gsub!(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
|
|
253
|
+
full_path = native_path(path)
|
|
207
254
|
|
|
208
255
|
# save current variable value
|
|
209
256
|
old_value = ENV[var] || ''
|
|
@@ -215,7 +262,7 @@ class MiniPortile
|
|
|
215
262
|
|
|
216
263
|
# rely on LDFLAGS when cross-compiling
|
|
217
264
|
if File.exist?(lib_path) && (@host != @original_host)
|
|
218
|
-
full_path =
|
|
265
|
+
full_path = native_path(lib_path)
|
|
219
266
|
|
|
220
267
|
old_value = ENV.fetch("LDFLAGS", "")
|
|
221
268
|
|
|
@@ -225,19 +272,129 @@ class MiniPortile
|
|
|
225
272
|
end
|
|
226
273
|
end
|
|
227
274
|
|
|
275
|
+
# pkg: the pkg-config file name (without the .pc extension)
|
|
276
|
+
# dir: inject the directory path for the pkg-config file (probably only useful for tests)
|
|
277
|
+
# static: the name of the static library archive (without the "lib" prefix or the file extension), or nil for dynamic linking
|
|
278
|
+
#
|
|
279
|
+
# we might be able to be terribly clever and infer the name of the static archive file, but
|
|
280
|
+
# unfortunately projects have so much freedom in what they can report (for name, for libs, etc.)
|
|
281
|
+
# that it feels unreliable to try to do so, so I'm preferring to just have the developer make it
|
|
282
|
+
# explicit.
|
|
283
|
+
def mkmf_config(pkg: nil, dir: nil, static: nil)
|
|
284
|
+
require "mkmf"
|
|
285
|
+
|
|
286
|
+
if pkg
|
|
287
|
+
dir ||= File.join(lib_path, "pkgconfig")
|
|
288
|
+
pcfile = File.join(dir, "#{pkg}.pc")
|
|
289
|
+
unless File.exist?(pcfile)
|
|
290
|
+
raise ArgumentError, "pkg-config file '#{pcfile}' does not exist"
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
output "Configuring MakeMakefile for #{File.basename(pcfile)} (in #{File.dirname(pcfile)})\n"
|
|
294
|
+
|
|
295
|
+
# on macos, pkg-config will not return --cflags without this
|
|
296
|
+
ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"
|
|
297
|
+
|
|
298
|
+
# append to PKG_CONFIG_PATH as we go, so later pkg-config files can depend on earlier ones
|
|
299
|
+
ENV["PKG_CONFIG_PATH"] = [ENV["PKG_CONFIG_PATH"], dir].compact.join(File::PATH_SEPARATOR)
|
|
300
|
+
|
|
301
|
+
incflags = minimal_pkg_config(pcfile, "cflags-only-I")
|
|
302
|
+
cflags = minimal_pkg_config(pcfile, "cflags-only-other")
|
|
303
|
+
if static
|
|
304
|
+
ldflags = minimal_pkg_config(pcfile, "libs-only-L", "static")
|
|
305
|
+
libflags = minimal_pkg_config(pcfile, "libs-only-l", "static")
|
|
306
|
+
else
|
|
307
|
+
ldflags = minimal_pkg_config(pcfile, "libs-only-L")
|
|
308
|
+
libflags = minimal_pkg_config(pcfile, "libs-only-l")
|
|
309
|
+
end
|
|
310
|
+
else
|
|
311
|
+
output "Configuring MakeMakefile for #{@name} #{@version} (from #{path})\n"
|
|
312
|
+
|
|
313
|
+
lib_name = name.sub(/\Alib/, "") # TODO: use delete_prefix when we no longer support ruby 2.4
|
|
314
|
+
|
|
315
|
+
incflags = Dir.exist?(include_path) ? "-I#{include_path}" : ""
|
|
316
|
+
cflags = ""
|
|
317
|
+
ldflags = Dir.exist?(lib_path) ? "-L#{lib_path}" : ""
|
|
318
|
+
libflags = Dir.exist?(lib_path) ? "-l#{lib_name}" : ""
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
if static
|
|
322
|
+
libdir = lib_path
|
|
323
|
+
if pcfile
|
|
324
|
+
pcfile_libdir = minimal_pkg_config(pcfile, "variable=libdir").strip
|
|
325
|
+
libdir = pcfile_libdir unless pcfile_libdir.empty?
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
#
|
|
329
|
+
# keep track of the libraries we're statically linking against, and fix up ldflags and
|
|
330
|
+
# libflags to make sure we link statically against the recipe's libaries.
|
|
331
|
+
#
|
|
332
|
+
# this avoids the unintentionally dynamically linking against system libraries, and makes sure
|
|
333
|
+
# that if multiple pkg-config files reference each other that we are able to intercept flags
|
|
334
|
+
# from dependent packages that reference the static archive.
|
|
335
|
+
#
|
|
336
|
+
$MINI_PORTILE_STATIC_LIBS[static] = libdir
|
|
337
|
+
static_ldflags = $MINI_PORTILE_STATIC_LIBS.values.map { |v| "-L#{v}" }
|
|
338
|
+
static_libflags = $MINI_PORTILE_STATIC_LIBS.keys.map { |v| "-l#{v}" }
|
|
339
|
+
|
|
340
|
+
# remove `-L#{libdir}` and `-lfoo`. we don't need them since we link against the static
|
|
341
|
+
# archive using the full path.
|
|
342
|
+
ldflags = ldflags.shellsplit.reject { |f| static_ldflags.include?(f) }.shelljoin
|
|
343
|
+
libflags = libflags.shellsplit.reject { |f| static_libflags.include?(f) }.shelljoin
|
|
344
|
+
|
|
345
|
+
# prepend the full path to the static archive to the linker flags
|
|
346
|
+
static_archive = File.join(libdir, "lib#{static}.#{$LIBEXT}")
|
|
347
|
+
libflags = [static_archive, libflags].join(" ").strip
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
# prefer this package by prepending to search paths and library flags
|
|
351
|
+
#
|
|
352
|
+
# convert the ldflags into a list of directories and append to $LIBPATH (instead of just using
|
|
353
|
+
# $LDFLAGS) to ensure we get the `-Wl,-rpath` linker flag for re-finding shared libraries.
|
|
354
|
+
$INCFLAGS = [incflags, $INCFLAGS].join(" ").strip
|
|
355
|
+
libpaths = ldflags.shellsplit.map { |f| f.sub(/\A-L/, "") }
|
|
356
|
+
$LIBPATH = libpaths | $LIBPATH
|
|
357
|
+
$libs = [libflags, $libs].join(" ").strip
|
|
358
|
+
|
|
359
|
+
# prefer this package's compiler flags by appending them to the command line
|
|
360
|
+
$CFLAGS = [$CFLAGS, cflags].join(" ").strip
|
|
361
|
+
$CXXFLAGS = [$CXXFLAGS, cflags].join(" ").strip
|
|
362
|
+
end
|
|
363
|
+
|
|
228
364
|
def path
|
|
229
365
|
File.expand_path(port_path)
|
|
230
366
|
end
|
|
231
367
|
|
|
232
|
-
def
|
|
233
|
-
(
|
|
368
|
+
def include_path
|
|
369
|
+
File.join(path, "include")
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def lib_path
|
|
373
|
+
File.join(path, "lib")
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def cc_cmd
|
|
377
|
+
(ENV["CC"] || @cc_command || RbConfig::CONFIG["CC"] || "gcc").dup
|
|
378
|
+
end
|
|
379
|
+
alias :gcc_cmd :cc_cmd
|
|
380
|
+
|
|
381
|
+
def cxx_cmd
|
|
382
|
+
(ENV["CXX"] || @cxx_command || RbConfig::CONFIG["CXX"] || "g++").dup
|
|
234
383
|
end
|
|
235
384
|
|
|
236
385
|
def make_cmd
|
|
237
386
|
(ENV["MAKE"] || @make_command || ENV["make"] || "make").dup
|
|
238
387
|
end
|
|
239
388
|
|
|
240
|
-
private
|
|
389
|
+
private
|
|
390
|
+
|
|
391
|
+
def native_path(path)
|
|
392
|
+
MiniPortile.native_path(path)
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def posix_path(path)
|
|
396
|
+
MiniPortile.posix_path(path)
|
|
397
|
+
end
|
|
241
398
|
|
|
242
399
|
def tmp_path
|
|
243
400
|
"tmp/#{@host}/ports/#{@name}/#{@version}"
|
|
@@ -306,24 +463,29 @@ private
|
|
|
306
463
|
gpg_exe = which('gpg2') || which('gpg') || raise("Neither GPG nor GPG2 is installed")
|
|
307
464
|
|
|
308
465
|
# import the key into our own keyring
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
466
|
+
gpg_error = nil
|
|
467
|
+
gpg_status = Open3.popen3(gpg_exe, "--status-fd", "1", "--no-default-keyring", "--keyring", KEYRING_NAME, "--import") do |gpg_in, gpg_out, gpg_err, _thread|
|
|
468
|
+
gpg_in.write gpg[:key]
|
|
469
|
+
gpg_in.close
|
|
470
|
+
gpg_error = gpg_err.read
|
|
471
|
+
gpg_out.read
|
|
313
472
|
end
|
|
314
473
|
key_ids = gpg_status.scan(/\[GNUPG:\] IMPORT_OK \d+ (?<key_id>[0-9a-f]+)/i).map(&:first)
|
|
315
|
-
raise "invalid gpg key provided" if key_ids.empty?
|
|
474
|
+
raise "invalid gpg key provided:\n#{gpg_error}" if key_ids.empty?
|
|
316
475
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
476
|
+
begin
|
|
477
|
+
# verify the signature against our keyring
|
|
478
|
+
gpg_status, gpg_error, _status = Open3.capture3(gpg_exe, "--status-fd", "1", "--no-default-keyring", "--keyring", KEYRING_NAME, "--verify", signature_file, file[:local_path])
|
|
479
|
+
|
|
480
|
+
raise "signature mismatch:\n#{gpg_error}" unless gpg_status.match(/^\[GNUPG:\] VALIDSIG/)
|
|
481
|
+
ensure
|
|
482
|
+
# remove the key from our keyring
|
|
483
|
+
key_ids.each do |key_id|
|
|
484
|
+
IO.popen([gpg_exe, "--batch", "--yes", "--no-default-keyring", "--keyring", KEYRING_NAME, "--delete-keys", key_id], &:read)
|
|
485
|
+
raise "unable to delete the imported key" unless $?.exitstatus==0
|
|
486
|
+
end
|
|
324
487
|
end
|
|
325
488
|
|
|
326
|
-
raise "signature mismatch" unless gpg_status.match(/^\[GNUPG:\] VALIDSIG/)
|
|
327
489
|
|
|
328
490
|
else
|
|
329
491
|
digest = case
|
|
@@ -347,30 +509,6 @@ private
|
|
|
347
509
|
}
|
|
348
510
|
end
|
|
349
511
|
|
|
350
|
-
TAR_EXECUTABLES = %w[gtar bsdtar tar basic-bsdtar]
|
|
351
|
-
def tar_exe
|
|
352
|
-
@@tar_exe ||= begin
|
|
353
|
-
TAR_EXECUTABLES.find { |c|
|
|
354
|
-
which(c)
|
|
355
|
-
} or raise("tar not found - please make sure that one of the following commands is in the PATH: #{TAR_EXECUTABLES.join(", ")}")
|
|
356
|
-
end
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
def tar_compression_switch(filename)
|
|
360
|
-
case File.extname(filename)
|
|
361
|
-
when '.gz', '.tgz'
|
|
362
|
-
'z'
|
|
363
|
-
when '.bz2', '.tbz2'
|
|
364
|
-
'j'
|
|
365
|
-
when '.xz'
|
|
366
|
-
'J'
|
|
367
|
-
when '.Z'
|
|
368
|
-
'Z'
|
|
369
|
-
else
|
|
370
|
-
''
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
|
|
374
512
|
# From: http://stackoverflow.com/a/5471032/7672
|
|
375
513
|
# Thanks, Mislav!
|
|
376
514
|
#
|
|
@@ -397,6 +535,8 @@ private
|
|
|
397
535
|
output = `#{gcc_cmd} -v 2>&1`
|
|
398
536
|
if m = output.match(/^Target\: (.*)$/)
|
|
399
537
|
@detect_host = m[1]
|
|
538
|
+
else
|
|
539
|
+
@detect_host = nil
|
|
400
540
|
end
|
|
401
541
|
|
|
402
542
|
@detect_host
|
|
@@ -405,12 +545,39 @@ private
|
|
|
405
545
|
end
|
|
406
546
|
end
|
|
407
547
|
|
|
548
|
+
TAR_EXECUTABLES = %w[gtar bsdtar tar basic-bsdtar]
|
|
549
|
+
def tar_exe
|
|
550
|
+
@@tar_exe ||= begin
|
|
551
|
+
TAR_EXECUTABLES.find { |c|
|
|
552
|
+
which(c)
|
|
553
|
+
} or raise("tar not found - please make sure that one of the following commands is in the PATH: #{TAR_EXECUTABLES.join(", ")}")
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
def xzcat_exe
|
|
558
|
+
@@xzcat_exe ||= which("xzcat") ? "xzcat" : raise("xzcat not found")
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
def tar_command(file, target)
|
|
562
|
+
case File.extname(file)
|
|
563
|
+
when '.gz', '.tgz'
|
|
564
|
+
[tar_exe, 'xzf', file, '-C', target]
|
|
565
|
+
when '.bz2', '.tbz2'
|
|
566
|
+
[tar_exe, 'xjf', file, '-C', target]
|
|
567
|
+
when '.xz'
|
|
568
|
+
# NOTE: OpenBSD's tar command does not support the -J option
|
|
569
|
+
"#{xzcat_exe.shellescape} #{file.shellescape} | #{tar_exe.shellescape} xf - -C #{target.shellescape}"
|
|
570
|
+
else
|
|
571
|
+
[tar_exe, 'xf', file, '-C', target]
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
408
575
|
def extract_file(file, target)
|
|
409
576
|
filename = File.basename(file)
|
|
410
577
|
FileUtils.mkdir_p target
|
|
411
578
|
|
|
412
579
|
message "Extracting #{filename} into #{target}... "
|
|
413
|
-
execute('extract',
|
|
580
|
+
execute('extract', tar_command(file, target) , {:cd => Dir.pwd, :initial_message => false})
|
|
414
581
|
end
|
|
415
582
|
|
|
416
583
|
# command could be an array of args, or one string containing a command passed to the shell. See
|
|
@@ -420,6 +587,7 @@ private
|
|
|
420
587
|
opt_debug = command_opts.fetch(:debug, false)
|
|
421
588
|
opt_cd = command_opts.fetch(:cd) { work_path }
|
|
422
589
|
opt_env = command_opts.fetch(:env) { Hash.new }
|
|
590
|
+
opt_altlog = command_opts.fetch(:altlog, nil)
|
|
423
591
|
|
|
424
592
|
log_out = log_file(action)
|
|
425
593
|
|
|
@@ -450,12 +618,12 @@ private
|
|
|
450
618
|
output "OK"
|
|
451
619
|
return true
|
|
452
620
|
else
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
output(
|
|
458
|
-
output("
|
|
621
|
+
output "ERROR. Please review logs to see what happened:\n"
|
|
622
|
+
[log_out, opt_altlog].compact.each do |log|
|
|
623
|
+
next unless File.exist?(log)
|
|
624
|
+
output("----- contents of '#{log}' -----")
|
|
625
|
+
output(File.read(log))
|
|
626
|
+
output("----- end of file -----")
|
|
459
627
|
end
|
|
460
628
|
raise "Failed to complete #{action} task"
|
|
461
629
|
end
|
|
@@ -545,7 +713,7 @@ private
|
|
|
545
713
|
return download_file(redirect.url, full_path, count-1)
|
|
546
714
|
rescue => e
|
|
547
715
|
count = count - 1
|
|
548
|
-
puts "#{count} retrie(s) left for #{filename} (#{e.message})"
|
|
716
|
+
@logger.puts "#{count} retrie(s) left for #{filename} (#{e.message})"
|
|
549
717
|
if count > 0
|
|
550
718
|
sleep 1
|
|
551
719
|
return download_file_http(url, full_path, count)
|
|
@@ -604,4 +772,29 @@ private
|
|
|
604
772
|
FileUtils.mkdir_p File.dirname(full_path)
|
|
605
773
|
FileUtils.mv temp_file.path, full_path, :force => true
|
|
606
774
|
end
|
|
775
|
+
|
|
776
|
+
#
|
|
777
|
+
# this minimal version of pkg_config is based on ruby 29dc9378 (2023-01-09)
|
|
778
|
+
#
|
|
779
|
+
# specifically with the fix from b90e56e6 to support multiple pkg-config options, and removing
|
|
780
|
+
# code paths that aren't helpful for mini-portile's use case of parsing pc files.
|
|
781
|
+
#
|
|
782
|
+
def minimal_pkg_config(pkg, *pcoptions)
|
|
783
|
+
if pcoptions.empty?
|
|
784
|
+
raise ArgumentError, "no pkg-config options are given"
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
if ($PKGCONFIG ||=
|
|
788
|
+
(pkgconfig = MakeMakefile.with_config("pkg-config") {MakeMakefile.config_string("PKG_CONFIG") || "pkg-config"}) &&
|
|
789
|
+
MakeMakefile.find_executable0(pkgconfig) && pkgconfig)
|
|
790
|
+
pkgconfig = $PKGCONFIG
|
|
791
|
+
else
|
|
792
|
+
raise RuntimeError, "pkg-config is not found"
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
pcoptions = Array(pcoptions).map { |o| "--#{o}" }
|
|
796
|
+
response = IO.popen([pkgconfig, *pcoptions, pkg], err:[:child, :out], &:read)
|
|
797
|
+
raise RuntimeError, response unless $?.success?
|
|
798
|
+
response.strip
|
|
799
|
+
end
|
|
607
800
|
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
require 'mini_portile2/mini_portile'
|
|
2
|
+
require 'open3'
|
|
2
3
|
|
|
3
4
|
class MiniPortileCMake < MiniPortile
|
|
5
|
+
attr_accessor :system_name
|
|
6
|
+
|
|
4
7
|
def configure_prefix
|
|
5
8
|
"-DCMAKE_INSTALL_PREFIX=#{File.expand_path(port_path)}"
|
|
6
9
|
end
|
|
@@ -8,16 +11,14 @@ class MiniPortileCMake < MiniPortile
|
|
|
8
11
|
def initialize(name, version, **kwargs)
|
|
9
12
|
super(name, version, **kwargs)
|
|
10
13
|
@cmake_command = kwargs[:cmake_command]
|
|
14
|
+
@cmake_build_type = kwargs[:cmake_build_type]
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
def configure_defaults
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
else
|
|
19
|
-
[]
|
|
20
|
-
end
|
|
18
|
+
[
|
|
19
|
+
generator_defaults,
|
|
20
|
+
cmake_compile_flags,
|
|
21
|
+
].flatten
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def configure
|
|
@@ -48,4 +49,71 @@ class MiniPortileCMake < MiniPortile
|
|
|
48
49
|
def cmake_cmd
|
|
49
50
|
(ENV["CMAKE"] || @cmake_command || "cmake").dup
|
|
50
51
|
end
|
|
52
|
+
|
|
53
|
+
def cmake_build_type
|
|
54
|
+
(ENV["CMAKE_BUILD_TYPE"] || @cmake_build_type || "Release").dup
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def generator_defaults
|
|
60
|
+
if MiniPortile.mswin? && generator_available?('NMake')
|
|
61
|
+
['-G', 'NMake Makefiles']
|
|
62
|
+
elsif MiniPortile.mingw? && generator_available?('MSYS')
|
|
63
|
+
['-G', 'MSYS Makefiles']
|
|
64
|
+
else
|
|
65
|
+
[]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def cmake_compile_flags
|
|
70
|
+
# RbConfig::CONFIG['CC'] and RbConfig::CONFIG['CXX'] can contain additional flags, for example
|
|
71
|
+
# "clang++ -std=gnu++11" or "clang -fdeclspec". CMake is just looking for the command name.
|
|
72
|
+
cc_compiler = cc_cmd.split.first
|
|
73
|
+
cxx_compiler = cxx_cmd.split.first
|
|
74
|
+
|
|
75
|
+
# needed to ensure cross-compilation with CMake targets the right CPU and compilers
|
|
76
|
+
[
|
|
77
|
+
"-DCMAKE_SYSTEM_NAME=#{cmake_system_name}",
|
|
78
|
+
"-DCMAKE_SYSTEM_PROCESSOR=#{cpu_type}",
|
|
79
|
+
"-DCMAKE_C_COMPILER=#{cc_compiler}",
|
|
80
|
+
"-DCMAKE_CXX_COMPILER=#{cxx_compiler}",
|
|
81
|
+
"-DCMAKE_BUILD_TYPE=#{cmake_build_type}",
|
|
82
|
+
]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Full list: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.4/Modules/CMakeDetermineSystem.cmake?ref_type=tags#L12-31
|
|
86
|
+
def cmake_system_name
|
|
87
|
+
return system_name if system_name
|
|
88
|
+
|
|
89
|
+
if MiniPortile.linux?
|
|
90
|
+
'Linux'
|
|
91
|
+
elsif MiniPortile.darwin?
|
|
92
|
+
'Darwin'
|
|
93
|
+
elsif MiniPortile.windows?
|
|
94
|
+
'Windows'
|
|
95
|
+
elsif MiniPortile.freebsd?
|
|
96
|
+
'FreeBSD'
|
|
97
|
+
elsif MiniPortile.openbsd?
|
|
98
|
+
'OpenBSD'
|
|
99
|
+
elsif MiniPortile.solaris?
|
|
100
|
+
'SunOS'
|
|
101
|
+
else
|
|
102
|
+
raise "Unable to set CMAKE_SYSTEM_NAME for #{MiniPortile.target_os}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def generator_available?(generator_type)
|
|
107
|
+
stdout_str, status = Open3.capture2("#{cmake_cmd} --help")
|
|
108
|
+
|
|
109
|
+
raise 'Unable to determine whether CMake supports #{generator_type} Makefile generator' unless status.success?
|
|
110
|
+
|
|
111
|
+
stdout_str.include?("#{generator_type} Makefiles")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def cpu_type
|
|
115
|
+
return 'x86_64' if MiniPortile.target_cpu == 'x64'
|
|
116
|
+
|
|
117
|
+
MiniPortile.target_cpu
|
|
118
|
+
end
|
|
51
119
|
end
|
data/mini_portile2.gemspec
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require "mini_portile2/version"
|
|
1
|
+
require_relative "lib/mini_portile2/version"
|
|
5
2
|
|
|
6
3
|
Gem::Specification.new do |spec|
|
|
7
4
|
spec.name = "mini_portile2"
|
|
@@ -10,8 +7,12 @@ Gem::Specification.new do |spec|
|
|
|
10
7
|
spec.authors = ["Luis Lavena", "Mike Dalessio", "Lars Kanis"]
|
|
11
8
|
spec.email = "mike.dalessio@gmail.com"
|
|
12
9
|
|
|
13
|
-
spec.summary = "
|
|
14
|
-
spec.description =
|
|
10
|
+
spec.summary = "Simple autoconf and cmake builder for developers"
|
|
11
|
+
spec.description = <<~TEXT
|
|
12
|
+
Simple autoconf and cmake builder for developers. It provides a standard way to compile against
|
|
13
|
+
dependency libraries without requiring system-wide installation. It also simplifies
|
|
14
|
+
vendoring and cross-compilation by providing a consistent build interface.
|
|
15
|
+
TEXT
|
|
15
16
|
|
|
16
17
|
spec.homepage = "https://github.com/flavorjones/mini_portile"
|
|
17
18
|
spec.licenses = ["MIT"]
|
|
@@ -33,10 +34,5 @@ Gem::Specification.new do |spec|
|
|
|
33
34
|
|
|
34
35
|
spec.required_ruby_version = ">= 2.3.0"
|
|
35
36
|
|
|
36
|
-
spec.
|
|
37
|
-
spec.add_development_dependency "minitar", "~> 0.9"
|
|
38
|
-
spec.add_development_dependency "minitest", "~> 5.15"
|
|
39
|
-
spec.add_development_dependency "minitest-hooks", "~> 1.5"
|
|
40
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
|
41
|
-
spec.add_development_dependency "webrick", "~> 1.7"
|
|
37
|
+
spec.metadata["changelog_uri"] = spec.homepage + "/blob/main/CHANGELOG.md"
|
|
42
38
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
prefix=/foo/libxml2/2.11.5
|
|
2
|
+
exec_prefix=${prefix}
|
|
3
|
+
libdir=/foo/libxml2/2.11.5/lib
|
|
4
|
+
includedir=${prefix}/include
|
|
5
|
+
modules=1
|
|
6
|
+
|
|
7
|
+
Name: libXML
|
|
8
|
+
Version: 2.11.5
|
|
9
|
+
Description: libXML library version2.
|
|
10
|
+
Requires:
|
|
11
|
+
Libs: -L${libdir} -lxml2
|
|
12
|
+
Libs.private: -L/foo/zlib/1.3/lib -lz -lm
|
|
13
|
+
Cflags: -I${includedir}/libxml2 -ggdb3
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
prefix=/foo/libxslt/1.1.38
|
|
2
|
+
exec_prefix=${prefix}
|
|
3
|
+
libdir=/foo/libxslt/1.1.38/lib
|
|
4
|
+
includedir=${prefix}/include
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Name: libexslt
|
|
8
|
+
Version: 0.8.21
|
|
9
|
+
Description: EXSLT Extension library
|
|
10
|
+
Requires: libxml-2.0, libxslt
|
|
11
|
+
Cflags: -I${includedir}
|
|
12
|
+
Libs: -L${libdir} -lexslt
|
|
13
|
+
Libs.private: -lm
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
prefix=/foo/libxslt/1.1.38
|
|
2
|
+
exec_prefix=${prefix}
|
|
3
|
+
libdir=/foo/libxslt/1.1.38/lib
|
|
4
|
+
includedir=${prefix}/include
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Name: libxslt
|
|
8
|
+
Version: 1.1.38
|
|
9
|
+
Description: XSLT library version 2.
|
|
10
|
+
Requires: libxml-2.0
|
|
11
|
+
Cflags: -I${includedir} -Wno-deprecated-enum-enum-conversion
|
|
12
|
+
Libs: -L${libdir} -lxslt
|
|
13
|
+
Libs.private: -lm
|