wyvrnpm 2.10.2 → 2.12.2
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.
- package/README.md +1914 -1860
- package/bin/{wyvrn.js → wyvrnpm.js} +66 -0
- package/cmake/cpp.cmake +9 -9
- package/cmake/functions.cmake +224 -224
- package/cmake/macros.cmake +284 -284
- package/package.json +3 -2
- package/src/auth.js +66 -66
- package/src/binary-dir.js +95 -0
- package/src/bootstrap/cookbook.js +196 -196
- package/src/bootstrap/detect.js +150 -150
- package/src/bootstrap/index.js +220 -220
- package/src/bootstrap/version.js +72 -72
- package/src/build/cache.js +344 -344
- package/src/build/clone.js +170 -170
- package/src/build/cmake.js +342 -342
- package/src/build/index.js +299 -297
- package/src/build/msvc-env.js +260 -260
- package/src/build/recipe.js +188 -188
- package/src/commands/add.js +141 -141
- package/src/commands/bootstrap.js +96 -96
- package/src/commands/build.js +482 -452
- package/src/commands/cache.js +189 -189
- package/src/commands/clean.js +80 -80
- package/src/commands/configure.js +92 -92
- package/src/commands/init.js +70 -70
- package/src/commands/install-skill.js +115 -115
- package/src/commands/install.js +730 -674
- package/src/commands/link.js +320 -320
- package/src/commands/profile.js +237 -237
- package/src/commands/publish.js +584 -555
- package/src/commands/show.js +252 -252
- package/src/commands/version.js +187 -0
- package/src/compat.js +273 -273
- package/src/conf/index.js +415 -391
- package/src/conf/namespaces.js +94 -94
- package/src/context.js +230 -230
- package/src/http-fetch.js +53 -53
- package/src/ignore.js +118 -118
- package/src/logger.js +122 -122
- package/src/options.js +303 -303
- package/src/settings-overrides.js +152 -152
- package/src/toolchain/deps.js +164 -164
- package/src/toolchain/index.js +212 -212
- package/src/toolchain/presets.js +356 -340
- package/src/toolchain/template.cmake +77 -77
- package/src/upload-built.js +265 -265
- package/src/version-range.js +301 -301
- package/src/zip-safe.js +52 -52
- package/src/zip-stream.js +126 -0
package/src/build/index.js
CHANGED
|
@@ -1,297 +1,299 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { cloneAtSha } = require('./clone');
|
|
8
|
-
const { normalizeRecipe, hasBuildRecipe } = require('./recipe');
|
|
9
|
-
const { configureBuildInstall } = require('./cmake');
|
|
10
|
-
const { getBuildPaths, hasValidArtefact } = require('./cache');
|
|
11
|
-
|
|
12
|
-
const { normalizeDependencies } = require('../manifest');
|
|
13
|
-
const { resolveDependencies } = require('../resolve');
|
|
14
|
-
const { hashProfile, mergeProfile, sha256Of } = require('../profile');
|
|
15
|
-
const { generateToolchain } = require('../toolchain');
|
|
16
|
-
const { normalizeOptionsDeclaration, resolveEffectiveOptions } = require('../options');
|
|
17
|
-
const { readRecipeConf, cmakeCacheVariables } = require('../conf');
|
|
18
|
-
const { wyvrnFetch } = require('../http-fetch');
|
|
19
|
-
const log = require('../logger');
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Recursively walk a directory and add every file into
|
|
23
|
-
* paths relative to `base`. Matches the structure emitted by
|
|
24
|
-
* zip contents are the DIRECT SUBTREE of `base`, not
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
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
|
-
* @param {
|
|
65
|
-
* @param {
|
|
66
|
-
* @param {string} args.
|
|
67
|
-
* @param {
|
|
68
|
-
* @param {
|
|
69
|
-
*
|
|
70
|
-
* @param {string} args.
|
|
71
|
-
*
|
|
72
|
-
* @param {string} args.
|
|
73
|
-
* @param {string
|
|
74
|
-
* @param {string} args.
|
|
75
|
-
* @param {
|
|
76
|
-
* @param {string}
|
|
77
|
-
* @param {
|
|
78
|
-
*
|
|
79
|
-
* @param {
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
zip
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const { StreamingZipWriter } = require('../zip-stream');
|
|
7
|
+
const { cloneAtSha } = require('./clone');
|
|
8
|
+
const { normalizeRecipe, hasBuildRecipe } = require('./recipe');
|
|
9
|
+
const { configureBuildInstall } = require('./cmake');
|
|
10
|
+
const { getBuildPaths, hasValidArtefact } = require('./cache');
|
|
11
|
+
|
|
12
|
+
const { normalizeDependencies } = require('../manifest');
|
|
13
|
+
const { resolveDependencies } = require('../resolve');
|
|
14
|
+
const { hashProfile, mergeProfile, sha256Of } = require('../profile');
|
|
15
|
+
const { generateToolchain } = require('../toolchain');
|
|
16
|
+
const { normalizeOptionsDeclaration, resolveEffectiveOptions } = require('../options');
|
|
17
|
+
const { readRecipeConf, cmakeCacheVariables } = require('../conf');
|
|
18
|
+
const { wyvrnFetch } = require('../http-fetch');
|
|
19
|
+
const log = require('../logger');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Recursively walk a directory and add every file into a streaming zip
|
|
23
|
+
* writer at paths relative to `base`. Matches the structure emitted by
|
|
24
|
+
* `publish` — zip contents are the DIRECT SUBTREE of `base`, not
|
|
25
|
+
* `base` itself. The `zip` argument can be any object exposing
|
|
26
|
+
* `addLocalFile(fullPath, zipDir)` (see [src/zip-stream.js](../zip-stream.js)).
|
|
27
|
+
*/
|
|
28
|
+
function addFolder(zip, dir, base) {
|
|
29
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
30
|
+
const full = path.join(dir, entry);
|
|
31
|
+
const rel = path.relative(base, full).replace(/\\/g, '/');
|
|
32
|
+
const stat = fs.statSync(full);
|
|
33
|
+
if (stat.isDirectory()) {
|
|
34
|
+
addFolder(zip, full, base);
|
|
35
|
+
} else {
|
|
36
|
+
const zipDir = path.dirname(rel);
|
|
37
|
+
zip.addLocalFile(full, zipDir === '.' ? '' : zipDir);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build a package from source and produce an artefact zip indistinguishable
|
|
44
|
+
* from a pre-built download.
|
|
45
|
+
*
|
|
46
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
47
|
+
* Flow (PLAN-BUILD-MISSING phase 3):
|
|
48
|
+
* 1. Check the build cache for a ready artefact → copy and return.
|
|
49
|
+
* 2. Shallow-clone `{gitRepo}` at `{gitSha}` into the cache.
|
|
50
|
+
* 3. Read the cloned `wyvrn.json`; require a `build` section.
|
|
51
|
+
* 4. Recursively resolve + download the package's OWN dependencies into a
|
|
52
|
+
* scratch `wyvrn_internal/` co-located with the source. Source-build
|
|
53
|
+
* propagates via `buildMode: "missing"`, so transitive source-only deps
|
|
54
|
+
* Just Work.
|
|
55
|
+
* 5. Generate the CMake toolchain via `generateToolchain()` — the shared
|
|
56
|
+
* entry point documented in PLAN-CMAKE-TOOLCHAIN Phase F. Never hand-
|
|
57
|
+
* roll profile→flag translation here.
|
|
58
|
+
* 6. Configure + build + install via `configureBuildInstall()`.
|
|
59
|
+
* 7. Zip the install dir → `wyvrn.zip`, compute `contentSha256`.
|
|
60
|
+
* 8. Copy the zip to `destZipPath` so `downloadDependencies` can extract
|
|
61
|
+
* it like any other v2 artefact.
|
|
62
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
63
|
+
*
|
|
64
|
+
* @param {object} args
|
|
65
|
+
* @param {string} args.name
|
|
66
|
+
* @param {string} args.version
|
|
67
|
+
* @param {import('../profile').WyvrnProfile} args.profile
|
|
68
|
+
* @param {string} args.profileName
|
|
69
|
+
* @param {string} args.profileHash
|
|
70
|
+
* @param {Record<string, any>|null} [args.options] Effective options for this build.
|
|
71
|
+
* Used to expand `${options.*}` in the recipe.
|
|
72
|
+
* @param {string} args.gitRepo
|
|
73
|
+
* @param {string} args.gitSha
|
|
74
|
+
* @param {string} args.destZipPath Where the caller expects the artefact zip.
|
|
75
|
+
* @param {string[]} args.packageSources Used to resolve this package's own deps.
|
|
76
|
+
* @param {string} args.platform v1 fallback platform for transitive deps.
|
|
77
|
+
* @param {number} args.timeoutMs
|
|
78
|
+
* @param {string} [args.buildMode] Propagated into transitive downloads. Default 'missing'.
|
|
79
|
+
* @param {string[]} [args.configs] Override recipe.configs (which defaults to
|
|
80
|
+
* all four CMake configurations).
|
|
81
|
+
* @param {object} [args.authOptions]
|
|
82
|
+
* @returns {Promise<{
|
|
83
|
+
* found: true,
|
|
84
|
+
* contentSha256: string,
|
|
85
|
+
* profileHash: string,
|
|
86
|
+
* gitSha: string,
|
|
87
|
+
* gitRepo: string,
|
|
88
|
+
* source: string, // build-cache path (for logging)
|
|
89
|
+
* resolvedFrom: 'v2-source-build',
|
|
90
|
+
* artefactPath: string, // absolute path to the built zip in the cache
|
|
91
|
+
* clonedManifestPath: string, // absolute path to the cloned wyvrn.json (for upload-built)
|
|
92
|
+
* }>}
|
|
93
|
+
* @throws {Error} when the cloned manifest lacks a `build` section, when
|
|
94
|
+
* CMake is missing, or when the compile itself fails.
|
|
95
|
+
*/
|
|
96
|
+
async function buildFromSource(args) {
|
|
97
|
+
const {
|
|
98
|
+
name, version,
|
|
99
|
+
profile, profileName, profileHash,
|
|
100
|
+
options = null,
|
|
101
|
+
gitRepo, gitSha,
|
|
102
|
+
destZipPath,
|
|
103
|
+
packageSources,
|
|
104
|
+
platform,
|
|
105
|
+
timeoutMs,
|
|
106
|
+
buildMode = 'missing',
|
|
107
|
+
configs,
|
|
108
|
+
authOptions = {},
|
|
109
|
+
} = args;
|
|
110
|
+
|
|
111
|
+
if (!gitRepo || !gitSha) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Cannot source-build ${name}@${version}: the registry has no git metadata ` +
|
|
114
|
+
`(gitRepo/gitSha) for this version. Publisher must re-publish with git info.`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const paths = getBuildPaths({ name, version, profileHash });
|
|
119
|
+
|
|
120
|
+
// ── 1. Cache hit? Short-circuit to copy and return ──────────────────────
|
|
121
|
+
if (hasValidArtefact({ name, version, profileHash })) {
|
|
122
|
+
log.info(` source-build cache hit: ${paths.artefact}`);
|
|
123
|
+
fs.copyFileSync(paths.artefact, destZipPath);
|
|
124
|
+
const contentSha256 = sha256Of(paths.artefact);
|
|
125
|
+
return {
|
|
126
|
+
found: true,
|
|
127
|
+
contentSha256,
|
|
128
|
+
profileHash,
|
|
129
|
+
gitSha,
|
|
130
|
+
gitRepo,
|
|
131
|
+
source: paths.root,
|
|
132
|
+
resolvedFrom: 'v2-source-build',
|
|
133
|
+
artefactPath: paths.artefact,
|
|
134
|
+
clonedManifestPath: path.join(paths.src, 'wyvrn.json'),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
log.info(` source-build starting: ${name}@${version} [${profileHash}]`);
|
|
139
|
+
log.info(` cache dir: ${paths.root}`);
|
|
140
|
+
|
|
141
|
+
// ── 2. Clone source ─────────────────────────────────────────────────────
|
|
142
|
+
fs.mkdirSync(paths.root, { recursive: true });
|
|
143
|
+
await cloneAtSha({ gitRepo, gitSha, destDir: paths.src });
|
|
144
|
+
|
|
145
|
+
// ── 3. Read cloned manifest + recipe ────────────────────────────────────
|
|
146
|
+
const manifestPath = path.join(paths.src, 'wyvrn.json');
|
|
147
|
+
if (!fs.existsSync(manifestPath)) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Cloned source does not contain wyvrn.json at ${manifestPath}. ` +
|
|
150
|
+
`${name}@${version} cannot be source-built.`,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
const clonedManifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
154
|
+
if (!hasBuildRecipe(clonedManifest)) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`${name}@${version} has no "build" section in its wyvrn.json at ${gitSha.slice(0, 12)}. ` +
|
|
157
|
+
`Source-build is opt-in — the publisher must add a build recipe.`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
// Pass effective options into the recipe so `${options.<name>}` tokens in
|
|
161
|
+
// `build.configure` / `build.buildArgs` expand to the concrete values that
|
|
162
|
+
// produced this build's profileHash. Pass the cloned manifest so PLAN-CONF.md
|
|
163
|
+
// §4.7 collision detection catches a publisher who declared the same KEY in
|
|
164
|
+
// both build.configure and conf.cmake.cache.
|
|
165
|
+
const recipe = normalizeRecipe(clonedManifest.build, options, clonedManifest);
|
|
166
|
+
|
|
167
|
+
// PLAN-CONF.md §4.8.2: source-build of a dep consumes ONLY the dep's own
|
|
168
|
+
// recipe conf — never the root project's merged conf. Translating the
|
|
169
|
+
// dep's cmake.cache namespace into -D args here keeps the dep's source-
|
|
170
|
+
// build CMake invocation aligned with its author's declared defaults
|
|
171
|
+
// while preserving cross-consumer reproducibility. The root's CLI
|
|
172
|
+
// --conf / wyvrn.local.json overlay is invisible at this seam.
|
|
173
|
+
const clonedConfFlat = readRecipeConf(clonedManifest);
|
|
174
|
+
const clonedCacheVars = cmakeCacheVariables(clonedConfFlat);
|
|
175
|
+
if (Object.keys(clonedCacheVars).length > 0) {
|
|
176
|
+
const confDerivedArgs = Object.entries(clonedCacheVars)
|
|
177
|
+
.map(([k, v]) => `-D${k}=${v}`);
|
|
178
|
+
recipe.configure = [...recipe.configure, ...confDerivedArgs];
|
|
179
|
+
log.info(
|
|
180
|
+
` conf.cmake.cache → ${confDerivedArgs.length} source-build ` +
|
|
181
|
+
`configure arg(s) from the dep's own recipe`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ── 4. Recursively resolve + download this package's OWN deps ──────────
|
|
186
|
+
// Lazy-require: downloadDependencies is where we were called from, so
|
|
187
|
+
// pulling it in at module-load would be a circular import.
|
|
188
|
+
// eslint-disable-next-line global-require
|
|
189
|
+
const { downloadDependencies } = require('../download');
|
|
190
|
+
|
|
191
|
+
const rawPackageDeps = normalizeDependencies(
|
|
192
|
+
clonedManifest.dependencies ?? clonedManifest.Dependencies,
|
|
193
|
+
);
|
|
194
|
+
const depsForResolution = Object.fromEntries(
|
|
195
|
+
Object.entries(rawPackageDeps).map(([n, d]) => [n, d.version]),
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
log.info(` resolving ${Object.keys(depsForResolution).length} transitive dep(s)`);
|
|
199
|
+
const transitiveManifests = new Map();
|
|
200
|
+
const resolvedDeps = await resolveDependencies(
|
|
201
|
+
depsForResolution, packageSources, platform, wyvrnFetch, new Map(),
|
|
202
|
+
transitiveManifests,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
// Build an enriched deps map. Same logic as install.js: per-dep settings
|
|
206
|
+
// + recipe-declared options resolved against what the *cloned* source
|
|
207
|
+
// manifest asks for. No CLI overrides — transitive options come solely
|
|
208
|
+
// from the source package's `dependencies.<n>.options`.
|
|
209
|
+
const enrichedDeps = new Map();
|
|
210
|
+
for (const [depName, depVersion] of resolvedDeps) {
|
|
211
|
+
const depOverrides = rawPackageDeps[depName]?.settings ?? {};
|
|
212
|
+
const effectiveProfile = mergeProfile(profile, depOverrides);
|
|
213
|
+
|
|
214
|
+
const transitiveManifest = transitiveManifests.get(depName);
|
|
215
|
+
const declaration = transitiveManifest?.options
|
|
216
|
+
? normalizeOptionsDeclaration(transitiveManifest.options, `${depName}@${depVersion}`)
|
|
217
|
+
: null;
|
|
218
|
+
const effectiveOptions = resolveEffectiveOptions(
|
|
219
|
+
declaration,
|
|
220
|
+
rawPackageDeps[depName]?.options ?? {},
|
|
221
|
+
{},
|
|
222
|
+
`${depName}@${depVersion}`,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const depProfileHash = hashProfile(effectiveProfile, effectiveOptions);
|
|
226
|
+
enrichedDeps.set(depName, {
|
|
227
|
+
version: depVersion,
|
|
228
|
+
profileHash: depProfileHash,
|
|
229
|
+
profile: effectiveProfile,
|
|
230
|
+
options: effectiveOptions,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (enrichedDeps.size > 0) {
|
|
235
|
+
await downloadDependencies(
|
|
236
|
+
enrichedDeps, packageSources, platform, paths.internal,
|
|
237
|
+
wyvrnFetch, Math.max(30, Math.round(timeoutMs / 1000)),
|
|
238
|
+
{ ...authOptions, buildMode },
|
|
239
|
+
);
|
|
240
|
+
} else {
|
|
241
|
+
fs.mkdirSync(paths.internal, { recursive: true });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ── 5. Generate the CMake toolchain into wyvrn_internal/ ─────────────────
|
|
245
|
+
const { toolchain } = generateToolchain({
|
|
246
|
+
destDir: paths.internal,
|
|
247
|
+
profile,
|
|
248
|
+
profileName,
|
|
249
|
+
profileHash,
|
|
250
|
+
packageNames: [...resolvedDeps.keys()].sort(),
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// ── 6. Configure + build + install ──────────────────────────────────────
|
|
254
|
+
// Caller can override recipe.configs (e.g. for CI that only wants Release);
|
|
255
|
+
// otherwise the recipe's own default of all four CMake configurations is
|
|
256
|
+
// respected.
|
|
257
|
+
const effectiveConfigs = (configs && configs.length > 0) ? configs : recipe.configs;
|
|
258
|
+
log.info(` building ${name}@${version} (configs: ${effectiveConfigs.join(', ')})`);
|
|
259
|
+
await configureBuildInstall({
|
|
260
|
+
recipe,
|
|
261
|
+
srcRoot: paths.src,
|
|
262
|
+
buildPaths: { build: paths.build, install: paths.install },
|
|
263
|
+
toolchainFile: toolchain,
|
|
264
|
+
configs: effectiveConfigs,
|
|
265
|
+
profile,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// ── 7. Zip install dir → wyvrn.zip ──────────────────────────────────────
|
|
269
|
+
if (!fs.existsSync(paths.install) || fs.readdirSync(paths.install).length === 0) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`CMake install produced no files at ${paths.install}. ` +
|
|
272
|
+
`Check the package's install() rules in its CMakeLists.txt.`,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
log.info(` zipping install dir → ${paths.artefact}`);
|
|
276
|
+
const zip = new StreamingZipWriter(paths.artefact);
|
|
277
|
+
addFolder(zip, paths.install, paths.install);
|
|
278
|
+
await zip.finalize();
|
|
279
|
+
|
|
280
|
+
const contentSha256 = sha256Of(paths.artefact);
|
|
281
|
+
log.info(` source-build SHA256: ${contentSha256.slice(0, 16)}...`);
|
|
282
|
+
|
|
283
|
+
// ── 8. Hand off to the caller's extraction flow ─────────────────────────
|
|
284
|
+
fs.copyFileSync(paths.artefact, destZipPath);
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
found: true,
|
|
288
|
+
contentSha256,
|
|
289
|
+
profileHash,
|
|
290
|
+
gitSha,
|
|
291
|
+
gitRepo,
|
|
292
|
+
source: paths.root,
|
|
293
|
+
resolvedFrom: 'v2-source-build',
|
|
294
|
+
artefactPath: paths.artefact,
|
|
295
|
+
clonedManifestPath: manifestPath,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
module.exports = { buildFromSource };
|