mini_portile2 2.8.3 → 2.8.5.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51973caa0015d6919e11d6e081cec2e26f146cf329e5f2ec9b34b97e1485d13a
4
- data.tar.gz: e5a8eeb01caa0e047ba7d0c75e19e726b18aa8af4fa6fc89e40367671d8bc919
3
+ metadata.gz: 235fc41ae2e4aab6133eb8edb741bb535194af46c1aca4e70f0785d2c1253322
4
+ data.tar.gz: 4ffdc351e59c3cec669361e0fb7b50b536d113363a7ed1c91d8fb681453df4fa
5
5
  SHA512:
6
- metadata.gz: 7711d008192576bddd38a396a372581cfff4e6e2ec48c95ac669c61db470bad9a9e508cf314ab6fa859069477262c1c8c7d30beb043d3ce6a571c80351ef0e79
7
- data.tar.gz: 553bc5519d22489492ee5eb16c80048731523a1cf45e8f7eb3c2f5a29de9b0a61bfa350894cbd0a82a769c6972ddd1083deb379b262f53ea9092a6e4abb910cd
6
+ metadata.gz: 03deed0dd932686706f7956fda4f167fb46c73f87f443c058163226019de21d16252c509b453fccfaa8b661bf3f9667b0c1f2fec66edcef042a968fcd847811f
7
+ data.tar.gz: a5d574f3b181ed8303ae0c799e6092fde2166fd1dc5937961f7b8016eef441a287cf80c4abf1bb2ec0f036894a12ea80f12edb30cec631981f6d8f042ad87959
@@ -67,5 +67,22 @@ jobs:
67
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,19 @@
1
1
  ## mini_portile changelog
2
2
 
3
+ ### 2.8.5.rc1 / 2023-09-13
4
+
5
+ #### Added
6
+
7
+ - New method `MiniPortile#mkmf_config` will set up MakeMakefile variables to properly link against the recipe. This should make it easier for C extensions to package third-party libraries.
8
+ - With no arguments, will set up just `$INCFLAGS`, `$libs`, and `$LIBPATH`.
9
+ - Optionally, if provided a pkg-config file, will use that config to more precisely set `$INCFLAGS`, `$libs`, `$LIBPATH`, and `$CFLAGS`/`$CXXFLAGS`.
10
+
11
+
12
+ ### 2.8.4 / 2023-07-18
13
+
14
+ - 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!)
15
+
16
+
3
17
  ### 2.8.3 / 2023-07-18
4
18
 
5
19
  #### Fixed
@@ -35,17 +35,63 @@ class MiniPortile
35
35
  attr_accessor :host, :files, :patch_files, :target, :logger, :source_directory
36
36
 
37
37
  def self.windows?
38
- RbConfig::CONFIG['target_os'] =~ /mswin|mingw/
38
+ target_os =~ /mswin|mingw/
39
39
  end
40
40
 
41
41
  # GNU MinGW compiled Ruby?
42
42
  def self.mingw?
43
- RbConfig::CONFIG['target_os'] =~ /mingw/
43
+ target_os =~ /mingw/
44
44
  end
45
45
 
46
46
  # MS Visual-C compiled Ruby?
47
47
  def self.mswin?
48
- RbConfig::CONFIG['target_os'] =~ /mswin/
48
+ target_os =~ /mswin/
49
+ end
50
+
51
+ def self.darwin?
52
+ target_os =~ /darwin/
53
+ end
54
+
55
+ def self.freebsd?
56
+ target_os =~ /freebsd/
57
+ end
58
+
59
+ def self.openbsd?
60
+ target_os =~ /openbsd/
61
+ end
62
+
63
+ def self.linux?
64
+ target_os =~ /linux/
65
+ end
66
+
67
+ def self.solaris?
68
+ target_os =~ /solaris/
69
+ end
70
+
71
+ def self.target_os
72
+ RbConfig::CONFIG['target_os']
73
+ end
74
+
75
+ def self.target_cpu
76
+ RbConfig::CONFIG['target_cpu']
77
+ end
78
+
79
+ def self.native_path(path)
80
+ path = File.expand_path(path)
81
+ if File::ALT_SEPARATOR
82
+ path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
83
+ else
84
+ path
85
+ end
86
+ end
87
+
88
+ def self.posix_path(path)
89
+ path = File.expand_path(path)
90
+ if File::ALT_SEPARATOR
91
+ "/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR)
92
+ else
93
+ path
94
+ end
49
95
  end
