Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 91080a7a9d | |||
| 81b04d3dff |
+15
-22
@@ -9,40 +9,33 @@ RUN apt-get update && \
|
|||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
gcc \
|
gcc \
|
||||||
|
libc6-dev \
|
||||||
gcc-aarch64-linux-gnu \
|
gcc-aarch64-linux-gnu \
|
||||||
|
libc6-dev-arm64-cross \
|
||||||
|
linux-libc-dev-arm64-cross \
|
||||||
gcc-mingw-w64-x86-64 \
|
gcc-mingw-w64-x86-64 \
|
||||||
binutils-mingw-w64-x86-64 \
|
binutils-mingw-w64-x86-64 \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
libgl1-mesa-dev \
|
libgl1-mesa-dev \
|
||||||
xorg-dev \
|
xorg-dev \
|
||||||
libgl1-mesa-dev:arm64 \
|
libgl1-mesa-dev:arm64 \
|
||||||
xorg-dev:arm64 && \
|
libx11-dev:arm64 \
|
||||||
|
libxcursor-dev:arm64 \
|
||||||
|
libxrandr-dev:arm64 \
|
||||||
|
libxinerama-dev:arm64 \
|
||||||
|
libxi-dev:arm64 \
|
||||||
|
libxxf86vm-dev:arm64 && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
# Copy module files first so Docker can cache downloaded dependencies while the
|
# Copy module files first so Docker can cache downloaded dependencies while the
|
||||||
# application source changes. This makes repeated local builds much faster.
|
# application source changes. The release script later mounts the live repository
|
||||||
|
# over /src, but the module cache remains in the image and keeps repeated builds
|
||||||
|
# faster.
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
COPY . .
|
# The image intentionally stops here. Artifact build commands live in
|
||||||
|
# scripts/build-release-linux.sh so a developer can choose targets interactively
|
||||||
# CGO is required by Fyne. This builder produces the release artifacts from
|
# without rebuilding this environment image for every selection.
|
||||||
# Linux: Linux amd64, Linux arm64, and a Windows amd64 binary cross-compiled with
|
|
||||||
# MinGW. The Windows resource is generated inside the container so Explorer still
|
|
||||||
# sees the application icon.
|
|
||||||
RUN version="$(sed -n 's/^var Version = "\(.*\)"/\1/p' src/core/version.go)" && \
|
|
||||||
version="${version:-0.0.0-dev}" && \
|
|
||||||
mkdir -p /out/linux /out/windows && \
|
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
|
||||||
go build -trimpath -ldflags "-s -w -X github.com/pysentry/pysentry/src/core.Version=${version}" \
|
|
||||||
-o "/out/linux/pysentry-${version}-linux-amd64" ./cmd/pysentry && \
|
|
||||||
CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 \
|
|
||||||
PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig \
|
|
||||||
go build -trimpath -ldflags "-s -w -X github.com/pysentry/pysentry/src/core.Version=${version}" \
|
|
||||||
-o "/out/linux/pysentry-${version}-linux-arm64" ./cmd/pysentry && \
|
|
||||||
x86_64-w64-mingw32-windres -O coff -o cmd/pysentry/rsrc_windows_amd64.syso packaging/windows/pysentry.rc && \
|
|
||||||
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \
|
|
||||||
go build -trimpath -ldflags "-s -w -H=windowsgui -X github.com/pysentry/pysentry/src/core.Version=${version}" \
|
|
||||||
-o "/out/windows/pysentry-${version}-windows-amd64.exe" ./cmd/pysentry
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ PySentry is being designed and implemented with assistance from OpenAI Codex.
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Native desktop GUI built with Fyne.
|
- Native desktop GUI built with [Fyne](https://fyne.io/).
|
||||||
- Job storage in one clean YAML file.
|
- Job storage in one clean YAML file.
|
||||||
- App settings in a separate YAML file.
|
- App settings in a separate YAML file.
|
||||||
- `@every` schedules and standard 5-field cron expressions.
|
- `@every` schedules and standard 5-field cron expressions.
|
||||||
@@ -21,16 +21,37 @@ PySentry is being designed and implemented with assistance from OpenAI Codex.
|
|||||||
|
|
||||||
Common:
|
Common:
|
||||||
|
|
||||||
- Go 1.22 or newer.
|
- [Go](https://go.dev/) 1.22 or newer.
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
||||||
- MSYS2 with UCRT64 GCC in `C:\msys64\ucrt64\bin`.
|
- MSYS2 with UCRT64 GCC in `C:\msys64\ucrt64\bin`.
|
||||||
|
|
||||||
|
Install these dependencies on Windows:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 1. Install Go 1.22 or newer from https://go.dev/dl/.
|
||||||
|
# The default installer path is C:\Program Files\Go.
|
||||||
|
go version
|
||||||
|
|
||||||
|
# 2. Install MSYS2 from https://www.msys2.org/.
|
||||||
|
# Use the default installation path so UCRT64 tools are placed under
|
||||||
|
# C:\msys64\ucrt64\bin.
|
||||||
|
|
||||||
|
# 3. Open "MSYS2 UCRT64" from the Start menu and install GCC plus windres.
|
||||||
|
pacman -Syu
|
||||||
|
pacman -S --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-binutils
|
||||||
|
|
||||||
|
# 4. In PowerShell, check that the compiler is available where the build script
|
||||||
|
# expects it. build-windows.bat prepends this directory automatically.
|
||||||
|
Test-Path C:\msys64\ucrt64\bin\gcc.exe
|
||||||
|
Test-Path C:\msys64\ucrt64\bin\windres.exe
|
||||||
|
```
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
|
|
||||||
- A C compiler.
|
- A C compiler.
|
||||||
- Fyne native build dependencies, including OpenGL/X11 development packages.
|
- [Fyne](https://fyne.io/) native build dependencies, including OpenGL/X11 development packages.
|
||||||
|
|
||||||
On Debian/Ubuntu, the Linux dependencies are typically:
|
On Debian/Ubuntu, the Linux dependencies are typically:
|
||||||
|
|
||||||
@@ -97,13 +118,20 @@ dist\linux\pysentry-0.1.0-linux-amd64
|
|||||||
Release build from Linux:
|
Release build from Linux:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Builds Linux amd64, Linux arm64, and Windows amd64 artifacts from one
|
# Interactively choose Linux amd64, Linux arm64, Windows amd64, or all artifacts
|
||||||
# Linux/Docker workflow. The Dockerfile includes Linux Fyne dependencies plus
|
# from one Linux/Docker workflow. The Dockerfile contains the builder
|
||||||
# cross-compilers for arm64 Linux and the Windows .exe.
|
# environment; the build commands live in this script.
|
||||||
chmod +x ./scripts/build-release-linux.sh
|
chmod +x ./scripts/build-release-linux.sh
|
||||||
./scripts/build-release-linux.sh
|
./scripts/build-release-linux.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Non-interactive release builds can pass target names:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build only Linux arm64 and Windows amd64 artifacts.
|
||||||
|
./scripts/build-release-linux.sh linux-arm64 windows-amd64
|
||||||
|
```
|
||||||
|
|
||||||
The binaries are copied to:
|
The binaries are copied to:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -287,7 +315,7 @@ Build outputs are written to `dist/`. The old local `bin/` directory is not used
|
|||||||
|
|
||||||
PySentry keeps the direct dependency list intentionally small:
|
PySentry keeps the direct dependency list intentionally small:
|
||||||
|
|
||||||
- `fyne.io/fyne/v2` for the native GUI.
|
- [`fyne.io/fyne/v2`](https://fyne.io/) for the native GUI.
|
||||||
- `github.com/robfig/cron/v3` for cron schedule parsing.
|
- `github.com/robfig/cron/v3` for cron schedule parsing.
|
||||||
- `gopkg.in/yaml.v3` for YAML settings and jobs.
|
- `gopkg.in/yaml.v3` for YAML settings and jobs.
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,14 @@ output="${1:-dist/linux/pysentry-${version}-linux-amd64}"
|
|||||||
# environment in Docker makes Linux builds repeatable from Windows hosts and CI.
|
# environment in Docker makes Linux builds repeatable from Windows hosts and CI.
|
||||||
docker build -f Dockerfile -t gitea.mixdep.ru/mix/pysentry-builder .
|
docker build -f Dockerfile -t gitea.mixdep.ru/mix/pysentry-builder .
|
||||||
|
|
||||||
# The image build produces /out/linux and /out/windows. This helper copies only
|
|
||||||
# the Linux binary for compatibility with the older Linux-only workflow; use
|
|
||||||
# build-release-linux.sh when both platform artifacts are needed.
|
|
||||||
container_id="$(docker create gitea.mixdep.ru/mix/pysentry-builder)"
|
|
||||||
cleanup() {
|
|
||||||
docker rm "$container_id" >/dev/null
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
mkdir -p "$(dirname "$output")"
|
mkdir -p "$(dirname "$output")"
|
||||||
docker cp "${container_id}:/out/linux/pysentry-${version}-linux-amd64" "$output"
|
docker run --rm \
|
||||||
|
-e "VERSION=${version}" \
|
||||||
|
-e "OUTPUT=${output}" \
|
||||||
|
-v "$(pwd):/src" \
|
||||||
|
-w /src \
|
||||||
|
gitea.mixdep.ru/mix/pysentry-builder \
|
||||||
|
bash -lc 'CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w -X github.com/pysentry/pysentry/src/core.Version=${VERSION}" -o "${OUTPUT}" ./cmd/pysentry'
|
||||||
|
|
||||||
# Icons are embedded in the Go binary, so there is no assets directory to copy
|
# Icons are embedded in the Go binary, so there is no assets directory to copy
|
||||||
# after extracting the Linux executable.
|
# after extracting the Linux executable.
|
||||||
|
|||||||
+124
-13
@@ -1,22 +1,133 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Build all release artifacts from a Linux host or CI runner. The Docker image
|
# Build selected release artifacts from a Linux host or CI runner. The Docker
|
||||||
# contains Linux/Fyne dependencies for amd64 and arm64, plus the MinGW
|
# image contains Linux/Fyne dependencies for amd64 and arm64, plus the MinGW
|
||||||
# cross-compiler used for the Windows GUI executable.
|
# cross-compiler used for the Windows GUI executable. Actual build commands live
|
||||||
|
# here rather than in Dockerfile so target selection does not require rebuilding
|
||||||
|
# the image.
|
||||||
tag="gitea.mixdep.ru/mix/pysentry-builder"
|
tag="gitea.mixdep.ru/mix/pysentry-builder"
|
||||||
|
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
repo_root="$(cd "${script_dir}/.." && pwd)"
|
||||||
|
cd "$repo_root"
|
||||||
|
|
||||||
|
version="$(sed -n 's/^var Version = "\(.*\)"/\1/p' src/core/version.go)"
|
||||||
|
version="${version:-0.0.0-dev}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [target...]
|
||||||
|
|
||||||
|
Targets:
|
||||||
|
all Build every release artifact.
|
||||||
|
linux-amd64 Build dist/linux/pysentry-${version}-linux-amd64.
|
||||||
|
linux-arm64 Build dist/linux/pysentry-${version}-linux-arm64.
|
||||||
|
windows-amd64 Build dist/windows/pysentry-${version}-windows-amd64.exe.
|
||||||
|
|
||||||
|
When no target is passed and the script runs in a terminal, it asks what to build.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
-h|--help|help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
choose_targets() {
|
||||||
|
if [ "$#" -gt 0 ]; then
|
||||||
|
printf '%s\n' "$@"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -t 0 ]; then
|
||||||
|
printf '%s\n' all
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Select release artifacts to build:"
|
||||||
|
echo " 1) all"
|
||||||
|
echo " 2) linux-amd64"
|
||||||
|
echo " 3) linux-arm64"
|
||||||
|
echo " 4) windows-amd64"
|
||||||
|
echo "Enter numbers or target names separated by spaces or commas."
|
||||||
|
read -r -p "Build target [all]: " answer
|
||||||
|
answer="${answer:-all}"
|
||||||
|
echo "$answer" | tr ',' ' ' | tr ' ' '\n' | sed '/^$/d'
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_targets() {
|
||||||
|
while IFS= read -r target; do
|
||||||
|
case "$target" in
|
||||||
|
1|all)
|
||||||
|
printf '%s\n' linux-amd64 linux-arm64 windows-amd64
|
||||||
|
;;
|
||||||
|
2|linux-amd64)
|
||||||
|
printf '%s\n' linux-amd64
|
||||||
|
;;
|
||||||
|
3|linux-arm64)
|
||||||
|
printf '%s\n' linux-arm64
|
||||||
|
;;
|
||||||
|
4|windows-amd64)
|
||||||
|
printf '%s\n' windows-amd64
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown build target: $target" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
run_in_builder() {
|
||||||
|
docker run --rm \
|
||||||
|
-e "VERSION=${version}" \
|
||||||
|
-v "${repo_root}:/src" \
|
||||||
|
-w /src \
|
||||||
|
"$tag" \
|
||||||
|
bash -lc "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_linux_amd64() {
|
||||||
|
run_in_builder 'mkdir -p dist/linux && CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w -X github.com/pysentry/pysentry/src/core.Version=${VERSION}" -o "dist/linux/pysentry-${VERSION}-linux-amd64" ./cmd/pysentry'
|
||||||
|
}
|
||||||
|
|
||||||
|
build_linux_arm64() {
|
||||||
|
run_in_builder 'mkdir -p dist/linux && CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CGO_CFLAGS="--sysroot=/ -I/usr/include/aarch64-linux-gnu" CGO_LDFLAGS="--sysroot=/ -L/usr/lib/aarch64-linux-gnu" PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig go build -trimpath -ldflags "-s -w -X github.com/pysentry/pysentry/src/core.Version=${VERSION}" -o "dist/linux/pysentry-${VERSION}-linux-arm64" ./cmd/pysentry'
|
||||||
|
}
|
||||||
|
|
||||||
|
build_windows_amd64() {
|
||||||
|
run_in_builder 'mkdir -p dist/windows && x86_64-w64-mingw32-windres -O coff -o cmd/pysentry/rsrc_windows_amd64.syso packaging/windows/pysentry.rc && CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "-s -w -H=windowsgui -X github.com/pysentry/pysentry/src/core.Version=${VERSION}" -o "dist/windows/pysentry-${VERSION}-windows-amd64.exe" ./cmd/pysentry'
|
||||||
|
}
|
||||||
|
|
||||||
|
mapfile -t targets < <(choose_targets "$@" | normalize_targets | awk '!seen[$0]++')
|
||||||
|
if [ "${#targets[@]}" -eq 0 ]; then
|
||||||
|
echo "No build targets selected." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Building Docker builder image: $tag"
|
||||||
docker build -f Dockerfile -t "$tag" .
|
docker build -f Dockerfile -t "$tag" .
|
||||||
|
|
||||||
container_id="$(docker create "$tag")"
|
for target in "${targets[@]}"; do
|
||||||
cleanup() {
|
echo "Building $target..."
|
||||||
docker rm "$container_id" >/dev/null
|
case "$target" in
|
||||||
}
|
linux-amd64)
|
||||||
trap cleanup EXIT
|
build_linux_amd64
|
||||||
|
;;
|
||||||
mkdir -p dist/linux dist/windows
|
linux-arm64)
|
||||||
docker cp "${container_id}:/out/linux/." dist/linux
|
build_linux_arm64
|
||||||
docker cp "${container_id}:/out/windows/." dist/windows
|
;;
|
||||||
|
windows-amd64)
|
||||||
|
build_windows_amd64
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
echo "Built release artifacts:"
|
echo "Built release artifacts:"
|
||||||
find dist/linux dist/windows -maxdepth 1 -type f -print
|
find dist/linux dist/windows -maxdepth 1 -type f -print 2>/dev/null || true
|
||||||
|
|||||||
Reference in New Issue
Block a user