Release under the SolidCraft name: binaries, assets and installers (#383)

* Release under the SolidCraft name: binaries, assets and installers

The desktop binary is now `solidcraft` and the CLI `solidcraft-cli` (the two app packages
are renamed; their folders move with the rest of the rename later). Every release asset is
named solidcraft-<ver>-… / SolidCraft-<ver>-windows-x64.exe, and the installers show the
SolidCraft product name.

Kept so existing installs keep updating (docs/compatibility.md):
- `solvecraft-cli` alias binary in every package, forwarding to solidcraft-cli with a
  deprecation note on stderr (tests/legacy_alias.rs).
- Linux app ID ai.storyteller.solvecraft (Flatpak ID, desktop entry, Wayland app_id).
- MSI UpgradeCode, so the MSI upgrades in place.
- deb Replaces/Conflicts/Provides and rpm Obsoletes/Provides solvecraft.
- An old-named .zsync copy so earlier AppImages find updates; a legacy .flatpakrepo copy.
- .solvecraft file associations; SOLVECRAFT_* fallbacks in the packaging scripts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

* MSI: register the legacy .solvecraft extension without a duplicate open verb

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
bherbruckandClaude Opus 5.5 authored and GitHub committed 2026-10-12 16:05:35 -04:00
1 parent f06b76e14f
commit 6090e89b3f
50 files changed
+478 -317

No files matched your search

+15 -9
View File
@@ -4,9 +4,12 @@
#
# Exports:
# ROOT workspace root
# VERSION [workspace.package] version from Cargo.toml (override: SOLVECRAFT_VERSION)
# VERSION [workspace.package] version from Cargo.toml (override: SOLIDCRAFT_VERSION)
#
# Every SOLIDCRAFT_* override also accepts the pre-rename SOLVECRAFT_* name when the new one is
# unset (compatibility shim, see docs/compatibility.md).
# DIST output directory for release artifacts (default: $ROOT/dist/release)
# SOLVECRAFT_BUILD_DATE UTC build date, YYYY-MM-DD
# SOLIDCRAFT_BUILD_DATE UTC build date, YYYY-MM-DD
# CARGO_TARGET_DIR cargo's target dir (default: $ROOT/target)
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
@@ -20,7 +23,7 @@ workspace_version() {
' "$ROOT/Cargo.toml"
}
VERSION="${SOLVECRAFT_VERSION:-$(workspace_version)}"
VERSION="${SOLIDCRAFT_VERSION:-${SOLVECRAFT_VERSION:-$(workspace_version)}}"
if [ -z "$VERSION" ]; then
echo "error: could not read [workspace.package] version from $ROOT/Cargo.toml" >&2
exit 1
@@ -32,8 +35,11 @@ mkdir -p "$DIST"
DIST="$(cd "$DIST" && pwd)"
export DIST
export SOLVECRAFT_BUILD_DATE="${SOLVECRAFT_BUILD_DATE:-$(date -u +%Y-%m-%d)}"
export SOLIDCRAFT_BUILD_DATE="${SOLIDCRAFT_BUILD_DATE:-${SOLVECRAFT_BUILD_DATE:-$(date -u +%Y-%m-%d)}}"
export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT/target}"
# Compatibility shim, see docs/compatibility.md: the reverse-DNS id (Flatpak app id, desktop,
# metainfo and MIME file names, icon name, Wayland app_id) keeps its pre-rename value so Flatpak
# installs keep updating and desktop integration keeps working.
APP_ID=ai.storyteller.solvecraft
export APP_ID
@@ -43,7 +49,7 @@ warn() {
}
# Copy the licence, notice and readme files into a package directory. The programs also carry
# them (Help > About > Licences, `solvecraft-cli licences`).
# them (Help > About > Licences, `solidcraft-cli licences`).
copy_docs() {
local dest="$1" f
for f in README.md LICENSE-MIT LICENSE-APACHE NOTICE THIRD-PARTY-LICENSES.txt; do
@@ -52,14 +58,14 @@ copy_docs() {
}
# The app icon in every size a package needs, drawn by the CLI (no image files are committed):
# $1 = the solvecraft-cli to run, $2 = output dir. Writes hicolor/<n>x<n>/apps/$APP_ID.png,
# solvecraft.ico and solvecraft-1024.png.
# $1 = the solidcraft-cli to run, $2 = output dir. Writes hicolor/<n>x<n>/apps/$APP_ID.png,
# solidcraft.ico and solidcraft-1024.png.
make_icons() {
local cli="$1" out="$2" s
for s in 16 24 32 48 64 128 256 512; do
mkdir -p "$out/hicolor/${s}x${s}/apps"
"$cli" icon --size "$s" --out "$out/hicolor/${s}x${s}/apps/$APP_ID.png" >/dev/null
done
"$cli" icon --out "$out/solvecraft.ico" >/dev/null
"$cli" icon --size 1024 --out "$out/solvecraft-1024.png" >/dev/null
"$cli" icon --out "$out/solidcraft.ico" >/dev/null
"$cli" icon --size 1024 --out "$out/solidcraft-1024.png" >/dev/null
}
+9 -5
View File
@@ -5,6 +5,7 @@ set -euo pipefail
site="${1:?site directory required}"
tag="${RELEASE_TAG:-}"
# Compatibility shim (docs/compatibility.md): the Flatpak app id keeps its pre-rename value.
app_id=ai.storyteller.solvecraft
if [ -z "$tag" ]; then
tag="$(gh api "repos/$GITHUB_REPOSITORY/releases?per_page=100" \
@@ -36,7 +37,7 @@ if curl --fail --silent --location --output /dev/null "$previous_url/summary"; t
ostree --repo="$repo_dir" remote delete previous
fi
for arch in x86_64 aarch64; do
asset="solvecraft-$version-linux-$arch.flatpak"
asset="solidcraft-$version-linux-$arch.flatpak"
gh release download "$tag" --repo "$GITHUB_REPOSITORY" --pattern "$asset" --dir "$bundles"
(
cd "$bundles"
@@ -53,7 +54,7 @@ flatpak build-update-repo --title="SolidCraft" --comment='Official SolidCraft re
--description='Official Flatpak repository for SolidCraft' \
--homepage="https://github.com/$GITHUB_REPOSITORY" --default-branch=stable "$repo_dir"
test -s "$repo_dir/summary"
cat >"$site/flatpak/solvecraft.flatpakrepo" <<META
cat >"$site/flatpak/solidcraft.flatpakrepo" <<META
[Flatpak Repo]
Title=SolidCraft
Comment=Official SolidCraft releases
@@ -62,9 +63,12 @@ Url=$base_url/flatpak/repo/
Homepage=https://github.com/$GITHUB_REPOSITORY
META
cat >"$site/flatpak/index.html" <<HTML
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>SolidCraft Flatpak repository</title></head><body><main><h1>SolidCraft Flatpak repository</h1><p>Latest published release: <strong>$tag</strong></p><p><a href="solvecraft.flatpakrepo">Add the SolidCraft repository</a></p><p>Flathub provides the required Freedesktop runtime. Add both remotes to the same user installation:</p><pre>flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak remote-add --user --if-not-exists solvecraft $base_url/flatpak/solvecraft.flatpakrepo
flatpak install --user solvecraft $app_id
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>SolidCraft Flatpak repository</title></head><body><main><h1>SolidCraft Flatpak repository</h1><p>Latest published release: <strong>$tag</strong></p><p><a href="solidcraft.flatpakrepo">Add the SolidCraft repository</a></p><p>Flathub provides the required Freedesktop runtime. Add both remotes to the same user installation:</p><pre>flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak remote-add --user --if-not-exists solidcraft $base_url/flatpak/solidcraft.flatpakrepo
flatpak install --user solidcraft $app_id
flatpak run $app_id</pre></main></body></html>
HTML
# Compatibility shim (docs/compatibility.md): links and instructions from before the rename point
# at solvecraft.flatpakrepo. Existing remotes keep working either way: they store the repo URL.
cp "$site/flatpak/solidcraft.flatpakrepo" "$site/flatpak/solvecraft.flatpakrepo"
touch "$site/.nojekyll"
+18 -16
View File
@@ -1,12 +1,12 @@
#!/usr/bin/env bash
# Build and package SolidCraft for FreeBSD:
#
# $DIST/solvecraft-<version>-freebsd-x86_64.tar.gz a /usr/local-style tree:
# solvecraft-<version>-freebsd-x86_64/{bin, share/applications, share/icons, share/mime,
# share/metainfo, share/doc/solvecraft}
# $DIST/solidcraft-<version>-freebsd-x86_64.tar.gz a /usr/local-style tree:
# solidcraft-<version>-freebsd-x86_64/{bin, share/applications, share/icons, share/mime,
# share/metainfo, share/doc/solidcraft}
#
# Install by copying the tree's contents into /usr/local:
# tar -xzf solvecraft-<version>-freebsd-x86_64.tar.gz --strip-components 1 -C /usr/local
# tar -xzf solidcraft-<version>-freebsd-x86_64.tar.gz --strip-components 1 -C /usr/local
#
# Usage: packaging/freebsd/package.sh [--skip-build]
# Needs: bash, cargo, and the packages installed by release.yml's FreeBSD job.
@@ -31,13 +31,13 @@ case "$(uname -m)" in
arm64 | aarch64) ARCH=aarch64 ;;
*) echo "unsupported architecture $(uname -m)" >&2; exit 2 ;;
esac
BASENAME="solvecraft-$VERSION-freebsd-$ARCH"
BASENAME="solidcraft-$VERSION-freebsd-$ARCH"
echo "==> SolidCraft $VERSION for FreeBSD $ARCH"
# The release VM has 12 GB; full parallelism on the biggest crates runs it out of memory.
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-4}"
if [ "$SKIP_BUILD" = 0 ]; then
(cd "$ROOT" && cargo build --release --locked -p solvecraft -p solvecraft-cli)
(cd "$ROOT" && cargo build --release --locked -p solidcraft -p solidcraft-cli)
fi
WORK="$CARGO_TARGET_DIR/freebsd-package"
STAGE="$WORK/$BASENAME"
@@ -46,25 +46,27 @@ rm -rf "$WORK"
# FreeBSD's install(1) has no -D: create the directories first.
mkdir -p "$STAGE/bin" "$STAGE/share/applications" "$STAGE/share/mime/packages" \
"$STAGE/share/metainfo" "$STAGE/share/icons" "$STAGE/share/doc/solvecraft"
install -m 755 "$BIN/solvecraft" "$BIN/solvecraft-cli" "$STAGE/bin/"
strip "$STAGE/bin/solvecraft" "$STAGE/bin/solvecraft-cli" 2>/dev/null || true
"$STAGE/share/metainfo" "$STAGE/share/icons" "$STAGE/share/doc/solidcraft"
# solvecraft-cli: the old CLI name, forwarding to solidcraft-cli (compatibility shim,
# docs/compatibility.md).
install -m 755 "$BIN/solidcraft" "$BIN/solidcraft-cli" "$BIN/solvecraft-cli" "$STAGE/bin/"
strip "$STAGE/bin/solidcraft" "$STAGE/bin/solidcraft-cli" "$STAGE/bin/solvecraft-cli" 2>/dev/null || true
# The desktop entry, MIME type, metainfo and icons are the freedesktop files Linux ships.
install -m 644 "$LINUX/$APP_ID.desktop" "$STAGE/share/applications/$APP_ID.desktop"
install -m 644 "$LINUX/$APP_ID.mime.xml" "$STAGE/share/mime/packages/$APP_ID.xml"
sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$SOLVECRAFT_BUILD_DATE/g" \
sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$SOLIDCRAFT_BUILD_DATE/g" \
"$LINUX/$APP_ID.metainfo.xml.in" >"$STAGE/share/metainfo/$APP_ID.metainfo.xml"
make_icons "$STAGE/bin/solvecraft-cli" "$WORK/icons"
make_icons "$STAGE/bin/solidcraft-cli" "$WORK/icons"
cp -R "$WORK/icons/hicolor" "$STAGE/share/icons/"
copy_docs "$STAGE/share/doc/solvecraft"
copy_docs "$STAGE/share/doc/solidcraft"
for f in bin/solvecraft bin/solvecraft-cli "share/applications/$APP_ID.desktop" \
"share/icons/hicolor/256x256/apps/$APP_ID.png" share/doc/solvecraft/LICENSE-MIT \
share/doc/solvecraft/LICENSE-APACHE share/doc/solvecraft/THIRD-PARTY-LICENSES.txt; do
for f in bin/solidcraft bin/solidcraft-cli bin/solvecraft-cli "share/applications/$APP_ID.desktop" \
"share/icons/hicolor/256x256/apps/$APP_ID.png" share/doc/solidcraft/LICENSE-MIT \
share/doc/solidcraft/LICENSE-APACHE share/doc/solidcraft/THIRD-PARTY-LICENSES.txt; do
if [ ! -e "$STAGE/$f" ]; then echo "error: $f is missing from the package" >&2; exit 1; fi
done
tar -C "$WORK" -czf "$DIST/$BASENAME.tar.gz" "$BASENAME"
echo "wrote $DIST/$BASENAME.tar.gz"
"$STAGE/bin/solvecraft-cli" --version
"$STAGE/bin/solidcraft-cli" --version
echo "==> done"
+6 -4
View File
@@ -3,20 +3,22 @@
# Adapted from PhotoCraft's AppRun (storytold/photocraft, Apache-2.0; see ATTRIBUTION.md).
#
# On Wayland the compositor resolves a window's dock icon by taking the window's
# app_id (ai.storyteller.solvecraft) and looking up an installed .desktop file.
# app_id (ai.storyteller.solvecraft, kept as a compatibility shim) and looking up an installed .desktop file.
# An AppImage installs nothing, so every AppImage run would otherwise show the
# generic "Wayland" icon. Best-effort desktop integration: on first run
# (and whenever the AppImage's path changes) install the .desktop entry and the
# hicolor icons into $XDG_DATA_HOME, then launch. Every failure here must leave
# the launch untouched. Opt out with SOLVECRAFT_NO_DESKTOP_INTEGRATION=1.
# the launch untouched. Opt out with SOLIDCRAFT_NO_DESKTOP_INTEGRATION=1 (the pre-rename
# SOLVECRAFT_NO_DESKTOP_INTEGRATION still works: compatibility shim, docs/compatibility.md).
set -u
APPDIR="$(dirname "$(readlink -f "$0")")"
# Compatibility shim (docs/compatibility.md): the pre-rename reverse-DNS id.
DESK_ID=ai.storyteller.solvecraft
integrate() {
case "${SOLVECRAFT_NO_DESKTOP_INTEGRATION:-}" in
case "${SOLIDCRAFT_NO_DESKTOP_INTEGRATION:-${SOLVECRAFT_NO_DESKTOP_INTEGRATION:-}}" in
1 | true | yes) return 0 ;;
esac
# The AppImage runtime exports $APPIMAGE; without it (an extracted AppDir) there
@@ -70,4 +72,4 @@ integrate() {
}
integrate
exec "$APPDIR/usr/bin/solvecraft" "$@"
exec "$APPDIR/usr/bin/solidcraft" "$@"
@@ -3,12 +3,12 @@ Type=Application
Name=SolidCraft
GenericName=3D CAD
Comment=Parametric 3D CAD: sketch, constrain, extrude, and change a parameter to rebuild
Exec=solvecraft %f
TryExec=solvecraft
Exec=solidcraft %f
TryExec=solidcraft
Icon=ai.storyteller.solvecraft
Terminal=false
StartupNotify=true
StartupWMClass=solvecraft
StartupWMClass=solidcraft
Categories=Graphics;3DGraphics;Engineering;
Keywords=cad;3d;parametric;sketch;step;stl;modelling;modeling;
MimeType=application/x-solvecraft;model/step;model/iges;model/stl;model/3mf;
MimeType=application/x-solidcraft;model/step;model/iges;model/stl;model/3mf;
@@ -53,9 +53,9 @@
<control>pointing</control>
</supports>
<provides>
<binary>solvecraft</binary>
<binary>solvecraft-cli</binary>
<mediatype>application/x-solvecraft</mediatype>
<binary>solidcraft</binary>
<binary>solidcraft-cli</binary>
<mediatype>application/x-solidcraft</mediatype>
</provides>
<content_rating type="oars-1.1"/>
<releases>
@@ -2,10 +2,13 @@
<!-- shared-mime-info definitions for types the system database may not have.
Installed to /usr/share/mime/packages/ (update-mime-database runs on install). -->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-solvecraft">
<mime-type type="application/x-solidcraft">
<comment>SolidCraft design</comment>
<icon name="ai.storyteller.solvecraft"/>
<sub-class-of type="application/json"/>
<glob pattern="*.solidcraft"/>
<!-- Compatibility shim (docs/compatibility.md): designs saved before the rename. -->
<glob pattern="*.solvecraft"/>
<alias type="application/x-solvecraft"/>
</mime-type>
</mime-info>
+6 -6
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env bash
# Repackage a SolidCraft Linux tarball as a single-file Flatpak bundle:
#
# $DIST/solvecraft-<version>-linux-<arch>.flatpak
# $DIST/solidcraft-<version>-linux-<arch>.flatpak
#
# Usage: packaging/linux/flatpak-bundle.sh [--no-test] [TARBALL]
#
# TARBALL defaults to $DIST/solvecraft-<version>-linux-<arch>.tar.gz from package.sh. The bundle
# TARBALL defaults to $DIST/solidcraft-<version>-linux-<arch>.tar.gz from package.sh. The bundle
# is built for the host architecture (x86_64 or aarch64), which must match the tarball's.
# Needs flatpak, flatpak-builder and the SVG pixbuf loader (librsvg2-common) for the host's
# `appstreamcli compose`; the freedesktop runtime and SDK named in the manifest are
@@ -37,7 +37,7 @@ case "$ARCH" in
aarch64 | arm64) ARCH=aarch64 ;;
*) echo "unsupported architecture $ARCH" >&2; exit 2 ;;
esac
BASENAME="solvecraft-$VERSION-linux-$ARCH"
BASENAME="solidcraft-$VERSION-linux-$ARCH"
TARBALL="${TARBALL:-$DIST/$BASENAME.tar.gz}"
[ -f "$TARBALL" ] || { echo "error: $TARBALL not found (run packaging/linux/package.sh --formats tar first)" >&2; exit 1; }
for tool in flatpak flatpak-builder; do
@@ -50,7 +50,7 @@ WORK="$CARGO_TARGET_DIR/flatpak-bundle"
rm -rf "$WORK"
mkdir -p "$WORK/stage"
tar -xzf "$TARBALL" -C "$WORK/stage" --strip-components=1
[ -x "$WORK/stage/bin/solvecraft" ] || { echo "error: $TARBALL has no bin/solvecraft" >&2; exit 1; }
[ -x "$WORK/stage/bin/solidcraft" ] || { echo "error: $TARBALL has no bin/solidcraft" >&2; exit 1; }
cp "$HERE/flatpak/$APP_ID.bundle.yml" "$WORK/$APP_ID.yml"
flatpak remote-add --user --if-not-exists flathub "$FLATHUB"
@@ -66,8 +66,8 @@ echo "wrote $OUT"
if [ "$TEST" = 1 ]; then
flatpak install --user -y --noninteractive --reinstall "$OUT"
flatpak info --user "$APP_ID"
flatpak run --command=solvecraft-cli "$APP_ID" --version
flatpak run --command=sh "$APP_ID" -c 'ls /app/share/applications /app/share/metainfo /app/share/mime/packages /app/share/icons/hicolor/256x256/apps /app/share/doc/solvecraft'
flatpak run --command=solidcraft-cli "$APP_ID" --version
flatpak run --command=sh "$APP_ID" -c 'ls /app/share/applications /app/share/metainfo /app/share/mime/packages /app/share/icons/hicolor/256x256/apps /app/share/doc/solidcraft'
python3 "$HERE/flatpak-smoke.py" --backend both
fi
echo "==> done"
+4 -3
View File
@@ -28,7 +28,7 @@ work=$(mktemp -d)
export XDG_CONFIG_HOME="$work/config" XDG_DATA_HOME="$work/data" XDG_CACHE_HOME="$work/cache"
mkdir -p "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" "$XDG_CACHE_HOME"
unset WGPU_BACKEND WGPU_BACKENDS
solvecraft --control 18837 >"$work/app.log" 2>&1 &
solidcraft --control 18837 >"$work/app.log" 2>&1 &
app=$!
cleanup() {
kill "$app" 2>/dev/null || true
@@ -165,10 +165,10 @@ def frame_statistics(png):
def probe(gl_saved_four=False):
shell = SANDBOX_PROBE
if gl_saved_four:
shell = shell.replace('solvecraft --control',
shell = shell.replace('solidcraft --control',
'mkdir -p "$XDG_DATA_HOME/solvecraft"\n'
'printf \'{"msaa":4}\' >"$XDG_DATA_HOME/solvecraft/graphics.json"\n'
'export WGPU_BACKEND=gl\nsolvecraft --control')
'export WGPU_BACKEND=gl\nsolidcraft --control')
result = subprocess.run(["flatpak", "run", "--user", "--command=bash", APP_ID, "-c", shell],
text=True, capture_output=True, timeout=125)
if result.returncode:
@@ -201,6 +201,7 @@ def run_backend(backend):
env.pop("WAYLAND_DISPLAY", None)
env.pop("WAYLAND_SOCKET", None)
env.pop("DISPLAY", None)
env.pop("SOLIDCRAFT_WAYLAND", None)
env.pop("SOLVECRAFT_WAYLAND", None)
command = ["dbus-run-session", "--"]
compositor = None
@@ -1,17 +1,19 @@
# Flatpak manifest for the single-file bundle attached to every GitHub release
# (solvecraft-<version>-linux-<arch>.flatpak). Build it with packaging/linux/flatpak-bundle.sh.
# (solidcraft-<version>-linux-<arch>.flatpak). Build it with packaging/linux/flatpak-bundle.sh.
# Adapted from PhotoCraft's (storytold/photocraft, Apache-2.0; see ATTRIBUTION.md).
#
# It repackages the release's own Linux tarball (solvecraft-<version>-linux-<arch>.tar.gz, built
# It repackages the release's own Linux tarball (solidcraft-<version>-linux-<arch>.tar.gz, built
# on Ubuntu 22.04 by package.sh) instead of compiling Rust inside flatpak-builder: no network
# during the build, and the same binaries as the AppImage/deb/rpm. The binaries need glibc >= 2.35
# and load X11, Wayland, xkbcommon and Vulkan at runtime; the freedesktop runtime has all of
# them, and the GPU driver comes from its org.freedesktop.Platform.GL extension.
# Compatibility shim, see docs/compatibility.md: the Flatpak app id keeps its pre-rename value.
# A new id would be a different app to Flatpak, and existing installs would stop updating.
id: ai.storyteller.solvecraft
runtime: org.freedesktop.Platform
runtime-version: '26.08'
sdk: org.freedesktop.Sdk
command: solvecraft
command: solidcraft
finish-args:
# Display: Wayland first; X11 only when no Wayland compositor is running.
- --socket=wayland
@@ -28,16 +30,18 @@ finish-args:
# the sandbox; `flatpak override --user --share=network ai.storyteller.solvecraft` exposes it to
# host agents) and home/host filesystem access.
modules:
- name: solvecraft
- name: solidcraft
buildsystem: simple
build-commands:
- install -Dm755 bin/solvecraft /app/bin/solvecraft
- install -Dm755 bin/solidcraft /app/bin/solidcraft
- install -Dm755 bin/solidcraft-cli /app/bin/solidcraft-cli
# The old CLI name, forwarding to solidcraft-cli (compatibility shim, docs/compatibility.md).
- install -Dm755 bin/solvecraft-cli /app/bin/solvecraft-cli
- install -Dm644 share/applications/ai.storyteller.solvecraft.desktop /app/share/applications/ai.storyteller.solvecraft.desktop
- install -Dm644 share/mime/packages/ai.storyteller.solvecraft.xml /app/share/mime/packages/ai.storyteller.solvecraft.xml
# Already has the release's version and date substituted by package.sh.
- install -Dm644 share/metainfo/ai.storyteller.solvecraft.metainfo.xml /app/share/metainfo/ai.storyteller.solvecraft.metainfo.xml
- mkdir -p /app/share/icons /app/share/doc && cp -R share/icons/hicolor /app/share/icons/ && cp -R share/doc/solvecraft /app/share/doc/
- mkdir -p /app/share/icons /app/share/doc && cp -R share/icons/hicolor /app/share/icons/ && cp -R share/doc/solidcraft /app/share/doc/
sources:
- type: dir
path: stage
+20 -5
View File
@@ -1,7 +1,15 @@
# .deb and .rpm packages (nfpm: https://nfpm.goreleaser.com). Run by package.sh, which stages
# the file tree, substitutes its path for ${STAGE} (nfpm doesn't expand env vars in `src`) and
# exports VERSION and NFPM_ARCH. Adapted from PhotoCraft's (storytold/photocraft, Apache-2.0).
name: solvecraft
name: solidcraft
# Compatibility shim (docs/compatibility.md): releases before the rename were packaged as `solvecraft`.
# Installing this package replaces that one (Debian Replaces/Conflicts, set under overrides.deb;
# nfpm writes `replaces` as RPM Obsoletes), so `apt install ./solidcraft-….deb` or `dnf install ./solidcraft-….rpm`
# upgrades an old install instead of failing on the shared desktop and icon files.
replaces:
- solvecraft
provides:
- solvecraft
arch: ${NFPM_ARCH}
platform: linux
version: ${VERSION}
@@ -10,14 +18,14 @@ version_schema: semver
release: 1
section: graphics
priority: optional
maintainer: ${SOLVECRAFT_MAINTAINER}
maintainer: ${SOLIDCRAFT_MAINTAINER}
vendor: SolidCraft contributors
homepage: https://bherbruck.github.io/solidcraft/
license: MIT OR Apache-2.0
description: |-
Open-source parametric 3D CAD in the style of Fusion
Sketches with a constraint solver, a parametric feature timeline, components and
joints, sheet metal; STEP, IGES, 3MF, STL and OBJ. Includes solvecraft-cli, a
joints, sheet metal; STEP, IGES, 3MF, STL and OBJ. Includes solidcraft-cli, a
headless command runner and MCP server for AI agents.
# The binaries link only glibc and libgcc_s directly. Windowing (X11/Wayland, xkbcommon) and the
@@ -25,6 +33,9 @@ description: |-
# the package tools can't find them: list them here.
overrides:
deb:
# Debian's rename pattern: Replaces + Conflicts + Provides (docs/compatibility.md).
conflicts:
- solvecraft
depends:
- libc6 (>= 2.35)
- libgcc-s1
@@ -59,9 +70,13 @@ overrides:
- xdg-desktop-portal
contents:
- src: ${STAGE}/usr/bin/solvecraft
dst: /usr/bin/solvecraft
- src: ${STAGE}/usr/bin/solidcraft
dst: /usr/bin/solidcraft
file_info: { mode: 0755 }
- src: ${STAGE}/usr/bin/solidcraft-cli
dst: /usr/bin/solidcraft-cli
file_info: { mode: 0755 }
# Compatibility shim (docs/compatibility.md): the old CLI name forwards to solidcraft-cli.
- src: ${STAGE}/usr/bin/solvecraft-cli
dst: /usr/bin/solvecraft-cli
file_info: { mode: 0755 }
+28 -19
View File
@@ -1,11 +1,12 @@
#!/usr/bin/env bash
# Build and package SolidCraft for Linux (<arch> is x86_64 or aarch64):
#
# $DIST/solvecraft-<version>-linux-<arch>.AppImage any distro with glibc >= the build host's
# $DIST/solvecraft-<version>-linux-<arch>.AppImage.zsync delta updates (needs zsyncmake)
# $DIST/solvecraft-<version>-linux-<arch>.deb Debian, Ubuntu, Mint, Pop!_OS, ...
# $DIST/solvecraft-<version>-linux-<arch>.rpm Fedora, openSUSE, RHEL, ...
# $DIST/solvecraft-<version>-linux-<arch>.tar.gz plain FHS-style tree (bin/, share/)
# $DIST/solidcraft-<version>-linux-<arch>.AppImage any distro with glibc >= the build host's
# $DIST/solidcraft-<version>-linux-<arch>.AppImage.zsync delta updates (needs zsyncmake)
# $DIST/solvecraft-<version>-linux-<arch>.AppImage.zsync the same, for pre-rename AppImages
# $DIST/solidcraft-<version>-linux-<arch>.deb Debian, Ubuntu, Mint, Pop!_OS, ...
# $DIST/solidcraft-<version>-linux-<arch>.rpm Fedora, openSUSE, RHEL, ...
# $DIST/solidcraft-<version>-linux-<arch>.tar.gz plain FHS-style tree (bin/, share/)
#
# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar"]
#
@@ -37,17 +38,17 @@ case "$ARCH" in
aarch64 | arm64) ARCH=aarch64; DEB_ARCH=arm64 ;;
*) echo "unsupported architecture $ARCH" >&2; exit 2 ;;
esac
export SOLVECRAFT_MAINTAINER="${SOLVECRAFT_MAINTAINER:-SolidCraft contributors <https://github.com/bherbruck/solidcraft>}"
BASENAME="solvecraft-$VERSION-linux-$ARCH"
export SOLIDCRAFT_MAINTAINER="${SOLIDCRAFT_MAINTAINER:-${SOLVECRAFT_MAINTAINER:-SolidCraft contributors <https://github.com/bherbruck/solidcraft>}}" # SOLVECRAFT_*: compatibility shim, see docs/compatibility.md
BASENAME="solidcraft-$VERSION-linux-$ARCH"
echo "==> SolidCraft $VERSION for Linux $ARCH ($FORMATS)"
if [ "$SKIP_BUILD" = 0 ]; then
if [ -n "${CROSS_TARGET:-}" ]; then
(cd "$ROOT" && cargo build --release --locked -p solvecraft -p solvecraft-cli --target "$CROSS_TARGET")
(cd "$ROOT" && cargo build --release --locked -p solidcraft -p solidcraft-cli --target "$CROSS_TARGET")
BIN="$CARGO_TARGET_DIR/$CROSS_TARGET/release"
else
(cd "$ROOT" && cargo build --release --locked -p solvecraft -p solvecraft-cli)
(cd "$ROOT" && cargo build --release --locked -p solidcraft -p solidcraft-cli)
BIN="$CARGO_TARGET_DIR/release"
fi
else
@@ -62,19 +63,21 @@ STAGE="$WORK/root"
rm -rf "$WORK"
# ---- stage an FHS tree (shared by every format) -------------------------------------------------
install -Dm755 "$BIN/solvecraft" "$STAGE/usr/bin/solvecraft"
install -Dm755 "$BIN/solidcraft" "$STAGE/usr/bin/solidcraft"
install -Dm755 "$BIN/solidcraft-cli" "$STAGE/usr/bin/solidcraft-cli"
# Compatibility shim (docs/compatibility.md): the old CLI name forwards to solidcraft-cli.
install -Dm755 "$BIN/solvecraft-cli" "$STAGE/usr/bin/solvecraft-cli"
strip "$STAGE/usr/bin/solvecraft" "$STAGE/usr/bin/solvecraft-cli" 2>/dev/null || true
strip "$STAGE/usr/bin/solidcraft" "$STAGE/usr/bin/solidcraft-cli" "$STAGE/usr/bin/solvecraft-cli" 2>/dev/null || true
install -Dm644 "$HERE/$APP_ID.desktop" "$STAGE/usr/share/applications/$APP_ID.desktop"
install -Dm644 "$HERE/$APP_ID.mime.xml" "$STAGE/usr/share/mime/packages/$APP_ID.xml"
mkdir -p "$STAGE/usr/share/metainfo"
sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$SOLVECRAFT_BUILD_DATE/g" \
sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$SOLIDCRAFT_BUILD_DATE/g" \
"$HERE/$APP_ID.metainfo.xml.in" >"$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
make_icons "$STAGE/usr/bin/solvecraft-cli" "$WORK/icons"
make_icons "$STAGE/usr/bin/solidcraft-cli" "$WORK/icons"
mkdir -p "$STAGE/usr/share/icons"
cp -R "$WORK/icons/hicolor" "$STAGE/usr/share/icons/"
mkdir -p "$STAGE/usr/share/doc/solvecraft"
copy_docs "$STAGE/usr/share/doc/solvecraft"
mkdir -p "$STAGE/usr/share/doc/solidcraft"
copy_docs "$STAGE/usr/share/doc/solidcraft"
if command -v desktop-file-validate >/dev/null; then
desktop-file-validate "$STAGE/usr/share/applications/$APP_ID.desktop"
@@ -107,7 +110,7 @@ fi
# ---- AppImage -----------------------------------------------------------------------------------
if has appimage; then
APPDIR="$WORK/SolveCraft.AppDir"
APPDIR="$WORK/SolidCraft.AppDir"
cp -R "$STAGE" "$APPDIR"
mv "$APPDIR/usr/share/doc" "$WORK/doc-unused"
# AppRun is a script, not a symlink: it installs the .desktop entry and icons into
@@ -133,19 +136,25 @@ if has appimage; then
# Update information: AppImageUpdate and the like fetch only the changed blocks of a newer
# release through the .zsync published next to each AppImage. `latest` is the newest published
# release that is not a pre-release.
REPO="${GITHUB_REPOSITORY:-bherbruck/solvecraft}"
UPDATE_INFO="gh-releases-zsync|${REPO%%/*}|${REPO#*/}|latest|solvecraft-*-linux-$ARCH.AppImage.zsync"
REPO="${GITHUB_REPOSITORY:-bherbruck/solidcraft}"
UPDATE_INFO="gh-releases-zsync|${REPO%%/*}|${REPO#*/}|latest|solidcraft-*-linux-$ARCH.AppImage.zsync"
# Extract-and-run: works without FUSE (containers, CI). With zsyncmake on the host appimagetool
# also writes the .zsync, into its working directory, hence the cd.
(cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream -u "$UPDATE_INFO" "$APPDIR" "$OUT")
echo "wrote $OUT"
if [ -s "$OUT.zsync" ]; then
echo "wrote $OUT.zsync"
# Compatibility shim (docs/compatibility.md): AppImages from before the rename look for
# `solvecraft-*-linux-$ARCH.AppImage.zsync` in the latest release. The same .zsync under that
# name (its URL is the new AppImage's file name, relative to the release) updates them to
# SolidCraft.
cp "$OUT.zsync" "$DIST/solvecraft-$VERSION-linux-$ARCH.AppImage.zsync"
echo "wrote $DIST/solvecraft-$VERSION-linux-$ARCH.AppImage.zsync (legacy update alias)"
else
warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it"
fi
fi
"$STAGE/usr/bin/solvecraft-cli" --version
"$STAGE/usr/bin/solidcraft-cli" --version
echo "==> done"
ls -lh "$DIST"
+4 -3
View File
@@ -13,7 +13,7 @@
<key>CFBundleExecutable</key>
<string>SolidCraft</string>
<key>CFBundleIdentifier</key>
<string>ai.storyteller.solvecraft</string>
<string>ai.storyteller.solidcraft</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
@@ -24,7 +24,7 @@
<string>@SHORT_VERSION@</string>
<key>CFBundleVersion</key>
<string>@SHORT_VERSION@</string>
<key>SolveCraftVersion</key>
<key>SolidCraftVersion</key>
<string>@VERSION@</string>
<key>CFBundleIconFile</key>
<string>SolidCraft</string>
@@ -43,7 +43,8 @@
<key>CFBundleTypeName</key>
<string>SolidCraft design</string>
<key>CFBundleTypeExtensions</key>
<array><string>solvecraft</string></array>
<!-- solvecraft: designs saved before the rename (compatibility shim, docs/compatibility.md). -->
<array><string>solidcraft</string><string>solvecraft</string></array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
+6 -9
View File
@@ -2,16 +2,13 @@ Install SolidCraft
Drag SolidCraft.app onto Applications.
Updating an older SolveCraft.app installation
Updating an older installation
1. Quit the app.
2. In Applications, rename the existing SolveCraft.app to SolidCraft.app.
3. Drag SolidCraft.app from this disk image onto Applications and choose Replace.
2. Drag SolidCraft.app from this disk image onto Applications and choose Replace.
If both names are already present, keep SolidCraft.app and move the old
SolveCraft.app to the Trash. The disk image does not remove old installations.
If your Dock shortcut still uses the old name, remove it from the Dock, then
open SolidCraft.app from Applications and choose Options > Keep in Dock.
Some earlier releases were installed as SolveCraft.app. Move that one to the Trash
once SolidCraft.app is in Applications, and replace any Dock shortcut with the
old name (open SolidCraft.app, then choose Options > Keep in Dock).
Your designs and settings keep their existing locations. The bundle identifier
remains ai.storyteller.solvecraft; saved designs still use .solvecraft.
Your designs and settings are not affected by the update.
+21 -15
View File
@@ -1,8 +1,9 @@
#!/usr/bin/env bash
# Build and package SolidCraft for macOS:
#
# $DIST/solvecraft-<version>-macos-<arch>.dmg SolidCraft.app on a drag-to-Applications DMG
# $DIST/solvecraft-cli-<version>-macos-<arch>.zip the headless CLI with the licence files
# $DIST/solidcraft-<version>-macos-<arch>.dmg SolidCraft.app on a drag-to-Applications DMG
# $DIST/solidcraft-cli-<version>-macos-<arch>.zip the headless CLI (and its solvecraft-cli
# compatibility alias) with the licence files
#
# Usage: packaging/macos/package.sh [--arch universal|aarch64|x86_64] [--skip-build]
#
@@ -12,6 +13,9 @@ set -euo pipefail
# shellcheck source=../env.sh
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
HERE="$ROOT/packaging/macos"
# macOS has no Flatpak-style update channel keyed by this id, so it follows the new name
# (the Linux reverse-DNS APP_ID stays as a compatibility shim; docs/compatibility.md).
MACOS_BUNDLE_ID=ai.storyteller.solidcraft
ARCH=universal
SKIP_BUILD=0
@@ -35,19 +39,19 @@ export MACOSX_DEPLOYMENT_TARGET=11.0
SHORT_VERSION="${VERSION%%-*}"
WORK="$CARGO_TARGET_DIR/macos-package"
APP="$WORK/SolidCraft.app"
DMG="$DIST/solvecraft-$VERSION-macos-$ARCH.dmg"
CLI_ZIP="$DIST/solvecraft-cli-$VERSION-macos-$ARCH.zip"
DMG="$DIST/solidcraft-$VERSION-macos-$ARCH.dmg"
CLI_ZIP="$DIST/solidcraft-cli-$VERSION-macos-$ARCH.zip"
echo "==> SolidCraft $VERSION for macOS ($ARCH)"
if [ "$SKIP_BUILD" = 0 ]; then
args=()
for t in "${TARGETS[@]}"; do args+=(--target "$t"); done
(cd "$ROOT" && cargo build --release --locked -p solvecraft -p solvecraft-cli "${args[@]}")
(cd "$ROOT" && cargo build --release --locked -p solidcraft -p solidcraft-cli "${args[@]}")
fi
rm -rf "$WORK"
mkdir -p "$WORK/bin"
for bin in solvecraft solvecraft-cli; do
for bin in solidcraft solidcraft-cli solvecraft-cli; do
inputs=()
for t in "${TARGETS[@]}"; do inputs+=("$CARGO_TARGET_DIR/$t/release/$bin"); done
lipo -create -output "$WORK/bin/$bin" "${inputs[@]}"
@@ -57,13 +61,13 @@ done
# ---- SolidCraft.app ----------------------------------------------------------------------------
echo "==> assembling $APP"
mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources"
cp "$WORK/bin/solvecraft" "$APP/Contents/MacOS/SolidCraft"
cp "$WORK/bin/solidcraft" "$APP/Contents/MacOS/SolidCraft"
# The icon, drawn by the CLI (no image files are committed).
SET="$WORK/SolidCraft.iconset"
mkdir -p "$SET"
for s in 16 32 128 256 512; do
"$WORK/bin/solvecraft-cli" icon --size "$s" --out "$SET/icon_${s}x${s}.png" >/dev/null
"$WORK/bin/solvecraft-cli" icon --size $((s * 2)) --out "$SET/icon_${s}x${s}@2x.png" >/dev/null
"$WORK/bin/solidcraft-cli" icon --size "$s" --out "$SET/icon_${s}x${s}.png" >/dev/null
"$WORK/bin/solidcraft-cli" icon --size $((s * 2)) --out "$SET/icon_${s}x${s}@2x.png" >/dev/null
done
iconutil -c icns -o "$APP/Contents/Resources/SolidCraft.icns" "$SET"
mkdir -p "$APP/Contents/Resources/Licenses"
@@ -95,12 +99,11 @@ hdiutil attach -readonly -nobrowse -mountpoint "$MNT" "$DMG"
ls -la "$MNT" "$MNT/SolidCraft.app/Contents" "$MNT/SolidCraft.app/Contents/MacOS" "$MNT/SolidCraft.app/Contents/Resources"
test -L "$MNT/Applications" && test "$(readlink "$MNT/Applications")" = /Applications
plutil -lint "$MNT/SolidCraft.app/Contents/Info.plist"
# Check the names Finder/LaunchServices actually use, as well as compatibility identity.
# Check the names Finder/LaunchServices actually use, and the bundle identity.
for key in CFBundleName CFBundleDisplayName CFBundleExecutable CFBundleIconFile; do
test "$(/usr/libexec/PlistBuddy -c "Print :$key" "$MNT/SolidCraft.app/Contents/Info.plist")" = SolidCraft
done
test "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$MNT/SolidCraft.app/Contents/Info.plist")" = "$APP_ID"
test ! -e "$MNT/SolveCraft.app"
test "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$MNT/SolidCraft.app/Contents/Info.plist")" = "$MACOS_BUNDLE_ID"
test -s "$MNT/SolidCraft.app/Contents/Resources/SolidCraft.icns"
cmp "$HERE/README.txt" "$MNT/README.txt"
case "$ARCH" in universal) WANT=(arm64 x86_64) ;; aarch64) WANT=(arm64) ;; *) WANT=(x86_64) ;; esac
@@ -115,14 +118,17 @@ hdiutil detach "$MNT"
# ---- CLI ---------------------------------------------------------------------------------------
echo "==> building $CLI_ZIP"
CLI_DIR="$WORK/solvecraft-cli-$VERSION-macos-$ARCH"
CLI_DIR="$WORK/solidcraft-cli-$VERSION-macos-$ARCH"
mkdir -p "$CLI_DIR"
cp "$WORK/bin/solidcraft-cli" "$CLI_DIR/"
codesign --force --sign - --timestamp=none --identifier "$MACOS_BUNDLE_ID-cli" "$CLI_DIR/solidcraft-cli"
# Compatibility shim (docs/compatibility.md): the old CLI name forwards to solidcraft-cli.
cp "$WORK/bin/solvecraft-cli" "$CLI_DIR/"
codesign --force --sign - --timestamp=none --identifier ai.storyteller.solvecraft-cli "$CLI_DIR/solvecraft-cli"
codesign --force --sign - --timestamp=none --identifier "$MACOS_BUNDLE_ID-cli-alias" "$CLI_DIR/solvecraft-cli"
copy_docs "$CLI_DIR"
rm -f "$CLI_ZIP"
ditto -c -k --keepParent "$CLI_DIR" "$CLI_ZIP"
"$WORK/bin/solvecraft-cli" --version
"$WORK/bin/solidcraft-cli" --version
echo "==> done"
ls -lh "$DMG" "$CLI_ZIP"
+1 -1
View File
@@ -69,7 +69,7 @@ class DesktopProbe(unittest.TestCase):
def test_cli_version_or_partial_control_output_is_not_desktop_success(self):
with self.assertRaises(ValueError):
SMOKE.validate_replies("solvecraft-cli 0.3.0\n")
SMOKE.validate_replies("solidcraft-cli 0.3.0\n")
with self.assertRaises(ValueError):
SMOKE.validate_replies(output(healthy_replies()[:1]))
+3 -3
View File
@@ -1,10 +1,10 @@
#!/usr/bin/env bash
# Build the browser version and zip it: $DIST/solvecraft-web-<version>.zip
# Build the browser version and zip it: $DIST/solidcraft-web-<version>.zip
#
# Usage: packaging/web/package.sh [--skip-build]
#
# Needs: trunk and the wasm32-unknown-unknown target. The zip holds a self-contained static site
# in solvecraft-web-<version>/ that works from any URL path (public_url = "./" in Trunk.toml).
# in solidcraft-web-<version>/ that works from any URL path (public_url = "./" in Trunk.toml).
# Saving designs needs HTTPS or localhost (the browser's private file storage).
# Adapted from PhotoCraft's packaging (storytold/photocraft, Apache-2.0; see ATTRIBUTION.md).
set -euo pipefail
@@ -24,7 +24,7 @@ if grep -Eq '(src|href)="/[^/]' "$SITE/index.html"; then
exit 1
fi
NAME="solvecraft-web-$VERSION"
NAME="solidcraft-web-$VERSION"
WORK="$CARGO_TARGET_DIR/web-package"
rm -rf "$WORK"
mkdir -p "$WORK/$NAME"
+25 -22
View File
@@ -1,15 +1,16 @@
<#
.SYNOPSIS
Build and package SolveCraft for Windows.
Build and package SolidCraft for Windows.
.DESCRIPTION
Produces, in $env:DIST (default: dist/release):
solvecraft-<version>-windows-<arch>.msi per-machine installer (WiX v5)
solvecraft-<version>-windows-<arch>-portable.zip solvecraft.exe + solvecraft-cli.exe + licences
SolveCraft-<version>-windows-<arch>.exe the app alone (x64 only: a plain download)
solidcraft-<version>-windows-<arch>.msi per-machine installer (WiX v5)
solidcraft-<version>-windows-<arch>-portable.zip solidcraft.exe + solidcraft-cli.exe + licences
(+ the solvecraft-cli.exe compatibility alias)
SolidCraft-<version>-windows-<arch>.exe the app alone (x64 only: a plain download)
The binaries link the C runtime statically (+crt-static), so nothing else needs installing.
The icon comes from $env:SOLVECRAFT_ICONS (solvecraft.ico, made by `solvecraft-cli icon`), or
The icon comes from $env:SOLIDCRAFT_ICONS (solidcraft.ico, made by `solidcraft-cli icon`), or
is drawn by the CLI just built when this machine can run it. Nothing is signed.
Needs: Rust (MSVC toolchain + the target) and WiX v5:
@@ -36,7 +37,7 @@ function Invoke-Native([string] $What, [scriptblock] $Block) {
}
# The version lives in one place: [workspace.package] version in the root Cargo.toml.
$Version = $env:SOLVECRAFT_VERSION
$Version = $env:SOLIDCRAFT_VERSION
if (-not $Version) {
$inPkg = $false
foreach ($line in Get-Content (Join-Path $Root 'Cargo.toml')) {
@@ -60,7 +61,7 @@ if (-not $SkipBuild) {
# proc-macros are unaffected.
$flagVar = 'CARGO_TARGET_' + ($Target.ToUpper() -replace '-', '_') + '_RUSTFLAGS'
[Environment]::SetEnvironmentVariable($flagVar, '-C target-feature=+crt-static')
Invoke-Native "cargo build ($Target)" { cargo build --release --locked -p solvecraft -p solvecraft-cli --target $Target }
Invoke-Native "cargo build ($Target)" { cargo build --release --locked -p solidcraft -p solidcraft-cli --target $Target }
}
$Bin = Join-Path $TargetDir "$Target\release"
@@ -72,33 +73,35 @@ function Get-PeHeader([string] $Path) {
return @{ Machine = [BitConverter]::ToUInt16($bytes, $pe + 4); Subsystem = [BitConverter]::ToUInt16($bytes, $pe + 0x5C) }
}
$Machine = switch ($Arch) { 'x64' { 0x8664 } 'x86' { 0x14C } 'arm64' { 0xAA64 } }
foreach ($check in @(@('solvecraft.exe', 2), @('solvecraft-cli.exe', 3))) {
# solvecraft-cli.exe: the old CLI name, forwarding to solidcraft-cli.exe (compatibility shim,
# docs/compatibility.md). Built by `-p solidcraft-cli` with the CLI.
foreach ($check in @(@('solidcraft.exe', 2), @('solidcraft-cli.exe', 3), @('solvecraft-cli.exe', 3))) {
$h = Get-PeHeader (Join-Path $Bin $check[0])
if ($h.Machine -ne $Machine) { throw "$($check[0]) is for machine 0x$('{0:X}' -f $h.Machine), expected 0x$('{0:X}' -f $Machine) ($Arch)" }
if ($h.Subsystem -ne $check[1]) { throw "$($check[0]) has PE subsystem $($h.Subsystem), expected $($check[1])" }
Write-Output "ok $($check[0]): $Arch, PE subsystem $($h.Subsystem)"
}
$Stage = Join-Path $TargetDir "windows-package\$Arch"
& (Join-Path $PSScriptRoot 'check-icon.ps1') -Path (Join-Path $Bin 'solvecraft.exe')
& (Join-Path $PSScriptRoot 'check-icon.ps1') -Path (Join-Path $Bin 'solidcraft.exe')
Remove-Item -Recurse -Force $Stage -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $Stage | Out-Null
Copy-Item (Join-Path $Bin 'solvecraft.exe'), (Join-Path $Bin 'solvecraft-cli.exe') $Stage
Copy-Item (Join-Path $Bin 'solidcraft.exe'), (Join-Path $Bin 'solidcraft-cli.exe'), (Join-Path $Bin 'solvecraft-cli.exe') $Stage
foreach ($f in 'LICENSE-MIT', 'LICENSE-APACHE', 'NOTICE', 'THIRD-PARTY-LICENSES.txt') { Copy-Item (Join-Path $Root $f) $Stage }
$HostArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()
$CanRun = ($Arch -ne 'arm64' -or $HostArch -eq 'arm64')
$Icon = if ($env:SOLVECRAFT_ICONS) { Join-Path $env:SOLVECRAFT_ICONS 'solvecraft.ico' } else { Join-Path $Stage 'solvecraft.ico' }
$Icon = if ($env:SOLIDCRAFT_ICONS) { Join-Path $env:SOLIDCRAFT_ICONS 'solidcraft.ico' } else { Join-Path $Stage 'solidcraft.ico' }
if (-not (Test-Path $Icon)) {
if (-not $CanRun) { throw "no icon: set SOLVECRAFT_ICONS to a folder with solvecraft.ico (an $Arch CLI can't run on this $HostArch machine)" }
Invoke-Native 'draw the icon' { & (Join-Path $Stage 'solvecraft-cli.exe') icon --out $Icon }
if (-not $CanRun) { throw "no icon: set SOLIDCRAFT_ICONS to a folder with solidcraft.ico (an $Arch CLI can't run on this $HostArch machine)" }
Invoke-Native 'draw the icon' { & (Join-Path $Stage 'solidcraft-cli.exe') icon --out $Icon }
}
# ---- MSI ---------------------------------------------------------------------------------------
$Msi = Join-Path $Dist "solvecraft-$Version-windows-$Arch.msi"
$Msi = Join-Path $Dist "solidcraft-$Version-windows-$Arch.msi"
Invoke-Native 'wix build' {
wix build (Join-Path $PSScriptRoot 'solvecraft.wxs') -arch $Arch `
wix build (Join-Path $PSScriptRoot 'solidcraft.wxs') -arch $Arch `
-ext WixToolset.UI.wixext -ext WixToolset.Util.wixext `
-culture en-US -loc (Join-Path $PSScriptRoot 'solvecraft.en-us.wxl') `
-culture en-US -loc (Join-Path $PSScriptRoot 'solidcraft.en-us.wxl') `
-d "Version=$MsiVersion" -d "DisplayVersion=$Version" -d "BinDir=$Stage" -d "IconPath=$Icon" `
-o $Msi
}
@@ -109,26 +112,26 @@ Invoke-Native 'MSI shortcut icon validation (ICE50)' {
Remove-Item -Force -ErrorAction SilentlyContinue ([IO.Path]::ChangeExtension($Msi, '.wixpdb'))
# ---- portable zip ------------------------------------------------------------------------------
$Portable = Join-Path $TargetDir "windows-package\solvecraft-$Version-windows-$Arch-portable"
$Portable = Join-Path $TargetDir "windows-package\solidcraft-$Version-windows-$Arch-portable"
Remove-Item -Recurse -Force $Portable -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $Portable | Out-Null
Copy-Item (Join-Path $Stage '*.exe') $Portable
foreach ($f in 'README.md', 'LICENSE-MIT', 'LICENSE-APACHE', 'NOTICE', 'THIRD-PARTY-LICENSES.txt') { Copy-Item (Join-Path $Root $f) $Portable }
$Zip = Join-Path $Dist "solvecraft-$Version-windows-$Arch-portable.zip"
$Zip = Join-Path $Dist "solidcraft-$Version-windows-$Arch-portable.zip"
Remove-Item -Force $Zip -ErrorAction SilentlyContinue
Compress-Archive -Path $Portable -DestinationPath $Zip
# ---- the app as a plain download (x64) ---------------------------------------------------------
$Outputs = @($Msi, $Zip)
if ($Arch -eq 'x64') {
$Exe = Join-Path $Dist "SolveCraft-$Version-windows-$Arch.exe"
Copy-Item (Join-Path $Stage 'solvecraft.exe') $Exe
$Exe = Join-Path $Dist "SolidCraft-$Version-windows-$Arch.exe"
Copy-Item (Join-Path $Stage 'solidcraft.exe') $Exe
$Outputs += $Exe
}
if ($CanRun) {
Invoke-Native 'solvecraft-cli --version' { & (Join-Path $Stage 'solvecraft-cli.exe') --version }
Invoke-Native 'solidcraft-cli --version' { & (Join-Path $Stage 'solidcraft-cli.exe') --version }
} else {
Write-Output "skipping solvecraft-cli --version: an $Arch build doesn't run on this $HostArch machine"
Write-Output "skipping solidcraft-cli --version: an $Arch build doesn't run on this $HostArch machine"
}
Get-Item $Outputs | Format-Table Name, Length
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Overrides for the setup wizard's WixUI strings, so its pages name the version being installed
([SolvecraftVersion] is the full version, pre-release tag included, set in solvecraft.wxs).
([SolidcraftVersion] is the full version, pre-release tag included, set in solidcraft.wxs).
Adapted from PhotoCraft's (storytold/photocraft, Apache-2.0; see ATTRIBUTION.md).
-->
<WixLocalization Culture="en-US" xmlns="http://wixtoolset.org/schemas/v4/wxl">
<String Id="WelcomeDlgTitle" Value="{\WixUI_Font_Bigger}Welcome to the [ProductName] [SolvecraftVersion] Setup Wizard" />
<String Id="WelcomeDlgDescription" Value="The Setup Wizard will install [ProductName] version [SolvecraftVersion] on your computer. Click Next to continue or Cancel to exit the Setup Wizard." />
<String Id="VerifyReadyDlgInstallTitle" Value="{\WixUI_Font_Title}Ready to install [ProductName] [SolvecraftVersion]" />
<String Id="ExitDialogTitle" Value="{\WixUI_Font_Bigger}Completed the [ProductName] [SolvecraftVersion] Setup Wizard" />
<String Id="WelcomeDlgTitle" Value="{\WixUI_Font_Bigger}Welcome to the [ProductName] [SolidcraftVersion] Setup Wizard" />
<String Id="WelcomeDlgDescription" Value="The Setup Wizard will install [ProductName] version [SolidcraftVersion] on your computer. Click Next to continue or Cancel to exit the Setup Wizard." />
<String Id="VerifyReadyDlgInstallTitle" Value="{\WixUI_Font_Title}Ready to install [ProductName] [SolidcraftVersion]" />
<String Id="ExitDialogTitle" Value="{\WixUI_Font_Bigger}Completed the [ProductName] [SolidcraftVersion] Setup Wizard" />
</WixLocalization>
@@ -2,19 +2,21 @@
<!--
SolidCraft MSI (WiX Toolset v5, plus the UI and Util extensions). Built by package.ps1:
wix build solvecraft.wxs -arch x64 -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext
-culture en-US -loc solvecraft.en-us.wxl -d Version=1.2.3 -d DisplayVersion=1.2.3-rc.1
wix build solidcraft.wxs -arch x64 -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext
-culture en-US -loc solidcraft.en-us.wxl -d Version=1.2.3 -d DisplayVersion=1.2.3-rc.1
-d BinDir=... -d IconPath=... -o out.msi
Per-machine install with a setup wizard: Welcome, install folder (Program Files\SolveCraft by
Per-machine install with a setup wizard: Welcome, install folder (Program Files\SolidCraft by
default, remembered for upgrades), Ready, progress, and a Finish page with a ticked "Launch
SolidCraft" box. Installs a Start Menu shortcut, solvecraft-cli, the licence files (including
THIRD-PARTY-LICENSES.txt), makes SolidCraft the owner of `.solvecraft` and offers it under
SolidCraft" box. Installs a Start Menu shortcut, solidcraft-cli, the licence files (including
THIRD-PARTY-LICENSES.txt), makes SolidCraft the owner of `.solidcraft` (and of the pre-rename `.solvecraft`), and offers it under
"Open with" for STEP, IGES, 3MF and STL. `msiexec /qn` installs silently.
Adapted from PhotoCraft's (storytold/photocraft, Apache-2.0; see ATTRIBUTION.md).
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
<!-- Never change the UpgradeCode: it is what lets a new MSI replace every earlier install,
including those from before the SolveCraft -> SolidCraft rename (docs/compatibility.md). -->
<Package
Name="SolidCraft"
Manufacturer="SolidCraft contributors"
@@ -30,24 +32,27 @@
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<!-- Advertised shortcuts to an .exe need an .exe icon identifier (ICE50). -->
<Icon Id="SolvecraftIcon.exe" SourceFile="$(var.IconPath)" />
<Property Id="ARPPRODUCTICON" Value="SolvecraftIcon.exe" />
<Icon Id="SolidcraftIcon.exe" SourceFile="$(var.IconPath)" />
<Property Id="ARPPRODUCTICON" Value="SolidcraftIcon.exe" />
<Property Id="ARPURLINFOABOUT" Value="https://bherbruck.github.io/solidcraft/" />
<Property Id="ARPURLUPDATEINFO" Value="https://github.com/bherbruck/solidcraft/releases" />
<Property Id="ARPHELPLINK" Value="https://github.com/bherbruck/solidcraft/issues" />
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="SolveCraft" />
<Directory Id="INSTALLFOLDER" Name="SolidCraft" />
</StandardDirectory>
<StandardDirectory Id="ProgramMenuFolder" />
<!-- An upgrade installs where the user put the previous version (written by SolvecraftApp). -->
<!-- An upgrade installs where the user put the previous version (written by SolidcraftApp). -->
<!-- Since the rename the folder and this key say SolidCraft. A pre-rename install recorded
Software\SolveCraft, which isn't read: its upgrade (same UpgradeCode) removes the old
folder and installs into Program Files\SolidCraft (docs/compatibility.md). -->
<Property Id="INSTALLFOLDER">
<RegistrySearch Id="PreviousInstallFolder" Root="HKLM" Key="Software\SolveCraft" Name="InstallDir" Type="raw" />
<RegistrySearch Id="PreviousInstallFolder" Root="HKLM" Key="Software\SolidCraft" Name="InstallDir" Type="raw" />
</Property>
<Feature Id="Main" Title="SolidCraft" Level="1">
<ComponentGroupRef Id="SolvecraftFiles" />
<ComponentGroupRef Id="SolidcraftFiles" />
</Feature>
<!-- WixUI_InstallDir without its licence page (MIT OR Apache-2.0: nothing to accept). -->
@@ -55,63 +60,75 @@
<UI>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2" Condition="NOT Installed" />
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2" />
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchSolvecraft"
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchSolidcraft"
Condition="WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 AND NOT Installed" />
</UI>
<Property Id="SolvecraftVersion" Value="$(var.DisplayVersion)" />
<Property Id="SolidcraftVersion" Value="$(var.DisplayVersion)" />
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT" Value="SolidCraft $(var.DisplayVersion) is installed. You can start it any time from the Start menu." />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch SolidCraft" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<Property Id="WixShellExecTarget" Value="[#SolvecraftExe]" />
<Property Id="WixShellExecTarget" Value="[#SolidcraftExe]" />
<!-- Runs in the wizard's own (unelevated) process, so the app starts as the user. -->
<CustomAction Id="LaunchSolvecraft" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixShellExec" Impersonate="yes" Return="ignore" />
<CustomAction Id="LaunchSolidcraft" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixShellExec" Impersonate="yes" Return="ignore" />
</Package>
<Fragment>
<ComponentGroup Id="SolvecraftFiles" Directory="INSTALLFOLDER">
<Component Id="SolvecraftApp" Guid="290BEF27-C200-4069-AA43-7DE6A39CDB0A">
<File Id="SolvecraftExe" Source="$(var.BinDir)\solvecraft.exe" KeyPath="yes">
<ComponentGroup Id="SolidcraftFiles" Directory="INSTALLFOLDER">
<!-- A new GUID with the rename: the key file changed from solvecraft.exe to solidcraft.exe.
The UpgradeCode above is unchanged, so this MSI major-upgrades a pre-rename install. -->
<Component Id="SolidcraftApp" Guid="A379D509-D776-4B34-A3A4-71FBF5724971">
<File Id="SolidcraftExe" Source="$(var.BinDir)\solidcraft.exe" KeyPath="yes">
<Shortcut Id="StartMenuShortcut" Directory="ProgramMenuFolder" Name="SolidCraft"
Description="SolidCraft parametric 3D CAD" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
Icon="SolvecraftIcon.exe" IconIndex="0" />
Icon="SolidcraftIcon.exe" IconIndex="0" />
</File>
<!-- .solvecraft: SolidCraft's own format; SolidCraft is its default app. -->
<ProgId Id="Solvecraft.Design" Description="SolidCraft Design" Icon="SolvecraftExe" IconIndex="0">
<Extension Id="solvecraft" ContentType="application/x-solvecraft">
<Verb Id="open" Command="Open" TargetFile="SolvecraftExe" Argument="&quot;%1&quot;" />
<!-- .solidcraft: SolidCraft's own format; SolidCraft is its default app. -->
<ProgId Id="Solidcraft.Design" Description="SolidCraft Design" Icon="SolidcraftExe" IconIndex="0">
<Extension Id="solidcraft" ContentType="application/x-solidcraft">
<Verb Id="open" Command="Open" TargetFile="SolidcraftExe" Argument="&quot;%1&quot;" />
</Extension>
</ProgId>
<!-- Compatibility shim (docs/compatibility.md): designs saved before the rename open as
the same ProgId. Registered by hand: a second Extension under one ProgId would write
its open verb twice (WIX0091). -->
<RegistryValue Root="HKLM" Key="Software\Classes\.solvecraft" Value="Solidcraft.Design" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.solvecraft" Name="Content Type" Value="application/x-solvecraft" Type="string" />
<!-- STEP, IGES and meshes: offered under "Open with", never forced as the default. -->
<ProgId Id="Solvecraft.Model" Description="3D model" Icon="SolvecraftExe" IconIndex="0" />
<RegistryValue Root="HKLM" Key="Software\Classes\Solvecraft.Model\shell\open\command" Value="&quot;[#SolvecraftExe]&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.step\OpenWithProgids" Name="Solvecraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.stp\OpenWithProgids" Name="Solvecraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.igs\OpenWithProgids" Name="Solvecraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.iges\OpenWithProgids" Name="Solvecraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.3mf\OpenWithProgids" Name="Solvecraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.stl\OpenWithProgids" Name="Solvecraft.Model" Value="" Type="string" />
<ProgId Id="Solidcraft.Model" Description="3D model" Icon="SolidcraftExe" IconIndex="0" />
<RegistryValue Root="HKLM" Key="Software\Classes\Solidcraft.Model\shell\open\command" Value="&quot;[#SolidcraftExe]&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.step\OpenWithProgids" Name="Solidcraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.stp\OpenWithProgids" Name="Solidcraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.igs\OpenWithProgids" Name="Solidcraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.iges\OpenWithProgids" Name="Solidcraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.3mf\OpenWithProgids" Name="Solidcraft.Model" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.stl\OpenWithProgids" Name="Solidcraft.Model" Value="" Type="string" />
<!-- "Open with" app list and the Run dialog (Win+R "solvecraft"). -->
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe" Name="FriendlyAppName" Value="SolidCraft" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\shell\open\command" Value="&quot;[#SolvecraftExe]&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".solvecraft" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".step" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".stp" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".igs" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".iges" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".3mf" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solvecraft.exe\SupportedTypes" Name=".stl" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\solvecraft.exe" Value="[#SolvecraftExe]" Type="string" />
<RegistryValue Root="HKLM" Key="Software\SolveCraft" Name="InstallDir" Value="[INSTALLFOLDER]" Type="string" />
<!-- "Open with" app list and the Run dialog (Win+R "solidcraft"). -->
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe" Name="FriendlyAppName" Value="SolidCraft" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\shell\open\command" Value="&quot;[#SolidcraftExe]&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".solidcraft" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".solvecraft" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".step" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".stp" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".igs" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".iges" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".3mf" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\solidcraft.exe\SupportedTypes" Name=".stl" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\solidcraft.exe" Value="[#SolidcraftExe]" Type="string" />
<RegistryValue Root="HKLM" Key="Software\SolidCraft" Name="InstallDir" Value="[INSTALLFOLDER]" Type="string" />
</Component>
<Component Id="SolvecraftCli">
<File Id="SolvecraftCliExe" Source="$(var.BinDir)\solvecraft-cli.exe" KeyPath="yes" />
<Component Id="SolidcraftCli">
<File Id="SolidcraftCliExe" Source="$(var.BinDir)\solidcraft-cli.exe" KeyPath="yes" />
</Component>
<!-- Compatibility shim (docs/compatibility.md): the old CLI name, forwarding to solidcraft-cli. -->
<Component Id="SolidcraftCliAlias">
<File Id="SolvecraftCliAliasExe" Source="$(var.BinDir)\solvecraft-cli.exe" KeyPath="yes" />
</Component>
<!-- Several unversioned files: an explicit GUID (WIX0367). -->
<Component Id="SolvecraftLicences" Guid="CDEDEE8D-4BE9-4872-A2EA-EE623A6C7E91">
<Component Id="SolidcraftLicences" Guid="CDEDEE8D-4BE9-4872-A2EA-EE623A6C7E91">
<File Id="LicenseMit" Source="$(var.BinDir)\LICENSE-MIT" KeyPath="yes" />
<File Id="LicenseApache" Source="$(var.BinDir)\LICENSE-APACHE" />
<File Id="Notice" Source="$(var.BinDir)\NOTICE" />