50
96
 
51
97
  def initialize(name, version, **kwargs)
@@ -58,12 +104,12 @@ class MiniPortile
58
104
  @logger = STDOUT
59
105
  @source_directory = nil
60
106
 
61
- @original_host = @host = detect_host
62
-
63
107
  @gcc_command = kwargs[:gcc_command]
64
108
  @make_command = kwargs[:make_command]
65
109
  @open_timeout = kwargs[:open_timeout] || DEFAULT_TIMEOUT
66
110
  @read_timeout = kwargs[:read_timeout] || DEFAULT_TIMEOUT
111
+
112
+ @original_host = @host = detect_host
67
113
  end
68
114
 
69
115
  def source_directory=(path)
@@ -212,7 +258,7 @@ class MiniPortile
212
258
 
213
259
  # rely on LDFLAGS when cross-compiling
214
260
  if File.exist?(lib_path) && (@host != @original_host)
215
- full_path = File.expand_path(lib_path)
261
+ full_path = native_path(lib_path)
216
262
 
217
263
  old_value = ENV.fetch("LDFLAGS", "")
218
264
 
@@ -222,6 +268,58 @@ class MiniPortile
222
268
  end
223
269
  end
224
270
 
271
+ def mkmf_config(pkg: nil, dir: nil)
272
+ require "mkmf"
273
+
274
+ if pkg
275
+ dir ||= File.join(path, "lib", "pkgconfig")
276
+ pcfile = File.join(dir, "#{pkg}.pc")
277
+ unless File.exist?(pcfile)
278
+ raise ArgumentError, "pkg-config file '#{pcfile}' does not exist"
279
+ end
280
+
281
+ output "Configuring MakeMakefile for #{File.basename(pcfile)} (in #{File.dirname(pcfile)})\n"
282
+
283
+ # on macos, pkg-config will not return --cflags without this
284
+ ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"
285
+
286
+ # append to PKG_CONFIG_PATH as we go, so later pkg-config files can depend on earlier ones
287
+ ENV["PKG_CONFIG_PATH"] = [ENV["PKG_CONFIG_PATH"], dir].compact.join(File::PATH_SEPARATOR)
288
+
289
+ incflags = minimal_pkg_config(pcfile, "cflags-only-I")
290
+ cflags = minimal_pkg_config(pcfile, "cflags-only-other")
291
+ ldflags = minimal_pkg_config(pcfile, "libs-only-L", "static")
292
+ libflags = minimal_pkg_config(pcfile, "libs-only-l", "static")
293
+ else
294
+ output "Configuring MakeMakefile for #{@name} #{@version} (from #{path})\n"
295
+
296
+ include_path = File.join(path, "include")
297
+ lib_path = File.join(path, "lib")
298
+
299
+ lib_name = name.sub(/\Alib/, "") # TODO: use delete_prefix when we no longer support ruby 2.4
300
+
301
+ incflags = "-I#{include_path}" if Dir.exist?(include_path)
302
+ ldflags = "-L#{lib_path}" if Dir.exist?(lib_path)
303
+ libflags = "-l#{lib_name}" if Dir.exist?(lib_path)
304
+ end
305
+
306
+ if ldflags
307
+ libpaths = ldflags.split.map { |f| f.sub(/\A-L/, "") }
308
+ end
309
+
310
+ # prefer this package by prepending directories to the search path
311
+ #
312
+ # use $LIBPATH instead of $LDFLAGS to ensure we get the `-Wl,-rpath` linker flag for re-finding
313
+ # shared libraries
314
+ $INCFLAGS = [incflags, $INCFLAGS].join(" ").strip if incflags
315
+ $LIBPATH = libpaths | $LIBPATH if libpaths
316
+
317
+ # prefer this package's flags by appending them to the command line
318
+ $CFLAGS = [$CFLAGS, cflags].join(" ").strip if cflags
319
+ $CXXFLAGS = [$CXXFLAGS, cflags].join(" ").strip if cflags
320
+ $libs = [$libs, libflags].join(" ").strip if libflags
321
+ end
322
+
225
323
  def path
