forked from JCMais/node-libcurl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvcpkg-setup.js
More file actions
171 lines (150 loc) · 5.8 KB
/
Copy pathvcpkg-setup.js
File metadata and controls
171 lines (150 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// this should not use any third party dependencies! Only native Node.js modules!
const { execSync: exec } = require('child_process')
const fs = require('fs')
const path = require('path')
const {
triplet,
moduleRoot,
vcpkgRoot,
vcpkgInstalledRoot,
} = require('./vcpkg-common')
const {
getAvailableVersions,
findBestVersion,
} = require('./vcpkg-openssl-version')
const modulePackageJson = require('../package.json')
const commonEnv = {
...process.env,
VCPKG_DISABLE_METRICS: '1',
}
async function setupVcpkg() {
try {
let vcpkgExe
// Check for global vcpkg
if (process.env.VCPKG_ROOT) {
vcpkgExe = path.join(process.env.VCPKG_ROOT, 'vcpkg.exe')
if (!fs.existsSync(vcpkgExe)) {
console.error('VCPKG_ROOT set but vcpkg.exe not found')
process.exit(1)
}
console.log(`Using global vcpkg at ${process.env.VCPKG_ROOT}`)
} else {
// Bootstrap local vcpkg
if (!fs.existsSync(vcpkgRoot)) {
console.log(`Cloning vcpkg into ${vcpkgRoot}...`)
// `-c core.longpaths=true` lets git write files past Windows'
// 260-char MAX_PATH limit. vcpkg's pack/keep filenames already
// sit close to that limit on their own, and consumers installing
// node-libcurl via pnpm pile a deep `node_modules/.pnpm/<hash>/...`
// prefix on top — easy to overflow without this flag. On
// Linux/macOS the flag is a harmless no-op.
fs.mkdirSync(path.dirname(vcpkgRoot), { recursive: true })
exec(
`git -c core.longpaths=true clone https://github.com/microsoft/vcpkg.git "${vcpkgRoot}"`,
{
cwd: path.dirname(vcpkgRoot),
maxBuffer: 10 * 1024 * 1024,
stdio: 'inherit',
},
)
} else {
console.log(`Using local vcpkg at ${vcpkgRoot}`)
}
vcpkgExe = path.join(vcpkgRoot, 'vcpkg.exe')
if (!fs.existsSync(vcpkgExe)) {
console.log('Bootstrapping vcpkg...')
exec(`"${path.join(vcpkgRoot, 'bootstrap-vcpkg.bat')}"`, {
cwd: vcpkgRoot,
maxBuffer: 10 * 1024 * 1024,
stdio: 'inherit',
env: commonEnv,
})
}
}
await createVcpkgJson()
// Install dependencies. --x-install-root sends `vcpkg_installed` to a
// path outside the module root so the per-port cmake builds (and the
// bundled msys2 pkg-config they call) don't trip over MAX_PATH when
// node-libcurl is being installed via a deep pnpm consumer path.
fs.mkdirSync(vcpkgInstalledRoot, { recursive: true })
console.log(`Installing curl with ${triplet}...`)
console.log(` vcpkg_installed: ${vcpkgInstalledRoot}`)
const installCmd = `"${vcpkgExe}" install --triplet ${triplet} --x-install-root="${vcpkgInstalledRoot}"`
exec(installCmd, {
cwd: moduleRoot,
maxBuffer: 20 * 1024 * 1024,
stdio: 'inherit',
env: commonEnv,
})
const installedRoot = path.join(vcpkgInstalledRoot, triplet)
console.log(`✓ vcpkg setup complete`)
console.log(` Installed to: ${installedRoot}`)
} catch (error) {
console.error('vcpkg setup failed:', error.message)
if (error.stdout) console.error('stdout:', error.stdout)
if (error.stderr) console.error('stderr:', error.stderr)
process.exit(1)
}
}
async function createVcpkgJson() {
const vcpkgJsonTemplate = fs.readFileSync(
path.join(moduleRoot, 'vcpkg.template.json'),
'utf8',
)
const nodeOpenSSLVersion = process.versions.openssl.replace('+quic', '')
// Resolve OpenSSL version against what's available in vcpkg
let opensslVersion = nodeOpenSSLVersion
const availableVersions = getAvailableVersions(vcpkgRoot)
if (availableVersions) {
const result = findBestVersion(nodeOpenSSLVersion, availableVersions)
opensslVersion = result.version
if (!result.isExact) {
console.warn(
`WARNING: OpenSSL ${nodeOpenSSLVersion} is not available in vcpkg.`,
)
console.warn(` Using ${opensslVersion} instead.`)
if (result.message) {
console.warn(` ${result.message}`)
}
} else {
console.log(`Using OpenSSL ${opensslVersion} from vcpkg`)
}
} else {
console.warn('WARNING: Could not read vcpkg versions database.')
console.warn(
' Attempting to use exact OpenSSL version from Node.js.',
)
}
let vcpkgJson = vcpkgJsonTemplate
.replace('$$OPENSSL_VERSION$$', opensslVersion)
.replace('$$NODE_LIBCURL_VERSION$$', modulePackageJson.version)
const parsed = JSON.parse(vcpkgJson)
const curlDep = parsed.dependencies.find((d) => d.name === 'curl')
// The http3 feature depends on ngtcp2, which requires a QUIC-capable
// OpenSSL (>= 3.5.0 with enable-quic). Older Node.js versions bundle
// OpenSSL < 3.5, so building http3 with them would fail at vcpkg compile
// time (ngtcp2's OpenSSL backend requires SSL_set_quic_tls_cbs, only
// available in 3.5+). Remove the feature when the resolved OpenSSL version
// doesn't meet the requirement.
const [oMajor, oMinor] = opensslVersion.split('.').map(Number)
const opensslGe350 = oMajor > 3 || (oMajor === 3 && oMinor >= 5)
if (!opensslGe350 && curlDep) {
const idx = curlDep.features.indexOf('http3')
if (idx !== -1) {
curlDep.features.splice(idx, 1)
console.log(
`OpenSSL ${opensslVersion} < 3.5.0: removing http3 feature from vcpkg.json (ngtcp2 requires QUIC-capable OpenSSL)`,
)
}
}
// Add GSSAPI feature on non-Windows platforms for Kerberos/SPNEGO support.
// On Windows, SSPI (already included) handles Negotiate authentication.
if (process.platform !== 'win32') {
if (curlDep && !curlDep.features.includes('gssapi')) {
curlDep.features.push('gssapi')
}
}
vcpkgJson = JSON.stringify(parsed, null, 2)
fs.writeFileSync(path.join(moduleRoot, 'vcpkg.json'), vcpkgJson)
}
setupVcpkg()