mini_portile2 2.8.1 → 2.8.5
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 +22 -5
- data/.gitignore +1 -0
- data/CHANGELOG.md +37 -0
- data/README.md +15 -2
- data/lib/mini_portile2/mini_portile.rb +202 -25
- data/lib/mini_portile2/mini_portile_cmake.rb +100 -7
- data/lib/mini_portile2/version.rb +1 -1
- data/mini_portile2.gemspec +7 -6
- 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/test_activate.rb +139 -0
- data/test/test_cmake.rb +179 -8
- data/test/test_mkmf_config.rb +202 -0
- data/test/test_recipe.rb +18 -0
- metadata +20 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f53843a25ac2651fd9970c34a44edf44de0904f99d9e63eadb3802f8dcd59bc
|
4
|
+
data.tar.gz: 075527f5c56f12de2ba5e3dfd72965a0093f62558eabb02571be5aee61cbe9f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e251640701cf8ea166e1ce6725b8e7bf3d3dbf20a659a6b90ffe127667a80f908fab5b7f816f8a766edd4166464d5375c53a3c31c862a4a7a04e0e87929127d
|
7
|
+
data.tar.gz: 1d540e216342ef799de2188935d6de440b865606a244dd7ca6a27146a259bf5a1211c53b49668eee668187770e5e030d06508b4605779c4366999dcf831cc2b3
|
data/.github/workflows/ci.yml
CHANGED
@@ -25,7 +25,7 @@ jobs:
|
|
25
25
|
fail-fast: false
|
26
26
|
matrix:
|
27
27
|
platform: [ubuntu-latest, windows-latest, macos-latest]
|
28
|
-
ruby: ["2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1", "head"]
|
28
|
+
ruby: ["2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1", "3.2", "head"]
|
29
29
|
runs-on: ${{ matrix.platform }}
|
30
30
|
steps:
|
31
31
|
- name: configure git crlf on windows
|
@@ -33,7 +33,7 @@ jobs:
|
|
33
33
|
run: |
|
34
34
|
git config --system core.autocrlf false
|
35
35
|
git config --system core.eol lf
|
36
|
-
- uses: actions/checkout@
|
36
|
+
- uses: actions/checkout@v3
|
37
37
|
- uses: MSP-Greg/setup-ruby-pkgs@v1
|
38
38
|
with:
|
39
39
|
apt-get: _update_ build-essential cmake
|
@@ -57,15 +57,32 @@ jobs:
|
|
57
57
|
run: |
|
58
58
|
git config --system core.autocrlf false
|
59
59
|
git config --system core.eol lf
|
60
|
-
- uses: actions/checkout@
|
60
|
+
- uses: actions/checkout@v3
|
61
61
|
- uses: MSP-Greg/setup-ruby-pkgs@v1
|
62
62
|
with:
|
63
63
|
apt-get: _update_ build-essential cmake
|
64
64
|
mingw: _upgrade_ cmake
|
65
65
|
ruby-version: ${{ matrix.ruby }}
|
66
66
|
bundler-cache: true
|
67
|
-
- uses: actions/cache@
|
67
|
+
- uses: actions/cache@v3
|
68
68
|
with:
|
69
69
|
path: examples/ports/archives
|
70
|
-
key:
|
70
|
+
key: examples-${{ hashFiles('examples/Rakefile') }}
|
71
|
+
- run: bundle exec rake test:examples
|
72
|
+
|
73
|
+
fedora: # see https://github.com/flavorjones/mini_portile/issues/118
|
74
|
+
runs-on: ubuntu-latest
|
75
|
+
container:
|
76
|
+
image: fedora:35
|
77
|
+
steps:
|
78
|
+
- run: |
|
79
|
+
dnf group install -y "C Development Tools and Libraries"
|
80
|
+
dnf install -y ruby ruby-devel libyaml-devel git-all patch cmake xz
|
81
|
+
- uses: actions/checkout@v3
|
82
|
+
- uses: actions/cache@v3
|
83
|
+
with:
|
84
|
+
path: examples/ports/archives
|
85
|
+
key: examples-${{ hashFiles('examples/Rakefile') }}
|
86
|
+
- run: bundle install
|
87
|
+
- run: bundle exec rake test:unit
|
71
88
|
- run: bundle exec rake test:examples
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,42 @@
|
|
1
1
|
## mini_portile changelog
|
2
2
|
|
3
|
+
### 2.8.5 / 2023-10-22
|
4
|
+
|
5
|
+
#### Added
|
6
|
+
|
7
|
+
- New methods `#lib_path` and `#include_path` which point at the installed directories under `ports`. (by @flavorjones)
|
8
|
+
- Add config param for CMAKE_BUILD_TYPE, which now defaults to `Release`. (#136 by @Watson1978)
|
9
|
+
|
10
|
+
#### Experimental
|
11
|
+
|
12
|
+
Introduce experimental support for `MiniPortile#mkmf_config` which sets up MakeMakefile variables to properly link against the recipe. This should make it easier for C extensions to package third-party libraries. (by @flavorjones)
|
13
|
+
|
14
|
+
- With no arguments, will set up just `$INCFLAGS`, `$libs`, and `$LIBPATH`.
|
15
|
+
- Optionally, if provided a pkg-config file, will use that config to more precisely set `$INCFLAGS`, `$libs`, `$LIBPATH`, and `$CFLAGS`/`$CXXFLAGS`.
|
16
|
+
- Optionally, if provided the name of a static archive, will rewrite linker flags to ensure correct linkage.
|
17
|
+
|
18
|
+
Note that the behavior may change slightly before official support is announced. Please comment on [#118](https://github.com/flavorjones/mini_portile/issues/118) if you have feedback.
|
19
|
+
|
20
|
+
|
21
|
+
### 2.8.4 / 2023-07-18
|
22
|
+
|
23
|
+
- cmake: set CMAKE compile flags to configure cross-compilation similarly to `autotools` `--host` flag: `SYSTEM_NAME`, `SYSTEM_PROCESSOR`, `C_COMPILER`, and `CXX_COMPILER`. [#130] (Thanks, @stanhu!)
|
24
|
+
|
25
|
+
|
26
|
+
### 2.8.3 / 2023-07-18
|
27
|
+
|
28
|
+
#### Fixed
|
29
|
+
|
30
|
+
- cmake: only use MSYS/NMake generators when available. [#129] (Thanks, @stanhu!)
|
31
|
+
|
32
|
+
|
33
|
+
### 2.8.2 / 2023-04-30
|
34
|
+
|
35
|
+
#### Fixed
|
36
|
+
|
37
|
+
- Ensure that the `source_directory` option will work when given a Windows path to an autoconf directory. [#126]
|
38
|
+
|
39
|
+
|
3
40
|
### 2.8.1 / 2022-12-24
|
4
41
|
|
5
42
|
#### Fixed
|
data/README.md
CHANGED
@@ -138,8 +138,8 @@ This is configurable as above, except for Windows systems where it's hardcoded t
|
|
138
138
|
The cmake command used is configurable, and in order of preference will use:
|
139
139
|
|
140
140
|
- the `CMAKE` environment variable (if present)
|
141
|
-
- the
|
142
|
-
- `"cmake"`
|
141
|
+
- the `:cmake_command` keyword argument passed into the constructor
|
142
|
+
- `"cmake"` (the default)
|
143
143
|
|
144
144
|
You can pass it in like so:
|
145
145
|
|
@@ -147,6 +147,19 @@ You can pass it in like so:
|
|
147
147
|
MiniPortileCMake.new("libfoobar", "1.3.5", cmake_command: "cmake3")
|
148
148
|
```
|
149
149
|
|
150
|
+
#### `cmake_build_type`
|
151
|
+
|
152
|
+
The cmake build type is configurable as of v2.8.5, and in order of preference will use:
|
153
|
+
|
154
|
+
- the `CMAKE_BUILD_TYPE` environment variable (if present)
|
155
|
+
- the `:cmake_build_type` keyword argument passed into the constructor
|
156
|
+
- `"Release"` (the default)
|
157
|
+
|
158
|
+
You can pass it in like so:
|
159
|
+
|
160
|
+
``` ruby
|
161
|
+
MiniPortileCMake.new("libfoobar", "1.3.5", cmake_build_type: "Debug")
|
162
|
+
```
|
150
163
|
|
151
164
|
### Local source directories
|
152
165
|
|
@@ -27,25 +27,73 @@ class Net::HTTP
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
$MINI_PORTILE_STATIC_LIBS = {}
|
31
|
+
|
30
32
|
class MiniPortile
|
31
33
|
DEFAULT_TIMEOUT = 10
|
32
34
|
|
33
|
-
attr_reader :name, :version, :original_host
|
35
|
+
attr_reader :name, :version, :original_host, :source_directory
|
34
36
|
attr_writer :configure_options
|
35
|
-
attr_accessor :host, :files, :patch_files, :target, :logger
|
37
|
+
attr_accessor :host, :files, :patch_files, :target, :logger
|
36
38
|
|
37
39
|
def self.windows?
|
38
|
-
|
40
|
+
target_os =~ /mswin|mingw/
|
39
41
|
end
|
40
42
|
|
41
43
|
# GNU MinGW compiled Ruby?
|
42
44
|
def self.mingw?
|
43
|
-
|
45
|
+
target_os =~ /mingw/
|
44
46
|
end
|
45
47
|
|
46
48
|
# MS Visual-C compiled Ruby?
|
47
49
|
def self.mswin?
|
48
|
-
|
50
|
+
target_os =~ /mswin/
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.darwin?
|
54
|
+
target_os =~ /darwin/
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.freebsd?
|
58
|
+
target_os =~ /freebsd/
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.openbsd?
|
62
|
+
target_os =~ /openbsd/
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.linux?
|
66
|
+
target_os =~ /linux/
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.solaris?
|
70
|
+
target_os =~ /solaris/
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.target_os
|
74
|
+
RbConfig::CONFIG['target_os']
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.target_cpu
|
78
|
+
RbConfig::CONFIG['target_cpu']
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.native_path(path)
|
82
|
+
path = File.expand_path(path)
|
83
|
+
if File::ALT_SEPARATOR
|
84
|
+
path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
|
85
|
+
else
|
86
|
+
path
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.posix_path(path)
|
91
|
+
path = File.expand_path(path)
|
92
|
+
if File::ALT_SEPARATOR
|
93
|
+
"/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR)
|
94
|
+
else
|
95
|
+
path
|
96
|
+
end
|
49
97
|
end
|
50
98
|
|
51
99
|
def initialize(name, version, **kwargs)
|
@@ -58,21 +106,21 @@ class MiniPortile
|
|
58
106
|
@logger = STDOUT
|
59
107
|
@source_directory = nil
|
60
108
|
|
61
|
-
@original_host = @host = detect_host
|
62
|
-
|
63
109
|
@gcc_command = kwargs[:gcc_command]
|
64
110
|
@make_command = kwargs[:make_command]
|
65
111
|
@open_timeout = kwargs[:open_timeout] || DEFAULT_TIMEOUT
|
66
112
|
@read_timeout = kwargs[:read_timeout] || DEFAULT_TIMEOUT
|
113
|
+
|
114
|
+
@original_host = @host = detect_host
|
67
115
|
end
|
68
116
|
|
69
117
|
def source_directory=(path)
|
70
|
-
@source_directory =
|
118
|
+
@source_directory = posix_path(path)
|
71
119
|
end
|
72
120
|
|
73
121
|
def prepare_build_directory
|
74
122
|
raise "source_directory is not set" if source_directory.nil?
|
75
|
-
output "Building #{@name}
|
123
|
+
output "Building #{@name} from source at '#{source_directory}'"
|
76
124
|
FileUtils.mkdir_p(File.join(tmp_path, [name, version].join("-")))
|
77
125
|
FileUtils.rm_rf(port_path) # make sure we always re-install
|
78
126
|
end
|
@@ -137,7 +185,7 @@ class MiniPortile
|
|
137
185
|
# Windows doesn't recognize the shebang.
|
138
186
|
command.unshift("sh")
|
139
187
|
end
|
140
|
-
execute('configure', command + computed_options)
|
188
|
+
execute('configure', command + computed_options, altlog: "config.log")
|
141
189
|
end
|
142
190
|
|
143
191
|
def compile
|
@@ -191,19 +239,15 @@ class MiniPortile
|
|
191
239
|
end
|
192
240
|
|
193
241
|
def activate
|
194
|
-
lib_path = File.join(port_path, "lib")
|
195
242
|
vars = {
|
196
243
|
'PATH' => File.join(port_path, 'bin'),
|
197
|
-
'CPATH' =>
|
198
|
-
'LIBRARY_PATH' => lib_path
|
244
|
+
'CPATH' => include_path,
|
245
|
+
'LIBRARY_PATH' => lib_path,
|
199
246
|
}.reject { |env, path| !File.directory?(path) }
|
200
247
|
|
201
248
|
output "Activating #{@name} #{@version} (from #{port_path})..."
|
202
249
|
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
|
250
|
+
full_path = native_path(path)
|
207
251
|
|
208
252
|
# save current variable value
|
209
253
|
old_value = ENV[var] || ''
|
@@ -215,7 +259,7 @@ class MiniPortile
|
|
215
259
|
|
216
260
|
# rely on LDFLAGS when cross-compiling
|
217
261
|
if File.exist?(lib_path) && (@host != @original_host)
|
218
|
-
full_path =
|
262
|
+
full_path = native_path(lib_path)
|
219
263
|
|
220
264
|
old_value = ENV.fetch("LDFLAGS", "")
|
221
265
|
|
@@ -225,10 +269,109 @@ class MiniPortile
|
|
225
269
|
end
|
226
270
|
end
|
227
271
|
|
272
|
+
# pkg: the pkg-config file name (without the .pc extension)
|
273
|
+
# dir: inject the directory path for the pkg-config file (probably only useful for tests)
|
274
|
+
# static: the name of the static library archive (without the "lib" prefix or the file extension), or nil for dynamic linking
|
275
|
+
#
|
276
|
+
# we might be able to be terribly clever and infer the name of the static archive file, but
|
277
|
+
# unfortunately projects have so much freedom in what they can report (for name, for libs, etc.)
|
278
|
+
# that it feels unreliable to try to do so, so I'm preferring to just have the developer make it
|
279
|
+
# explicit.
|
280
|
+
def mkmf_config(pkg: nil, dir: nil, static: nil)
|
281
|
+
require "mkmf"
|
282
|
+
|
283
|
+
if pkg
|
284
|
+
dir ||= File.join(lib_path, "pkgconfig")
|
285
|
+
pcfile = File.join(dir, "#{pkg}.pc")
|
286
|
+
unless File.exist?(pcfile)
|
287
|
+
raise ArgumentError, "pkg-config file '#{pcfile}' does not exist"
|
288
|
+
end
|
289
|
+
|
290
|
+
output "Configuring MakeMakefile for #{File.basename(pcfile)} (in #{File.dirname(pcfile)})\n"
|
291
|
+
|
292
|
+
# on macos, pkg-config will not return --cflags without this
|
293
|
+
ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"
|
294
|
+
|
295
|
+
# append to PKG_CONFIG_PATH as we go, so later pkg-config files can depend on earlier ones
|
296
|
+
ENV["PKG_CONFIG_PATH"] = [ENV["PKG_CONFIG_PATH"], dir].compact.join(File::PATH_SEPARATOR)
|
297
|
+
|
298
|
+
incflags = minimal_pkg_config(pcfile, "cflags-only-I")
|
299
|
+
cflags = minimal_pkg_config(pcfile, "cflags-only-other")
|
300
|
+
if static
|
301
|
+
ldflags = minimal_pkg_config(pcfile, "libs-only-L", "static")
|
302
|
+
libflags = minimal_pkg_config(pcfile, "libs-only-l", "static")
|
303
|
+
else
|
304
|
+
ldflags = minimal_pkg_config(pcfile, "libs-only-L")
|
305
|
+
libflags = minimal_pkg_config(pcfile, "libs-only-l")
|
306
|
+
end
|
307
|
+
else
|
308
|
+
output "Configuring MakeMakefile for #{@name} #{@version} (from #{path})\n"
|
309
|
+
|
310
|
+
lib_name = name.sub(/\Alib/, "") # TODO: use delete_prefix when we no longer support ruby 2.4
|
311
|
+
|
312
|
+
incflags = Dir.exist?(include_path) ? "-I#{include_path}" : ""
|
313
|
+
cflags = ""
|
314
|
+
ldflags = Dir.exist?(lib_path) ? "-L#{lib_path}" : ""
|
315
|
+
libflags = Dir.exist?(lib_path) ? "-l#{lib_name}" : ""
|
316
|
+
end
|
317
|
+
|
318
|
+
if static
|
319
|
+
libdir = lib_path
|
320
|
+
if pcfile
|
321
|
+
variables = minimal_pkg_config(pcfile, "print-variables").split("\n").map(&:strip)
|
322
|
+
if variables.include?("libdir")
|
323
|
+
libdir = minimal_pkg_config(pcfile, "variable=libdir")
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
#
|
328
|
+
# keep track of the libraries we're statically linking against, and fix up ldflags and
|
329
|
+
# libflags to make sure we link statically against the recipe's libaries.
|
330
|
+
#
|
331
|
+
# this avoids the unintentionally dynamically linking against system libraries, and makes sure
|
332
|
+
# that if multiple pkg-config files reference each other that we are able to intercept flags
|
333
|
+
# from dependent packages that reference the static archive.
|
334
|
+
#
|
335
|
+
$MINI_PORTILE_STATIC_LIBS[static] = libdir
|
336
|
+
static_ldflags = $MINI_PORTILE_STATIC_LIBS.values.map { |v| "-L#{v}" }
|
337
|
+
static_libflags = $MINI_PORTILE_STATIC_LIBS.keys.map { |v| "-l#{v}" }
|
338
|
+
|
339
|
+
# remove `-L#{libdir}` and `-lfoo`. we don't need them since we link against the static
|
340
|
+
# archive using the full path.
|
341
|
+
ldflags = ldflags.shellsplit.reject { |f| static_ldflags.include?(f) }.shelljoin
|
342
|
+
libflags = libflags.shellsplit.reject { |f| static_libflags.include?(f) }.shelljoin
|
343
|
+
|
344
|
+
# prepend the full path to the static archive to the linker flags
|
345
|
+
static_archive = File.join(libdir, "lib#{static}.#{$LIBEXT}")
|
346
|
+
libflags = [static_archive, libflags].join(" ").strip
|
347
|
+
end
|
348
|
+
|
349
|
+
# prefer this package by prepending to search paths and library flags
|
350
|
+
#
|
351
|
+
# convert the ldflags into a list of directories and append to $LIBPATH (instead of just using
|
352
|
+
# $LDFLAGS) to ensure we get the `-Wl,-rpath` linker flag for re-finding shared libraries.
|
353
|
+
$INCFLAGS = [incflags, $INCFLAGS].join(" ").strip
|
354
|
+
libpaths = ldflags.shellsplit.map { |f| f.sub(/\A-L/, "") }
|
355
|
+
$LIBPATH = libpaths | $LIBPATH
|
356
|
+
$libs = [libflags, $libs].join(" ").strip
|
357
|
+
|
358
|
+
# prefer this package's compiler flags by appending them to the command line
|
359
|
+
$CFLAGS = [$CFLAGS, cflags].join(" ").strip
|
360
|
+
$CXXFLAGS = [$CXXFLAGS, cflags].join(" ").strip
|
361
|
+
end
|
362
|
+
|
228
363
|
def path
|
229
364
|
File.expand_path(port_path)
|
230
365
|
end
|
231
366
|
|
367
|
+
def include_path
|
368
|
+
File.join(path, "include")
|
369
|
+
end
|
370
|
+
|
371
|
+
def lib_path
|
372
|
+
File.join(path, "lib")
|
373
|
+
end
|
374
|
+
|
232
375
|
def gcc_cmd
|
233
376
|
(ENV["CC"] || @gcc_command || RbConfig::CONFIG["CC"] || "gcc").dup
|
234
377
|
end
|
@@ -237,7 +380,15 @@ class MiniPortile
|
|
237
380
|
(ENV["MAKE"] || @make_command || ENV["make"] || "make").dup
|
238
381
|
end
|
239
382
|
|
240
|
-
private
|
383
|
+
private
|
384
|
+
|
385
|
+
def native_path(path)
|
386
|
+
MiniPortile.native_path(path)
|
387
|
+
end
|
388
|
+
|
389
|
+
def posix_path(path)
|
390
|
+
MiniPortile.posix_path(path)
|
391
|
+
end
|
241
392
|
|
242
393
|
def tmp_path
|
243
394
|
"tmp/#{@host}/ports/#{@name}/#{@version}"
|
@@ -420,6 +571,7 @@ private
|
|
420
571
|
opt_debug = command_opts.fetch(:debug, false)
|
421
572
|
opt_cd = command_opts.fetch(:cd) { work_path }
|
422
573
|
opt_env = command_opts.fetch(:env) { Hash.new }
|
574
|
+
opt_altlog = command_opts.fetch(:altlog, nil)
|
423
575
|
|
424
576
|
log_out = log_file(action)
|
425
577
|
|
@@ -450,12 +602,12 @@ private
|
|
450
602
|
output "OK"
|
451
603
|
return true
|
452
604
|
else
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
output(
|
458
|
-
output("
|
605
|
+
output "ERROR. Please review logs to see what happened:\n"
|
606
|
+
[log_out, opt_altlog].compact.each do |log|
|
607
|
+
next unless File.exist?(log)
|
608
|
+
output("----- contents of '#{log}' -----")
|
609
|
+
output(File.read(log))
|
610
|
+
output("----- end of file -----")
|
459
611
|
end
|
460
612
|
raise "Failed to complete #{action} task"
|
461
613
|
end
|
@@ -604,4 +756,29 @@ private
|
|
604
756
|
FileUtils.mkdir_p File.dirname(full_path)
|
605
757
|
FileUtils.mv temp_file.path, full_path, :force => true
|
606
758
|
end
|
759
|
+
|
760
|
+
#
|
761
|
+
# this minimal version of pkg_config is based on ruby 29dc9378 (2023-01-09)
|
762
|
+
#
|
763
|
+
# specifically with the fix from b90e56e6 to support multiple pkg-config options, and removing
|
764
|
+
# code paths that aren't helpful for mini-portile's use case of parsing pc files.
|
765
|
+
#
|
766
|
+
def minimal_pkg_config(pkg, *pcoptions)
|
767
|
+
if pcoptions.empty?
|
768
|
+
raise ArgumentError, "no pkg-config options are given"
|
769
|
+
end
|
770
|
+
|
771
|
+
if ($PKGCONFIG ||=
|
772
|
+
(pkgconfig = MakeMakefile.with_config("pkg-config") {MakeMakefile.config_string("PKG_CONFIG") || "pkg-config"}) &&
|
773
|
+
MakeMakefile.find_executable0(pkgconfig) && pkgconfig)
|
774
|
+
pkgconfig = $PKGCONFIG
|
775
|
+
else
|
776
|
+
raise RuntimeError, "pkg-config is not found"
|
777
|
+
end
|
778
|
+
|
779
|
+
pcoptions = Array(pcoptions).map { |o| "--#{o}" }
|
780
|
+
response = IO.popen([pkgconfig, *pcoptions, pkg], err:[:child, :out], &:read)
|
781
|
+
raise RuntimeError, response unless $?.success?
|
782
|
+
response.strip
|
783
|
+
end
|
607
784
|
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,96 @@ 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
|
+
c_compiler, cxx_compiler = find_c_and_cxx_compilers(host)
|
71
|
+
|
72
|
+
# needed to ensure cross-compilation with CMake targets the right CPU and compilers
|
73
|
+
[
|
74
|
+
"-DCMAKE_SYSTEM_NAME=#{cmake_system_name}",
|
75
|
+
"-DCMAKE_SYSTEM_PROCESSOR=#{cpu_type}",
|
76
|
+
"-DCMAKE_C_COMPILER=#{c_compiler}",
|
77
|
+
"-DCMAKE_CXX_COMPILER=#{cxx_compiler}",
|
78
|
+
"-DCMAKE_BUILD_TYPE=#{cmake_build_type}",
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_compiler(compilers)
|
83
|
+
compilers.find { |binary| which(binary) }
|
84
|
+
end
|
85
|
+
|
86
|
+
# configure automatically searches for the right compiler based on the
|
87
|
+
# `--host` parameter. However, CMake doesn't have an equivalent feature.
|
88
|
+
# Search for the right compiler for the target architecture using
|
89
|
+
# some basic heruistics.
|
90
|
+
def find_c_and_cxx_compilers(host)
|
91
|
+
c_compiler = ENV["CC"]
|
92
|
+
cxx_compiler = ENV["CXX"]
|
93
|
+
|
94
|
+
if MiniPortile.darwin?
|
95
|
+
c_compiler ||= 'clang'
|
96
|
+
cxx_compiler ||='clang++'
|
97
|
+
else
|
98
|
+
c_compiler ||= 'gcc'
|
99
|
+
cxx_compiler ||= 'g++'
|
100
|
+
end
|
101
|
+
|
102
|
+
c_platform_compiler = "#{host}-#{c_compiler}"
|
103
|
+
cxx_platform_compiler = "#{host}-#{cxx_compiler}"
|
104
|
+
c_compiler = find_compiler([c_platform_compiler, c_compiler])
|
105
|
+
cxx_compiler = find_compiler([cxx_platform_compiler, cxx_compiler])
|
106
|
+
|
107
|
+
[c_compiler, cxx_compiler]
|
108
|
+
end
|
109
|
+
|
110
|
+
# Full list: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.4/Modules/CMakeDetermineSystem.cmake?ref_type=tags#L12-31
|
111
|
+
def cmake_system_name
|
112
|
+
return system_name if system_name
|
113
|
+
|
114
|
+
if MiniPortile.linux?
|
115
|
+
'Linux'
|
116
|
+
elsif MiniPortile.darwin?
|
117
|
+
'Darwin'
|
118
|
+
elsif MiniPortile.windows?
|
119
|
+
'Windows'
|
120
|
+
elsif MiniPortile.freebsd?
|
121
|
+
'FreeBSD'
|
122
|
+
elsif MiniPortile.openbsd?
|
123
|
+
'OpenBSD'
|
124
|
+
elsif MiniPortile.solaris?
|
125
|
+
'SunOS'
|
126
|
+
else
|
127
|
+
raise "Unable to set CMAKE_SYSTEM_NAME for #{MiniPortile.target_os}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def generator_available?(generator_type)
|
132
|
+
stdout_str, status = Open3.capture2("#{cmake_cmd} --help")
|
133
|
+
|
134
|
+
raise 'Unable to determine whether CMake supports #{generator_type} Makefile generator' unless status.success?
|
135
|
+
|
136
|
+
stdout_str.include?("#{generator_type} Makefiles")
|
137
|
+
end
|
138
|
+
|
139
|
+
def cpu_type
|
140
|
+
return 'x86_64' if MiniPortile.target_cpu == 'x64'
|
141
|
+
|
142
|
+
MiniPortile.target_cpu
|
143
|
+
end
|
51
144
|
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"]
|
@@ -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
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
class TestActivate < TestCase
|
4
|
+
attr_reader :recipe
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
|
9
|
+
@save_env = %w[PATH CPATH LIBRARY_PATH LDFLAGS].inject({}) do |env, var|
|
10
|
+
env.update(var => ENV[var])
|
11
|
+
end
|
12
|
+
|
13
|
+
FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
|
14
|
+
|
15
|
+
@recipe = MiniPortile.new("foo", "1.0.0").tap do |recipe|
|
16
|
+
recipe.logger = StringIO.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
|
22
|
+
|
23
|
+
@save_env.each do |var, val|
|
24
|
+
ENV[var] = val
|
25
|
+
end
|
26
|
+
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_PATH_env_var_when_bin_does_not_exist
|
31
|
+
ENV["PATH"] = "foo"
|
32
|
+
refute(Dir.exist?(bin_path))
|
33
|
+
refute_includes(path_elements('PATH'), bin_path)
|
34
|
+
|
35
|
+
recipe.activate
|
36
|
+
|
37
|
+
refute_includes(path_elements('PATH'), bin_path)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_PATH_env_var_when_bin_exists
|
41
|
+
ENV["PATH"] = "foo"
|
42
|
+
FileUtils.mkdir_p(bin_path)
|
43
|
+
refute_includes(path_elements('PATH'), bin_path)
|
44
|
+
|
45
|
+
recipe.activate
|
46
|
+
|
47
|
+
assert_includes(path_elements('PATH'), bin_path)
|
48
|
+
assert_equal(path_elements('PATH').first, bin_path)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_CPATH_env_var_when_include_does_not_exist
|
52
|
+
ENV["CPATH"] = "foo"
|
53
|
+
refute(Dir.exist?(include_path))
|
54
|
+
refute_includes(path_elements('CPATH'), include_path)
|
55
|
+
|
56
|
+
recipe.activate
|
57
|
+
|
58
|
+
refute_includes(path_elements('CPATH'), include_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_CPATH_env_var_when_include_exists
|
62
|
+
ENV["CPATH"] = "foo"
|
63
|
+
FileUtils.mkdir_p(include_path)
|
64
|
+
refute_includes(path_elements('CPATH'), include_path)
|
65
|
+
|
66
|
+
recipe.activate
|
67
|
+
|
68
|
+
assert_includes(path_elements('CPATH'), include_path)
|
69
|
+
assert_equal(path_elements('CPATH').first, include_path)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_LIBRARY_PATH_env_var_when_lib_does_not_exist
|
73
|
+
ENV["LIBRARY_PATH"] = "foo"
|
74
|
+
refute(Dir.exist?(lib_path))
|
75
|
+
refute_includes(path_elements('LIBRARY_PATH'), lib_path)
|
76
|
+
|
77
|
+
recipe.activate
|
78
|
+
|
79
|
+
refute_includes(path_elements('LIBRARY_PATH'), lib_path)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_LIBRARY_PATH_env_var_when_lib_exists
|
83
|
+
ENV["LIBRARY_PATH"] = "foo"
|
84
|
+
FileUtils.mkdir_p(lib_path)
|
85
|
+
refute_includes(path_elements('LIBRARY_PATH'), lib_path)
|
86
|
+
|
87
|
+
recipe.activate
|
88
|
+
|
89
|
+
assert_includes(path_elements('LIBRARY_PATH'), lib_path)
|
90
|
+
assert_equal(path_elements('LIBRARY_PATH').first, lib_path)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_LDFLAGS_env_var_when_not_cross_compiling
|
94
|
+
ENV["LDFLAGS"] = "-lfoo"
|
95
|
+
FileUtils.mkdir_p(lib_path)
|
96
|
+
assert_equal(recipe.host, recipe.original_host) # assert on setup)
|
97
|
+
|
98
|
+
refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
|
99
|
+
|
100
|
+
recipe.activate
|
101
|
+
|
102
|
+
refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_LDFLAGS_env_var_when_cross_compiling
|
106
|
+
ENV["LDFLAGS"] = "-lfoo"
|
107
|
+
recipe.host = recipe.original_host + "-x" # make them not-equal
|
108
|
+
FileUtils.mkdir_p(lib_path)
|
109
|
+
|
110
|
+
refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
|
111
|
+
|
112
|
+
recipe.activate
|
113
|
+
|
114
|
+
assert_includes(flag_elements('LDFLAGS'), "-L#{lib_path}")
|
115
|
+
assert_equal(flag_elements('LDFLAGS').first, "-L#{lib_path}")
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def path_elements(varname)
|
121
|
+
ENV.fetch(varname, "").split(File::PATH_SEPARATOR)
|
122
|
+
end
|
123
|
+
|
124
|
+
def flag_elements(varname)
|
125
|
+
ENV.fetch(varname, "").split
|
126
|
+
end
|
127
|
+
|
128
|
+
def bin_path
|
129
|
+
MiniPortile.native_path(File.join(recipe.path, "bin"))
|
130
|
+
end
|
131
|
+
|
132
|
+
def include_path
|
133
|
+
MiniPortile.native_path(File.join(recipe.path, "include"))
|
134
|
+
end
|
135
|
+
|
136
|
+
def lib_path
|
137
|
+
MiniPortile.native_path(File.join(recipe.path, "lib"))
|
138
|
+
end
|
139
|
+
end
|
data/test/test_cmake.rb
CHANGED
@@ -14,13 +14,11 @@ class TestCMake < TestCase
|
|
14
14
|
create_tar(@tar_path, @assets_path, "test-cmake-1.0")
|
15
15
|
start_webrick(File.dirname(@tar_path))
|
16
16
|
|
17
|
-
@recipe =
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
recipe.cook
|
23
|
-
end
|
17
|
+
@recipe = init_recipe
|
18
|
+
|
19
|
+
git_dir = File.join(@assets_path, "git")
|
20
|
+
with_custom_git_dir(git_dir) do
|
21
|
+
recipe.cook
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
@@ -57,9 +55,16 @@ class TestCMake < TestCase
|
|
57
55
|
binary = File.join(recipe.path, "bin", exe_name)
|
58
56
|
assert File.exist?(binary), binary
|
59
57
|
end
|
58
|
+
|
59
|
+
def init_recipe
|
60
|
+
MiniPortileCMake.new("test-cmake", "1.0").tap do |recipe|
|
61
|
+
recipe.files << "http://localhost:#{HTTP_PORT}/#{ERB::Util.url_encode(File.basename(@tar_path))}"
|
62
|
+
recipe.patch_files << File.join(@assets_path, "patch 1.diff")
|
63
|
+
end
|
64
|
+
end
|
60
65
|
end
|
61
66
|
|
62
|
-
class TestCMakeConfig <
|
67
|
+
class TestCMakeConfig < TestCMake
|
63
68
|
def test_make_command_configuration
|
64
69
|
MiniPortile.stub(:mswin?, false) do
|
65
70
|
without_env("MAKE") do
|
@@ -77,6 +82,109 @@ class TestCMakeConfig < TestCase
|
|
77
82
|
end
|
78
83
|
end
|
79
84
|
|
85
|
+
def test_configure_defaults_with_macos
|
86
|
+
recipe = init_recipe
|
87
|
+
recipe.host = 'some-host'
|
88
|
+
|
89
|
+
with_env({ "CC" => nil, "CXX" => nil }) do
|
90
|
+
MiniPortile.stub(:darwin?, true) do
|
91
|
+
with_stubbed_target(os: 'darwin22', cpu: 'arm64') do
|
92
|
+
with_compilers(recipe, host_prefix: true, c_compiler: 'clang', cxx_compiler: 'clang++') do
|
93
|
+
Open3.stub(:capture2, cmake_help_mock('Unix')) do
|
94
|
+
assert_equal(
|
95
|
+
[
|
96
|
+
"-DCMAKE_SYSTEM_NAME=Darwin",
|
97
|
+
"-DCMAKE_SYSTEM_PROCESSOR=arm64",
|
98
|
+
"-DCMAKE_C_COMPILER=some-host-clang",
|
99
|
+
"-DCMAKE_CXX_COMPILER=some-host-clang++",
|
100
|
+
"-DCMAKE_BUILD_TYPE=Release"
|
101
|
+
],
|
102
|
+
recipe.configure_defaults)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_configure_defaults_with_manual_system_name
|
111
|
+
recipe = init_recipe
|
112
|
+
recipe.system_name = 'Custom'
|
113
|
+
|
114
|
+
MiniPortile.stub(:darwin?, false) do
|
115
|
+
with_stubbed_target do
|
116
|
+
with_compilers(recipe) do
|
117
|
+
Open3.stub(:capture2, cmake_help_mock('Unix')) do
|
118
|
+
assert_equal(
|
119
|
+
[
|
120
|
+
"-DCMAKE_SYSTEM_NAME=Custom",
|
121
|
+
"-DCMAKE_SYSTEM_PROCESSOR=x86_64",
|
122
|
+
"-DCMAKE_C_COMPILER=gcc",
|
123
|
+
"-DCMAKE_CXX_COMPILER=g++",
|
124
|
+
"-DCMAKE_BUILD_TYPE=Release"
|
125
|
+
],
|
126
|
+
recipe.configure_defaults)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_configure_defaults_with_unix_makefiles
|
134
|
+
recipe = init_recipe
|
135
|
+
|
136
|
+
MiniPortile.stub(:linux?, true) do
|
137
|
+
MiniPortile.stub(:darwin?, false) do
|
138
|
+
with_stubbed_target do
|
139
|
+
with_compilers(recipe) do
|
140
|
+
Open3.stub(:capture2, cmake_help_mock('Unix')) do
|
141
|
+
MiniPortile.stub(:mingw?, true) do
|
142
|
+
assert_equal(default_x86_compile_flags,
|
143
|
+
recipe.configure_defaults)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_configure_defaults_with_msys_makefiles
|
153
|
+
recipe = init_recipe
|
154
|
+
|
155
|
+
MiniPortile.stub(:linux?, true) do
|
156
|
+
MiniPortile.stub(:darwin?, false) do
|
157
|
+
with_stubbed_target do
|
158
|
+
with_compilers(recipe) do
|
159
|
+
Open3.stub(:capture2, cmake_help_mock('MSYS')) do
|
160
|
+
MiniPortile.stub(:mingw?, true) do
|
161
|
+
assert_equal(['-G', 'MSYS Makefiles'] + default_x86_compile_flags, recipe.configure_defaults)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_configure_defaults_with_nmake_makefiles
|
171
|
+
recipe = init_recipe
|
172
|
+
|
173
|
+
MiniPortile.stub(:linux?, true) do
|
174
|
+
MiniPortile.stub(:darwin?, false) do
|
175
|
+
with_stubbed_target do
|
176
|
+
with_compilers(recipe) do
|
177
|
+
Open3.stub(:capture2, cmake_help_mock('NMake')) do
|
178
|
+
MiniPortile.stub(:mswin?, true) do
|
179
|
+
assert_equal(['-G', 'NMake Makefiles'] + default_x86_compile_flags, recipe.configure_defaults)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
80
188
|
def test_cmake_command_configuration
|
81
189
|
without_env("CMAKE") do
|
82
190
|
assert_equal("cmake", MiniPortileCMake.new("test", "1.0.0").cmake_cmd)
|
@@ -87,4 +195,67 @@ class TestCMakeConfig < TestCase
|
|
87
195
|
assert_equal("asdf", MiniPortileCMake.new("test", "1.0.0", cmake_command: "xyzzy").cmake_cmd)
|
88
196
|
end
|
89
197
|
end
|
198
|
+
|
199
|
+
def test_cmake_build_type_configuration
|
200
|
+
without_env("CMAKE_BUILD_TYPE") do
|
201
|
+
assert_equal("Release", MiniPortileCMake.new("test", "1.0.0").cmake_build_type)
|
202
|
+
assert_equal("xyzzy", MiniPortileCMake.new("test", "1.0.0", cmake_build_type: "xyzzy").cmake_build_type)
|
203
|
+
end
|
204
|
+
with_env("CMAKE_BUILD_TYPE"=>"Debug") do
|
205
|
+
assert_equal("Debug", MiniPortileCMake.new("test", "1.0.0").cmake_build_type)
|
206
|
+
assert_equal("Debug", MiniPortileCMake.new("test", "1.0.0", cmake_build_type: "xyzzy").cmake_build_type)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
|
212
|
+
def with_stubbed_target(os: 'linux', cpu: 'x86_64')
|
213
|
+
MiniPortile.stub(:target_os, os) do
|
214
|
+
MiniPortile.stub(:target_cpu, cpu) do
|
215
|
+
yield
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def with_compilers(recipe, host_prefix: false, c_compiler: 'gcc', cxx_compiler: 'g++')
|
221
|
+
mock = MiniTest::Mock.new
|
222
|
+
|
223
|
+
if host_prefix
|
224
|
+
mock.expect(:call, true, ["#{recipe.host}-#{c_compiler}"])
|
225
|
+
mock.expect(:call, true, ["#{recipe.host}-#{cxx_compiler}"])
|
226
|
+
else
|
227
|
+
mock.expect(:call, false, ["#{recipe.host}-#{c_compiler}"])
|
228
|
+
mock.expect(:call, true, [c_compiler])
|
229
|
+
mock.expect(:call, false, ["#{recipe.host}-#{cxx_compiler}"])
|
230
|
+
mock.expect(:call, true, [cxx_compiler])
|
231
|
+
end
|
232
|
+
|
233
|
+
recipe.stub(:which, mock) do
|
234
|
+
yield
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def default_x86_compile_flags
|
239
|
+
[
|
240
|
+
"-DCMAKE_SYSTEM_NAME=Linux",
|
241
|
+
"-DCMAKE_SYSTEM_PROCESSOR=x86_64",
|
242
|
+
"-DCMAKE_C_COMPILER=gcc",
|
243
|
+
"-DCMAKE_CXX_COMPILER=g++",
|
244
|
+
"-DCMAKE_BUILD_TYPE=Release"
|
245
|
+
]
|
246
|
+
end
|
247
|
+
|
248
|
+
def cmake_help_mock(generator_type)
|
249
|
+
open3_mock = MiniTest::Mock.new
|
250
|
+
cmake_script = <<~SCRIPT
|
251
|
+
echo "The following generators are available on this platform (* marks default):"
|
252
|
+
echo "* #{generator_type} Makefiles = Generates standard #{generator_type.upcase} makefiles."
|
253
|
+
SCRIPT
|
254
|
+
|
255
|
+
exit_status = MiniTest::Mock.new
|
256
|
+
exit_status.expect(:success?, true)
|
257
|
+
expected_output = [cmake_script, exit_status]
|
258
|
+
open3_mock.expect(:call, expected_output, ['cmake --help'])
|
259
|
+
open3_mock
|
260
|
+
end
|
90
261
|
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
require "mkmf" # initialize $LDFLAGS et al here, instead of in the middle of a test
|
4
|
+
|
5
|
+
class TestMkmfConfig < TestCase
|
6
|
+
attr_reader :recipe
|
7
|
+
|
8
|
+
LIBXML_PCP = File.join(__dir__, "assets", "pkgconf", "libxml2")
|
9
|
+
LIBXSLT_PCP = File.join(__dir__, "assets", "pkgconf", "libxslt")
|
10
|
+
|
11
|
+
def make_recipe(name, version)
|
12
|
+
MiniPortile.new(name, version).tap do |recipe|
|
13
|
+
recipe.logger = StringIO.new # hush output
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup
|
18
|
+
super
|
19
|
+
|
20
|
+
@save_env = %w[PATH CPATH LIBRARY_PATH LDFLAGS PKG_CONFIG_PATH].inject({}) do |env, var|
|
21
|
+
env.update(var => ENV[var])
|
22
|
+
end
|
23
|
+
$INCFLAGS = "-I/xxx"
|
24
|
+
$LIBPATH = ["xxx"]
|
25
|
+
$CFLAGS = "-xxx"
|
26
|
+
$CXXFLAGS = "-xxx"
|
27
|
+
$libs = "-lxxx"
|
28
|
+
$MINI_PORTILE_STATIC_LIBS = {}
|
29
|
+
|
30
|
+
FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
|
31
|
+
|
32
|
+
@recipe = make_recipe("libfoo", "1.0.0")
|
33
|
+
end
|
34
|
+
|
35
|
+
def teardown
|
36
|
+
FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
|
37
|
+
|
38
|
+
$INCFLAGS = ""
|
39
|
+
$LIBPATH = []
|
40
|
+
$CFLAGS = ""
|
41
|
+
$CXXFLAGS = ""
|
42
|
+
$libs = ""
|
43
|
+
$MINI_PORTILE_STATIC_LIBS = {}
|
44
|
+
@save_env.each do |var, val|
|
45
|
+
ENV[var] = val
|
46
|
+
end
|
47
|
+
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_mkmf_config_recipe_LIBPATH_global_lib_dir_does_not_exist
|
52
|
+
recipe.mkmf_config
|
53
|
+
|
54
|
+
refute_includes($LIBPATH, recipe.lib_path)
|
55
|
+
refute_includes($libs.shellsplit, "-lfoo")
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_mkmf_config_recipe_LIBPATH_global_not_static
|
59
|
+
FileUtils.mkdir_p(recipe.lib_path)
|
60
|
+
|
61
|
+
recipe.mkmf_config
|
62
|
+
|
63
|
+
assert_includes($LIBPATH, recipe.lib_path)
|
64
|
+
assert_operator($LIBPATH.index(recipe.lib_path), :<, $LIBPATH.index("xxx")) # prepend
|
65
|
+
|
66
|
+
assert_includes($libs.shellsplit, "-lfoo") # note the recipe name is "libfoo"
|
67
|
+
assert_match(%r{-lfoo.*-lxxx}, $libs) # prepend
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_mkmf_config_recipe_LIBPATH_global_static
|
71
|
+
FileUtils.mkdir_p(recipe.lib_path)
|
72
|
+
static_lib_path = File.join(recipe.lib_path, "libfoo.#{$LIBEXT}")
|
73
|
+
|
74
|
+
recipe.mkmf_config(static: "foo")
|
75
|
+
|
76
|
+
refute_includes($LIBPATH, recipe.lib_path)
|
77
|
+
|
78
|
+
refute_includes($libs.shellsplit, "-lfoo") # note the recipe name is "libfoo"
|
79
|
+
assert_includes($libs.shellsplit, static_lib_path)
|
80
|
+
assert_match(%r{#{static_lib_path}.*-lxxx}, $libs) # prepend
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_mkmf_config_recipe_INCFLAGS_global_include_dir_does_not_exist
|
84
|
+
recipe.mkmf_config
|
85
|
+
|
86
|
+
refute_includes($INCFLAGS.shellsplit, "-I#{recipe.include_path}")
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_mkmf_config_recipe_INCFLAGS_global
|
90
|
+
FileUtils.mkdir_p(recipe.include_path)
|
91
|
+
|
92
|
+
recipe.mkmf_config
|
93
|
+
|
94
|
+
assert_includes($INCFLAGS.shellsplit, "-I#{recipe.include_path}")
|
95
|
+
assert_match(%r{-I#{recipe.include_path}.*-I/xxx}, $INCFLAGS) # prepend
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_mkmf_config_pkgconf_does_not_exist
|
99
|
+
assert_raises(ArgumentError) do
|
100
|
+
recipe.mkmf_config(pkg: "foo")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_mkmf_config_pkgconf_LIBPATH_global_not_static
|
105
|
+
# can't get the pkgconf utility to install on windows with ruby 2.3 in CI
|
106
|
+
skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
|
107
|
+
|
108
|
+
recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP)
|
109
|
+
|
110
|
+
assert_includes($LIBPATH, "/foo/libxml2/2.11.5/lib")
|
111
|
+
assert_operator($LIBPATH.index("/foo/libxml2/2.11.5/lib"), :<, $LIBPATH.index("xxx")) # prepend
|
112
|
+
refute_includes($LIBPATH, "/foo/zlib/1.3/lib")
|
113
|
+
|
114
|
+
assert_includes($libs.shellsplit, "-lxml2")
|
115
|
+
assert_match(%r{-lxml2.*-lxxx}, $libs) # prepend
|
116
|
+
refute_includes($libs.shellsplit, "-lz")
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_mkmf_config_pkgconf_LIBPATH_global_static
|
120
|
+
# can't get the pkgconf utility to install on windows with ruby 2.3 in CI
|
121
|
+
skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
|
122
|
+
|
123
|
+
static_lib_path = "/foo/libxml2/2.11.5/lib/libxml2.#{$LIBEXT}"
|
124
|
+
|
125
|
+
recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP, static: "xml2")
|
126
|
+
|
127
|
+
refute_includes($LIBPATH, "/foo/libxml2/2.11.5/lib")
|
128
|
+
refute_includes($libs.shellsplit, "-lxml2")
|
129
|
+
assert_includes($libs.shellsplit, static_lib_path)
|
130
|
+
assert_match(%r{#{static_lib_path}.*-lxxx}, $libs) # prepend
|
131
|
+
|
132
|
+
assert_includes($LIBPATH, "/foo/zlib/1.3/lib") # from --static
|
133
|
+
assert_includes($libs.shellsplit, "-lz") # from --static
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_mkmf_config_pkgconf_CFLAGS_global
|
137
|
+
# can't get the pkgconf utility to install on windows with ruby 2.3 in CI
|
138
|
+
skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
|
139
|
+
|
140
|
+
recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP)
|
141
|
+
|
142
|
+
assert_includes($INCFLAGS.shellsplit, "-I/foo/libxml2/2.11.5/include/libxml2")
|
143
|
+
assert_match(%r{-I/foo/libxml2/2.11.5/include/libxml2.*-I/xxx}, $INCFLAGS) # prepend
|
144
|
+
|
145
|
+
assert_includes($CFLAGS.shellsplit, "-ggdb3")
|
146
|
+
assert_match(%r{-xxx.*-ggdb3}, $CFLAGS) # append
|
147
|
+
|
148
|
+
assert_includes($CXXFLAGS.shellsplit, "-ggdb3")
|
149
|
+
assert_match(%r{-xxx.*-ggdb3}, $CXXFLAGS) # append
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_mkmf_config_pkgconf_path_accumulation
|
153
|
+
# can't get the pkgconf utility to install on windows with ruby 2.3 in CI
|
154
|
+
skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
|
155
|
+
|
156
|
+
(ENV["PKG_CONFIG_PATH"] || "").split(File::PATH_SEPARATOR).tap do |pcpaths|
|
157
|
+
refute_includes(pcpaths, LIBXML_PCP)
|
158
|
+
refute_includes(pcpaths, LIBXSLT_PCP)
|
159
|
+
end
|
160
|
+
|
161
|
+
make_recipe("libxml2", "2.11.5").tap do |recipe|
|
162
|
+
recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP, static: "xml2")
|
163
|
+
|
164
|
+
ENV["PKG_CONFIG_PATH"].split(File::PATH_SEPARATOR).tap do |pcpaths|
|
165
|
+
assert_includes(pcpaths, LIBXML_PCP)
|
166
|
+
refute_includes(pcpaths, LIBXSLT_PCP)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
make_recipe("libxslt", "1.13.8").tap do |recipe|
|
171
|
+
recipe.mkmf_config(pkg: "libxslt", dir: LIBXSLT_PCP, static: "xslt")
|
172
|
+
|
173
|
+
ENV["PKG_CONFIG_PATH"].split(File::PATH_SEPARATOR).tap do |pcpaths|
|
174
|
+
assert_includes(pcpaths, LIBXML_PCP)
|
175
|
+
assert_includes(pcpaths, LIBXSLT_PCP)
|
176
|
+
end
|
177
|
+
|
178
|
+
recipe.mkmf_config(pkg: "libexslt", dir: LIBXSLT_PCP, static: "exslt")
|
179
|
+
end
|
180
|
+
|
181
|
+
$INCFLAGS.shellsplit.tap do |incflags|
|
182
|
+
assert_includes(incflags, "-I/foo/libxml2/2.11.5/include/libxml2")
|
183
|
+
assert_includes(incflags, "-I/foo/libxslt/1.1.38/include")
|
184
|
+
end
|
185
|
+
$CFLAGS.shellsplit.tap do |cflags|
|
186
|
+
assert_includes(cflags, "-ggdb3")
|
187
|
+
assert_includes(cflags, "-Wno-deprecated-enum-enum-conversion")
|
188
|
+
end
|
189
|
+
refute_includes($LIBPATH, "/foo/libxml2/2.11.5/lib")
|
190
|
+
refute_includes($LIBPATH, "/foo/libxslt/1.1.38/lib")
|
191
|
+
assert_includes($LIBPATH, "/foo/zlib/1.3/lib") # from `--static`
|
192
|
+
$libs.shellsplit.tap do |libflags|
|
193
|
+
refute_includes(libflags, "-lxml2")
|
194
|
+
assert_includes(libflags, "/foo/libxml2/2.11.5/lib/libxml2.#{$LIBEXT}")
|
195
|
+
refute_includes(libflags, "-lxslt")
|
196
|
+
assert_includes(libflags, "/foo/libxslt/1.1.38/lib/libxslt.#{$LIBEXT}")
|
197
|
+
refute_includes(libflags, "-lexslt")
|
198
|
+
assert_includes(libflags, "/foo/libxslt/1.1.38/lib/libexslt.#{$LIBEXT}")
|
199
|
+
assert_includes(libflags, "-lz") # from `--static`
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
data/test/test_recipe.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
class TestRecipe < TestCase
|
4
|
+
def test_path
|
5
|
+
recipe = MiniPortile.new("libfoo", "1.0.0")
|
6
|
+
assert_equal(File.expand_path(File.join(recipe.target, recipe.host, recipe.name, recipe.version)), recipe.path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_lib_path
|
10
|
+
recipe = MiniPortile.new("libfoo", "1.0.0")
|
11
|
+
assert_equal(File.join(recipe.path, "lib"), recipe.lib_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_include_path
|
15
|
+
recipe = MiniPortile.new("libfoo", "1.0.0")
|
16
|
+
assert_equal(File.join(recipe.path, "include"), recipe.include_path)
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_portile2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luis Lavena
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-10-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -96,9 +96,10 @@ dependencies:
|
|
96
96
|
- - "~>"
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: '1.7'
|
99
|
-
description:
|
100
|
-
and
|
101
|
-
system.
|
99
|
+
description: |
|
100
|
+
Simple autoconf and cmake builder for developers. It provides a standard way to compile against
|
101
|
+
dependency libraries without requiring system-wide installation. It also simplifies
|
102
|
+
vendoring and cross-compilation by providing a consistent build interface.
|
102
103
|
email: mike.dalessio@gmail.com
|
103
104
|
executables: []
|
104
105
|
extensions: []
|
@@ -123,17 +124,23 @@ files:
|
|
123
124
|
- test/assets/gpg-fixtures/data.asc
|
124
125
|
- test/assets/gpg-fixtures/data.invalid.asc
|
125
126
|
- test/assets/patch 1.diff
|
127
|
+
- test/assets/pkgconf/libxml2/libxml-2.0.pc
|
128
|
+
- test/assets/pkgconf/libxslt/libexslt.pc
|
129
|
+
- test/assets/pkgconf/libxslt/libxslt.pc
|
126
130
|
- test/assets/test mini portile-1.0.0/configure
|
127
131
|
- test/assets/test-cmake-1.0/CMakeLists.txt
|
128
132
|
- test/assets/test-cmake-1.0/hello.c
|
129
133
|
- test/assets/test-download-archive.tar.gz
|
130
134
|
- test/helper.rb
|
135
|
+
- test/test_activate.rb
|
131
136
|
- test/test_cmake.rb
|
132
137
|
- test/test_cook.rb
|
133
138
|
- test/test_digest.rb
|
134
139
|
- test/test_download.rb
|
135
140
|
- test/test_execute.rb
|
141
|
+
- test/test_mkmf_config.rb
|
136
142
|
- test/test_proxy.rb
|
143
|
+
- test/test_recipe.rb
|
137
144
|
homepage: https://github.com/flavorjones/mini_portile
|
138
145
|
licenses:
|
139
146
|
- MIT
|
@@ -153,24 +160,30 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
160
|
- !ruby/object:Gem::Version
|
154
161
|
version: '0'
|
155
162
|
requirements: []
|
156
|
-
rubygems_version: 3.
|
163
|
+
rubygems_version: 3.4.19
|
157
164
|
signing_key:
|
158
165
|
specification_version: 4
|
159
|
-
summary:
|
166
|
+
summary: Simple autoconf and cmake builder for developers
|
160
167
|
test_files:
|
161
168
|
- test/assets/git/config
|
162
169
|
- test/assets/gpg-fixtures/data
|
163
170
|
- test/assets/gpg-fixtures/data.asc
|
164
171
|
- test/assets/gpg-fixtures/data.invalid.asc
|
165
172
|
- test/assets/patch 1.diff
|
173
|
+
- test/assets/pkgconf/libxml2/libxml-2.0.pc
|
174
|
+
- test/assets/pkgconf/libxslt/libexslt.pc
|
175
|
+
- test/assets/pkgconf/libxslt/libxslt.pc
|
166
176
|
- test/assets/test mini portile-1.0.0/configure
|
167
177
|
- test/assets/test-cmake-1.0/CMakeLists.txt
|
168
178
|
- test/assets/test-cmake-1.0/hello.c
|
169
179
|
- test/assets/test-download-archive.tar.gz
|
170
180
|
- test/helper.rb
|
181
|
+
- test/test_activate.rb
|
171
182
|
- test/test_cmake.rb
|
172
183
|
- test/test_cook.rb
|
173
184
|
- test/test_digest.rb
|
174
185
|
- test/test_download.rb
|
175
186
|
- test/test_execute.rb
|
187
|
+
- test/test_mkmf_config.rb
|
176
188
|
- test/test_proxy.rb
|
189
|
+
- test/test_recipe.rb
|