226
324
  File.expand_path(port_path)
227
325
  end
@@ -237,21 +335,11 @@ class MiniPortile
237
335
  private
238
336
 
239
337
  def native_path(path)
240
- path = File.expand_path(path)
241
- if File::ALT_SEPARATOR
242
- path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
243
- else
244
- path
245
- end
338
+ MiniPortile.native_path(path)
246
339
  end
247
340
 
248
341
  def posix_path(path)
249
- path = File.expand_path(path)
250
- if File::ALT_SEPARATOR
251
- "/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR)
252
- else
253
- path
254
- end
342
+ MiniPortile.posix_path(path)
255
343
  end
256
344
 
257
345
  def tmp_path
@@ -620,4 +708,29 @@ class MiniPortile
620
708
  FileUtils.mkdir_p File.dirname(full_path)
621
709
  FileUtils.mv temp_file.path, full_path, :force => true
622
710
  end
711
+
712
+ #
713
+ # this minimal version of pkg_config is based on ruby 29dc9378 (2023-01-09)
714
+ #
715
+ # specifically with the fix from b90e56e6 to support multiple pkg-config options, and removing
716
+ # code paths that aren't helpful for mini-portile's use case of parsing pc files.
717
+ #
718
+ def minimal_pkg_config(pkg, *pcoptions)
719
+ if pcoptions.empty?
720
+ raise ArgumentError, "no pkg-config options are given"
721
+ end
722
+
723
+ if ($PKGCONFIG ||=
724
+ (pkgconfig = MakeMakefile.with_config("pkg-config") {MakeMakefile.config_string("PKG_CONFIG") || "pkg-config"}) &&
725
+ MakeMakefile.find_executable0(pkgconfig) && pkgconfig)
726
+ pkgconfig = $PKGCONFIG
727
+ else
728
+ raise RuntimeError, "pkg-config is not found"
729
+ end
730
+
731
+ pcoptions = Array(pcoptions).map { |o| "--#{o}" }
732
+ response = IO.popen([pkgconfig, *pcoptions, pkg], err:[:child, :out], &:read)
733
+ raise RuntimeError, response unless $?.success?
734
+ response.strip
735
+ end
623
736
  end
@@ -2,6 +2,8 @@ require 'mini_portile2/mini_portile'
2
2
  require 'open3'
3
3
 
4
4
  class MiniPortileCMake < MiniPortile
5
+ attr_accessor :system_name
6
+
5
7
  def configure_prefix
6
8
  "-DCMAKE_INSTALL_PREFIX=#{File.expand_path(port_path)}"
7
9
  end
@@ -12,13 +14,10 @@ class MiniPortileCMake < MiniPortile
12
14
  end
13
15
 
14
16
  def configure_defaults
15
- if MiniPortile.mswin? && generator_available?('NMake')
16
- ['-G', 'NMake Makefiles']
17
- elsif MiniPortile.mingw? && generator_available?('MSYS')
18
- ['-G', 'MSYS Makefiles']
19
- else
20
- []
21
- end
17
+ [
18
+ generator_defaults,
19
+ cmake_compile_flags,
20
+ ].flatten
22
21
  end
23
22
 
24
23
  def configure
@@ -52,6 +51,77 @@ class MiniPortileCMake < MiniPortile
52
51
 
53
52
  private
54
53
 
