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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d467d59c8fe3298a010263ffcf5de58be5ba9be7757dbce500fd96251a2c864e
4
- data.tar.gz: 70534d0b13bcdc0fe91c5524f8d40414ee1cc29fc357806aea4bbe52cc39129b
3
+ metadata.gz: 8f53843a25ac2651fd9970c34a44edf44de0904f99d9e63eadb3802f8dcd59bc
4
+ data.tar.gz: 075527f5c56f12de2ba5e3dfd72965a0093f62558eabb02571be5aee61cbe9f5
5
5
  SHA512:
6
- metadata.gz: d67bc2e58d7fa53a4315fdaa1ab56f8ca5fe6b0a42e020b511e3aef3f7185690fbb51ee8f1bd5ccec48f0b37ef9037f45d7c56973ae3fdffadcfddc8679b6594
7
- data.tar.gz: f2ab11a49573096c9b7fe150d1fcde07161a36514b6bb885e455f82cf270a70465987b131d359e898bd99850c616989afcbf48a9de1b5dbfb46831f9eea46f42
6
+ metadata.gz: 0e251640701cf8ea166e1ce6725b8e7bf3d3dbf20a659a6b90ffe127667a80f908fab5b7f816f8a766edd4166464d5375c53a3c31c862a4a7a04e0e87929127d
7
+ data.tar.gz: 1d540e216342ef799de2188935d6de440b865606a244dd7ca6a27146a259bf5a1211c53b49668eee668187770e5e030d06508b4605779c4366999dcf831cc2b3
@@ -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@v2
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@v2
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@v2
67
+ - uses: actions/cache@v3
68
68
  with:
69
69
  path: examples/ports/archives
70
- key: ${{ matrix.platform }}-examples-${{ hashFiles('examples/Rakefile') }}
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
@@ -3,3 +3,4 @@ Gemfile.lock
3
3
  pkg
4
4
  ports
5
5
  tmp
6
+ mkmf.log
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 `cmake_command` value passed in to the constructor
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, :source_directory
37
+ attr_accessor :host, :files, :patch_files, :target, :logger
36
38
 
37
39
  def self.windows?
38
- RbConfig::CONFIG['target_os'] =~ /mswin|mingw/
40
+ target_os =~ /mswin|mingw/
39
41
  end
40
42
 
41
43
  # GNU MinGW compiled Ruby?
42
44
  def self.mingw?
43
- RbConfig::CONFIG['target_os'] =~ /mingw/
45
+ target_os =~ /mingw/
44
46
  end
45
47
 
46
48
  # MS Visual-C compiled Ruby?
47
49
  def self.mswin?
48
- RbConfig::CONFIG['target_os'] =~ /mswin/
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 = File.expand_path(path)
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} #{@version} from source at '#{source_directory}'"
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' => File.join(port_path, 'include'),
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 = File.expand_path(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 = File.expand_path(lib_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
- if File.exist? log_out
454
- output "ERROR, review '#{log_out}' to see what happened. Last lines are:"
455
- output("=" * 72)
456
- log_lines = File.readlines(log_out)
457
- output(log_lines[-[log_lines.length, 20].min .. -1])
458
- output("=" * 72)
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
- if MiniPortile.mswin?
15
- ['-G', 'NMake Makefiles']
16
- elsif MiniPortile.mingw?
17
- ['-G', 'MSYS Makefiles']
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
@@ -1,3 +1,3 @@
1
1
  class MiniPortile
2
- VERSION = "2.8.1"
2
+ VERSION = "2.8.5"
3
3
  end
@@ -1,7 +1,4 @@
1
- # coding: utf-8
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 = "Simplistic port-like solution for developers"
14
- spec.description = "Simplistic port-like solution for developers. It provides a standard and simplified way to compile against dependency libraries without messing up your system."
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 = MiniPortileCMake.new("test-cmake", "1.0").tap do |recipe|
18
- recipe.files << "http://localhost:#{HTTP_PORT}/#{ERB::Util.url_encode(File.basename(@tar_path))}"
19
- recipe.patch_files << File.join(@assets_path, "patch 1.diff")
20
- git_dir = File.join(@assets_path, "git")
21
- with_custom_git_dir(git_dir) do
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 < TestCase
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
@@ -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.1
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: 2022-12-24 00:00:00.000000000 Z
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: Simplistic port-like solution for developers. It provides a standard
100
- and simplified way to compile against dependency libraries without messing up your
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.3.26
163
+ rubygems_version: 3.4.19
157
164
  signing_key:
158
165
  specification_version: 4
159
- summary: Simplistic port-like solution for developers
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