crosspack 0.2.1 → 0.5.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 +4 -4
- data/CHANGELOG.md +69 -0
- data/README.md +148 -117
- data/exe/crosspack +118 -44
- data/lib/crossbuild/build_manifest.rb +122 -27
- data/lib/crossbuild/builder.rb +32 -6
- data/lib/crossbuild/dep_installer.rb +127 -0
- data/lib/crossbuild/distributor.rb +15 -2
- data/lib/crossbuild/matrix.rb +29 -2
- data/lib/crossbuild/platform.rb +35 -2
- data/lib/crossbuild/runner.rb +1 -1
- data/lib/crossbuild/version.rb +1 -1
- data/lib/crossbuild/version_scheme.rb +3 -2
- data/lib/crossbuild.rb +15 -7
- data/lib/crosspack/builders/pkgbuild.rb +1 -1
- data/lib/crosspack/builders/rpm.rb +2 -1
- data/lib/crosspack/builds.rb +12 -0
- data/lib/crosspack/config.rb +164 -0
- data/lib/crosspack/manifest.rb +44 -30
- data/lib/crosspack/matrix.rb +2 -2
- data/lib/crosspack/package_manifest.rb +16 -26
- data/lib/crosspack/packer.rb +34 -15
- data/lib/crosspack/resolver.rb +2 -2
- data/lib/crosspack/version.rb +1 -1
- data/lib/crosspack.rb +3 -2
- metadata +10 -9
- data/exe/crossbuild +0 -76
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4f1b1bcc611377577384101685763d88198c0b27dc9323a8370fda526b7440d8
|
|
4
|
+
data.tar.gz: b3c121e02cfebbcfe8112bd4597f2009b35aecee53019a0c51aa2bb791f51007
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f69bb73a73517c21764f8e9bd7c31436f2d6a8615b437ea7912c06e4790a353c8952b7d4834c5a883352773fedb00ee73786689a3864a51e95f6835760aa003
|
|
7
|
+
data.tar.gz: df5e860abc414316410211b72fdf22d82f18a95cc211fa37d9316503625ae5fbffee86fa6a66f959a15f3a3a4cc44661d6dac05b002c2c1b6e438923dbc71d41
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,75 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.0] - 2026-09-13
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
- One config file: `build.yaml`, `package.yaml` and `deps.yaml` are merged
|
|
12
|
+
into a single `crosspack.yml` with `build:` / `package:` / `deps:`
|
|
13
|
+
sections and a shared top-level `name:` (plus optional `version:`, the
|
|
14
|
+
build version scheme). The three old files are no longer read — move each
|
|
15
|
+
file's body under its section, hoist `name`/`version` to the top. No
|
|
16
|
+
migration path is provided (0.4.0 was never published beyond local gem
|
|
17
|
+
builds).
|
|
18
|
+
- CLI: `-f/--file` now points at crosspack.yml (default `./crosspack.yml`);
|
|
19
|
+
the `--package` and `--build` flags are gone.
|
|
20
|
+
- Library API: `Crosspack.pack` takes `config:` (a Config or a path to
|
|
21
|
+
crosspack.yml); `Crossbuild.build` accepts a Config, a path or a ready
|
|
22
|
+
BuildManifest; the manifest classes no longer read files —
|
|
23
|
+
`Manifest.load` / `PackageManifest.load` / `BuildManifest.load` are gone,
|
|
24
|
+
`Crosspack::Config.load` is the single loader.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- `Crosspack::Config`: top-level validation (name required once, version
|
|
28
|
+
scheme, unknown keys) with the shared name/version injected into the
|
|
29
|
+
build section and the name into the package section; each section keeps
|
|
30
|
+
its own schema and path-pointing error messages.
|
|
31
|
+
|
|
32
|
+
## [0.4.0] - 2026-09-13
|
|
33
|
+
|
|
34
|
+
### Breaking
|
|
35
|
+
- The separate `crossbuild` executable is gone: one command, one staged
|
|
36
|
+
pipeline — `crosspack deps <target>` → `crosspack build <target>` →
|
|
37
|
+
`crosspack pack <target>`. The former crossbuild commands moved under
|
|
38
|
+
`crosspack` (validate/matrix/version gained build.yaml coverage; the gem
|
|
39
|
+
now installs only the `crosspack` binary).
|
|
40
|
+
- build.yaml `deps:` schema: host rules are now mappings with per-system
|
|
41
|
+
`verify` and `install` commands instead of a global `check:` plus a
|
|
42
|
+
bare command string. The 0.3.0 schema was never released outside the
|
|
43
|
+
local gem build, so no migration path is provided.
|
|
44
|
+
- `crosspack pack <target>` takes the target as a positional argument
|
|
45
|
+
(the old `--target` flag is gone) and `--version` is now optional: it
|
|
46
|
+
defaults to the version stamped by the build stage.
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- Stage pipeline with gating: `crosspack build <target>` resolves the
|
|
50
|
+
matrix entry distributing to that target, runs the deps stage first,
|
|
51
|
+
and fans artifacts out into that target's builds/ directory only;
|
|
52
|
+
`crosspack pack <target>` refuses to run before the build stage
|
|
53
|
+
("Build stage not done for target ... — Run: crosspack build <target>").
|
|
54
|
+
- The build stage stamps `.crosspack-build` (version) into every
|
|
55
|
+
`builds/<target>/` directory; `crosspack pack` reads it as the default
|
|
56
|
+
package version.
|
|
57
|
+
- deps.yaml schema versioning: an optional top-level `version:` (default
|
|
58
|
+
1). A deps.yaml declaring a newer schema than this crosspack is
|
|
59
|
+
rejected at load time with an upgrade hint; the key is reserved and no
|
|
60
|
+
longer parsed as a canonical dependency name.
|
|
61
|
+
- deps: rules may be verify-only (no install command) — presence is
|
|
62
|
+
checked, and a missing dependency reports which `install:` to add.
|
|
63
|
+
|
|
64
|
+
## [0.3.0] - 2026-09-13
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
- build.yaml `deps:` section: build dependencies with per-host install
|
|
68
|
+
commands (e.g. `ubuntu: sudo apt-get install -y imagemagick`, `windows:
|
|
69
|
+
winget install ...`, or any project script). Host selectors resolve in
|
|
70
|
+
order: distro id from `/etc/os-release`, `ID_LIKE` tokens, os, `"*"`.
|
|
71
|
+
- `crossbuild deps` command: doctor + install of the deps: dependencies;
|
|
72
|
+
`--check` reports presence only and exits 1 when something is missing.
|
|
73
|
+
- `crossbuild build` now verifies/installs deps: dependencies before the
|
|
74
|
+
matrix entries; `--no-deps` skips the pass.
|
|
75
|
+
- `crossbuild matrix` lists how each deps: entry resolves on this host.
|
|
76
|
+
|
|
8
77
|
## [0.2.1] - 2026-09-11
|
|
9
78
|
|
|
10
79
|
### Fixed
|
data/README.md
CHANGED
|
@@ -1,53 +1,122 @@
|
|
|
1
1
|
# crosspack
|
|
2
2
|
|
|
3
3
|
Cross-platform build **and** pack toolchain for Wails-style desktop apps,
|
|
4
|
-
shipped as one gem
|
|
4
|
+
shipped as one gem, one command, one config file and a staged pipeline:
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
distro × version × arch, driven by two small manifests.
|
|
6
|
+
```
|
|
7
|
+
crosspack deps <target> # verify/install the build host's dependencies
|
|
8
|
+
crosspack build <target> # compile the target's matrix entry into builds/
|
|
9
|
+
crosspack pack <target> # package builds/<target> as a native package
|
|
10
|
+
```
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
Every stage is keyed by the same target vocabulary — `debian-12`,
|
|
13
|
+
`ubuntu-24.04`, `fedora-41`, `arch`, `macos`, `windows-11.0` — and gated by
|
|
14
|
+
the previous one: `build` refuses to start before the deps stage passes, and
|
|
15
|
+
`pack` refuses to run before `build` filled `builds/<target>/`. The build
|
|
16
|
+
stage also stamps the version into the tree, so `pack` normally needs no
|
|
17
|
+
`--version`:
|
|
17
18
|
|
|
18
19
|
```
|
|
19
|
-
|
|
20
|
-
crosspack
|
|
20
|
+
crosspack deps ubuntu-24.04
|
|
21
|
+
crosspack build ubuntu-24.04
|
|
22
|
+
crosspack pack ubuntu-24.04
|
|
21
23
|
```
|
|
22
24
|
|
|
23
|
-
##
|
|
25
|
+
## crosspack.yml — one file, three sections
|
|
26
|
+
|
|
27
|
+
The top level carries the shared facts — `name` (required once) and the
|
|
28
|
+
optional `version` scheme — and three sections: `build:` (what and where to
|
|
29
|
+
build), `package:` (what and how to pack) and `deps:` (runtime dependencies
|
|
30
|
+
resolved to concrete packages per distro). The shared name/version feed the
|
|
31
|
+
build section, the name feeds the package section; each section keeps its
|
|
32
|
+
own schema.
|
|
24
33
|
|
|
25
34
|
```yaml
|
|
26
35
|
name: myapp
|
|
27
36
|
version: calver # calver | git-tag | env:VAR | any literal string
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
|
|
38
|
+
build:
|
|
39
|
+
output: builds # default builds; mirrors package `sources`
|
|
40
|
+
|
|
41
|
+
deps: # build dependencies, per-host verify/install
|
|
42
|
+
imagemagick:
|
|
43
|
+
hosts: # first selector matching this host wins
|
|
44
|
+
ubuntu:
|
|
45
|
+
verify: dpkg -s imagemagick
|
|
46
|
+
install: sudo apt-get install -y imagemagick
|
|
47
|
+
darwin:
|
|
48
|
+
verify: magick -version
|
|
49
|
+
install: brew install imagemagick
|
|
50
|
+
windows:
|
|
51
|
+
verify: where magick
|
|
52
|
+
install: winget install -e --id ImageMagick.ImageMagick
|
|
53
|
+
"*": # any command — package manager or a project script
|
|
54
|
+
install: ./scripts/install-imagemagick.sh
|
|
55
|
+
|
|
56
|
+
matrix:
|
|
57
|
+
- build: linux/amd64 # os/arch this entry builds on (arch may be "any")
|
|
58
|
+
env: # extra env for the steps of this entry
|
|
59
|
+
CGO_ENABLED: "1"
|
|
60
|
+
steps: # shell commands, run from the project root
|
|
61
|
+
- wails build -platform linux/amd64 -ldflags "-X myapp/internal/app.appVersion={{version}}"
|
|
62
|
+
- cargo build --release -p helper --locked
|
|
63
|
+
artifacts:
|
|
64
|
+
from: build/bin # what got built
|
|
65
|
+
include: [myapp, helper, "*.onnx", "*.so*"] # default: ["*"]
|
|
66
|
+
to: [ubuntu-22.04, ubuntu-24.04, debian-12, debian-13]
|
|
67
|
+
mode: symlink # symlink | copy, default symlink
|
|
68
|
+
|
|
69
|
+
- id: windows # defaults to the build platform string
|
|
70
|
+
build: windows/amd64
|
|
71
|
+
steps:
|
|
72
|
+
- wails build -platform windows/amd64 -ldflags "-X ...={{version}}"
|
|
73
|
+
artifacts:
|
|
74
|
+
from: build/bin
|
|
75
|
+
include: [myapp.exe]
|
|
76
|
+
to: [windows-11.0]
|
|
77
|
+
|
|
78
|
+
package:
|
|
79
|
+
maintainer: Your Name <you@example.com>
|
|
80
|
+
summary: MyApp - cross-platform desktop application # optional
|
|
81
|
+
description: |-
|
|
82
|
+
MyApp - cross-platform desktop application.
|
|
83
|
+
Bundles helper binaries and model assets alongside the GUI...
|
|
84
|
+
license: Proprietary # optional, default Proprietary
|
|
85
|
+
section: utils # optional, deb only
|
|
86
|
+
|
|
87
|
+
sources: builds # compiled artifacts tree written by the build
|
|
88
|
+
# stage: builds/<family>/<version>/<arch>/ —
|
|
89
|
+
# pack without a matching build dir fails honestly
|
|
90
|
+
prefix: usr/local # install prefix inside the package
|
|
91
|
+
lib_dir: lib/myapp # optional, default lib/<name>
|
|
92
|
+
|
|
93
|
+
payload: # files from sources -> <prefix>/<lib_dir>/
|
|
94
|
+
- myapp
|
|
95
|
+
- helper
|
|
96
|
+
- model.onnx
|
|
97
|
+
|
|
98
|
+
executables: [myapp, helper] # chmod 755, must be in payload
|
|
99
|
+
|
|
100
|
+
links: # symlinks relative to prefix
|
|
101
|
+
bin/myapp: ../lib/myapp/myapp
|
|
102
|
+
|
|
103
|
+
desktop: # optional, .desktop generated
|
|
104
|
+
name: MyApp
|
|
105
|
+
comment: Cross-platform desktop application
|
|
106
|
+
categories: Utility;Audio
|
|
107
|
+
|
|
108
|
+
icon: build/appicon.png # optional, -> <prefix>/share/pixmaps/<name>.png
|
|
109
|
+
|
|
110
|
+
deps:
|
|
111
|
+
# canonical dependency names resolved to concrete packages per distro
|
|
112
|
+
# family/version; an optional `version:` declares the deps schema version
|
|
113
|
+
webkit2gtk:
|
|
114
|
+
targets:
|
|
115
|
+
debian:
|
|
116
|
+
"12": [libwebkit2gtk-4.1-0, libwebkit2gtk-4.0-37] # deb: a | b
|
|
117
|
+
fedora: { "*": [webkit2gtk4.1] }
|
|
118
|
+
macos: system # OS component
|
|
119
|
+
windows: system # preinstalled (WebView2)
|
|
51
120
|
```
|
|
52
121
|
|
|
53
122
|
Placeholders `{{version}}`, `{{name}}`, `{{platform}}`, `{{os}}`, `{{arch}}`
|
|
@@ -63,6 +132,20 @@ builds/ubuntu/24.04/amd64/myapp -> build/bin/myapp (symlink)
|
|
|
63
132
|
builds/windows/11.0/x86_64/myapp.exe
|
|
64
133
|
```
|
|
65
134
|
|
|
135
|
+
### Build dependencies (build.deps)
|
|
136
|
+
|
|
137
|
+
`build.deps` is the host axis to the top-level `deps:` section's target
|
|
138
|
+
axis: the `deps:` section declares what a *package* needs at runtime;
|
|
139
|
+
`build.deps` declares what the *build host* must have. Checks differ per
|
|
140
|
+
system, so every host rule carries its own commands: `verify` (presence
|
|
141
|
+
probe; exit 0 = present; without it the name is looked up in PATH) and
|
|
142
|
+
`install` (how to install it; may be omitted for verify-only rules).
|
|
143
|
+
Selectors are tried in order: distro id from `/etc/os-release` (`ubuntu`),
|
|
144
|
+
then `ID_LIKE` tokens (`debian`), then the os (`linux`, `darwin`,
|
|
145
|
+
`windows`), then `"*"`. The deps stage runs verify → install → re-verify
|
|
146
|
+
for every dependency; a dependency that is still missing fails the stage.
|
|
147
|
+
Commands support the `{{name}}`/`{{os}}`/... placeholders.
|
|
148
|
+
|
|
66
149
|
### Version schemes
|
|
67
150
|
|
|
68
151
|
| scheme | value |
|
|
@@ -72,81 +155,27 @@ builds/windows/11.0/x86_64/myapp.exe
|
|
|
72
155
|
| `env:VAR` | taken from `VAR`; build fails loudly when unset |
|
|
73
156
|
| other string | used verbatim, e.g. `version: 1.2.3` |
|
|
74
157
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
crossbuild validate # build.yaml against the schema
|
|
79
|
-
crossbuild matrix # entries × host buildability table
|
|
80
|
-
crossbuild version # computed version
|
|
81
|
-
crossbuild build [--target linux/amd64] # all host-buildable entries, or one
|
|
82
|
-
crossbuild targets # what is in builds/ ready to pack
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
`build` refuses invalid manifests with path-pointing errors, runs only the
|
|
86
|
-
entries whose `build:` platform matches the host, then distributes.
|
|
87
|
-
|
|
88
|
-
## crosspack: two manifests
|
|
158
|
+
The whole file is validated against embedded schemas with actionable,
|
|
159
|
+
path-pointing error messages; every stage refuses to run on an invalid
|
|
160
|
+
config.
|
|
89
161
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
```yaml
|
|
93
|
-
name: myapp
|
|
94
|
-
maintainer: Your Name <you@example.com>
|
|
95
|
-
summary: MyApp - cross-platform desktop application # optional
|
|
96
|
-
description: |-
|
|
97
|
-
MyApp - cross-platform desktop application.
|
|
98
|
-
Bundles helper binaries and model assets alongside the GUI...
|
|
99
|
-
license: Proprietary # optional, default Proprietary
|
|
100
|
-
section: utils # optional, deb only
|
|
101
|
-
|
|
102
|
-
sources: builds # compiled artifacts tree written by crossbuild:
|
|
103
|
-
# builds/<family>/<version>/<arch>/ — pack without
|
|
104
|
-
# a matching build directory fails honestly
|
|
105
|
-
prefix: usr/local # install prefix inside the package
|
|
106
|
-
lib_dir: lib/myapp # optional, default lib/<name>
|
|
107
|
-
|
|
108
|
-
payload: # files from sources -> <prefix>/<lib_dir>/
|
|
109
|
-
- myapp
|
|
110
|
-
- helper
|
|
111
|
-
- model.onnx
|
|
112
|
-
|
|
113
|
-
executables: [myapp, helper] # chmod 755, must be in payload
|
|
114
|
-
|
|
115
|
-
links: # symlinks relative to prefix
|
|
116
|
-
bin/myapp: ../lib/myapp/myapp
|
|
117
|
-
|
|
118
|
-
desktop: # optional, .desktop generated
|
|
119
|
-
name: MyApp
|
|
120
|
-
comment: Cross-platform desktop application
|
|
121
|
-
categories: Utility;Audio
|
|
122
|
-
|
|
123
|
-
icon: build/appicon.png # optional, -> <prefix>/share/pixmaps/<name>.png
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**`deps.yaml`** — canonical dependency names resolved to concrete packages
|
|
127
|
-
per distro family/version (see the file itself for the full schema):
|
|
162
|
+
## CLI
|
|
128
163
|
|
|
129
|
-
```yaml
|
|
130
|
-
webkit2gtk:
|
|
131
|
-
targets:
|
|
132
|
-
debian:
|
|
133
|
-
"12": [libwebkit2gtk-4.1-0, libwebkit2gtk-4.0-37] # deb: a | b
|
|
134
|
-
fedora: { "*": [webkit2gtk4.1] }
|
|
135
|
-
macos: system # OS component
|
|
136
|
-
windows: system # preinstalled (WebView2)
|
|
137
164
|
```
|
|
165
|
+
# staged pipeline
|
|
166
|
+
crosspack deps <target> [--check] # verify/install build deps (--check: report only)
|
|
167
|
+
crosspack build <target>|--all [--no-deps] [--version X]
|
|
168
|
+
crosspack pack <target> [--version X] # version defaults to the build stamp
|
|
138
169
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
170
|
+
# inspection
|
|
171
|
+
crosspack validate # crosspack.yml: top level + all sections
|
|
172
|
+
crosspack resolve <target> # Depends line for the target
|
|
173
|
+
crosspack matrix # deps x target + build matrix tables
|
|
174
|
+
crosspack version # computed build version
|
|
175
|
+
crosspack targets # what is in builds/ ready to pack
|
|
142
176
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
```
|
|
146
|
-
crosspack validate # both package.yaml and deps.yaml
|
|
147
|
-
crosspack resolve --target debian-12 # Depends line for the target
|
|
148
|
-
crosspack matrix # dependency x target table
|
|
149
|
-
crosspack pack --target debian-12 --version 2026.08.31-1234 [--root .]
|
|
177
|
+
# options
|
|
178
|
+
-f, --file PATH # path to crosspack.yml (default: ./crosspack.yml)
|
|
150
179
|
```
|
|
151
180
|
|
|
152
181
|
`pack` picks the builder from the target and writes to
|
|
@@ -163,27 +192,29 @@ crosspacks/arch/x86_64/PKGBUILD
|
|
|
163
192
|
```ruby
|
|
164
193
|
require 'crosspack' # pulls in Crossbuild too
|
|
165
194
|
|
|
166
|
-
Crossbuild.build('
|
|
167
|
-
Crossbuild.build('
|
|
195
|
+
Crossbuild.build('crosspack.yml', root: Dir.pwd) # all host entries
|
|
196
|
+
Crossbuild.build('crosspack.yml', target: 'ubuntu-24.04') # the stages' build, library-level
|
|
168
197
|
|
|
169
198
|
Crosspack.pack(
|
|
170
|
-
|
|
199
|
+
config: 'crosspack.yml',
|
|
171
200
|
target: Crosspack::Target.parse('debian-12', arch: 'amd64'),
|
|
172
|
-
version:
|
|
201
|
+
version: nil, # nil -> the version stamped by the build stage
|
|
173
202
|
root: Dir.pwd, output_base: 'crosspacks'
|
|
174
203
|
)
|
|
175
204
|
```
|
|
176
205
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
`
|
|
206
|
+
`Crosspack::Config.load('crosspack.yml')` parses and validates the file
|
|
207
|
+
once and exposes the sections as manifests. Lower-level pieces are public
|
|
208
|
+
too: on the build side `Crossbuild::BuildManifest`, `VersionScheme`,
|
|
209
|
+
`Runner`, `Distributor`, `Matrix`, `Builder`, `DepInstaller`, `Platform`;
|
|
210
|
+
on the pack side `Crosspack::PackageManifest`, `Manifest`, `Resolver`,
|
|
211
|
+
`Matrix`, `Target`, `Builds`, `Builders::*`.
|
|
181
212
|
|
|
182
213
|
Deb needs `dpkg-deb` (present on any Debian/Ubuntu), rpm needs
|
|
183
214
|
`rpmbuild` (`sudo apt install rpm`), PKGBUILD generation needs nothing.
|
|
184
215
|
The WiX builder generates `.wxs` sources (run the WiX Toolset yourself to
|
|
185
|
-
get an MSI), the macOS builder stages the `.app` bundle (signing,
|
|
186
|
-
and .dmg creation are out of scope). Requires Ruby >= 3.2.
|
|
216
|
+
get an MSI), the macOS builder stages the `.app` bundle (signing,
|
|
217
|
+
notarization and .dmg creation are out of scope). Requires Ruby >= 3.2.
|
|
187
218
|
|
|
188
219
|
## Tests
|
|
189
220
|
|
data/exe/crosspack
CHANGED
|
@@ -5,8 +5,10 @@ require 'optparse'
|
|
|
5
5
|
|
|
6
6
|
begin
|
|
7
7
|
require 'crosspack'
|
|
8
|
+
require 'crossbuild'
|
|
8
9
|
rescue LoadError
|
|
9
10
|
require_relative '../lib/crosspack'
|
|
11
|
+
require_relative '../lib/crossbuild'
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def abort_with(message)
|
|
@@ -14,21 +16,26 @@ def abort_with(message)
|
|
|
14
16
|
exit 1
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
options = { file:
|
|
18
|
-
version: nil, root: Dir.pwd, output_base:
|
|
19
|
+
options = { file: Crosspack::Config::DEFAULT_PATH, arch: 'amd64',
|
|
20
|
+
format: nil, version: nil, root: Dir.pwd, output_base: nil,
|
|
21
|
+
check_only: false, no_deps: false, all: false }
|
|
19
22
|
parser = OptionParser.new do |opts|
|
|
20
|
-
opts.banner = "crosspack #{Crosspack::VERSION} —
|
|
23
|
+
opts.banner = "crosspack #{Crosspack::VERSION} — staged pipeline: deps → build → pack\n" \
|
|
21
24
|
"Usage: crosspack <command> [options]\n" \
|
|
22
|
-
|
|
25
|
+
"Stages: deps <target> [--check] verify/install build deps for the target's host\n" \
|
|
26
|
+
" build <target>|--all compile the target's matrix entry into builds/\n" \
|
|
27
|
+
" pack <target> [--version X] package builds/<target> (version from the build stamp)\n" \
|
|
28
|
+
'Commands: validate, resolve, matrix, version, targets'
|
|
23
29
|
|
|
24
|
-
opts.on('-f', '--file PATH', 'path to
|
|
25
|
-
opts.on('--package PATH', 'path to package.yaml (default: ./package.yaml)') { |v| options[:package] = v }
|
|
26
|
-
opts.on('--target TARGET', 'target: debian-12, ubuntu-24.04, fedora-41, arch, macos, windows') { |v| options[:target] = v }
|
|
30
|
+
opts.on('-f', '--file PATH', 'path to crosspack.yml (default: ./crosspack.yml)') { |v| options[:file] = v }
|
|
27
31
|
opts.on('--arch ARCH', 'architecture: amd64/x86_64, arm64/aarch64 (default: amd64)') { |v| options[:arch] = v }
|
|
28
32
|
opts.on('--format FORMAT', 'output format for resolve: deb, rpm, pkgbuild (default: derived from the target)') { |v| options[:format] = v.to_sym }
|
|
29
|
-
opts.on('--version VERSION', '
|
|
33
|
+
opts.on('--version VERSION', 'override the version for build/pack') { |v| options[:version] = v }
|
|
30
34
|
opts.on('--root PATH', 'project root for relative paths (default: .)') { |v| options[:root] = v }
|
|
31
|
-
opts.on('--output-base DIR', 'output directory (default: ./crosspacks)') { |v| options[:output_base] = v }
|
|
35
|
+
opts.on('--output-base DIR', 'output directory (build stage: the manifest output, default builds; pack: default ./crosspacks)') { |v| options[:output_base] = v }
|
|
36
|
+
opts.on('--check', 'with `deps`: only report presence, never install (exit 1 if missing)') { options[:check_only] = true }
|
|
37
|
+
opts.on('--no-deps', 'with `build`: skip the deps stage') { options[:no_deps] = true }
|
|
38
|
+
opts.on('--all', 'with `build`: every host-buildable matrix entry (default target selection off)') { options[:all] = true }
|
|
32
39
|
opts.on('-h', '--help', 'show help') do
|
|
33
40
|
puts opts
|
|
34
41
|
exit
|
|
@@ -43,77 +50,144 @@ end
|
|
|
43
50
|
command = ARGV.shift
|
|
44
51
|
abort_with 'No command given. See: crosspack --help' if command.nil?
|
|
45
52
|
|
|
46
|
-
# Positional
|
|
47
|
-
|
|
53
|
+
# Positional argument: a target for the stage commands (deps/build/pack,
|
|
54
|
+
# resolve), a crosspack.yml path for validate.
|
|
55
|
+
positional = ARGV.shift if ARGV.first && !ARGV.first.start_with?('-')
|
|
56
|
+
|
|
57
|
+
options[:file] = positional if command == 'validate' && positional
|
|
48
58
|
|
|
49
59
|
begin
|
|
50
|
-
|
|
60
|
+
config = Crosspack::Config.load(File.expand_path(options[:file], options[:root]))
|
|
51
61
|
rescue Crosspack::InvalidManifestError => e
|
|
52
62
|
abort_with e.message
|
|
53
63
|
end
|
|
54
64
|
|
|
65
|
+
# validate prints the full report itself and exits by status; everything
|
|
66
|
+
# else stops on a broken top level first.
|
|
67
|
+
if command != 'validate'
|
|
68
|
+
abort_with config.error_report unless config.valid?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# The matrix entry that builds `target` — the deps/build stages operate on
|
|
72
|
+
# its host platform.
|
|
73
|
+
def entry_for_target!(manifest, target, host_os, host_arch)
|
|
74
|
+
entry = manifest.entry_for_target(target)
|
|
75
|
+
host = "#{host_os}/#{Crossbuild::Platform.display_arch(host_arch)}"
|
|
76
|
+
unless entry.buildable_on?(host_os, host_arch)
|
|
77
|
+
abort_with "The entry for #{target.inspect} (#{entry.id}) builds on #{entry.platform}, " \
|
|
78
|
+
"this host is #{host} — cross-compilation is not supported"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
entry
|
|
82
|
+
end
|
|
83
|
+
|
|
55
84
|
case command
|
|
56
85
|
when 'validate'
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
puts manifest.error_report
|
|
86
|
+
deps_manifest = config.deps_manifest
|
|
87
|
+
pkg = config.package_manifest
|
|
88
|
+
build_manifest = config.build_manifest
|
|
89
|
+
puts config.error_report
|
|
90
|
+
puts deps_manifest.error_report
|
|
63
91
|
puts pkg.error_report
|
|
64
|
-
|
|
92
|
+
puts build_manifest.error_report
|
|
93
|
+
ok = config.valid? && deps_manifest.valid? && pkg.valid? && build_manifest.valid?
|
|
94
|
+
exit(ok ? 0 : 1)
|
|
65
95
|
when 'matrix'
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
deps_manifest = config.deps_manifest
|
|
97
|
+
abort_with 'the deps: section is invalid — run: crosspack validate' unless deps_manifest.valid?
|
|
98
|
+
puts Crosspack::Matrix.new(deps_manifest).render
|
|
99
|
+
build_manifest = config.build_manifest
|
|
100
|
+
if build_manifest.valid?
|
|
101
|
+
puts "\n#{Crossbuild::Matrix.new(build_manifest).render}"
|
|
102
|
+
else
|
|
103
|
+
warn "\nnote: no valid build: section — build matrix not shown (crosspack validate)"
|
|
74
104
|
end
|
|
105
|
+
when 'resolve'
|
|
106
|
+
target_str = positional
|
|
107
|
+
abort_with 'Specify a target: crosspack resolve debian-12 (see crosspack --help)' unless target_str
|
|
75
108
|
begin
|
|
109
|
+
manifest = config.deps_manifest
|
|
110
|
+
target = Crosspack::Target.parse(target_str, arch: options[:arch])
|
|
76
111
|
resolver = Crosspack::Resolver.new(manifest)
|
|
77
112
|
format = options[:format] || target.format
|
|
78
113
|
result = resolver.depends(target, format: format)
|
|
114
|
+
puts "# #{target} (#{format})"
|
|
79
115
|
if result.is_a?(Array)
|
|
80
|
-
puts "# #{target} (#{format})"
|
|
81
116
|
result.each { |d| puts d }
|
|
82
117
|
else
|
|
83
|
-
puts "# #{target} (#{format})"
|
|
84
118
|
puts "Depends: #{result}"
|
|
85
119
|
end
|
|
86
|
-
rescue Crosspack::
|
|
87
|
-
abort_with "
|
|
120
|
+
rescue Crosspack::Target::Error => e
|
|
121
|
+
abort_with "Invalid target #{target_str.inspect}: #{e.message}"
|
|
122
|
+
rescue Crosspack::InvalidManifestError, Crosspack::ResolveError => e
|
|
123
|
+
abort_with e.message
|
|
124
|
+
end
|
|
125
|
+
when 'version'
|
|
126
|
+
build_manifest = config.build_manifest
|
|
127
|
+
abort_with 'the build: section is invalid — run: crosspack validate' unless build_manifest.valid?
|
|
128
|
+
begin
|
|
129
|
+
puts Crossbuild::VersionScheme.new(build_manifest.version).compute(root: options[:root])
|
|
130
|
+
rescue Crossbuild::VersionScheme::Error => e
|
|
131
|
+
abort_with e.message
|
|
132
|
+
end
|
|
133
|
+
when 'deps'
|
|
134
|
+
abort_with 'Specify a target: crosspack deps debian-12 (see crosspack --help)' unless positional
|
|
135
|
+
build_manifest = config.build_manifest
|
|
136
|
+
abort_with 'the build: section is invalid — run: crosspack validate' unless build_manifest.valid?
|
|
137
|
+
entry_for_target!(build_manifest, positional, Crossbuild::Platform.os, Crossbuild::Platform.arch)
|
|
138
|
+
installer = Crossbuild::DepInstaller.new(build_manifest, root: options[:root])
|
|
139
|
+
begin
|
|
140
|
+
if options[:check_only]
|
|
141
|
+
installer.check_all
|
|
142
|
+
puts "deps on this host:\n#{installer.report}"
|
|
143
|
+
exit(installer.statuses.any? { |s| !s.installed } ? 1 : 0)
|
|
144
|
+
end
|
|
145
|
+
installer.ensure_all
|
|
146
|
+
rescue Crossbuild::Error => e
|
|
147
|
+
abort_with e.message
|
|
88
148
|
end
|
|
149
|
+
puts "deps ready:\n#{installer.report}"
|
|
150
|
+
when 'build'
|
|
151
|
+
build_manifest = config.build_manifest
|
|
152
|
+
abort_with 'the build: section is invalid — run: crosspack validate' unless build_manifest.valid?
|
|
153
|
+
if options[:all]
|
|
154
|
+
target = nil
|
|
155
|
+
else
|
|
156
|
+
abort_with 'Specify a target: crosspack build ubuntu-24.04 (or --all for every host-buildable entry)' unless positional
|
|
157
|
+
target = positional
|
|
158
|
+
end
|
|
159
|
+
begin
|
|
160
|
+
result = Crossbuild::Builder.new(build_manifest, root: options[:root],
|
|
161
|
+
output_base: options[:output_base], version: options[:version],
|
|
162
|
+
deps: !options[:no_deps]).run(target: target)
|
|
163
|
+
rescue Crossbuild::Error, Crosspack::InvalidManifestError => e
|
|
164
|
+
abort_with e.message
|
|
165
|
+
end
|
|
166
|
+
puts "\n📦 #{result.entries.size} entr#{result.entries.size == 1 ? 'y' : 'ies'} built, version #{result.version}"
|
|
167
|
+
puts 'Pack with: crosspack pack <target>'
|
|
89
168
|
when 'pack'
|
|
90
|
-
abort_with 'Specify a target:
|
|
169
|
+
abort_with 'Specify a target: crosspack pack debian-12' unless positional
|
|
91
170
|
begin
|
|
92
|
-
target = Crosspack::Target.parse(
|
|
171
|
+
target = Crosspack::Target.parse(positional, arch: options[:arch])
|
|
93
172
|
path = Crosspack.pack(
|
|
94
|
-
|
|
95
|
-
deps: options[:file],
|
|
173
|
+
config: config,
|
|
96
174
|
target: target,
|
|
97
175
|
version: options[:version],
|
|
98
176
|
root: options[:root],
|
|
99
|
-
output_base: options[:output_base]
|
|
177
|
+
output_base: options[:output_base] || 'crosspacks'
|
|
100
178
|
)
|
|
101
179
|
rescue Crosspack::Target::Error => e
|
|
102
|
-
abort_with "Invalid target #{
|
|
180
|
+
abort_with "Invalid target #{positional.inspect}: #{e.message}"
|
|
103
181
|
rescue Crosspack::InvalidManifestError, Crosspack::ResolveError, Crosspack::BuildError => e
|
|
104
182
|
abort_with e.message
|
|
105
183
|
end
|
|
106
184
|
puts "📦 #{path}"
|
|
107
185
|
when 'targets'
|
|
108
186
|
# What can actually be packed: builds tree + resolvable deps per target.
|
|
109
|
-
|
|
110
|
-
sources =
|
|
111
|
-
Crosspack::PackageManifest.load(pkg_path).sources
|
|
112
|
-
rescue Crosspack::InvalidManifestError
|
|
113
|
-
nil
|
|
114
|
-
end
|
|
187
|
+
pkg = config.package_manifest
|
|
188
|
+
sources = pkg.valid? ? pkg.sources : nil
|
|
115
189
|
root = sources ? File.expand_path(sources, options[:root]) : File.join(options[:root], 'builds')
|
|
116
190
|
puts Crosspack::Builds.report(root)
|
|
117
191
|
else
|
|
118
|
-
abort_with "Unknown command #{command.inspect}. Available: validate, resolve, matrix,
|
|
192
|
+
abort_with "Unknown command #{command.inspect}. Available: deps, build, pack, validate, resolve, matrix, version, targets"
|
|
119
193
|
end
|