54
+ def generator_defaults
55
+ if MiniPortile.mswin? && generator_available?('NMake')
56
+ ['-G', 'NMake Makefiles']
57
+ elsif MiniPortile.mingw? && generator_available?('MSYS')
58
+ ['-G', 'MSYS Makefiles']
59
+ else
60
+ []
61
+ end
62
+ end
63
+
64
+ def cmake_compile_flags
65
+ c_compiler, cxx_compiler = find_c_and_cxx_compilers(host)
66
+
67
+ # needed to ensure cross-compilation with CMake targets the right CPU and compilers
68
+ [
69
+ "-DCMAKE_SYSTEM_NAME=#{cmake_system_name}",
70
+ "-DCMAKE_SYSTEM_PROCESSOR=#{cpu_type}",
71
+ "-DCMAKE_C_COMPILER=#{c_compiler}",
72
+ "-DCMAKE_CXX_COMPILER=#{cxx_compiler}"
73
+ ]
74
+ end
75
+
76
+ def find_compiler(compilers)
77
+ compilers.find { |binary| which(binary) }
78
+ end
79
+
80
+ # configure automatically searches for the right compiler based on the
81
+ # `--host` parameter. However, CMake doesn't have an equivalent feature.
82
+ # Search for the right compiler for the target architecture using
83
+ # some basic heruistics.
84
+ def find_c_and_cxx_compilers(host)
85
+ c_compiler = ENV["CC"]
86
+ cxx_compiler = ENV["CXX"]
87
+
88
+ if MiniPortile.darwin?
89
+ c_compiler ||= 'clang'
90
+ cxx_compiler ||='clang++'
91
+ else
92
+ c_compiler ||= 'gcc'
93
+ cxx_compiler ||= 'g++'
94
+ end
95
+
96
+ c_platform_compiler = "#{host}-#{c_compiler}"
97
+ cxx_platform_compiler = "#{host}-#{cxx_compiler}"
98
+ c_compiler = find_compiler([c_platform_compiler, c_compiler])
99
+ cxx_compiler = find_compiler([cxx_platform_compiler, cxx_compiler])
100
+
101
+ [c_compiler, cxx_compiler]
102
+ end
103
+
104
+ # Full list: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.4/Modules/CMakeDetermineSystem.cmake?ref_type=tags#L12-31
105
+ def cmake_system_name
106
+ return system_name if system_name
107
+
108
+ if MiniPortile.linux?
109
+ 'Linux'
110
+ elsif MiniPortile.darwin?
111
+ 'Darwin'
112
+ elsif MiniPortile.windows?
113
+ 'Windows'
114
+ elsif MiniPortile.freebsd?
115
+ 'FreeBSD'
116
+ elsif MiniPortile.openbsd?
117
+ 'OpenBSD'
118
+ elsif MiniPortile.solaris?
119
+ 'SunOS'
120
+ else
121
+ raise "Unable to set CMAKE_SYSTEM_NAME for #{MiniPortile.target_os}"
122
+ end
123
+ end
124
+
55
125
  def generator_available?(generator_type)
56
126
  stdout_str, status = Open3.capture2("#{cmake_cmd} --help")
57
127
 
@@ -59,4 +129,10 @@ class MiniPortileCMake < MiniPortile
59
129
 
60
130
  stdout_str.include?("#{generator_type} Makefiles")
61
131
  end
132
+
133
+ def cpu_type
134
+ return 'x86_64' if MiniPortile.target_cpu == 'x64'
135
+
136
+ MiniPortile.target_cpu
137
+ end
62
138
  end
@@ -1,3 +1,3 @@
1
1
  class MiniPortile
2
- VERSION = "2.8.3"
2
+ VERSION = "2.8.5.rc1"
3
3
  end
@@ -0,0 +1,13 @@
1
+ prefix=/foo/libxml2/2.11.5
2
+ exec_prefix=${prefix}
3
+ libdir=/foo/libxml2/2.11.5/lib
4
+ includedir=${prefix}/include
5
+ modules=1
6
+
7
+ Name: libXML
8
+ Version: 2.11.5
9
+ Description: libXML library version2.
10
+ Requires:
11
+ Libs: -L${libdir} -lxml2
12
+ Libs.private: -L/foo/zlib/1.3/lib -lz -lm
13
+ Cflags: -I${includedir}/libxml2 -ggdb3
@@ -0,0 +1,13 @@
1
+ prefix=/foo/libxslt/1.1.38
2
+ exec_prefix=${prefix}
3
+ libdir=/foo/libxslt/1.1.38/lib
4
+ includedir=${prefix}/include
5
+
6
+
7
+ Name: libexslt
8
+ Version: 0.8.21
9
+ Description: EXSLT Extension library
10
+ Requires: libxml-2.0, libxslt
11
+ Cflags: -I${includedir}
12
+ Libs: -L${libdir} -lexslt
13
+ Libs.private: -lm
@@ -0,0 +1,13 @@
1
+ prefix=/foo/libxslt/1.1.38
2
+ exec_prefix=${prefix}
3
+ libdir=/foo/libxslt/1.1.38/lib
4
+ includedir=${prefix}/include
5
+
6
+
7
+ Name: libxslt
8
+ Version: 1.1.38
9
+ Description: XSLT library version 2.
10
+ Requires: libxml-2.0
11
+ Cflags: -I${includedir} -Wno-deprecated-enum-enum-conversion
12
+ Libs: -L${libdir} -lxslt
13
+ Libs.private: -lm
@@ -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,6 +55,13 @@ 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
67
  class TestCMakeConfig < TestCMake
