wyvrnpm 2.3.2 → 2.4.1
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 +68 -5
- package/bin/wyvrn.js +36 -0
- package/claude/skills/wyvrnpm.skill +0 -0
- package/cmake/macros.cmake +51 -0
- package/package.json +1 -1
- package/src/commands/add.js +140 -0
- package/src/commands/build.js +48 -5
- package/src/commands/install.js +1 -0
- package/src/compat.js +21 -9
- package/src/download.js +1 -1
- package/src/toolchain/index.js +71 -0
- package/src/toolchain/presets.js +40 -3
- package/src/toolchain/template.cmake +11 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A simple, private C++ package manager that works with any static file hosting pr
|
|
|
4
4
|
|
|
5
5
|
There is no central registry. You control where packages are hosted.
|
|
6
6
|
|
|
7
|
-
> **README version: 2.
|
|
7
|
+
> **README version: 2.4.0** — Highlights since 2.1.0: `wyvrnpm add <name>` for dependency authoring, `HeaderOnlyLib` packages that survive cross-arch `find_package()`, `WYVRN_ARCH_SUFFIX` + the `WYVRN_APPLY_ARCH_SUFFIX(<target>)` helper so x64/x86 artefacts coexist on disk, `wyvrnpm build --generator / -G` to swap CMake generators from the CLI, package `options`, version ranges (`^`, `~`, explicit comparators), `--format=json` output, and `--upload-built` to warm the registry with source-built artefacts.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -37,16 +37,19 @@ wyvrnpm configure add-source --kind publish --name default --url s3://my-bucket
|
|
|
37
37
|
# 3. Detect and save your build environment as the default profile
|
|
38
38
|
wyvrnpm configure profile detect
|
|
39
39
|
|
|
40
|
-
# 4.
|
|
40
|
+
# 4. Add dependencies (resolves latest from your configured sources)
|
|
41
|
+
wyvrnpm add zlib fmt@^10.0.0
|
|
42
|
+
|
|
43
|
+
# 5. Install dependencies (resolved against your build profile)
|
|
41
44
|
wyvrnpm install
|
|
42
45
|
|
|
43
|
-
#
|
|
46
|
+
# 6. Configure and build via the generated CMake preset
|
|
44
47
|
wyvrnpm build
|
|
45
48
|
|
|
46
|
-
#
|
|
49
|
+
# 7. Publish your package (uses the active profile automatically)
|
|
47
50
|
wyvrnpm publish
|
|
48
51
|
|
|
49
|
-
#
|
|
52
|
+
# 8. (Optional) Link local packages for development
|
|
50
53
|
cd ../my-local-lib && wyvrnpm link
|
|
51
54
|
cd ../my-app && wyvrnpm link my-local-lib
|
|
52
55
|
```
|
|
@@ -109,6 +112,42 @@ wyvrnpm init --root ./my-project
|
|
|
109
112
|
|
|
110
113
|
---
|
|
111
114
|
|
|
115
|
+
### `wyvrnpm add`
|
|
116
|
+
|
|
117
|
+
Adds one or more dependencies to `wyvrn.json` without downloading them. Useful when you know the package name but not the latest version.
|
|
118
|
+
|
|
119
|
+
- **Bare name** — resolves `latest.json` from your configured install sources and writes `"^<latest>"` (caret range, major-pinned).
|
|
120
|
+
- **`name@<version>`** — writes the given string verbatim. Accepts exact pins (`1.2.3.4`), caret/tilde ranges (`^1.2.3.4`, `~1.2.3.4`), and explicit comparators (`>=1.80.0 <2.0.0`).
|
|
121
|
+
|
|
122
|
+
If the dependency is already listed, it is replaced. When the prior entry was an object (`{ version, settings, options }`), the `settings` and `options` are preserved — only the version field is updated.
|
|
123
|
+
|
|
124
|
+
`add` does **not** run install. Chain `wyvrnpm install` afterwards to download.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Resolve latest, write "^<latest>"
|
|
128
|
+
wyvrnpm add zlib
|
|
129
|
+
|
|
130
|
+
# Pin exactly
|
|
131
|
+
wyvrnpm add zlib@1.3.0.0
|
|
132
|
+
|
|
133
|
+
# Use a caret / tilde / comparator range
|
|
134
|
+
wyvrnpm add fmt@^10.0.0
|
|
135
|
+
wyvrnpm add boost@">=1.80.0 <2.0.0"
|
|
136
|
+
|
|
137
|
+
# Multiple in one call
|
|
138
|
+
wyvrnpm add zlib fmt@10.2.0.0 spdlog
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Options**
|
|
142
|
+
|
|
143
|
+
| Option | Default | Description |
|
|
144
|
+
|---|---|---|
|
|
145
|
+
| `--source` / `-s` | *(config)* | Base URL used for the `latest` lookup. Repeat for multiple. |
|
|
146
|
+
| `--platform` | `win_x64` | v1 legacy platform sub-path (used as a fallback during `latest` lookup). |
|
|
147
|
+
| `--manifest` | `./wyvrn.json` | Path to the manifest file. |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
112
151
|
### `wyvrnpm install`
|
|
113
152
|
|
|
114
153
|
Resolves the full dependency graph and downloads all packages.
|
|
@@ -164,6 +203,25 @@ After download, `install` also generates:
|
|
|
164
203
|
- `wyvrn_internal/wyvrn_profile.json` — snapshot of the active build profile.
|
|
165
204
|
- `CMakePresets.json` (or `CMakeUserPresets.json` if the project root file is user-owned) with a `wyvrn-<profile>` configure preset. Presets for other profiles are preserved so multiple profiles coexist.
|
|
166
205
|
|
|
206
|
+
**Toolchain variables exposed to your `CMakeLists.txt` (valid BEFORE `project()`)**:
|
|
207
|
+
|
|
208
|
+
| Variable | Value |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `WYVRN_PROFILE_NAME` / `WYVRN_PROFILE_HASH` | Active profile name + 16-char hash |
|
|
211
|
+
| `WYVRN_PROFILE_OS` / `WYVRN_PROFILE_ARCH` | OS + architecture from the profile |
|
|
212
|
+
| `WYVRN_PROFILE_COMPILER` / `WYVRN_PROFILE_COMPILER_VERSION` | Compiler identity |
|
|
213
|
+
| `WYVRN_PROFILE_CPPSTD` / `WYVRN_PROFILE_RUNTIME` | C++ standard + MSVC runtime linkage |
|
|
214
|
+
| `WYVRN_ARCH_SUFFIX` | `"64"` for 64-bit arches, `"32"` for 32-bit, empty for unmapped. Derived at toolchain-generation time so it's usable before `project()` — unlike `CMAKE_SIZEOF_VOID_P`. |
|
|
215
|
+
|
|
216
|
+
The optional helper `WYVRN_APPLY_ARCH_SUFFIX(<target> [BASE_NAME <name>])` from the bundled `macros.cmake` applies the suffix to a target's `OUTPUT_NAME` so x64 and x86 builds of the same library coexist on disk without overwriting each other. Target linkage (`target_link_libraries`) is unaffected — only the produced filename changes.
|
|
217
|
+
|
|
218
|
+
```cmake
|
|
219
|
+
project(String CXX)
|
|
220
|
+
add_library(String STATIC ...)
|
|
221
|
+
WYVRN_APPLY_ARCH_SUFFIX(String) # → String64.lib / String32.lib
|
|
222
|
+
WYVRN_APPLY_ARCH_SUFFIX(String BASE_NAME my-str) # → my-str64.lib / my-str32.lib
|
|
223
|
+
```
|
|
224
|
+
|
|
167
225
|
---
|
|
168
226
|
|
|
169
227
|
### `wyvrnpm build`
|
|
@@ -189,6 +247,10 @@ wyvrnpm build --target my-lib
|
|
|
189
247
|
# Wipe the build directory first
|
|
190
248
|
wyvrnpm build --clean
|
|
191
249
|
|
|
250
|
+
# Override the preset's generator (pair with --clean when switching generators)
|
|
251
|
+
wyvrnpm build --clean --generator "Visual Studio 17 2022"
|
|
252
|
+
wyvrnpm build --clean -G "Ninja Multi-Config"
|
|
253
|
+
|
|
192
254
|
# Build, then install to the CMake install prefix
|
|
193
255
|
wyvrnpm build --install
|
|
194
256
|
wyvrnpm build --install --install-prefix C:\out\stage
|
|
@@ -210,6 +272,7 @@ wyvrnpm build -- -j 8
|
|
|
210
272
|
| `--target` / `-t` | *(all)* | Specific CMake target to build. |
|
|
211
273
|
| `--verbose` / `-v` | `false` | Pass `--verbose` to `cmake --build`. |
|
|
212
274
|
| `--clean` | `false` | Remove the build directory before configuring. |
|
|
275
|
+
| `--generator` / `-G` | *(from preset)* | Override the CMake generator used at configure time (e.g. `"Visual Studio 17 2022"`, `"Ninja"`, `"Ninja Multi-Config"`). CMake bakes the generator into the cache, so pair with `--clean` when switching. When the effective generator is Visual Studio, `-A <platform>` is auto-derived from the profile's arch (`x86→Win32`, `x86_64→x64`, `armv8→ARM64`, `armv7→ARM`) so VS doesn't silently default to x64 on 32-bit profiles. |
|
|
213
276
|
| `--install` | `false` | Run `cmake --install` after a successful build. |
|
|
214
277
|
| `--install-prefix` | *(baked in)* | Override `CMAKE_INSTALL_PREFIX` for `--install` without reconfiguring. |
|
|
215
278
|
| `--auto-install` | `true` | Auto-run `wyvrnpm install` when the toolchain is stale. Disable with `--no-auto-install`. |
|
package/bin/wyvrn.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const yargs = require('yargs');
|
|
6
6
|
const init = require('../src/commands/init');
|
|
7
|
+
const add = require('../src/commands/add');
|
|
7
8
|
const install = require('../src/commands/install');
|
|
8
9
|
const clean = require('../src/commands/clean');
|
|
9
10
|
const publish = require('../src/commands/publish');
|
|
@@ -35,6 +36,34 @@ yargs
|
|
|
35
36
|
(argv) => init(argv),
|
|
36
37
|
)
|
|
37
38
|
|
|
39
|
+
// ── add ───────────────────────────────────────────────────────────────────
|
|
40
|
+
.command(
|
|
41
|
+
'add <packages...>',
|
|
42
|
+
'Add dependencies to wyvrn.json. Without @version, resolves latest and writes "^<latest>"; ' +
|
|
43
|
+
'with @version, writes the given string verbatim. Does not run install.',
|
|
44
|
+
(y) => {
|
|
45
|
+
y
|
|
46
|
+
.positional('packages', {
|
|
47
|
+
type: 'string',
|
|
48
|
+
array: true,
|
|
49
|
+
describe: 'One or more <name>[@<version>] specs',
|
|
50
|
+
})
|
|
51
|
+
.option('source', {
|
|
52
|
+
alias: 's',
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'Base URL of a package source for `latest` lookup (can be repeated)',
|
|
55
|
+
array: true,
|
|
56
|
+
})
|
|
57
|
+
.option('platform', {
|
|
58
|
+
type: 'string',
|
|
59
|
+
description: 'v1 legacy platform path (used as fallback when looking up latest)',
|
|
60
|
+
choices: ['win_x64', 'win_x86', 'linux_x64', 'linux_x86', 'osx_x64', 'osx_arm64'],
|
|
61
|
+
default: 'win_x64',
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
(argv) => add(argv),
|
|
65
|
+
)
|
|
66
|
+
|
|
38
67
|
// ── install ───────────────────────────────────────────────────────────────
|
|
39
68
|
.command(
|
|
40
69
|
'install',
|
|
@@ -156,6 +185,13 @@ yargs
|
|
|
156
185
|
default: false,
|
|
157
186
|
description: 'Remove the build directory before configuring',
|
|
158
187
|
})
|
|
188
|
+
.option('generator', {
|
|
189
|
+
alias: 'G',
|
|
190
|
+
type: 'string',
|
|
191
|
+
description:
|
|
192
|
+
'Override the preset\'s CMake generator (e.g. "Visual Studio 17 2022", "Ninja", "Ninja Multi-Config"). ' +
|
|
193
|
+
'CMake locks the generator into the build-dir cache, so pair this with --clean when switching generators.',
|
|
194
|
+
})
|
|
159
195
|
.option('install', {
|
|
160
196
|
type: 'boolean',
|
|
161
197
|
default: false,
|
|
Binary file
|
package/cmake/macros.cmake
CHANGED
|
@@ -25,6 +25,44 @@ macro(WYVRN_CONFIGURE_VERSION_HEADER)
|
|
|
25
25
|
)
|
|
26
26
|
endmacro()
|
|
27
27
|
|
|
28
|
+
# Apply WYVRN_ARCH_SUFFIX to a target's OUTPUT_NAME so the produced artefact
|
|
29
|
+
# carries an unambiguous arch marker. Opt-in — call it from your CMakeLists
|
|
30
|
+
# only if you want the suffixing:
|
|
31
|
+
#
|
|
32
|
+
# WYVRN_APPLY_ARCH_SUFFIX(String) # String64.lib / String32.lib
|
|
33
|
+
# WYVRN_APPLY_ARCH_SUFFIX(String BASE_NAME my-string) # my-string64.lib / my-string32.lib
|
|
34
|
+
#
|
|
35
|
+
# BASE_NAME defaults to the target name. The target linkage name (what
|
|
36
|
+
# consumers pass to target_link_libraries) is untouched — only the on-disk
|
|
37
|
+
# output file changes. Safe to call for any target type; does nothing if
|
|
38
|
+
# WYVRN_ARCH_SUFFIX is empty (unknown / unmapped arch).
|
|
39
|
+
function(WYVRN_APPLY_ARCH_SUFFIX _wyvrn_target)
|
|
40
|
+
set(options)
|
|
41
|
+
set(oneValueArgs BASE_NAME)
|
|
42
|
+
set(multiValueArgs)
|
|
43
|
+
cmake_parse_arguments(_WYVRN_ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
44
|
+
|
|
45
|
+
if(NOT TARGET ${_wyvrn_target})
|
|
46
|
+
message(FATAL_ERROR "WYVRN_APPLY_ARCH_SUFFIX: '${_wyvrn_target}' is not a target")
|
|
47
|
+
endif()
|
|
48
|
+
|
|
49
|
+
if("${WYVRN_ARCH_SUFFIX}" STREQUAL "")
|
|
50
|
+
# Unknown arch — leave the output name alone rather than stamping a
|
|
51
|
+
# misleading value. The caller can still set OUTPUT_NAME manually.
|
|
52
|
+
return()
|
|
53
|
+
endif()
|
|
54
|
+
|
|
55
|
+
if(_WYVRN_ARG_BASE_NAME)
|
|
56
|
+
set(_wyvrn_base "${_WYVRN_ARG_BASE_NAME}")
|
|
57
|
+
else()
|
|
58
|
+
set(_wyvrn_base "${_wyvrn_target}")
|
|
59
|
+
endif()
|
|
60
|
+
|
|
61
|
+
set_target_properties(${_wyvrn_target} PROPERTIES
|
|
62
|
+
OUTPUT_NAME "${_wyvrn_base}${WYVRN_ARCH_SUFFIX}"
|
|
63
|
+
)
|
|
64
|
+
endfunction()
|
|
65
|
+
|
|
28
66
|
function(WYVRN_INSTALL_PACKAGE_EXPORT)
|
|
29
67
|
set(options)
|
|
30
68
|
set(oneValueArgs
|
|
@@ -84,10 +122,23 @@ function(WYVRN_INSTALL_PACKAGE_EXPORT)
|
|
|
84
122
|
INSTALL_DESTINATION "${WYVRN_EXPORT_INSTALL_CMAKEDIR}"
|
|
85
123
|
)
|
|
86
124
|
|
|
125
|
+
# INTERFACE libraries (header-only) have no compiled binary, so the arch
|
|
126
|
+
# stamped by `write_basic_package_version_file()` by default makes CMake
|
|
127
|
+
# reject the package when the consumer's CMAKE_SIZEOF_VOID_P differs —
|
|
128
|
+
# even though the headers themselves are arch-portable. Pass
|
|
129
|
+
# ARCH_INDEPENDENT so a HeaderOnlyLib published from x86_64 is consumable
|
|
130
|
+
# from x86 (and vice versa). Binary kinds keep the arch check.
|
|
131
|
+
set(_wyvrn_version_args)
|
|
132
|
+
get_target_property(_wyvrn_target_type ${WYVRN_EXPORT_TARGET} TYPE)
|
|
133
|
+
if(_wyvrn_target_type STREQUAL "INTERFACE_LIBRARY")
|
|
134
|
+
list(APPEND _wyvrn_version_args ARCH_INDEPENDENT)
|
|
135
|
+
endif()
|
|
136
|
+
|
|
87
137
|
write_basic_package_version_file(
|
|
88
138
|
"${WYVRN_EXPORT_VERSION_OUTPUT}"
|
|
89
139
|
VERSION "${WYVRN_EXPORT_PACKAGE_VERSION}"
|
|
90
140
|
COMPATIBILITY SameMajorVersion
|
|
141
|
+
${_wyvrn_version_args}
|
|
91
142
|
)
|
|
92
143
|
|
|
93
144
|
install(FILES
|
package/package.json
CHANGED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const { readManifest, writeManifest } = require('../manifest');
|
|
6
|
+
const { resolveLatestVersion } = require('../resolve');
|
|
7
|
+
const { readConfig } = require('../config');
|
|
8
|
+
const log = require('../logger');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parse a `<name>[@<version>]` positional into its parts.
|
|
12
|
+
*
|
|
13
|
+
* `@` inside the version (e.g. tags like `latest`) is allowed — only the
|
|
14
|
+
* first `@` is treated as the separator.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} spec
|
|
17
|
+
* @returns {{ name: string, version: string | null }}
|
|
18
|
+
*/
|
|
19
|
+
function parseSpec(spec) {
|
|
20
|
+
const at = spec.indexOf('@');
|
|
21
|
+
if (at === -1) return { name: spec, version: null };
|
|
22
|
+
if (at === 0) throw new Error(`invalid package spec "${spec}" — missing name before "@"`);
|
|
23
|
+
const name = spec.slice(0, at);
|
|
24
|
+
const version = spec.slice(at + 1);
|
|
25
|
+
if (!version) throw new Error(`invalid package spec "${spec}" — missing version after "@"`);
|
|
26
|
+
return { name, version };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Add one or more dependencies to wyvrn.json.
|
|
31
|
+
*
|
|
32
|
+
* wyvrnpm add <name> → resolves latest, writes "^<latest>"
|
|
33
|
+
* wyvrnpm add <name>@<version> → writes "<version>" verbatim (exact or range)
|
|
34
|
+
*
|
|
35
|
+
* Existing entries are replaced. If the prior entry was an object
|
|
36
|
+
* (`{ version, settings, options }`), its settings/options are preserved —
|
|
37
|
+
* only `version` is updated.
|
|
38
|
+
*
|
|
39
|
+
* Does not run install. The user must `wyvrnpm install` afterwards.
|
|
40
|
+
*
|
|
41
|
+
* @param {object} argv
|
|
42
|
+
*/
|
|
43
|
+
async function add(argv) {
|
|
44
|
+
const manifestPath = path.resolve(argv.manifest);
|
|
45
|
+
const specs = (argv.packages ?? []).map(parseSpec);
|
|
46
|
+
|
|
47
|
+
if (specs.length === 0) {
|
|
48
|
+
log.error('no packages given. Usage: wyvrnpm add <name>[@<version>] [...]');
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Install sources — only needed when at least one spec omits @version and
|
|
53
|
+
// we have to hit `latest.json`.
|
|
54
|
+
let packageSources;
|
|
55
|
+
if (argv.source && argv.source.length > 0) {
|
|
56
|
+
packageSources = argv.source;
|
|
57
|
+
} else {
|
|
58
|
+
const config = readConfig();
|
|
59
|
+
packageSources = config.installSources.map((s) => s.url);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const needsResolve = specs.some((s) => s.version === null);
|
|
63
|
+
if (needsResolve && packageSources.length === 0) {
|
|
64
|
+
log.error(
|
|
65
|
+
'no install sources configured — cannot look up latest versions.\n' +
|
|
66
|
+
' Pass --source <url>, pin versions explicitly (`name@1.2.3.4`), or run:\n' +
|
|
67
|
+
' wyvrnpm configure add-source --kind install --name ... --url ...',
|
|
68
|
+
);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const manifest = readManifest(manifestPath);
|
|
73
|
+
|
|
74
|
+
// Preserve whichever dependencies key the manifest already uses. If neither
|
|
75
|
+
// exists, create lowercase `dependencies` (the v2 convention).
|
|
76
|
+
const depsKey =
|
|
77
|
+
Object.prototype.hasOwnProperty.call(manifest, 'dependencies') ? 'dependencies' :
|
|
78
|
+
Object.prototype.hasOwnProperty.call(manifest, 'Dependencies') ? 'Dependencies' :
|
|
79
|
+
'dependencies';
|
|
80
|
+
|
|
81
|
+
let deps = manifest[depsKey];
|
|
82
|
+
// Legacy array form → object. Editing by name is the whole point of `add`,
|
|
83
|
+
// and round-tripping as an array would silently drop per-dep settings.
|
|
84
|
+
if (Array.isArray(deps)) {
|
|
85
|
+
const obj = {};
|
|
86
|
+
for (const d of deps) {
|
|
87
|
+
const n = d.Name ?? d.name;
|
|
88
|
+
const v = d.Version ?? d.version;
|
|
89
|
+
if (n && v) obj[n] = v;
|
|
90
|
+
}
|
|
91
|
+
deps = obj;
|
|
92
|
+
} else if (!deps || typeof deps !== 'object') {
|
|
93
|
+
deps = {};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const spec of specs) {
|
|
97
|
+
let versionToWrite;
|
|
98
|
+
if (spec.version) {
|
|
99
|
+
versionToWrite = spec.version;
|
|
100
|
+
log.info(`${spec.name}: writing "${versionToWrite}" (as given)`);
|
|
101
|
+
} else {
|
|
102
|
+
const latest = await resolveLatestVersion(spec.name, packageSources, argv.platform, fetch);
|
|
103
|
+
versionToWrite = `^${latest}`;
|
|
104
|
+
log.info(`${spec.name}: latest is ${latest} → writing "${versionToWrite}"`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const prior = deps[spec.name];
|
|
108
|
+
if (prior !== undefined) {
|
|
109
|
+
const priorVer =
|
|
110
|
+
typeof prior === 'string' ? prior :
|
|
111
|
+
(prior && typeof prior === 'object') ? (prior.version ?? prior.Version ?? '(unknown)') :
|
|
112
|
+
'(unknown)';
|
|
113
|
+
log.info(` replacing existing entry: "${priorVer}"`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// If the prior entry was an object with settings/options, keep those —
|
|
117
|
+
// only bump the version field. Otherwise write the short-form string.
|
|
118
|
+
if (prior && typeof prior === 'object' && !Array.isArray(prior)) {
|
|
119
|
+
const updated = { ...prior };
|
|
120
|
+
if ('Version' in updated && !('version' in updated)) {
|
|
121
|
+
updated.Version = versionToWrite;
|
|
122
|
+
} else {
|
|
123
|
+
updated.version = versionToWrite;
|
|
124
|
+
}
|
|
125
|
+
deps[spec.name] = updated;
|
|
126
|
+
} else {
|
|
127
|
+
deps[spec.name] = versionToWrite;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
manifest[depsKey] = deps;
|
|
132
|
+
writeManifest(manifestPath, manifest);
|
|
133
|
+
|
|
134
|
+
const n = specs.length;
|
|
135
|
+
log.success(`Updated ${manifestPath} — ${n} package${n !== 1 ? 's' : ''}.`);
|
|
136
|
+
log.info('Run `wyvrnpm install` to download.');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = add;
|
|
140
|
+
module.exports.parseSpec = parseSpec;
|
package/src/commands/build.js
CHANGED
|
@@ -9,6 +9,7 @@ const { loadProfile } = require('../profile');
|
|
|
9
9
|
const { readManifest } = require('../manifest');
|
|
10
10
|
const { normalizeRecipe, hasBuildRecipe } = require('../build/recipe');
|
|
11
11
|
const { loadMsvcEnv } = require('../build/msvc-env');
|
|
12
|
+
const { archToVsPlatform, isVisualStudioGenerator } = require('../toolchain');
|
|
12
13
|
const install = require('./install');
|
|
13
14
|
const log = require('../logger');
|
|
14
15
|
|
|
@@ -70,11 +71,29 @@ function resolveBinaryDir({ rootDir, presetName }) {
|
|
|
70
71
|
|
|
71
72
|
/**
|
|
72
73
|
* Args passed to `cmake` for the configure step.
|
|
73
|
-
*
|
|
74
|
+
*
|
|
75
|
+
* `generator`, when set, appends `-G <name>` after `--preset`. CMake 3.21+
|
|
76
|
+
* lets CLI args override a preset's declared fields, so this swaps the
|
|
77
|
+
* generator at configure time without touching CMakePresets.json. Note:
|
|
78
|
+
* CMake bakes the chosen generator into the cache, so switching generators
|
|
79
|
+
* for an existing build directory requires `--clean` (otherwise CMake
|
|
80
|
+
* errors with "CMAKE_GENERATOR has changed").
|
|
81
|
+
*
|
|
82
|
+
* `vsPlatform`, when set, appends `-A <platform>`. Only meaningful for
|
|
83
|
+
* Visual Studio generators — they default to x64 when unspecified, which
|
|
84
|
+
* silently produces a 64-bit build even for a 32-bit profile. The caller
|
|
85
|
+
* is responsible for deriving this from the profile arch only when the
|
|
86
|
+
* effective generator is VS (see `isVisualStudioGenerator` +
|
|
87
|
+
* `archToVsPlatform`).
|
|
88
|
+
*
|
|
89
|
+
* @param {{ presetName: string, generator?: string|null, vsPlatform?: string|null }} args
|
|
74
90
|
* @returns {string[]}
|
|
75
91
|
*/
|
|
76
|
-
function buildConfigureArgs({ presetName }) {
|
|
77
|
-
|
|
92
|
+
function buildConfigureArgs({ presetName, generator = null, vsPlatform = null }) {
|
|
93
|
+
const args = ['--preset', presetName];
|
|
94
|
+
if (generator) args.push('-G', generator);
|
|
95
|
+
if (vsPlatform) args.push('-A', vsPlatform);
|
|
96
|
+
return args;
|
|
78
97
|
}
|
|
79
98
|
|
|
80
99
|
/**
|
|
@@ -211,8 +230,11 @@ async function build(argv) {
|
|
|
211
230
|
//
|
|
212
231
|
// Same mechanism the source-build path already uses (src/build/msvc-env.js).
|
|
213
232
|
let cmakeEnv = null;
|
|
233
|
+
let effectiveGenerator = argv.generator ?? null;
|
|
234
|
+
let effectiveProfile = null;
|
|
214
235
|
try {
|
|
215
236
|
const { profile: activeProfile } = loadProfile(profileName);
|
|
237
|
+
effectiveProfile = activeProfile;
|
|
216
238
|
// Which generator will the preset actually use? Read it from the
|
|
217
239
|
// project's own recipe if one exists. If not, default to null and let
|
|
218
240
|
// cmake/CMakePresets decide — in which case MSVC env activation is
|
|
@@ -225,16 +247,37 @@ async function build(argv) {
|
|
|
225
247
|
if (recipe.generators.length > 0) [presetGenerator] = recipe.generators;
|
|
226
248
|
} catch { /* templates need options → skip env activation */ }
|
|
227
249
|
}
|
|
250
|
+
// CLI --generator wins — that is the generator CMake will actually use,
|
|
251
|
+
// so it is the one that determines whether vcvarsall must be activated.
|
|
252
|
+
if (!effectiveGenerator) effectiveGenerator = presetGenerator;
|
|
228
253
|
cmakeEnv = await loadMsvcEnv({
|
|
229
254
|
profile: activeProfile,
|
|
230
|
-
skipForGenerator:
|
|
255
|
+
skipForGenerator: effectiveGenerator,
|
|
231
256
|
});
|
|
232
257
|
} catch (err) {
|
|
233
258
|
log.warn(`Could not resolve MSVC env activation: ${err.message}`);
|
|
234
259
|
}
|
|
235
260
|
|
|
236
261
|
// ── Configure ─────────────────────────────────────────────────────────────
|
|
237
|
-
|
|
262
|
+
// Auto-emit `-A <platform>` for Visual Studio generators, mapped from the
|
|
263
|
+
// active profile's arch. VS otherwise defaults to x64 regardless of the
|
|
264
|
+
// profile, which breaks x86 builds: CMake produces 64-bit artefacts but
|
|
265
|
+
// find_package() rejects the 32-bit installed dependencies with "version
|
|
266
|
+
// not compatible" (actually a CMAKE_SIZEOF_VOID_P mismatch, not a
|
|
267
|
+
// version-number check).
|
|
268
|
+
let vsPlatform = null;
|
|
269
|
+
if (isVisualStudioGenerator(effectiveGenerator) && effectiveProfile) {
|
|
270
|
+
vsPlatform = archToVsPlatform(effectiveProfile.arch);
|
|
271
|
+
if (vsPlatform) {
|
|
272
|
+
log.info(`Visual Studio generator + arch=${effectiveProfile.arch} → passing -A ${vsPlatform}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const configureArgs = buildConfigureArgs({
|
|
277
|
+
presetName,
|
|
278
|
+
generator: argv.generator,
|
|
279
|
+
vsPlatform,
|
|
280
|
+
});
|
|
238
281
|
log.info(`cmake ${configureArgs.join(' ')}`);
|
|
239
282
|
await runCmake(configureArgs, cmakeEnv);
|
|
240
283
|
|
package/src/commands/install.js
CHANGED
package/src/compat.js
CHANGED
|
@@ -34,12 +34,15 @@
|
|
|
34
34
|
* | version fields and leaves room for future "same major"
|
|
35
35
|
* | semantics without renaming.
|
|
36
36
|
*
|
|
37
|
-
* Missing fields default to `exact`. `os` and `arch` are
|
|
38
|
-
*
|
|
39
|
-
* binaries are never ABI-compatible.
|
|
37
|
+
* Missing fields default to `exact`. `os` and `arch` are normally forced
|
|
38
|
+
* to `exact` regardless of what the block says — cross-arch/cross-OS
|
|
39
|
+
* binaries are never ABI-compatible. The one exception is
|
|
40
|
+
* `kind: "HeaderOnlyLib"`: header-only packages ship no binary, so the
|
|
41
|
+
* publisher's declared modes for `os`/`arch` are respected. Binary kinds
|
|
42
|
+
* (`StaticLib`, `DynamicLib`, `ConsoleApp`, …) keep the hard guarantee.
|
|
40
43
|
*/
|
|
41
44
|
|
|
42
|
-
const
|
|
45
|
+
const OS_ARCH_FIELDS = new Set(['os', 'arch']);
|
|
43
46
|
|
|
44
47
|
const DEFAULT_COMPAT_FIELDS = [
|
|
45
48
|
'os',
|
|
@@ -55,19 +58,27 @@ const VALID_MODES = new Set(['exact', 'any', 'lte', 'gte', 'exact-or-newer']);
|
|
|
55
58
|
/**
|
|
56
59
|
* Normalise a raw compatibility block into `{ field → mode }`.
|
|
57
60
|
* Missing fields fall back to `exact`. Unknown modes fall back to `exact`.
|
|
58
|
-
*
|
|
61
|
+
*
|
|
62
|
+
* For binary kinds (`StaticLib`, `DynamicLib`, `ConsoleApp`, …) `os` and
|
|
63
|
+
* `arch` are forced to `exact` — publisher-declared modes are silently
|
|
64
|
+
* dropped because cross-arch binaries are never ABI-safe. For
|
|
65
|
+
* `kind: "HeaderOnlyLib"` the publisher's declared modes are respected,
|
|
66
|
+
* since there is no binary to be ABI-incompatible with.
|
|
59
67
|
*
|
|
60
68
|
* @param {object|null|undefined} rawCompat
|
|
69
|
+
* @param {string|null|undefined} [packageKind] Package manifest `kind` field.
|
|
61
70
|
* @returns {Record<string, string>}
|
|
62
71
|
*/
|
|
63
|
-
function normalizeCompat(rawCompat) {
|
|
72
|
+
function normalizeCompat(rawCompat, packageKind) {
|
|
64
73
|
const result = {};
|
|
65
74
|
for (const field of DEFAULT_COMPAT_FIELDS) result[field] = 'exact';
|
|
66
75
|
|
|
67
76
|
if (!rawCompat || typeof rawCompat !== 'object') return result;
|
|
68
77
|
|
|
78
|
+
const headerOnly = packageKind === 'HeaderOnlyLib';
|
|
79
|
+
|
|
69
80
|
for (const [field, spec] of Object.entries(rawCompat)) {
|
|
70
|
-
if (
|
|
81
|
+
if (!headerOnly && OS_ARCH_FIELDS.has(field)) continue;
|
|
71
82
|
const mode = typeof spec === 'string' ? spec : (spec && spec.mode);
|
|
72
83
|
if (mode && VALID_MODES.has(mode)) result[field] = mode;
|
|
73
84
|
}
|
|
@@ -147,13 +158,14 @@ function evaluateField(mode, consumerVal, packageVal) {
|
|
|
147
158
|
* @param {Record<string, any>} consumerProfile may include `options: {...}`
|
|
148
159
|
* @param {Record<string, any>} packageProfile may include `options: {...}`
|
|
149
160
|
* @param {object|null|undefined} rawCompat compatibility block from the package manifest
|
|
161
|
+
* @param {string|null|undefined} [packageKind] package manifest `kind` field — unlocks `os`/`arch` modes for HeaderOnlyLib
|
|
150
162
|
* @returns {{
|
|
151
163
|
* compatible: boolean,
|
|
152
164
|
* reasons: Array<{ field: string, mode: string, consumer: any, package: any, outcome: string }>,
|
|
153
165
|
* }}
|
|
154
166
|
*/
|
|
155
|
-
function evaluateCompat(consumerProfile, packageProfile, rawCompat) {
|
|
156
|
-
const compat = normalizeCompat(rawCompat);
|
|
167
|
+
function evaluateCompat(consumerProfile, packageProfile, rawCompat, packageKind) {
|
|
168
|
+
const compat = normalizeCompat(rawCompat, packageKind);
|
|
157
169
|
const reasons = [];
|
|
158
170
|
let compatible = true;
|
|
159
171
|
|
package/src/download.js
CHANGED
|
@@ -209,7 +209,7 @@ async function findCompatibleBuild({ name, version, consumerProfile, consumerOpt
|
|
|
209
209
|
: packageProfile);
|
|
210
210
|
|
|
211
211
|
const rawCompat = meta.compatibility ?? null;
|
|
212
|
-
const { compatible, reasons } = evaluateCompat(consumerFull, packageFull, rawCompat);
|
|
212
|
+
const { compatible, reasons } = evaluateCompat(consumerFull, packageFull, rawCompat, meta.kind);
|
|
213
213
|
if (compatible) {
|
|
214
214
|
candidates.push({ profileHash, packageProfile, reasons, buildEntry, meta });
|
|
215
215
|
}
|
package/src/toolchain/index.js
CHANGED
|
@@ -17,6 +17,73 @@ function getBundledCmakeDir() {
|
|
|
17
17
|
return dir.replace(/\\/g, '/');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// Arch bit-width mapping. Kept exhaustive against `ARCH_MAP` in profile.js
|
|
21
|
+
// so any arch a profile can hold has a deterministic "32"/"64" suffix.
|
|
22
|
+
// Unknown arch strings fall back to an empty suffix — the consumer's
|
|
23
|
+
// CMakeLists should then use another discriminator (e.g. profile hash).
|
|
24
|
+
const ARCH_BIT_SUFFIX = {
|
|
25
|
+
x86_64: '64',
|
|
26
|
+
x86: '32',
|
|
27
|
+
armv8: '64',
|
|
28
|
+
armv7: '32',
|
|
29
|
+
ppc64le: '64',
|
|
30
|
+
s390x: '64',
|
|
31
|
+
mips: '32',
|
|
32
|
+
mipsel: '32',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Map a profile `arch` value to the canonical "64" / "32" suffix that
|
|
37
|
+
* `WYVRN_ARCH_SUFFIX` exposes to consumer CMakeLists. Empty string for
|
|
38
|
+
* unknown arches — callers can pattern-match on that to fall back.
|
|
39
|
+
*
|
|
40
|
+
* @param {string|null|undefined} arch
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
function archToBitSuffix(arch) {
|
|
44
|
+
if (!arch) return '';
|
|
45
|
+
return ARCH_BIT_SUFFIX[arch] ?? '';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Visual Studio generator `-A <platform>` mapping. VS defaults to x64
|
|
49
|
+
// when `-A` is unspecified — which silently wins against a 32-bit profile
|
|
50
|
+
// and causes consumer-side `find_package()` to reject 32-bit artefacts
|
|
51
|
+
// with "The version found is not compatible" (a CMake pointer-size check,
|
|
52
|
+
// not a version-number check). Auto-emitting `-A` keeps VS + x86 honest.
|
|
53
|
+
const ARCH_VS_PLATFORM = {
|
|
54
|
+
x86_64: 'x64',
|
|
55
|
+
x86: 'Win32',
|
|
56
|
+
armv8: 'ARM64',
|
|
57
|
+
armv7: 'ARM',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Map a profile arch to the Visual Studio generator's `-A <platform>` value.
|
|
62
|
+
* Returns null for arches that don't map to a known VS platform — callers
|
|
63
|
+
* should skip `-A` in that case and let the user pass one explicitly.
|
|
64
|
+
*
|
|
65
|
+
* @param {string|null|undefined} arch
|
|
66
|
+
* @returns {string|null}
|
|
67
|
+
*/
|
|
68
|
+
function archToVsPlatform(arch) {
|
|
69
|
+
if (!arch) return null;
|
|
70
|
+
return ARCH_VS_PLATFORM[arch] ?? null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* True when the generator name identifies a Visual Studio generator (e.g.
|
|
75
|
+
* "Visual Studio 17 2022"). VS generators require `-A <platform>` /
|
|
76
|
+
* `architecture` in the preset; everyone else (Ninja, Make, Xcode, …)
|
|
77
|
+
* ignores it.
|
|
78
|
+
*
|
|
79
|
+
* @param {string|null|undefined} name
|
|
80
|
+
* @returns {boolean}
|
|
81
|
+
*/
|
|
82
|
+
function isVisualStudioGenerator(name) {
|
|
83
|
+
if (!name) return false;
|
|
84
|
+
return /^Visual Studio \d/.test(name);
|
|
85
|
+
}
|
|
86
|
+
|
|
20
87
|
/**
|
|
21
88
|
* Substitute `{{KEY}}` placeholders in a template string.
|
|
22
89
|
*
|
|
@@ -54,6 +121,7 @@ function buildPlaceholders({ profile, profileName, profileHash, packageNames })
|
|
|
54
121
|
PROFILE_HASH: profileHash,
|
|
55
122
|
PROFILE_OS: profile.os ?? '',
|
|
56
123
|
PROFILE_ARCH: profile.arch ?? '',
|
|
124
|
+
PROFILE_ARCH_SUFFIX: archToBitSuffix(profile.arch),
|
|
57
125
|
PROFILE_COMPILER: profile.compiler ?? '',
|
|
58
126
|
PROFILE_COMPILER_VERSION: profile['compiler.version'] ?? '',
|
|
59
127
|
PROFILE_CPPSTD: profile['compiler.cppstd'] ?? '20',
|
|
@@ -135,7 +203,10 @@ module.exports = {
|
|
|
135
203
|
generateToolchain,
|
|
136
204
|
generateCMakePresets,
|
|
137
205
|
getBundledCmakeDir,
|
|
206
|
+
archToVsPlatform,
|
|
207
|
+
isVisualStudioGenerator,
|
|
138
208
|
// Exported for tests
|
|
209
|
+
archToBitSuffix,
|
|
139
210
|
buildPlaceholders,
|
|
140
211
|
renderTemplate,
|
|
141
212
|
};
|
package/src/toolchain/presets.js
CHANGED
|
@@ -4,6 +4,21 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
6
|
const VENDOR_KEY = 'wyvrnpm/generated';
|
|
7
|
+
|
|
8
|
+
// Local copy of the arch→VS-platform mapping. Duplicated here rather than
|
|
9
|
+
// imported from ./index so preset generation can run standalone (keeps
|
|
10
|
+
// the dependency graph simple — presets.js doesn't otherwise need the
|
|
11
|
+
// toolchain generator). Keep in sync with `archToVsPlatform` in index.js.
|
|
12
|
+
const ARCH_VS_PLATFORM = {
|
|
13
|
+
x86_64: 'x64',
|
|
14
|
+
x86: 'Win32',
|
|
15
|
+
armv8: 'ARM64',
|
|
16
|
+
armv7: 'ARM',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function isVsGenerator(name) {
|
|
20
|
+
return typeof name === 'string' && /^Visual Studio \d/.test(name);
|
|
21
|
+
}
|
|
7
22
|
const SCHEMA_VERSION = 3; // requires CMake ≥ 3.21
|
|
8
23
|
|
|
9
24
|
/**
|
|
@@ -52,6 +67,11 @@ function isWyvrnGenerated(presets) {
|
|
|
52
67
|
* `CMAKE_TOOLCHAIN_FILE`. Usually
|
|
53
68
|
* derived from the project's own
|
|
54
69
|
* `build.configure` -D args.
|
|
70
|
+
* @param {string|null} [args.profileArch] Active profile arch — used to pin
|
|
71
|
+
* `architecture` for VS generators
|
|
72
|
+
* so `cmake --preset` produces
|
|
73
|
+
* binaries matching the profile
|
|
74
|
+
* (VS otherwise defaults to x64).
|
|
55
75
|
*/
|
|
56
76
|
function buildConfigurePreset({
|
|
57
77
|
profileName,
|
|
@@ -60,6 +80,7 @@ function buildConfigurePreset({
|
|
|
60
80
|
generator = null,
|
|
61
81
|
extraCacheVariables = null,
|
|
62
82
|
installDir = null,
|
|
83
|
+
profileArch = null,
|
|
63
84
|
}) {
|
|
64
85
|
const binaryDir = `\${sourceDir}/build/wyvrn-${profileName}`;
|
|
65
86
|
// Spread `extraCacheVariables` FIRST, then the wyvrn-owned entries. This
|
|
@@ -90,6 +111,19 @@ function buildConfigurePreset({
|
|
|
90
111
|
cacheVariables,
|
|
91
112
|
};
|
|
92
113
|
if (generator) preset.generator = generator;
|
|
114
|
+
|
|
115
|
+
// Visual Studio generators default to x64 when `architecture` is
|
|
116
|
+
// unspecified — which silently overrides the profile arch and makes
|
|
117
|
+
// find_package() reject 32-bit installed packages with a pointer-size
|
|
118
|
+
// mismatch. Pin `architecture` from the profile so `cmake --preset`
|
|
119
|
+
// produces the right artefacts end-to-end.
|
|
120
|
+
if (isVsGenerator(generator) && profileArch && ARCH_VS_PLATFORM[profileArch]) {
|
|
121
|
+
preset.architecture = {
|
|
122
|
+
value: ARCH_VS_PLATFORM[profileArch],
|
|
123
|
+
strategy: 'set',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
93
127
|
return preset;
|
|
94
128
|
}
|
|
95
129
|
|
|
@@ -127,6 +161,7 @@ function buildFreshPresetsFile({
|
|
|
127
161
|
generator = null,
|
|
128
162
|
extraCacheVariables = null,
|
|
129
163
|
installDir = null,
|
|
164
|
+
profileArch = null,
|
|
130
165
|
}) {
|
|
131
166
|
return {
|
|
132
167
|
version: SCHEMA_VERSION,
|
|
@@ -138,7 +173,7 @@ function buildFreshPresetsFile({
|
|
|
138
173
|
},
|
|
139
174
|
},
|
|
140
175
|
configurePresets: [buildConfigurePreset({
|
|
141
|
-
profileName, profileHash, toolchainRelPath, generator, extraCacheVariables, installDir,
|
|
176
|
+
profileName, profileHash, toolchainRelPath, generator, extraCacheVariables, installDir, profileArch,
|
|
142
177
|
})],
|
|
143
178
|
buildPresets: buildBuildPresets(profileName),
|
|
144
179
|
};
|
|
@@ -161,9 +196,10 @@ function mergeIntoExisting(existing, {
|
|
|
161
196
|
generator = null,
|
|
162
197
|
extraCacheVariables = null,
|
|
163
198
|
installDir = null,
|
|
199
|
+
profileArch = null,
|
|
164
200
|
}) {
|
|
165
201
|
const newConfigure = buildConfigurePreset({
|
|
166
|
-
profileName, profileHash, toolchainRelPath, generator, extraCacheVariables, installDir,
|
|
202
|
+
profileName, profileHash, toolchainRelPath, generator, extraCacheVariables, installDir, profileArch,
|
|
167
203
|
});
|
|
168
204
|
const newBuilds = buildBuildPresets(profileName);
|
|
169
205
|
const newConfigureNames = new Set([newConfigure.name]);
|
|
@@ -223,8 +259,9 @@ function generateCMakePresets({
|
|
|
223
259
|
generator = null,
|
|
224
260
|
extraCacheVariables = null,
|
|
225
261
|
installDir = null,
|
|
262
|
+
profileArch = null,
|
|
226
263
|
}) {
|
|
227
|
-
const args = { profileName, profileHash, toolchainRelPath, generator, extraCacheVariables, installDir };
|
|
264
|
+
const args = { profileName, profileHash, toolchainRelPath, generator, extraCacheVariables, installDir, profileArch };
|
|
228
265
|
const candidates = [
|
|
229
266
|
{ filePath: path.join(projectRoot, 'CMakePresets.json'), isUser: false },
|
|
230
267
|
{ filePath: path.join(projectRoot, 'CMakeUserPresets.json'), isUser: true },
|
|
@@ -17,6 +17,17 @@ set(WYVRN_PROFILE_NAME "{{PROFILE_NAME}}")
|
|
|
17
17
|
set(WYVRN_PROFILE_HASH "{{PROFILE_HASH}}")
|
|
18
18
|
set(WYVRN_PROFILE_OS "{{PROFILE_OS}}")
|
|
19
19
|
set(WYVRN_PROFILE_ARCH "{{PROFILE_ARCH}}")
|
|
20
|
+
|
|
21
|
+
# "64" for 64-bit arches (x86_64, armv8, …), "32" for 32-bit (x86, armv7, …),
|
|
22
|
+
# empty for arches outside the known mapping. Derived at generation time from
|
|
23
|
+
# the profile so it is valid BEFORE `project()` — unlike CMAKE_SIZEOF_VOID_P,
|
|
24
|
+
# which is only set after the first project() call. Intended for suffixing
|
|
25
|
+
# artefact names (e.g. "String${WYVRN_ARCH_SUFFIX}" → String64 / String32) so
|
|
26
|
+
# x64 and x86 builds can coexist on disk without overwriting each other.
|
|
27
|
+
# Call WYVRN_APPLY_ARCH_SUFFIX(<target>) from macros.cmake for the common
|
|
28
|
+
# per-target shape, or reference the variable directly for other uses.
|
|
29
|
+
set(WYVRN_ARCH_SUFFIX "{{PROFILE_ARCH_SUFFIX}}")
|
|
30
|
+
|
|
20
31
|
set(WYVRN_PROFILE_COMPILER "{{PROFILE_COMPILER}}")
|
|
21
32
|
set(WYVRN_PROFILE_COMPILER_VERSION "{{PROFILE_COMPILER_VERSION}}")
|
|
22
33
|
set(WYVRN_PROFILE_CPPSTD "{{PROFILE_CPPSTD}}")
|