vcdeps 0.1.0
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 +7 -0
- data/CHANGELOG.md +43 -0
- data/LICENSE.txt +21 -0
- data/README.md +258 -0
- data/exe/vcdeps +6 -0
- data/lib/vcdeps/bootstrap.rb +163 -0
- data/lib/vcdeps/cli.rb +206 -0
- data/lib/vcdeps/doctor.rb +263 -0
- data/lib/vcdeps/installed.rb +139 -0
- data/lib/vcdeps/manifest.rb +100 -0
- data/lib/vcdeps/mkmf.rb +125 -0
- data/lib/vcdeps/runner.rb +145 -0
- data/lib/vcdeps/tool.rb +146 -0
- data/lib/vcdeps/triplet.rb +77 -0
- data/lib/vcdeps/vendor.rb +160 -0
- data/lib/vcdeps/version.rb +5 -0
- data/lib/vcdeps.rb +180 -0
- metadata +121 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "rbconfig"
|
|
5
|
+
require "vcdeps/version"
|
|
6
|
+
|
|
7
|
+
module Vcdeps
|
|
8
|
+
# Syncs an Installed's runtime DLLs, per-port copyright files, and a standalone
|
|
9
|
+
# Fiddle-preload shim into a vendor directory (§2.2/§2.7). This is a SYNC, not
|
|
10
|
+
# a copy: vendor! OWNS <into>\*.dll, <into>\licenses\* and <into>\preload.rb —
|
|
11
|
+
# it overwrites the computed write list and DELETES any owned file no longer on
|
|
12
|
+
# it (so a port removed from vcpkg.json leaves no stale DLL the shim would
|
|
13
|
+
# preload and the precompiled-gem glob would ship). Nothing else under `into`
|
|
14
|
+
# is touched, so authors may keep unrelated assets there.
|
|
15
|
+
module Vendor
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
SHIM_NAME = "preload.rb"
|
|
19
|
+
LICENSES_DIR = "licenses"
|
|
20
|
+
|
|
21
|
+
# Returns the list of files written (absolute, backslashed). See §2.2 for the
|
|
22
|
+
# four-case table; stale owned files are deleted whenever `into` exists.
|
|
23
|
+
def sync!(installed, into:, licenses: true, shim: true, out: $stderr)
|
|
24
|
+
dlls = installed.dlls
|
|
25
|
+
copyrights = licenses ? installed.copyright_files : {}
|
|
26
|
+
|
|
27
|
+
# The write plan: a DLL is vendored only when there is something to vendor;
|
|
28
|
+
# the shim is written only when DLLs exist; licenses ship whenever copyright
|
|
29
|
+
# files exist (including static-md, where there are no DLLs).
|
|
30
|
+
write_dlls = dlls
|
|
31
|
+
write_shim = shim && !dlls.empty?
|
|
32
|
+
write_copies = copyrights
|
|
33
|
+
|
|
34
|
+
# Nothing to write AND nothing to clean (into absent) -> [] without
|
|
35
|
+
# creating `into` (§2.2 last case).
|
|
36
|
+
if write_dlls.empty? && write_copies.empty? && !write_shim &&
|
|
37
|
+
!File.directory?(into)
|
|
38
|
+
return []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
written = []
|
|
42
|
+
FileUtils.mkdir_p(into)
|
|
43
|
+
|
|
44
|
+
# Owned DLLs we intend to keep (base names), for the stale sweep.
|
|
45
|
+
kept_dll_names = []
|
|
46
|
+
write_dlls.each do |src|
|
|
47
|
+
base = File.basename(src)
|
|
48
|
+
dest = File.join(into, base)
|
|
49
|
+
FileUtils.cp(src, dest)
|
|
50
|
+
kept_dll_names << base.downcase
|
|
51
|
+
written << win(dest)
|
|
52
|
+
warn_on_ruby_bin_collision(base, out)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Licenses.
|
|
56
|
+
kept_license_names = []
|
|
57
|
+
unless write_copies.empty?
|
|
58
|
+
ldir = File.join(into, LICENSES_DIR)
|
|
59
|
+
FileUtils.mkdir_p(ldir)
|
|
60
|
+
write_copies.each do |port, src|
|
|
61
|
+
dest = File.join(ldir, "#{port}-copyright.txt")
|
|
62
|
+
FileUtils.cp(src, dest)
|
|
63
|
+
kept_license_names << File.basename(dest).downcase
|
|
64
|
+
written << win(dest)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Shim.
|
|
69
|
+
shim_path = File.join(into, SHIM_NAME)
|
|
70
|
+
if write_shim
|
|
71
|
+
File.write(shim_path, shim_source)
|
|
72
|
+
written << win(shim_path)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Stale sweep of OWNED files only.
|
|
76
|
+
sweep_stale!(into, kept_dll_names, kept_license_names, write_shim)
|
|
77
|
+
|
|
78
|
+
written
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The generated preload shim (exact §2.7 template). Standalone: stdlib only,
|
|
82
|
+
# no vcdeps require, safe to require twice, safe with zero DLLs present.
|
|
83
|
+
def shim_source
|
|
84
|
+
<<~SHIM
|
|
85
|
+
# frozen_string_literal: true
|
|
86
|
+
#
|
|
87
|
+
# Generated by vcdeps #{Vcdeps::VERSION}. Do not edit; regenerate with `vcdeps vendor`.
|
|
88
|
+
#
|
|
89
|
+
# Preloads the vendored vcpkg runtime DLLs by ABSOLUTE path before the C
|
|
90
|
+
# extension loads. Windows resolves an extension's dependent DLLs via the
|
|
91
|
+
# standard search order, which checks the loaded-module list (step 4) long
|
|
92
|
+
# before PATH (step 12) and NEVER checks the .so's own directory — so loading
|
|
93
|
+
# each DLL here, by full path, is what makes `require "<gem>/<gem>"` work.
|
|
94
|
+
#
|
|
95
|
+
# The dlopen handles are intentionally leaked for process lifetime: the DLLs
|
|
96
|
+
# must stay loaded as long as the extension is loaded.
|
|
97
|
+
require "fiddle"
|
|
98
|
+
|
|
99
|
+
pending = Dir[File.join(__dir__, "*.dll")].sort
|
|
100
|
+
until pending.empty?
|
|
101
|
+
progressed = false
|
|
102
|
+
pending.delete_if do |dll|
|
|
103
|
+
Fiddle.dlopen(dll)
|
|
104
|
+
progressed = true
|
|
105
|
+
true
|
|
106
|
+
rescue Fiddle::DLError
|
|
107
|
+
false # depends on a sibling not yet loaded — retry next pass
|
|
108
|
+
end
|
|
109
|
+
break unless progressed # truly unloadable; let the require raise its own LoadError
|
|
110
|
+
end
|
|
111
|
+
SHIM
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# --- internals -----------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
# Delete any *.dll directly in `into` not on the kept list, any licenses\*
|
|
117
|
+
# file not kept, and a stale shim when no shim is being written.
|
|
118
|
+
def sweep_stale!(into, kept_dll_names, kept_license_names, write_shim)
|
|
119
|
+
Dir[File.join(into.tr("\\", "/"), "*.dll")].each do |dll|
|
|
120
|
+
File.delete(dll) unless kept_dll_names.include?(File.basename(dll).downcase)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
ldir = File.join(into.tr("\\", "/"), LICENSES_DIR)
|
|
124
|
+
if File.directory?(ldir)
|
|
125
|
+
Dir[File.join(ldir, "*")].each do |f|
|
|
126
|
+
next unless File.file?(f)
|
|
127
|
+
|
|
128
|
+
File.delete(f) unless kept_license_names.include?(File.basename(f).downcase)
|
|
129
|
+
end
|
|
130
|
+
# Remove an empty licenses dir we no longer populate.
|
|
131
|
+
begin
|
|
132
|
+
Dir.rmdir(ldir) if Dir.empty?(ldir)
|
|
133
|
+
rescue SystemCallError
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
shim = File.join(into.tr("\\", "/"), SHIM_NAME)
|
|
139
|
+
File.delete(shim) if !write_shim && File.exist?(shim)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Warn when a vendored DLL base name also exists in Ruby's bindir
|
|
143
|
+
# (zlib1.dll/ffi-8.dll/yaml.dll shadowing, R§9.2) — first-loaded wins.
|
|
144
|
+
def warn_on_ruby_bin_collision(base, out)
|
|
145
|
+
bindir = RbConfig::CONFIG["bindir"].to_s
|
|
146
|
+
return if bindir.empty?
|
|
147
|
+
|
|
148
|
+
ruby_copy = File.join(bindir, base)
|
|
149
|
+
return unless File.exist?(ruby_copy)
|
|
150
|
+
|
|
151
|
+
out&.puts("[vcdeps] WARNING: #{base} also ships in #{bindir.tr('/', '\\')} " \
|
|
152
|
+
"— the copy loaded first wins process-wide; preload.rb runs " \
|
|
153
|
+
"first under normal require order.")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def win(path)
|
|
157
|
+
path.nil? ? path : path.tr("/", "\\")
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
data/lib/vcdeps.rb
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "tmpdir"
|
|
6
|
+
require "vcdeps/version"
|
|
7
|
+
|
|
8
|
+
# vcdeps — vcpkg-powered native dependencies for Ruby C extensions on Windows
|
|
9
|
+
# (MSVC). Declare ports in a manifest, get correct mkmf flags and loadable
|
|
10
|
+
# runtime DLLs, no global state. Companion to vcvars (the toolchain) the way
|
|
11
|
+
# vcpkg is companion to MSVC.
|
|
12
|
+
#
|
|
13
|
+
# # in ext/<gem>/extconf.rb, after require "mkmf":
|
|
14
|
+
# require "vcdeps/mkmf"
|
|
15
|
+
# Vcdeps.mkmf!(vendor: File.expand_path("../../lib/foo/vendor", __dir__))
|
|
16
|
+
#
|
|
17
|
+
# Library use:
|
|
18
|
+
#
|
|
19
|
+
# require "vcdeps"
|
|
20
|
+
# inst = Vcdeps.install!(manifest: "ext/foo")
|
|
21
|
+
# Vcdeps.vendor!(inst, into: "lib/foo/vendor")
|
|
22
|
+
#
|
|
23
|
+
# Windows MSVC (mswin) Ruby only. Pure Ruby — no compiler required to install.
|
|
24
|
+
module Vcdeps
|
|
25
|
+
class Error < StandardError; end # root; everything vcdeps raises
|
|
26
|
+
class ToolNotFound < Error; end # no usable vcpkg anywhere
|
|
27
|
+
class BootstrapError < Error; end # private bootstrap failed
|
|
28
|
+
class ManifestError < Error; end # vcpkg.json missing/unparsable/no baseline
|
|
29
|
+
class TripletError < Error; end # unknown arch, static-CRT triplet, arch mismatch
|
|
30
|
+
|
|
31
|
+
# `vcpkg install` exited nonzero. Carries the exact failing argv, the child
|
|
32
|
+
# exit status, and the last <= 4000 chars of combined output (UTF-8 scrubbed).
|
|
33
|
+
class InstallError < Error
|
|
34
|
+
attr_reader :command, :status, :log_tail
|
|
35
|
+
|
|
36
|
+
def initialize(message, command:, status:, log_tail:)
|
|
37
|
+
super(message)
|
|
38
|
+
@command = command
|
|
39
|
+
@status = status
|
|
40
|
+
@log_tail = log_tail
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
module_function
|
|
45
|
+
|
|
46
|
+
# The vcdeps state root: ENV["VCDEPS_HOME"] or %LOCALAPPDATA%\vcdeps.
|
|
47
|
+
# Deliberately a SHORT path (vcpkg port builds break in deep trees, R§7).
|
|
48
|
+
def home
|
|
49
|
+
base = ENV["VCDEPS_HOME"]
|
|
50
|
+
base = File.join(ENV["LOCALAPPDATA"] || Dir.tmpdir, "vcdeps") if base.nil? || base.empty?
|
|
51
|
+
base.tr("/", "\\")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Triplet for this Ruby (x64 -> "x64-windows", arm64 -> "arm64-windows", ...).
|
|
55
|
+
# Raises Vcdeps::TripletError for an unrecognized arch.
|
|
56
|
+
def default_triplet(arch = RbConfig::CONFIG["arch"])
|
|
57
|
+
Triplet.default(arch)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Locate a usable vcpkg (§2.3 resolution order). Returns a Tool or nil; with
|
|
61
|
+
# bootstrap: true a miss bootstraps a private instance instead of nil.
|
|
62
|
+
def tool(bootstrap: false, out: $stderr)
|
|
63
|
+
ToolFinder.find(bootstrap: bootstrap, out: out)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# tool(), but raises Vcdeps::ToolNotFound (with the three remedies) on a miss.
|
|
67
|
+
# Default consent for bootstrap comes from ENV so `gem install` can be
|
|
68
|
+
# unblocked without editing anything.
|
|
69
|
+
def tool!(bootstrap: ENV["VCDEPS_BOOTSTRAP"] == "1", out: $stderr)
|
|
70
|
+
found = tool(bootstrap: bootstrap, out: out)
|
|
71
|
+
return found if found
|
|
72
|
+
|
|
73
|
+
raise ToolNotFound, <<~MSG.strip
|
|
74
|
+
vcdeps: no usable vcpkg found. Pick one of:
|
|
75
|
+
(a) Install the VS "vcpkg package manager" component
|
|
76
|
+
(Microsoft.VisualStudio.Component.Vcpkg) — it is Recommended (not
|
|
77
|
+
Required) in the "Desktop development with C++" workload, so a
|
|
78
|
+
cl-capable box can still lack it.
|
|
79
|
+
(b) Set VCPKG_ROOT to an existing vcpkg instance.
|
|
80
|
+
(c) Run `vcdeps bootstrap` (or set VCDEPS_BOOTSTRAP=1 for non-interactive
|
|
81
|
+
installs).
|
|
82
|
+
See `vcdeps doctor` for details.
|
|
83
|
+
MSG
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Create the private, registration-free vcpkg instance under <home>\vcpkg
|
|
87
|
+
# (the vcpkg-init mechanism, R§2.4). Idempotent. Raises BootstrapError.
|
|
88
|
+
def bootstrap!(out: $stderr)
|
|
89
|
+
require "vcdeps/bootstrap"
|
|
90
|
+
Bootstrap.run!(out: out)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Run `vcpkg install` for <manifest>\vcpkg.json into <home>\installed\<key>.
|
|
94
|
+
# Streams combined output to `out` (nil to silence). Fast path: a present
|
|
95
|
+
# .vcdeps-complete marker means the install is provably current and vcpkg is
|
|
96
|
+
# not invoked (force: true bypasses it). Triplet precedence: kwarg >
|
|
97
|
+
# ENV["VCDEPS_TRIPLET"] > default_triplet.
|
|
98
|
+
#
|
|
99
|
+
# Raises ManifestError / TripletError / ToolNotFound / InstallError.
|
|
100
|
+
def install!(manifest: Dir.pwd, triplet: nil, tool: nil, force: false, out: $stderr)
|
|
101
|
+
manifest_dir = File.expand_path(manifest)
|
|
102
|
+
|
|
103
|
+
# Pre-flight the manifest BEFORE locating the tool (a missing vcpkg.json or
|
|
104
|
+
# missing baseline must never invoke vcpkg, §5.1/§5.2).
|
|
105
|
+
Manifest.load!(manifest_dir)
|
|
106
|
+
|
|
107
|
+
resolved_triplet = resolve_triplet(triplet)
|
|
108
|
+
Triplet.validate!(resolved_triplet)
|
|
109
|
+
|
|
110
|
+
resolved_tool = tool || tool!(out: out)
|
|
111
|
+
|
|
112
|
+
key = Manifest.key(manifest_dir, resolved_triplet, resolved_tool.version)
|
|
113
|
+
install_root = File.join(home, "installed", key).tr("/", "\\")
|
|
114
|
+
|
|
115
|
+
installed = Installed.new(root: install_root, triplet: resolved_triplet,
|
|
116
|
+
manifest_dir: manifest_dir, key: key, tool: resolved_tool)
|
|
117
|
+
|
|
118
|
+
# Fast path: marker present and not forced.
|
|
119
|
+
return installed if !force && Runner.marker_present?(install_root)
|
|
120
|
+
|
|
121
|
+
FileUtils.mkdir_p(install_root)
|
|
122
|
+
command = Runner.install_args(resolved_tool.exe, resolved_triplet,
|
|
123
|
+
manifest_dir, install_root, home)
|
|
124
|
+
Runner.run_install(command, env: Runner.child_env(resolved_tool.root),
|
|
125
|
+
chdir: manifest_dir, out: out)
|
|
126
|
+
Runner.write_marker!(install_root, key, resolved_tool.version)
|
|
127
|
+
|
|
128
|
+
installed
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Sync an Installed's runtime DLLs (+ copyright files, + preload shim) into
|
|
132
|
+
# `into` (§2.2). SYNC, not copy: owns <into>\*.dll, <into>\licenses\* and
|
|
133
|
+
# <into>\preload.rb. Returns the list of files written.
|
|
134
|
+
def vendor!(installed, into:, licenses: true, shim: true, out: $stderr)
|
|
135
|
+
require "vcdeps/vendor"
|
|
136
|
+
Vendor.sync!(installed, into: File.expand_path(into),
|
|
137
|
+
licenses: licenses, shim: shim, out: out)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Write/update "builtin-baseline" in <manifest>\vcpkg.json by running
|
|
141
|
+
# `vcpkg x-update-baseline --add-initial-baseline` with chdir: manifest.
|
|
142
|
+
# Returns the resulting baseline SHA (re-read from the manifest).
|
|
143
|
+
# Raises ManifestError / ToolNotFound / InstallError.
|
|
144
|
+
def baseline!(manifest: Dir.pwd, tool: nil, out: $stderr)
|
|
145
|
+
manifest_dir = File.expand_path(manifest)
|
|
146
|
+
path = File.join(manifest_dir, Manifest::MANIFEST_NAME)
|
|
147
|
+
unless File.exist?(path)
|
|
148
|
+
raise ManifestError, "vcdeps: no manifest at #{path.tr('/', '\\')} to add a " \
|
|
149
|
+
"baseline to."
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
resolved_tool = tool || tool!(out: out)
|
|
153
|
+
command = [resolved_tool.exe, "x-update-baseline", "--add-initial-baseline"]
|
|
154
|
+
Runner.run(command, env: Runner.child_env(resolved_tool.root),
|
|
155
|
+
chdir: manifest_dir, out: out)
|
|
156
|
+
|
|
157
|
+
manifest = Manifest.read_json(path)
|
|
158
|
+
manifest["builtin-baseline"].to_s
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Triplet precedence for install! (kwarg > VCDEPS_TRIPLET > default).
|
|
162
|
+
def resolve_triplet(kwarg)
|
|
163
|
+
return kwarg if kwarg && !kwarg.to_s.empty?
|
|
164
|
+
|
|
165
|
+
env = ENV["VCDEPS_TRIPLET"]
|
|
166
|
+
return env if env && !env.empty?
|
|
167
|
+
|
|
168
|
+
default_triplet
|
|
169
|
+
end
|
|
170
|
+
private_class_method :resolve_triplet
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
require "vcdeps/triplet"
|
|
174
|
+
require "vcdeps/tool"
|
|
175
|
+
require "vcdeps/manifest"
|
|
176
|
+
require "vcdeps/runner"
|
|
177
|
+
require "vcdeps/installed"
|
|
178
|
+
# NOTE: vcdeps/mkmf, vcdeps/vendor, vcdeps/bootstrap, vcdeps/doctor and
|
|
179
|
+
# vcdeps/cli are required lazily (mkmf must never be loaded into a normal
|
|
180
|
+
# process; the others are CLI-only or pulled in on first use).
|
metadata
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: vcdeps
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ned
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: vcvars
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.1'
|
|
19
|
+
- - ">="
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 0.1.1
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - "~>"
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '0.1'
|
|
29
|
+
- - ">="
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: 0.1.1
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: rake
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - "~>"
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '13.0'
|
|
39
|
+
type: :development
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - "~>"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '13.0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: minitest
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - "~>"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '5.0'
|
|
53
|
+
type: :development
|
|
54
|
+
prerelease: false
|
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '5.0'
|
|
60
|
+
description: |
|
|
61
|
+
vcdeps wires Microsoft's vcpkg package manager into mkmf: declare native
|
|
62
|
+
dependencies in ext/<gem>/vcpkg.json, call Vcdeps.mkmf! from extconf.rb, and
|
|
63
|
+
vcdeps locates (or bootstraps) vcpkg, installs the ports out of tree with the
|
|
64
|
+
correct dynamic-CRT triplet, prepends the include/lib paths so they win over
|
|
65
|
+
Ruby's own opt-dir, and vendors the runtime DLLs with a generated
|
|
66
|
+
Fiddle-preload shim so the built extension actually loads.
|
|
67
|
+
|
|
68
|
+
It provides a library API (install!/vendor!/baseline!/tool!), the extconf
|
|
69
|
+
entry point Vcdeps.mkmf!, and a CLI (vcdeps doctor/where/install/vendor/
|
|
70
|
+
baseline/bootstrap). Manifest mode only; builds and caches live under
|
|
71
|
+
%LOCALAPPDATA%\vcdeps, never inside the gem. Windows MSVC (mswin) Ruby
|
|
72
|
+
only. Pure Ruby — no compiler required to install vcdeps itself.
|
|
73
|
+
executables:
|
|
74
|
+
- vcdeps
|
|
75
|
+
extensions: []
|
|
76
|
+
extra_rdoc_files: []
|
|
77
|
+
files:
|
|
78
|
+
- CHANGELOG.md
|
|
79
|
+
- LICENSE.txt
|
|
80
|
+
- README.md
|
|
81
|
+
- exe/vcdeps
|
|
82
|
+
- lib/vcdeps.rb
|
|
83
|
+
- lib/vcdeps/bootstrap.rb
|
|
84
|
+
- lib/vcdeps/cli.rb
|
|
85
|
+
- lib/vcdeps/doctor.rb
|
|
86
|
+
- lib/vcdeps/installed.rb
|
|
87
|
+
- lib/vcdeps/manifest.rb
|
|
88
|
+
- lib/vcdeps/mkmf.rb
|
|
89
|
+
- lib/vcdeps/runner.rb
|
|
90
|
+
- lib/vcdeps/tool.rb
|
|
91
|
+
- lib/vcdeps/triplet.rb
|
|
92
|
+
- lib/vcdeps/vendor.rb
|
|
93
|
+
- lib/vcdeps/version.rb
|
|
94
|
+
homepage: https://github.com/main-path/vcdeps
|
|
95
|
+
licenses:
|
|
96
|
+
- MIT
|
|
97
|
+
metadata:
|
|
98
|
+
homepage_uri: https://github.com/main-path/vcdeps
|
|
99
|
+
source_code_uri: https://github.com/main-path/vcdeps
|
|
100
|
+
changelog_uri: https://github.com/main-path/vcdeps/blob/main/CHANGELOG.md
|
|
101
|
+
bug_tracker_uri: https://github.com/main-path/vcdeps/issues
|
|
102
|
+
rubygems_mfa_required: 'true'
|
|
103
|
+
rdoc_options: []
|
|
104
|
+
require_paths:
|
|
105
|
+
- lib
|
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '3.0'
|
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0'
|
|
116
|
+
requirements: []
|
|
117
|
+
rubygems_version: 3.6.9
|
|
118
|
+
specification_version: 4
|
|
119
|
+
summary: vcpkg-powered native dependencies for Ruby C extensions on Windows (MSVC),
|
|
120
|
+
companion to vcvars.
|
|
121
|
+
test_files: []
|