@@ -77,26 +82,103 @@ class TestCMakeConfig < TestCMake
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
+ ],
101
+ recipe.configure_defaults)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ def test_configure_defaults_with_manual_system_name
110
+ recipe = init_recipe
111
+ recipe.system_name = 'Custom'
112
+
113
+ MiniPortile.stub(:darwin?, false) do
114
+ with_stubbed_target do
115
+ with_compilers(recipe) do
116
+ Open3.stub(:capture2, cmake_help_mock('Unix')) do
117
+ assert_equal(
118
+ [
119
+ "-DCMAKE_SYSTEM_NAME=Custom",
120
+ "-DCMAKE_SYSTEM_PROCESSOR=x86_64",
121
+ "-DCMAKE_C_COMPILER=gcc",
122
+ "-DCMAKE_CXX_COMPILER=g++"
123
+ ],
124
+ recipe.configure_defaults)
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+
80
131
  def test_configure_defaults_with_unix_makefiles
81
- Open3.stub(:capture2, cmake_help_mock('Unix')) do
82
- MiniPortile.stub(:mingw?, true) do
83
- assert_equal([], @recipe.configure_defaults)
132
+ recipe = init_recipe
133
+
134
+ MiniPortile.stub(:linux?, true) do
135
+ MiniPortile.stub(:darwin?, false) do
136
+ with_stubbed_target do
137
+ with_compilers(recipe) do
138
+ Open3.stub(:capture2, cmake_help_mock('Unix')) do
139
+ MiniPortile.stub(:mingw?, true) do
140
+ assert_equal(default_x86_compile_flags,
141
+ recipe.configure_defaults)
142
+ end
143
+ end
144
+ end
145
+ end
84
146
  end
85
147
  end
86
148
  end
87
149
 
88
150
  def test_configure_defaults_with_msys_makefiles
89
- Open3.stub(:capture2, cmake_help_mock('MSYS')) do
90
- MiniPortile.stub(:mingw?, true) do
91
- assert_equal(['-G', 'MSYS Makefiles'], @recipe.configure_defaults)
151
+ recipe = init_recipe
152
+
153
+ MiniPortile.stub(:linux?, true) do
154
+ MiniPortile.stub(:darwin?, false) do
155
+ with_stubbed_target do
156
+ with_compilers(recipe) do
157
+ Open3.stub(:capture2, cmake_help_mock('MSYS')) do
158
+ MiniPortile.stub(:mingw?, true) do
159
+ assert_equal(['-G', 'MSYS Makefiles'] + default_x86_compile_flags, recipe.configure_defaults)
160
+ end
161
+ end
162
+ end
163
+ end
92
164
  end
93
165
  end
94
166
  end
95
167
 
96
168
  def test_configure_defaults_with_nmake_makefiles
97
- Open3.stub(:capture2, cmake_help_mock('NMake')) do
98
- MiniPortile.stub(:mswin?, true) do
99
- assert_equal(['-G', 'NMake Makefiles'], @recipe.configure_defaults)
169
+ recipe = init_recipe
170
+
171
+ MiniPortile.stub(:linux?, true) do
172
+ MiniPortile.stub(:darwin?, false) do
173
+ with_stubbed_target do
174
+ with_compilers(recipe) do
175
+ Open3.stub(:capture2, cmake_help_mock('NMake')) do
176
+ MiniPortile.stub(:mswin?, true) do
177
+ assert_equal(['-G', 'NMake Makefiles'] + default_x86_compile_flags, recipe.configure_defaults)
178
+ end
179
+ end
180
+ end
181
+ end
100
182
  end
