rubygems-requirements-system 0.0.3 → 0.0.4
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/README.md +28 -25
- data/Rakefile +31 -0
- data/doc/text/news.md +11 -0
- data/lib/rubygems-requirements-system/installer.rb +9 -2
- data/lib/rubygems-requirements-system/pkg-config.rb +682 -0
- data/lib/rubygems-requirements-system/version.rb +1 -1
- data/lib/rubygems_plugin.rb +2 -2
- data/plugins.rb +17 -0
- metadata +5 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0271d5e7218e5a925f41e5d890ad4eed1194572fbb2a140578df4bef80bbc666
|
4
|
+
data.tar.gz: 9631386ad89e63d5534cc0e5e463aa7231f777ec3c3738c80a9dbcbedd94d779
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3d2ac2e6e04d60114008135395b83c563251810bd5157af728dd0fd28dc1100610a7621895400f298f9ed2747122c21483ea3f43e4447ad92cde70aba7ce15f
|
7
|
+
data.tar.gz: b0679db240aa4a3c1feb263da1e36f17d2a984b7e29431e4d0159c1cfce3642e40d8498d99da652001789ead7965ee6decbbd073aecb4050bbde7c4fcf950867
|
data/README.md
CHANGED
@@ -40,21 +40,33 @@ developers and users. If we can reduce maintenance costs for
|
|
40
40
|
developers, developers can focus on new features and bug fixes than
|
41
41
|
releases.
|
42
42
|
|
43
|
-
## Usage
|
43
|
+
## Usage for users
|
44
44
|
|
45
|
-
|
45
|
+
If you're using Bundler, add the following line to your `Gemfile`:
|
46
46
|
|
47
47
|
```ruby
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
plugin "rubygems-requirements-system"
|
49
|
+
```
|
50
|
+
|
51
|
+
If you're not using Bundler, install `rubygems-requirements-system`:
|
52
|
+
|
53
|
+
```bash
|
54
|
+
gem install rubygems-requirements-system
|
53
55
|
```
|
54
56
|
|
57
|
+
## Usage for developers
|
58
|
+
|
59
|
+
Add dependency information to `Gem::Specification#requirements`.
|
60
|
+
|
55
61
|
### Basic usage
|
56
62
|
|
57
|
-
|
63
|
+
In most cases, you can just specify the followings:
|
64
|
+
|
65
|
+
1. Package ID
|
66
|
+
2. Platform ID
|
67
|
+
3. Package name on the platform
|
68
|
+
|
69
|
+
See the following example:
|
58
70
|
|
59
71
|
```ruby
|
60
72
|
Gem::Specification.new do |spec|
|
@@ -231,11 +243,11 @@ You can start another repository metadata by starting `id` metadata
|
|
231
243
|
for another repository:
|
232
244
|
|
233
245
|
```ruby
|
234
|
-
spec.requirements << "system: #{package}: #{platform}: repository: id: repository1
|
246
|
+
spec.requirements << "system: #{package}: #{platform}: repository: id: repository1"
|
235
247
|
spec.requirements << "system: #{package}: #{platform}: repository: #{key1_1}: #{value1_1}"
|
236
248
|
spec.requirements << "system: #{package}: #{platform}: repository: #{key1_2}: #{value1_2}"
|
237
249
|
# ...
|
238
|
-
spec.requirements << "system: #{package}: #{platform}: repository: id: repository2
|
250
|
+
spec.requirements << "system: #{package}: #{platform}: repository: id: repository2"
|
239
251
|
spec.requirements << "system: #{package}: #{platform}: repository: #{key2_1}: #{value2_1}"
|
240
252
|
spec.requirements << "system: #{package}: #{platform}: repository: #{key2_2}: #{value2_2}"
|
241
253
|
# ...
|
@@ -328,30 +340,21 @@ end
|
|
328
340
|
|
329
341
|
## Configurations
|
330
342
|
|
331
|
-
###
|
343
|
+
### Disable
|
332
344
|
|
333
|
-
If you
|
334
|
-
|
345
|
+
If you want to install system packages automatically, you need to
|
346
|
+
install rubygems-requirements-system gem explicitly (opt-in). You can
|
347
|
+
disable rubygems-requirements-system gem even when you install this
|
348
|
+
explicitly:
|
335
349
|
|
336
350
|
1. Set `RUBYGEMS_REQUIREMENTS_SYSTEM=false`
|
337
351
|
2. Add the following configuration to `~/.gemrc`:
|
338
352
|
|
339
353
|
```yaml
|
340
354
|
requirements_system:
|
341
|
-
enabled:
|
355
|
+
enabled: false
|
342
356
|
```
|
343
357
|
|
344
|
-
## Requirements
|
345
|
-
|
346
|
-
RubyGems 3.4.14 or later is required. RubyGems can load installed
|
347
|
-
plugin immediately since 3.4.14. Ruby 3.2.3 or later ships RubyGems
|
348
|
-
3.4.14 or later.
|
349
|
-
|
350
|
-
If `gem install glib2` installs rubygems-requirements-system gem as a
|
351
|
-
dependency, old RubyGems doesn't use a RubyGems plugin in
|
352
|
-
rubygems-requirements-system gem while installing glib2 gem. So glib2
|
353
|
-
gem dependencies aren't installed automatically.
|
354
|
-
|
355
358
|
## History
|
356
359
|
|
357
360
|
This is based on
|
data/Rakefile
CHANGED
@@ -16,6 +16,8 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
require "bundler/gem_helper"
|
19
|
+
require "json"
|
20
|
+
require "open-uri"
|
19
21
|
|
20
22
|
base_dir = File.dirname(__FILE__)
|
21
23
|
helper = Bundler::GemHelper.new(base_dir)
|
@@ -24,6 +26,35 @@ def helper.version_tag
|
|
24
26
|
end
|
25
27
|
helper.install
|
26
28
|
|
29
|
+
def github_api(path)
|
30
|
+
URI("https://api.github.com/#{path}").open do |response|
|
31
|
+
JSON.parse(response.read)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def github_content(repository, tag, path, &block)
|
36
|
+
uri = "https://raw.githubusercontent.com/#{repository}/" +
|
37
|
+
"refs/tags/#{tag}/#{path}"
|
38
|
+
URI(uri).open(&block)
|
39
|
+
end
|
40
|
+
|
41
|
+
namespace :vendor do
|
42
|
+
namespace :pkg_config do
|
43
|
+
desc "Update vendored pkg-config"
|
44
|
+
task :update do
|
45
|
+
latest = github_api("repos/ruby-gnome/pkg-config/releases/latest")
|
46
|
+
github_content("ruby-gnome/pkg-config",
|
47
|
+
latest["tag_name"],
|
48
|
+
"lib/pkg-config.rb") do |response|
|
49
|
+
output_path = "lib/rubygems-requirements-system/pkg-config.rb"
|
50
|
+
File.open(output_path, "w") do |output|
|
51
|
+
IO.copy_stream(response, output)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
27
58
|
release_task = Rake.application["release"]
|
28
59
|
# We use Trusted Publishing.
|
29
60
|
release_task.prerequisites.delete("build")
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 0.0.4 - 2025-03-05
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Bundled `pkg-config` gem.
|
8
|
+
|
9
|
+
* Changed to opt-in style. Each user must install this gem
|
10
|
+
explicitly.
|
11
|
+
|
12
|
+
* Added support for Bundler.
|
13
|
+
|
3
14
|
## 0.0.3 - 2025-01-13
|
4
15
|
|
5
16
|
### Improvements
|
@@ -15,14 +15,21 @@
|
|
15
15
|
|
16
16
|
require "shellwords"
|
17
17
|
|
18
|
-
require "pkg-config"
|
19
|
-
|
20
18
|
require_relative "version"
|
21
19
|
|
22
20
|
require_relative "platform"
|
23
21
|
require_relative "requirements-parser"
|
24
22
|
|
25
23
|
module RubyGemsRequirementsSystem
|
24
|
+
pkg_config_rb = File.join(__dir__, "pkg-config.rb")
|
25
|
+
load(pkg_config_rb, self)
|
26
|
+
unless const_defined?(:PKGConfig)
|
27
|
+
# Ruby < 3.1
|
28
|
+
File.open(pkg_config_rb) do |pkg_config_rb_file|
|
29
|
+
module_eval(pkg_config_rb_file.read, pkg_config_rb)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
26
33
|
class Installer
|
27
34
|
include Gem::UserInteraction
|
28
35
|
|
@@ -0,0 +1,682 @@
|
|
1
|
+
# Copyright (C) 2008-2025 Sutou Kouhei <kou@cozmixng.org>
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License as published by the Free Software Foundation; either
|
6
|
+
# version 2.1 of the License, or (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
+
# Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
14
|
+
# License along with this library; if not, write to the Free Software
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
|
+
|
17
|
+
require "pathname"
|
18
|
+
require "rbconfig"
|
19
|
+
require "shellwords"
|
20
|
+
|
21
|
+
module PKGConfig
|
22
|
+
VERSION = "1.6.0"
|
23
|
+
|
24
|
+
@@paths = []
|
25
|
+
@@override_variables = {}
|
26
|
+
|
27
|
+
module_function
|
28
|
+
def add_path(path)
|
29
|
+
@@paths << path
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_override_variable(key, value)
|
33
|
+
@@override_variables[key] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def msvc?
|
37
|
+
/mswin/.match(RUBY_PLATFORM) and /^cl\b/.match(RbConfig::CONFIG["CC"])
|
38
|
+
end
|
39
|
+
|
40
|
+
def package_config(package)
|
41
|
+
PackageConfig.new(package,
|
42
|
+
:msvc_syntax => msvc?,
|
43
|
+
:override_variables => @@override_variables,
|
44
|
+
:paths => @@paths)
|
45
|
+
end
|
46
|
+
|
47
|
+
def exist?(pkg)
|
48
|
+
package_config(pkg).exist?
|
49
|
+
end
|
50
|
+
|
51
|
+
def libs(pkg)
|
52
|
+
package_config(pkg).libs
|
53
|
+
end
|
54
|
+
|
55
|
+
def libs_only_l(pkg)
|
56
|
+
package_config(pkg).libs_only_l
|
57
|
+
end
|
58
|
+
|
59
|
+
def libs_only_L(pkg)
|
60
|
+
package_config(pkg).libs_only_L
|
61
|
+
end
|
62
|
+
|
63
|
+
def cflags(pkg)
|
64
|
+
package_config(pkg).cflags
|
65
|
+
end
|
66
|
+
|
67
|
+
def cflags_only_I(pkg)
|
68
|
+
package_config(pkg).cflags_only_I
|
69
|
+
end
|
70
|
+
|
71
|
+
def cflags_only_other(pkg)
|
72
|
+
package_config(pkg).cflags_only_other
|
73
|
+
end
|
74
|
+
|
75
|
+
def modversion(pkg)
|
76
|
+
package_config(pkg).version
|
77
|
+
end
|
78
|
+
|
79
|
+
def description(pkg)
|
80
|
+
package_config(pkg).description
|
81
|
+
end
|
82
|
+
|
83
|
+
def variable(pkg, name)
|
84
|
+
package_config(pkg).variable(name)
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_version?(pkg, major=0, minor=0, micro=0)
|
88
|
+
return false unless exist?(pkg)
|
89
|
+
ver = modversion(pkg).split(".").collect {|item| item.to_i}
|
90
|
+
(0..2).each {|i| ver[i] = 0 unless ver[i]}
|
91
|
+
|
92
|
+
(ver[0] > major ||
|
93
|
+
(ver[0] == major && ver[1] > minor) ||
|
94
|
+
(ver[0] == major && ver[1] == minor &&
|
95
|
+
ver[2] >= micro))
|
96
|
+
end
|
97
|
+
|
98
|
+
def have_package(pkg, major=nil, minor=0, micro=0)
|
99
|
+
message = "#{pkg}"
|
100
|
+
unless major.nil?
|
101
|
+
message << " version (>= #{major}.#{minor}.#{micro})"
|
102
|
+
end
|
103
|
+
major ||= 0
|
104
|
+
result = checking_for(checking_message(message), "%s") do
|
105
|
+
if check_version?(pkg, major, minor, micro)
|
106
|
+
"yes (#{modversion(pkg)})"
|
107
|
+
else
|
108
|
+
if exist?(pkg)
|
109
|
+
"no (#{modversion(pkg)})"
|
110
|
+
else
|
111
|
+
"no (nonexistent)"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
enough_version = result.start_with?("yes")
|
116
|
+
if enough_version
|
117
|
+
libraries = libs_only_l(pkg)
|
118
|
+
dldflags = libs(pkg)
|
119
|
+
dldflags = (Shellwords.shellwords(dldflags) -
|
120
|
+
Shellwords.shellwords(libraries))
|
121
|
+
dldflags = dldflags.map {|s| /\s/ =~ s ? "\"#{s}\"" : s }.join(" ")
|
122
|
+
$libs += " " + libraries
|
123
|
+
if /mswin/ =~ RUBY_PLATFORM
|
124
|
+
$DLDFLAGS += " " + dldflags
|
125
|
+
else
|
126
|
+
$LDFLAGS += " " + dldflags
|
127
|
+
end
|
128
|
+
$CFLAGS += " " + cflags_only_other(pkg)
|
129
|
+
if defined?($CXXFLAGS)
|
130
|
+
$CXXFLAGS += " " + cflags_only_other(pkg)
|
131
|
+
end
|
132
|
+
$INCFLAGS += " " + cflags_only_I(pkg)
|
133
|
+
end
|
134
|
+
enough_version
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class PackageConfig
|
139
|
+
class Error < StandardError
|
140
|
+
end
|
141
|
+
|
142
|
+
class NotFoundError < Error
|
143
|
+
end
|
144
|
+
|
145
|
+
SEPARATOR = File::PATH_SEPARATOR
|
146
|
+
|
147
|
+
class << self
|
148
|
+
@native_pkg_config = nil
|
149
|
+
def native_pkg_config
|
150
|
+
@native_pkg_config ||= guess_native_pkg_config
|
151
|
+
end
|
152
|
+
|
153
|
+
@native_pkg_config_prefix = nil
|
154
|
+
def native_pkg_config_prefix
|
155
|
+
@native_pkg_config_prefix ||= compute_native_pkg_config_prefix
|
156
|
+
end
|
157
|
+
|
158
|
+
@default_path = nil
|
159
|
+
def default_path
|
160
|
+
@default_path ||= compute_default_path
|
161
|
+
end
|
162
|
+
|
163
|
+
@custom_override_variables = nil
|
164
|
+
def custom_override_variables
|
165
|
+
@custom_override_variables ||= with_config("override-variables", "")
|
166
|
+
end
|
167
|
+
|
168
|
+
def clear_configure_args_cache
|
169
|
+
@native_pkg_config = nil
|
170
|
+
@native_pkg_config_prefix = nil
|
171
|
+
@default_path = nil
|
172
|
+
@custom_override_variables = nil
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
def with_config(config, default=nil)
|
177
|
+
if defined?(super)
|
178
|
+
super
|
179
|
+
else
|
180
|
+
default
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def guess_native_pkg_config
|
185
|
+
exeext = RbConfig::CONFIG["EXEEXT"]
|
186
|
+
candidates = [
|
187
|
+
with_config("pkg-config"),
|
188
|
+
ENV["PKG_CONFIG"],
|
189
|
+
"pkgconf#{exeext}",
|
190
|
+
"pkg-config#{exeext}",
|
191
|
+
].compact
|
192
|
+
candidates.each do |pkg_config|
|
193
|
+
pkg_config = Pathname.new(pkg_config)
|
194
|
+
return pkg_config if pkg_config.absolute? and pkg_config.exist?
|
195
|
+
unless pkg_config.absolute?
|
196
|
+
found_pkg_config = search_executable_from_path(pkg_config)
|
197
|
+
return found_pkg_config if found_pkg_config
|
198
|
+
end
|
199
|
+
unless pkg_config.absolute?
|
200
|
+
found_pkg_config = search_pkg_config_by_dln_find_exe(pkg_config)
|
201
|
+
return found_pkg_config if found_pkg_config
|
202
|
+
end
|
203
|
+
end
|
204
|
+
Pathname.new(candidates[0])
|
205
|
+
end
|
206
|
+
|
207
|
+
def search_executable_from_path(name)
|
208
|
+
(ENV["PATH"] || "").split(SEPARATOR).each do |path|
|
209
|
+
try_name = Pathname(path) + name
|
210
|
+
return try_name if try_name.executable?
|
211
|
+
end
|
212
|
+
nil
|
213
|
+
end
|
214
|
+
|
215
|
+
def search_pkg_config_by_dln_find_exe(pkg_config)
|
216
|
+
begin
|
217
|
+
require "dl/import"
|
218
|
+
rescue LoadError
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
dln = Module.new
|
222
|
+
dln.module_eval do
|
223
|
+
if DL.const_defined?(:Importer)
|
224
|
+
extend DL::Importer
|
225
|
+
else
|
226
|
+
extend DL::Importable
|
227
|
+
end
|
228
|
+
begin
|
229
|
+
dlload RbConfig::CONFIG["LIBRUBY"]
|
230
|
+
rescue RuntimeError
|
231
|
+
return nil if $!.message == "unknown error"
|
232
|
+
return nil if /: image not found\z/ =~ $!.message
|
233
|
+
raise
|
234
|
+
rescue DL::DLError
|
235
|
+
return nil
|
236
|
+
end
|
237
|
+
begin
|
238
|
+
extern "const char *dln_find_exe(const char *, const char *)"
|
239
|
+
rescue DL::DLError
|
240
|
+
return nil
|
241
|
+
end
|
242
|
+
end
|
243
|
+
path = dln.dln_find_exe(pkg_config.to_s, nil)
|
244
|
+
if path.nil? or path.size.zero?
|
245
|
+
nil
|
246
|
+
else
|
247
|
+
Pathname(path.to_s)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def compute_native_pkg_config_prefix
|
252
|
+
pkg_config = native_pkg_config
|
253
|
+
return nil unless pkg_config.absolute?
|
254
|
+
return nil unless pkg_config.exist?
|
255
|
+
|
256
|
+
pkg_config_prefix = pkg_config.parent.parent
|
257
|
+
if File::ALT_SEPARATOR
|
258
|
+
normalized_pkg_config_prefix =
|
259
|
+
pkg_config_prefix.to_s.split(File::ALT_SEPARATOR).join(File::SEPARATOR)
|
260
|
+
Pathname(normalized_pkg_config_prefix)
|
261
|
+
else
|
262
|
+
pkg_config_prefix
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def compute_default_path
|
267
|
+
default_paths = nil
|
268
|
+
if native_pkg_config
|
269
|
+
pc_path = run_command(native_pkg_config.to_s,
|
270
|
+
"--variable=pc_path",
|
271
|
+
"pkg-config")
|
272
|
+
if pc_path
|
273
|
+
default_paths = pc_path.strip.split(SEPARATOR)
|
274
|
+
default_paths = nil if default_paths.empty?
|
275
|
+
end
|
276
|
+
end
|
277
|
+
if default_paths.nil?
|
278
|
+
arch_depended_path = Dir.glob("/usr/lib/*/pkgconfig")
|
279
|
+
default_paths = []
|
280
|
+
pkg_config_prefix = native_pkg_config_prefix
|
281
|
+
if pkg_config_prefix
|
282
|
+
pkg_config_arch_depended_paths =
|
283
|
+
Dir.glob((pkg_config_prefix + "lib/*/pkgconfig").to_s)
|
284
|
+
default_paths.concat(pkg_config_arch_depended_paths)
|
285
|
+
default_paths << (pkg_config_prefix + "lib64/pkgconfig").to_s
|
286
|
+
default_paths << (pkg_config_prefix + "libx32/pkgconfig").to_s
|
287
|
+
default_paths << (pkg_config_prefix + "lib/pkgconfig").to_s
|
288
|
+
default_paths << (pkg_config_prefix + "libdata/pkgconfig").to_s
|
289
|
+
default_paths << (pkg_config_prefix + "share/pkgconfig").to_s
|
290
|
+
end
|
291
|
+
conda_prefix = ENV["CONDA_PREFIX"]
|
292
|
+
if conda_prefix
|
293
|
+
default_paths << File.join(conda_prefix, "lib", "pkgconfig")
|
294
|
+
default_paths << File.join(conda_prefix, "share", "pkgconfig")
|
295
|
+
end
|
296
|
+
default_paths << "/usr/local/lib64/pkgconfig"
|
297
|
+
default_paths << "/usr/local/libx32/pkgconfig"
|
298
|
+
default_paths << "/usr/local/lib/pkgconfig"
|
299
|
+
default_paths << "/usr/local/libdata/pkgconfig"
|
300
|
+
default_paths << "/usr/local/share/pkgconfig"
|
301
|
+
default_paths << "/opt/local/lib/pkgconfig"
|
302
|
+
default_paths.concat(arch_depended_path)
|
303
|
+
default_paths << "/usr/lib64/pkgconfig"
|
304
|
+
default_paths << "/usr/libx32/pkgconfig"
|
305
|
+
default_paths << "/usr/lib/pkgconfig"
|
306
|
+
default_paths << "/usr/libdata/pkgconfig"
|
307
|
+
default_paths << "/usr/X11R6/lib/pkgconfig"
|
308
|
+
default_paths << "/usr/X11R6/share/pkgconfig"
|
309
|
+
default_paths << "/usr/X11/lib/pkgconfig"
|
310
|
+
default_paths << "/opt/X11/lib/pkgconfig"
|
311
|
+
default_paths << "/usr/share/pkgconfig"
|
312
|
+
end
|
313
|
+
if Object.const_defined?(:RubyInstaller)
|
314
|
+
mingw_bin_path = RubyInstaller::Runtime.msys2_installation.mingw_bin_path
|
315
|
+
mingw_pkgconfig_path = Pathname.new(mingw_bin_path) + "../lib/pkgconfig"
|
316
|
+
default_paths.unshift(mingw_pkgconfig_path.cleanpath.to_s)
|
317
|
+
end
|
318
|
+
libdir = ENV["PKG_CONFIG_LIBDIR"]
|
319
|
+
default_paths.unshift(libdir) if libdir
|
320
|
+
|
321
|
+
paths = []
|
322
|
+
if /-darwin\d[\d\.]*\z/ =~ RUBY_PLATFORM and
|
323
|
+
/\A(\d+\.\d+)/ =~ run_command("sw_vers", "-productVersion")
|
324
|
+
mac_os_version = $1
|
325
|
+
homebrew_repository_candidates = []
|
326
|
+
if pkg_config_prefix
|
327
|
+
brew_path = pkg_config_prefix + "bin" + "brew"
|
328
|
+
if brew_path.exist?
|
329
|
+
homebrew_repository = run_command(brew_path.to_s, "--repository")
|
330
|
+
if homebrew_repository
|
331
|
+
homebrew_repository_candidates <<
|
332
|
+
Pathname.new(homebrew_repository.strip)
|
333
|
+
end
|
334
|
+
else
|
335
|
+
homebrew_repository_candidates << pkg_config_prefix + "Homebrew"
|
336
|
+
homebrew_repository_candidates << pkg_config_prefix
|
337
|
+
end
|
338
|
+
end
|
339
|
+
brew = search_executable_from_path("brew")
|
340
|
+
if brew
|
341
|
+
homebrew_repository = run_command("brew", "--repository")
|
342
|
+
if homebrew_repository
|
343
|
+
homebrew_repository_candidates <<
|
344
|
+
Pathname(homebrew_repository.to_s)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
homebrew_repository_candidates.uniq.each do |candidate|
|
348
|
+
pkgconfig_base_path = candidate + "Library/Homebrew/os/mac/pkgconfig"
|
349
|
+
path = pkgconfig_base_path + mac_os_version
|
350
|
+
unless path.exist?
|
351
|
+
path = pkgconfig_base_path + mac_os_version.gsub(/\.\d+\z/, "")
|
352
|
+
end
|
353
|
+
paths << path.to_s if path.exist?
|
354
|
+
end
|
355
|
+
end
|
356
|
+
paths.concat(default_paths)
|
357
|
+
paths.join(SEPARATOR)
|
358
|
+
end
|
359
|
+
|
360
|
+
def run_command(*command_line)
|
361
|
+
IO.pipe do |input, output|
|
362
|
+
begin
|
363
|
+
pid = spawn(*command_line,
|
364
|
+
out: output,
|
365
|
+
err: File::NULL)
|
366
|
+
output.close
|
367
|
+
_, status = Process.waitpid2(pid)
|
368
|
+
return nil unless status.success?
|
369
|
+
input.read
|
370
|
+
rescue SystemCallError
|
371
|
+
nil
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
attr_reader :name
|
378
|
+
attr_reader :paths
|
379
|
+
attr_accessor :msvc_syntax
|
380
|
+
def initialize(name, options={})
|
381
|
+
if Pathname(name).absolute?
|
382
|
+
@pc_path = name
|
383
|
+
@path_position = 0
|
384
|
+
@name = File.basename(@pc_path, ".*")
|
385
|
+
else
|
386
|
+
@pc_path = nil
|
387
|
+
@path_position = nil
|
388
|
+
@name = name
|
389
|
+
end
|
390
|
+
@options = options
|
391
|
+
path = @options[:path] || ENV["PKG_CONFIG_PATH"]
|
392
|
+
@paths = [path, self.class.default_path].compact.join(SEPARATOR).split(SEPARATOR)
|
393
|
+
@paths.unshift(*(@options[:paths] || []))
|
394
|
+
@paths = normalize_paths(@paths)
|
395
|
+
@msvc_syntax = @options[:msvc_syntax]
|
396
|
+
@variables = @declarations = nil
|
397
|
+
override_variables = self.class.custom_override_variables
|
398
|
+
@override_variables = parse_override_variables(override_variables)
|
399
|
+
default_override_variables = @options[:override_variables] || {}
|
400
|
+
@override_variables = default_override_variables.merge(@override_variables)
|
401
|
+
end
|
402
|
+
|
403
|
+
def eql?(other)
|
404
|
+
other.is_a?(self.class) and @name == other.name
|
405
|
+
end
|
406
|
+
|
407
|
+
def hash
|
408
|
+
@name.hash
|
409
|
+
end
|
410
|
+
|
411
|
+
def exist?
|
412
|
+
not pc_path.nil?
|
413
|
+
end
|
414
|
+
|
415
|
+
def requires
|
416
|
+
parse_requires(declaration("Requires"))
|
417
|
+
end
|
418
|
+
|
419
|
+
def requires_private
|
420
|
+
parse_requires(declaration("Requires.private"))
|
421
|
+
end
|
422
|
+
|
423
|
+
def cflags
|
424
|
+
path_flags, other_flags = collect_cflags
|
425
|
+
(path_flags + other_flags).join(" ")
|
426
|
+
end
|
427
|
+
|
428
|
+
def cflags_only_I
|
429
|
+
collect_cflags[0].join(" ")
|
430
|
+
end
|
431
|
+
|
432
|
+
def cflags_only_other
|
433
|
+
collect_cflags[1].join(" ")
|
434
|
+
end
|
435
|
+
|
436
|
+
def libs
|
437
|
+
collect_libs.join(" ")
|
438
|
+
end
|
439
|
+
|
440
|
+
def libs_only_l
|
441
|
+
collect_libs.find_all do |arg|
|
442
|
+
if @msvc_syntax
|
443
|
+
arg.end_with?(".lib")
|
444
|
+
else
|
445
|
+
arg.start_with?("-l")
|
446
|
+
end
|
447
|
+
end.join(" ")
|
448
|
+
end
|
449
|
+
|
450
|
+
def libs_only_L
|
451
|
+
collect_libs.find_all do |arg|
|
452
|
+
if @msvc_syntax
|
453
|
+
arg.start_with?("/libpath:")
|
454
|
+
else
|
455
|
+
arg.start_with?("-L")
|
456
|
+
end
|
457
|
+
end.join(" ")
|
458
|
+
end
|
459
|
+
|
460
|
+
def version
|
461
|
+
declaration("Version")
|
462
|
+
end
|
463
|
+
|
464
|
+
def description
|
465
|
+
declaration("Description")
|
466
|
+
end
|
467
|
+
|
468
|
+
def variable(name)
|
469
|
+
parse_pc if @variables.nil?
|
470
|
+
expand_value(@override_variables[name] || @variables[name])
|
471
|
+
end
|
472
|
+
|
473
|
+
def declaration(name)
|
474
|
+
parse_pc if @declarations.nil?
|
475
|
+
expand_value(@declarations[name])
|
476
|
+
end
|
477
|
+
|
478
|
+
def pc_path
|
479
|
+
if @pc_path
|
480
|
+
return @pc_path if File.exist?(@pc_path)
|
481
|
+
else
|
482
|
+
@paths.each_with_index do |path, i|
|
483
|
+
_pc_path = File.join(path, "#{@name}.pc")
|
484
|
+
if File.exist?(_pc_path)
|
485
|
+
@path_position = i + 1
|
486
|
+
return _pc_path
|
487
|
+
end
|
488
|
+
end
|
489
|
+
end
|
490
|
+
nil
|
491
|
+
end
|
492
|
+
|
493
|
+
protected
|
494
|
+
def path_position
|
495
|
+
@path_position
|
496
|
+
end
|
497
|
+
|
498
|
+
def collect_requires(&block)
|
499
|
+
dependencies = {}
|
500
|
+
pending_packages = yield(self).collect {|name| self.class.new(name, @options)}
|
501
|
+
until pending_packages.empty?
|
502
|
+
package = pending_packages.shift
|
503
|
+
next if dependencies.key?(package)
|
504
|
+
dependencies[package] = true
|
505
|
+
targets = yield(package)
|
506
|
+
targets.each do |name|
|
507
|
+
require_package = self.class.new(name, @options)
|
508
|
+
pending_packages.push(require_package)
|
509
|
+
end
|
510
|
+
end
|
511
|
+
dependencies.keys
|
512
|
+
end
|
513
|
+
|
514
|
+
private
|
515
|
+
def collect_cflags
|
516
|
+
target_packages = [self, *all_required_packages]
|
517
|
+
cflags_set = []
|
518
|
+
target_packages.each do |package|
|
519
|
+
cflags_set << package.declaration("Cflags")
|
520
|
+
end
|
521
|
+
all_cflags = normalize_cflags(Shellwords.split(cflags_set.join(" ")))
|
522
|
+
path_flags, other_flags = all_cflags.partition {|flag| /\A-I/ =~ flag}
|
523
|
+
path_flags = path_flags.collect {|flag| normalize_path_flag(flag, "-I")}
|
524
|
+
path_flags = path_flags.reject do |flag|
|
525
|
+
flag == "-I/usr/include"
|
526
|
+
end
|
527
|
+
path_flags = path_flags.uniq
|
528
|
+
if @msvc_syntax
|
529
|
+
path_flags = path_flags.collect do |flag|
|
530
|
+
flag.gsub(/\A-I/, "/I")
|
531
|
+
end
|
532
|
+
end
|
533
|
+
[path_flags, other_flags]
|
534
|
+
end
|
535
|
+
|
536
|
+
def normalize_path_flag(path_flag, flag_option)
|
537
|
+
return path_flag unless /-mingw(?:32|-ucrt)\z/ === RUBY_PLATFORM
|
538
|
+
|
539
|
+
pkg_config_prefix = self.class.native_pkg_config_prefix
|
540
|
+
return path_flag unless pkg_config_prefix
|
541
|
+
|
542
|
+
mingw_dir = pkg_config_prefix.basename.to_s
|
543
|
+
path = path_flag.sub(/\A#{Regexp.escape(flag_option)}/, "")
|
544
|
+
path = path.sub(/\A\/#{Regexp.escape(mingw_dir)}/i) do
|
545
|
+
pkg_config_prefix.to_s
|
546
|
+
end
|
547
|
+
"#{flag_option}#{path}"
|
548
|
+
end
|
549
|
+
|
550
|
+
def normalize_cflags(cflags)
|
551
|
+
normalized_cflags = []
|
552
|
+
enumerator = cflags.to_enum
|
553
|
+
begin
|
554
|
+
loop do
|
555
|
+
cflag = enumerator.next
|
556
|
+
normalized_cflags << cflag.dup
|
557
|
+
case cflag
|
558
|
+
when "-I"
|
559
|
+
normalized_cflags.last << enumerator.next
|
560
|
+
end
|
561
|
+
end
|
562
|
+
rescue StopIteration
|
563
|
+
end
|
564
|
+
normalized_cflags
|
565
|
+
end
|
566
|
+
|
567
|
+
def collect_libs
|
568
|
+
target_packages = [*required_packages, self]
|
569
|
+
libs_set = []
|
570
|
+
target_packages.each do |package|
|
571
|
+
libs_set << package.declaration("Libs")
|
572
|
+
end
|
573
|
+
flags = split_lib_flags(libs_set.join(" "))
|
574
|
+
flags = flags.collect do |flag|
|
575
|
+
flag = normalize_path_flag(flag, "-L") if flag.start_with?("-L")
|
576
|
+
flag
|
577
|
+
end
|
578
|
+
flags = flags.reject do |flag|
|
579
|
+
/\A-L\/usr\/lib(?:64|x32)?\z/ =~ flag
|
580
|
+
end
|
581
|
+
flags = flags.uniq
|
582
|
+
if @msvc_syntax
|
583
|
+
flags = flags.collect do |flag|
|
584
|
+
if flag.start_with?("-L")
|
585
|
+
flag.gsub(/\A-L/, "/libpath:")
|
586
|
+
elsif flag.start_with?("-l")
|
587
|
+
"#{flag[2..-1]}.lib"
|
588
|
+
else
|
589
|
+
flag
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|
593
|
+
flags
|
594
|
+
end
|
595
|
+
|
596
|
+
def split_lib_flags(libs_command_line)
|
597
|
+
all_flags = {}
|
598
|
+
flags = []
|
599
|
+
in_option = false
|
600
|
+
libs_command_line.gsub(/-([Ll]) /, "\\1").split.each do |arg|
|
601
|
+
if in_option
|
602
|
+
flags << arg
|
603
|
+
in_option = false
|
604
|
+
else
|
605
|
+
case arg
|
606
|
+
when /-[lL]/
|
607
|
+
next if all_flags.key?(arg)
|
608
|
+
all_flags[arg] = true
|
609
|
+
flags << arg
|
610
|
+
in_option = true
|
611
|
+
else
|
612
|
+
flags << arg
|
613
|
+
end
|
614
|
+
end
|
615
|
+
end
|
616
|
+
flags
|
617
|
+
end
|
618
|
+
|
619
|
+
IDENTIFIER_RE = /[a-zA-Z\d_\.]+/
|
620
|
+
def parse_pc
|
621
|
+
raise NotFoundError, ".pc doesn't exist: <#{@name}>" unless exist?
|
622
|
+
@variables = {}
|
623
|
+
@declarations = {}
|
624
|
+
File.open(pc_path) do |input|
|
625
|
+
input.each_line do |line|
|
626
|
+
if line.dup.force_encoding("UTF-8").valid_encoding?
|
627
|
+
line.force_encoding("UTF-8")
|
628
|
+
end
|
629
|
+
line = line.gsub(/#.*/, "").strip
|
630
|
+
next if line.empty?
|
631
|
+
case line
|
632
|
+
when /^(#{IDENTIFIER_RE})\s*=\s*/
|
633
|
+
match = Regexp.last_match
|
634
|
+
@variables[match[1]] = match.post_match.strip
|
635
|
+
when /^(#{IDENTIFIER_RE})\s*:\s*/
|
636
|
+
match = Regexp.last_match
|
637
|
+
@declarations[match[1]] = match.post_match.strip
|
638
|
+
end
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
def parse_requires(requires)
|
644
|
+
return [] if requires.nil?
|
645
|
+
requires_without_version = requires.gsub(/(?:<|>|<=|>=|=)\s*[\d.a-zA-Z_-]+\s*/, "")
|
646
|
+
requires_without_version.split(/[,\s]+/)
|
647
|
+
end
|
648
|
+
|
649
|
+
def parse_override_variables(override_variables)
|
650
|
+
variables = {}
|
651
|
+
override_variables.split(",").each do |variable|
|
652
|
+
name, value = variable.split("=", 2)
|
653
|
+
variables[name] = value
|
654
|
+
end
|
655
|
+
variables
|
656
|
+
end
|
657
|
+
|
658
|
+
def expand_value(value)
|
659
|
+
return nil if value.nil?
|
660
|
+
value.gsub(/\$\{(#{IDENTIFIER_RE})\}/) do
|
661
|
+
variable($1)
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
def required_packages
|
666
|
+
collect_requires do |package|
|
667
|
+
package.requires
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
def all_required_packages
|
672
|
+
collect_requires do |package|
|
673
|
+
package.requires_private + package.requires
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
def normalize_paths(paths)
|
678
|
+
paths.reject do |path|
|
679
|
+
path.empty? or !File.exist?(path)
|
680
|
+
end
|
681
|
+
end
|
682
|
+
end
|
data/lib/rubygems_plugin.rb
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
|
16
16
|
require_relative "rubygems-requirements-system/installer"
|
17
17
|
|
18
|
-
Gem.pre_install do |
|
19
|
-
installer = RubyGemsRequirementsSystem::Installer.new(
|
18
|
+
Gem.pre_install do |gem_installer|
|
19
|
+
installer = RubyGemsRequirementsSystem::Installer.new(gem_installer.spec)
|
20
20
|
installer.install
|
21
21
|
end
|
data/plugins.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (C) 2025 Ruby-GNOME Project Team
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
# Do nothing. We can use this as a Bundler plugin by this file. If we
|
17
|
+
# use this as a Bundler plugin, Bundler install this before other gems.
|
metadata
CHANGED
@@ -1,28 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubygems-requirements-system
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sutou Kouhei
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
11
|
-
dependencies:
|
12
|
-
- !ruby/object:Gem::Dependency
|
13
|
-
name: pkg-config
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
15
|
-
requirements:
|
16
|
-
- - ">="
|
17
|
-
- !ruby/object:Gem::Version
|
18
|
-
version: '0'
|
19
|
-
type: :runtime
|
20
|
-
prerelease: false
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
-
requirements:
|
23
|
-
- - ">="
|
24
|
-
- !ruby/object:Gem::Version
|
25
|
-
version: '0'
|
10
|
+
date: 2025-03-05 00:00:00.000000000 Z
|
11
|
+
dependencies: []
|
26
12
|
description: |-
|
27
13
|
Users need to install system packages to install an extension library
|
28
14
|
that depends on system packages. It bothers users because users need to
|
@@ -46,6 +32,7 @@ files:
|
|
46
32
|
- lib/rubygems-requirements-system/installer.rb
|
47
33
|
- lib/rubygems-requirements-system/os-release.rb
|
48
34
|
- lib/rubygems-requirements-system/package.rb
|
35
|
+
- lib/rubygems-requirements-system/pkg-config.rb
|
49
36
|
- lib/rubygems-requirements-system/platform.rb
|
50
37
|
- lib/rubygems-requirements-system/platform/alpine-linux.rb
|
51
38
|
- lib/rubygems-requirements-system/platform/alt-linux.rb
|
@@ -70,6 +57,7 @@ files:
|
|
70
57
|
- lib/rubygems-requirements-system/system-repository.rb
|
71
58
|
- lib/rubygems-requirements-system/version.rb
|
72
59
|
- lib/rubygems_plugin.rb
|
60
|
+
- plugins.rb
|
73
61
|
homepage: https://github.com/ruby-gnome/rubygems-requirements-system
|
74
62
|
licenses:
|
75
63
|
- LGPL-3.0-or-later
|