101
183
  end
102
184
  end
@@ -114,12 +196,47 @@ class TestCMakeConfig < TestCMake
114
196
 
115
197
  private
116
198
 
199
+ def with_stubbed_target(os: 'linux', cpu: 'x86_64')
200
+ MiniPortile.stub(:target_os, os) do
201
+ MiniPortile.stub(:target_cpu, cpu) do
202
+ yield
203
+ end
204
+ end
205
+ end
206
+
207
+ def with_compilers(recipe, host_prefix: false, c_compiler: 'gcc', cxx_compiler: 'g++')
208
+ mock = MiniTest::Mock.new
209
+
210
+ if host_prefix
211
+ mock.expect(:call, true, ["#{recipe.host}-#{c_compiler}"])
212
+ mock.expect(:call, true, ["#{recipe.host}-#{cxx_compiler}"])
213
+ else
214
+ mock.expect(:call, false, ["#{recipe.host}-#{c_compiler}"])
215
+ mock.expect(:call, true, [c_compiler])
216
+ mock.expect(:call, false, ["#{recipe.host}-#{cxx_compiler}"])
217
+ mock.expect(:call, true, [cxx_compiler])
218
+ end
219
+
220
+ recipe.stub(:which, mock) do
221
+ yield
222
+ end
223
+ end
224
+
225
+ def default_x86_compile_flags
226
+ [
227
+ "-DCMAKE_SYSTEM_NAME=Linux",
228
+ "-DCMAKE_SYSTEM_PROCESSOR=x86_64",
229
+ "-DCMAKE_C_COMPILER=gcc",
230
+ "-DCMAKE_CXX_COMPILER=g++"
231
+ ]
232
+ end
233
+
117
234
  def cmake_help_mock(generator_type)
118
235
  open3_mock = MiniTest::Mock.new
119
236
  cmake_script = <<~SCRIPT
120
- echo "The following generators are available on this platform (* marks default):"
121
- echo "* #{generator_type} Makefiles = Generates standard #{generator_type.upcase} makefiles."
122
- SCRIPT
237
+ echo "The following generators are available on this platform (* marks default):"
238
+ echo "* #{generator_type} Makefiles = Generates standard #{generator_type.upcase} makefiles."
239
+ SCRIPT
123
240
 
124
241
  exit_status = MiniTest::Mock.new
125
242
  exit_status.expect(:success?, true)
@@ -0,0 +1,159 @@
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, :include_path, :lib_path
7
+
8
+ LIBXML_PCP = File.join(__dir__, "assets", "pkgconf", "libxml2")
9
+ LIBXSLT_PCP = File.join(__dir__, "assets", "pkgconf", "libxslt")
10
+
11
+ def setup
12
+ super
13
+
14
+ @save_env = %w[PATH CPATH LIBRARY_PATH LDFLAGS PKG_CONFIG_PATH].inject({}) do |env, var|
15
+ env.update(var => ENV[var])
16
+ end
17
+ $INCFLAGS = "-I/xxx"
18
+ $LIBPATH = ["xxx"]
19
+ $CFLAGS = "-xxx"
20
+ $CXXFLAGS = "-xxx"
21
+ $libs = "-lxxx"
22
+
23
+ FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
24
+
25
+ @recipe = MiniPortile.new("libfoo", "1.0.0").tap do |recipe|
26
+ recipe.logger = StringIO.new
27
+ end
28
+ @include_path = File.join(@recipe.path, "include")
29
+ @lib_path = File.join(@recipe.path, "lib")
30
+ end
31
+
32
+ def teardown
33
+ FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files
34
+
35
+ $INCFLAGS = ""
36
+ $LIBPATH = []
37
+ $CFLAGS = ""
38
+ $CXXFLAGS = ""
39
+ $libs = ""
40
+ @save_env.each do |var, val|
41
+ ENV[var] = val
42
+ end
43
+
44
+ super
45
+ end
46
+
47
+ def test_mkmf_config_recipe_LIBPATH_global_lib_dir_does_not_exist
48
+ recipe.mkmf_config
49
+
50
+ refute_includes($LIBPATH, lib_path)
51
+ refute_includes($libs.split, "-lfoo")
52
+ end
53
+
54
+ def test_mkmf_config_recipe_LIBPATH_global
55
+ FileUtils.mkdir_p(lib_path)
56
+
57
+ recipe.mkmf_config
58
+
59
+ assert_includes($LIBPATH, lib_path)
60
+ assert_operator($LIBPATH.index(lib_path), :<, $LIBPATH.index("xxx")) # prepend
61
+
62
+ assert_includes($libs.split, "-lfoo") # note the recipe name is "libfoo"
63
+ assert_match(%r{-lxxx.*-lfoo}, $libs) # append
64
+ end
65
+
66
+ def test_mkmf_config_recipe_INCFLAGS_global_include_dir_does_not_exist
67
+ recipe.mkmf_config
68
+
69
+ refute_includes($INCFLAGS.split, "-I#{include_path}")
70
+ end
71
+
72
+ def test_mkmf_config_recipe_INCFLAGS_global
73
+ FileUtils.mkdir_p(include_path)
74
+
75
+ recipe.mkmf_config
76
+
77
+ assert_includes($INCFLAGS.split, "-I#{include_path}")
78
+ assert_match(%r{-I#{include_path}.*-I/xxx}, $INCFLAGS) # prepend
79
+ end
80
+
81
+ def test_mkmf_config_pkgconf_does_not_exist
82
+ assert_raises(ArgumentError) do
83
+ recipe.mkmf_config(pkg: "foo")
84
+ end
85
+ end
86
+
87
+ def test_mkmf_config_pkgconf_LIBPATH_global
88
+ # can't get the pkgconf utility to install on windows with ruby 2.3 in CI
89
+ skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
90
+
91
+ recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP)
92
+
93
+ assert_includes($LIBPATH, "/foo/libxml2/2.11.5/lib")
94
+ assert_operator($LIBPATH.index("/foo/libxml2/2.11.5/lib"), :<, $LIBPATH.index("xxx")) # prepend
95
+
96
+ assert_includes($libs.split, "-lxml2")
97
+ assert_match(%r{-lxxx.*-lxml2}, $libs) # append
98
+ end
99
+
100
+ def test_mkmf_config_pkgconf_CFLAGS_global
101
+ # can't get the pkgconf utility to install on windows with ruby 2.3 in CI
102
+ skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
103
+
104
+ recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP)
105
+
106
+ assert_includes($INCFLAGS.split, "-I/foo/libxml2/2.11.5/include/libxml2")
107
+ assert_match(%r{-I/foo/libxml2/2.11.5/include/libxml2.*-I/xxx}, $INCFLAGS) # prepend
108
+
109
+ assert_includes($CFLAGS.split, "-ggdb3")
110
+ assert_match(%r{-xxx.*-ggdb3}, $CFLAGS) # prepend
111
+
112
+ assert_includes($CXXFLAGS.split, "-ggdb3")
113
+ assert_match(%r{-xxx.*-ggdb3}, $CXXFLAGS) # prepend
114
+ end
115
+
116
+ def test_mkmf_config_pkgconf_path_accumulation
117
+ # can't get the pkgconf utility to install on windows with ruby 2.3 in CI
118
+ skip if MiniPortile.windows? && RUBY_VERSION < "2.4"
119
+
120
+ (ENV["PKG_CONFIG_PATH"] || "").split(File::PATH_SEPARATOR).tap do |pcpaths|
121
+ refute_includes(pcpaths, LIBXML_PCP)
122
+ refute_includes(pcpaths, LIBXSLT_PCP)
123
+ end
124
+
125
+ recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP)
126
+
127
+ ENV["PKG_CONFIG_PATH"].split(File::PATH_SEPARATOR).tap do |pcpaths|
128
+ assert_includes(pcpaths, LIBXML_PCP)
129
+ refute_includes(pcpaths, LIBXSLT_PCP)
130
+ end
131
+
132
+ recipe.mkmf_config(pkg: "libxslt", dir: LIBXSLT_PCP)
133
+
134
+ ENV["PKG_CONFIG_PATH"].split(File::PATH_SEPARATOR).tap do |pcpaths|
135
+ assert_includes(pcpaths, LIBXML_PCP)
136
+ assert_includes(pcpaths, LIBXSLT_PCP)
137
+ end
138
+
139
+ recipe.mkmf_config(pkg: "libexslt", dir: LIBXSLT_PCP)
140
+
141
+ $INCFLAGS.split.tap do |incflags|
142
+ assert_includes(incflags, "-I/foo/libxml2/2.11.5/include/libxml2")
143
+ assert_includes(incflags, "-I/foo/libxslt/1.1.38/include")
144
+ end
145
+ assert_includes($LIBPATH, "/foo/libxml2/2.11.5/lib")
146
+ assert_includes($LIBPATH, "/foo/libxslt/1.1.38/lib")
147
+ assert_includes($LIBPATH, "/foo/zlib/1.3/lib") # from `--static`
148
+ $CFLAGS.split.tap do |cflags|
149
+ assert_includes(cflags, "-ggdb3")
150
+ assert_includes(cflags, "-Wno-deprecated-enum-enum-conversion")
151
+ end
152
+ $libs.split.tap do |libflags|
153
+ assert_includes(libflags, "-lxml2")
154
+ assert_includes(libflags, "-lxslt")
155
+ assert_includes(libflags, "-lexslt")
156
+ assert_includes(libflags, "-lz") # from `--static`
157
+ end
158
+ end
159
+ 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.3
4
+ version: 2.8.5.rc1
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: 2023-07-18 00:00:00.000000000 Z
13
+ date: 2023-09-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -123,16 +123,21 @@ files:
123
123
  - test/assets/gpg-fixtures/data.asc
124
124
  - test/assets/gpg-fixtures/data.invalid.asc
125
125
  - test/assets/patch 1.diff
126
+ - test/assets/pkgconf/libxml2/libxml-2.0.pc
127
+ - test/assets/pkgconf/libxslt/libexslt.pc
128
+ - test/assets/pkgconf/libxslt/libxslt.pc
126
129
  - test/assets/test mini portile-1.0.0/configure
127
130
  - test/assets/test-cmake-1.0/CMakeLists.txt
128
131
  - test/assets/test-cmake-1.0/hello.c
129
132
  - test/assets/test-download-archive.tar.gz
130
133
  - test/helper.rb
134
+ - test/test_activate.rb
131
135
  - test/test_cmake.rb
132
136
  - test/test_cook.rb
133
137
  - test/test_digest.rb
134
138
  - test/test_download.rb
135
139
  - test/test_execute.rb
140
+ - test/test_mkmf_config.rb
136
141
  - test/test_proxy.rb
137
142
  homepage: https://github.com/flavorjones/mini_portile
138
143
  licenses:
@@ -149,11 +154,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
154
  version: 2.3.0
150
155
  required_rubygems_version: !ruby/object:Gem::Requirement
151
156
  requirements:
152
- - - ">="
157
+ - - ">"
153
158
  - !ruby/object:Gem::Version
154
- version: '0'
159
+ version: 1.3.1
155
160
  requirements: []
156
- rubygems_version: 3.4.10
161
+ rubygems_version: 3.4.19
157
162
  signing_key:
158
163
  specification_version: 4
159
164
  summary: Simplistic port-like solution for developers
@@ -163,14 +168,19 @@ test_files:
163
168
  - test/assets/gpg-fixtures/data.asc
164
169
  - test/assets/gpg-fixtures/data.invalid.asc
165
170
  - test/assets/patch 1.diff
171
+ - test/assets/pkgconf/libxml2/libxml-2.0.pc
172
+ - test/assets/pkgconf/libxslt/libexslt.pc
173
+ - test/assets/pkgconf/libxslt/libxslt.pc
166
174
  - test/assets/test mini portile-1.0.0/configure
167
175
  - test/assets/test-cmake-1.0/CMakeLists.txt
168
176
  - test/assets/test-cmake-1.0/hello.c
169
177
  - test/assets/test-download-archive.tar.gz
170
178
  - test/helper.rb
179
+ - test/test_activate.rb
171
180
  - test/test_cmake.rb
172
181
  - test/test_cook.rb
173
182
  - test/test_digest.rb
174
183
  - test/test_download.rb
175
184
  - test/test_execute.rb
185
+ - test/test_mkmf_config.rb
176
186
  - test/test_proxy.rb