🔧 Кросс-сборка CLI и GUI-приложения на Rust — проблемы и решения
DotPlus — это Rust-приложение с графическим и консольным интерфейсом. Изначально оно разрабатывалось под Windows, но в планах была сборка под Linux и Docker.
Решение: добавить полноценные Linux-сборки с поддержкой GUI и CLI и обеспечить стабильную доставку под несколько архитектур.
❗ Почему не просто cargo build?
Если хочется стабильную сборку не только под x86_64, но и под ARM (Raspberry Pi, серверы), одной команды cargo build недостаточно. Возникают проблемы:
Нужны кросс-компиляторы (
gcc-aarch64-linux-gnuи др.)Требуется ручная настройка sysroot, musl, glibc
При использовании GUI (через
eframeиegui) иногда всплывают платформозависимые проблемы с OpenGL, зависимостями илиrfd(файловые диалоги)
🛠 Решение: cross-rs
Чтобы не городить окружения вручную и не писать десятки --target-флагов с настройкой toolchain, я решил использовать cross — это официальный инструмент от сообщества Rust, который:
Использует Docker-образы с преднастроенным окружением для каждой архитектуры
Упрощает кросс-компиляцию одной командой:
cross build --release --target aarch64-unknown-linux-gnuРаботает из коробки как с CLI, так и с GUI (если система сборки внутри контейнера поддерживает нужные dev-пакеты)
⚙️ Конфигурация: cross.toml
Вот пример моего cross.toml, где перечислены поддерживаемые архитектуры:
[target.aarch64-unknown-linux-gnu]
image = "ghcr.io/cross-rs/aarch64-unknown-linux-gnu:edge"
[target.armv7-unknown-linux-gnueabihf]
image = "ghcr.io/cross-rs/armv7-unknown-linux-gnueabihf:edge"
[target.x86_64-unknown-linux-gnu]
image = "ghcr.io/cross-rs/x86_64-unknown-linux-gnu:edge"Образы edge — это свежие контейнеры с последними версиями компилятора и зависимостей. Именно они обеспечивают корректную сборку egui, eframe и rfd в Linux-окружении.
🧱 GUI + CLI: архитектура фич
[features]
default = ["gui"]
gui = ["eframe", "egui", "rfd", "egui_extras"]
notifications = ["notify-rust"]Благодаря этому:
Сборка CLI-версии возможна без GUI (
--no-default-features)На Linux можно собирать оба варианта одновременно, включая полноценное GTK/Wayland GUI через
eframe
Такой подход оказался крайне удобным: в одном проекте можно выпускать и headless-бинарник, и полноценное графическое приложение.
🪓 От чего пришлось отказаться
Несмотря на успех с cross, не обошлось без потерь:
musl-сборки (статически линкуемые) были отброшены —
eframeиrfdплохо работают в таком окруженииWindows ARM MIPS и прочие экзотические платформы — слишком нестабильны и слабо поддерживаются в
crossСлишком "чистая" сборка без Docker — пришлось отказаться от идеи собирать без контейнеров, так как зависимостей GUI слишком много, и они не всегда есть на GitHub Actions runner'ах
✅ Что в итоге получилось
В результате, с помощью cross теперь собираются полноценные GUI+CLI бинарники под Linux для трёх платформ:
Архитектура | Поддержка | Назначение |
| ✅ GUI/CLI | Десктопы и серверы |
| ✅ GUI/CLI | ARM64 серверы, RPi 4 и новее |
| ✅ GUI/CLI | RPi 3 и другие ARMv7 SBC |
✅ Итог: благодаря cross
DotPlus теперь полноценно работает на Linux с графическим интерфейсом и CLI. Одинаковый UX, стабильные сборки, возможность использовать на Raspberry Pi и сервере — всё это стало реальностью.
🚀 CI/CD: автоматизация сборки, кросс-компиляции и релизов
После успешной настройки cross для локальной кросс-компиляции стало ясно: ручной процесс не масштабируется. Хотелось воспроизводимой, полностью автоматизированной системы, которая при любом обновлении могла бы:
Собрать DotPlus под несколько архитектур
Подготовить установочные пакеты
.debи.rpmСобрать и опубликовать Docker-образ
Сформировать релиз и прикрепить артефакты
Так родился CI/CD-процесс на базе GitHub Actions, который покрывает весь цикл сборки и доставки.
📂 Общая структура
CI/CD реализован в одном workflow-файле 📄 build-multiarch.yml:
name: Build dotplus (.deb/.rpm) for all architectures
on:
push:
branches: [linux]
tags: ["v*"]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
env:
CROSS_SKIP_VERSION_CHECK: "1"
steps:
- name: 🧾 Checkout
uses: actions/checkout@v4
- name: ⚡️ Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: 🧬 Enable QEMU for multi-arch RPM
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: 🦀 Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
components: rustfmt
- name: 🎯 Add targets
run: |
rustup target add \
x86_64-unknown-linux-gnu \
aarch64-unknown-linux-gnu \
armv7-unknown-linux-gnueabihf
- name: 🐳 Install Docker & Cross
run: |
sudo apt update
sudo apt install -y docker.io containerd
if ! command -v cross &>/dev/null; then
cargo install cross
else
echo "✅ cross уже установлен, пропускаем"
fi
- name: 📦 Install deb/rpm tools
run: |
sudo apt install -y \
dpkg-dev debhelper rpm rpm2cpio fakeroot \
qemu-user-static binfmt-support \
gcc-multilib libc6-dev-i386 pkg-config \
libssl-dev libstdc++-12-dev
- name: 🔧 Make script executable
run: chmod +x tools/generate.sh
- name: 🛠 Run build script
run: ./tools/generate.sh
- name: ☁️ Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dotplus-packages
path: |
build/**/dotplus_*.deb
build/**/RPMS/**/*.rpm
docker:
runs-on: ubuntu-latest
needs: build
steps:
- name: 🧾 Checkout
uses: actions/checkout@v4
- name: 🦀 Install Rust + cross
run: |
rustup update
rustup target add x86_64-unknown-linux-musl
cargo install cross
- name: 🛠 Build static binary (musl, CLI-only)
run: cross build --release --target x86_64-unknown-linux-musl --no-default-features
- name: 🧰 Prepare Docker context
run: |
if [[ -f target/x86_64-unknown-linux-musl/release/dotplus ]]; then
cp target/x86_64-unknown-linux-musl/release/dotplus docker/dotplus
else
echo "❌ Static binary not found"
exit 1
fi
- name: 🐳 Build Docker image
run: docker build -t dotplus-cli -f docker/Dockerfile.cli ./docker
- name: ☁️ Save Docker image as archive
run: docker save dotplus-cli | gzip > dotplus-cli.tar.gz
- name: ☁️ Upload Docker image artifact
uses: actions/upload-artifact@v4
with:
name: dotplus-cli-docker
path: dotplus-cli.tar.gz
📄 build-multiarch.yml запускается при пуше в ветки release-linux или release-docker и выполняет сборку, упаковку, публикацию и деплой.
⚙️ Этапы пайплайна
Дата: 01.07.2025
Файл Workflow: build-multiarch.yml
Триггер: Push в ветку linux
📦 Этап 1: build (⏱ ~16 минут)
Шаг | Описание |
⚙️ | Инициализация задания |
📥 | Клонирование репозитория |
⚡ | Кэширование зависимостей |
🧩 | Эмуляция архитектур |
🦀 | Установка Rust |
🎯 | Добавление целевых архитектур |
🐳 | Установка Docker и |
🧰 | Установка сборочных инструментов |
🔧 | Подготовка сборочного скрипта |
▶️ | Сборка |
⬆️ | Загрузка артефактов |
♻️ Post-steps | Очистка: откат QEMU, кэша и |

.deb, .rpm🐳 Этап 2: docker (⏱ ~4 минуты)
Шаг | Описание |
⚙️ | Инициализация задания |
📥 | Клонирование репозитория |
🦀 | Установка Rust + кросс-компиляция |
🛠 | Сборка статичного бинарника (musl, CLI-only) |
🧳 | Подготовка контекста для Docker |
🔨 | Сборка образа |
💾 | Сохранение Docker-образа в архив |
⬆️ | Загрузка архива как артефакт |
♻️ Post-steps | Очистка: откат |


🔄 Кросс-сборка бинарников
Кросс-компиляция происходит с использованием cross, который изолирует сборку в готовых Docker-образах:
- name: Build for aarch64
run: cross build --release --target aarch64-unknown-linux-gnu
- name: Build for armv7
run: cross build --release --target armv7-unknown-linux-gnueabihf
- name: Build for x86_64
run: cross build --release --target x86_64-unknown-linux-gnuЭто гарантирует одинаковые бинарники независимо от среды, включая GUI-часть на Linux.
📦 Пакетирование: .deb и .rpm из CI
dotplus_1.0.0_amd64.debdotplus_1.0.0_arm64.debdotplus_1.0.0_armhf.debdotplus-1.0.0-1.x86_64.rpm
Установка на стороне пользователя:
sudo dpkg -i dotplus_1.0.0_amd64.deb
# или
sudo rpm -i dotplus-1.0.0-1.x86_64.rpm🔧 Как это устроено?
Проект включает шаблоны:
templates/control.in — шаблон для .deb
Package: dotplus
Version: {{VERSION}}
Section: utils
Priority: optional
Architecture: {{ARCH}}
Maintainer: Danil Nigmatullin <danil.communication@gmail.com>
Depends: {{DEPENDS}}
Description: QR and barcode generator with logo and CSV support (Rust CLI/GUI)
DotPlus is a Rust-based GUI and command-line tool for generating QR codes and barcodes.
It supports logo embedding, CSV import, and auto-update functionality.
Suitable for both terminal workflows and desktop users.templates/spec.in — шаблон для .rpm
Name: dotplus
Version: {{VERSION}}
Release: 1%{?dist}
Summary: QR and barcode generator with logo and CSV support (Rust CLI/GUI)
License: Freeware (Proprietary)
URL: https://github.com/nigdanil/dotplus
Source0: dotplus
BuildArch: {{ARCH}}
Requires: {{REQUIRES}}
%description
DotPlus is a Rust-based GUI and CLI tool for QR/barcode generation with logo and CSV support.
%prep
# No preparation steps needed
%install
[ -f %{SOURCE0} ] || { echo "Missing binary dotplus in SOURCES"; exit 1; }
[ -f %{_sourcedir}/arialmt.ttf ] || { echo "Missing font file arialmt.ttf"; exit 1; }
mkdir -p %{buildroot}/usr/bin
mkdir -p %{buildroot}/usr/share/dotplus/fonts
install -m 0755 %{SOURCE0} %{buildroot}/usr/bin/dotplus
install -m 0644 %{_sourcedir}/arialmt.ttf %{buildroot}/usr/share/dotplus/fonts/arialmt.ttf
%files
/usr/bin/dotplus
/usr/share/dotplus/fonts/arialmt.ttf
%changelog
* Mon Jun 30 2025 Danil Nigmatullin <danil.communication@gmail.com> - {{VERSION}}-1
- Initial RPM build
А также вспомогательный скрипт 📄 tools/generate.sh:
# tools/generate.sh
#!/usr/bin/env bash
set -e
VERSION="1.0.0"
echo "🚀 Starting multi-arch build: version $VERSION"
START=$(date +%s)
ARCHS=(
"amd64" # x86_64-unknown-linux-gnu
"arm64" # aarch64-unknown-linux-gnu
"armhf" # armv7-unknown-linux-gnueabihf
)
TARGETS=(
"x86_64-unknown-linux-gnu"
"aarch64-unknown-linux-gnu"
"armv7-unknown-linux-gnueabihf"
)
DEB_ARCHS=(
"amd64"
"arm64"
"armhf"
)
RPM_ARCHS=(
"x86_64"
"aarch64"
"armv7hl"
)
ROOT_DIR="$(git rev-parse --show-toplevel)"
TEMPLATE_DIR="$ROOT_DIR/templates"
mkdir -p build
FAILED=()
for i in "${!ARCHS[@]}"; do
ARCH="${ARCHS[$i]}"
TARGET="${TARGETS[$i]}"
DEB_ARCH="${DEB_ARCHS[$i]}"
RPM_ARCH="${RPM_ARCHS[$i]}"
echo "🔧 Building for $ARCH ($TARGET)..."
CROSS_SKIP_VERSION_CHECK=1 cross build \
--release \
--target "$TARGET" \
--manifest-path Cargo.toml \
--verbose || { echo "⚠️ Build failed for $TARGET"; FAILED+=("$ARCH"); continue; }
BIN="target/$TARGET/release/dotplus"
ls -lh "target/$TARGET/release"
if [[ ! -f "$BIN" ]]; then
echo "❌ Build failed for $TARGET"
FAILED+=("$ARCH")
continue
fi
BUILD_DIR="build/$ARCH"
DEB_DIR="$BUILD_DIR/deb"
RPM_DIR="$BUILD_DIR/rpm"
mkdir -p "$DEB_DIR/DEBIAN"
mkdir -p "$DEB_DIR/usr/bin"
mkdir -p "$RPM_DIR/SOURCES"
cp "$BIN" "$DEB_DIR/usr/bin/dotplus"
cp "$BIN" "$RPM_DIR/SOURCES/dotplus"
cp src/tools/font/arialmt.ttf "$RPM_DIR/SOURCES/arialmt.ttf"
# Копируем ресурсные файлы (шрифты)
mkdir -p "$DEB_DIR/usr/share/dotplus/fonts"
cp src/tools/font/arialmt.ttf "$DEB_DIR/usr/share/dotplus/fonts/"
# === .deb ===
sed \
-e "s/{{VERSION}}/$VERSION/" \
-e "s/{{ARCH}}/$DEB_ARCH/" \
-e "s/{{DEPENDS}}/libc6 (>= 2.29)/" \
"$TEMPLATE_DIR/control.in" > "$DEB_DIR/DEBIAN/control"
dpkg-deb --build "$DEB_DIR" "$BUILD_DIR/dotplus_${VERSION}_${DEB_ARCH}.deb"
# === .rpm ===
SPEC_OUT="$RPM_DIR/dotplus.spec"
sed \
-e "s/{{VERSION}}/$VERSION/" \
-e "s/{{ARCH}}/$RPM_ARCH/" \
-e "s/{{REQUIRES}}/glibc >= 2.29/" \
"$TEMPLATE_DIR/spec.in" > "$SPEC_OUT"
RPM_BUILDROOT="$RPM_DIR/BUILDROOT/dotplus-${VERSION}-1.${RPM_ARCH}"
mkdir -p "$RPM_BUILDROOT/usr/bin"
cp "$BIN" "$RPM_BUILDROOT/usr/bin/dotplus"
chmod +x "$RPM_BUILDROOT/usr/bin/dotplus"
# Копируем ресурсные файлы (шрифты)
FONT_SOURCE="src/tools/font/arialmt.ttf"
FONT_DEST="$RPM_DIR/BUILDROOT/dotplus-${VERSION}-1.${RPM_ARCH}/usr/share/dotplus/fonts"
mkdir -p "$FONT_DEST"
if [[ -f "$FONT_SOURCE" ]]; then
cp "$FONT_SOURCE" "$FONT_DEST"
echo "✅ Шрифт скопирован: $FONT_SOURCE → $FONT_DEST"
else
echo "⚠️ WARNING: $FONT_SOURCE не найден — удаляем строку из .spec"
sed -i '/\/usr\/share\/dotplus\/fonts\/arialmt.ttf/d' "$SPEC_OUT"
fi
if [[ "$ARCH" == "amd64" ]]; then
echo "📦 Building RPM for $ARCH..."
rpmbuild \
--define "_topdir $ROOT_DIR/$RPM_DIR" \
--define "_sourcedir $ROOT_DIR/$RPM_DIR/SOURCES" \
--define "_builddir $ROOT_DIR/$RPM_DIR/BUILD" \
--define "_specdir $ROOT_DIR/$RPM_DIR" \
--define "_rpmdir $ROOT_DIR/$RPM_DIR/RPMS" \
--define "_buildrootdir $ROOT_DIR/$RPM_DIR/BUILDROOT" \
--target "$RPM_ARCH-redhat-linux" \
-bb "$SPEC_OUT" || {
echo "❌ RPM build failed for $TARGET"
FAILED+=("$ARCH")
continue
}
RPM_OUTPUT=$(find "$RPM_DIR/RPMS" -name "*.rpm")
if [[ -n "$RPM_OUTPUT" ]]; then
echo "✅ RPM built for $ARCH: $RPM_OUTPUT"
else
echo "❌ RPM not found for $ARCH"
FAILED+=("$ARCH")
fi
else
echo "⚠️ Skipping RPM build for $ARCH"
fi
echo "✅ RPM build completed for $ARCH"
echo "📁 RPM output dir listing:"
ls -lR "$RPM_DIR"
echo "📦 Checking built RPMs:"
find "$RPM_DIR/RPMS" -type f 2>/dev/null || true
done
END=$(date +%s)
DURATION=$((END - START))
if [[ ${#FAILED[@]} -gt 0 ]]; then
echo "❌ Failed builds: ${FAILED[*]}"
else
echo "✅ All target builds succeeded"
fi
echo "🎉 Build finished in $DURATION seconds."
# 🧪 Покажем, какие пакеты были созданы
echo "📦 Built package files:"
find build -type f \( -name "*.deb" -o -name "*.rpm" \)
# Подсчёт количества .deb и .rpm
PACKAGE_COUNT=$(find build -type f \( -name "*.deb" -o -name "*.rpm" \) | wc -l | tr -d '[:space:]')
echo "🧪 DEBUG: Found packages:"
FOUND_PACKAGES=$(find build -type f \( -name "*.deb" -o -name "*.rpm" \))
echo "$FOUND_PACKAGES"
# Если ни одного пакета не создано — ошибка
if [[ "$PACKAGE_COUNT" -lt 1 ]]; then
echo "❌ No packages were created (check target paths or build errors)"
echo "💡 Hint: verify that .deb and .rpm were written to expected build/**/ paths"
exit 1
fi
echo "✅ Total packages created: $PACKAGE_COUNT"
Он принимает бинарник и архитектуру, генерирует .deb/.rpm с помощью dpkg-deb и rpmbuild, и сохраняет итоговые пакеты для релиза.
🐳 Docker-сборка
После сборки бинарников запускается Docker-сборка CLI-варианта DotPlus:
- name: Build Docker image
run: |
docker build -f docker/Dockerfile.cli -t ghcr.io/nigdanil/dotplus:latest .
docker push ghcr.io/nigdanil/dotplus:latestПростой Dockerfile.cli использует минимальную базу и добавляет только бинарник:
FROM debian:bookworm-slim
COPY dotplus /usr/local/bin/dotplus
ENTRYPOINT ["dotplus"]Публикация артефактов
Все собранные файлы (бинарники, .deb, .rpm) автоматически прикрепляются к GitHub Release. Это упрощает дистрибуцию: пользователи могут выбрать нужную архитектуру и просто скачать готовый пакет.
🧩 Что пришлось уче��ть
❌
muslиarm64-darwinне поддерживаются — нет стабильных образов или зависимости несовместимы⚠️
crossне кеширует образы между пушами, поэтому Docker нужен как для сборки, так и для доставки
📌 Итоговая картина релиза
Формат | Архитектуры | Описание |
| x86_64, armhf, arm64 | Универсальная ручная установка |
| x86_64, armhf, arm64 | Ubuntu, Debian, Raspberry Pi |
| x86_64 | Fedora, RHEL, CentOS, openSUSE |
Docker | Любая (универсально) | Без установки, CI/CD, DevOps |
🐳 Docker: зачем он понадобился и как встроился в сборку
Изначально идея добавить Docker-образ DotPlus не стояла на первом месте. Основной упор делался на нативные бинарники и установочные пакеты. Однако в процессе развития проекта стало ясно: Docker — это не просто "в довесок", а необходимый инструмент, без которого:
невозможно обеспечить стабильную кросс-сборку в CI;
нельзя удобно использовать CLI в автоматических сценариях;
сложно дистрибутировать DotPlus в окружениях DevOps и серверов.
🔍 Зачем вообще нужен Docker?
Основные причины интеграции Docker:
✅ Надежная изоляция окружения в CI/CD
Дажеcrossработает внутри Docker-контейнеров. Если ты не контролируешь окружение сборки (например, на GitHub Actions), Docker становится стандартом.✅ Упрощённый запуск без установки
CLI-версия DotPlus можно использовать прямо из Docker без установки бинарников, зависимостей и пакетов. Это особенно ценно для DevOps и автоматизации.✅ Платформа-агностичный дистрибутив
Один образ — один результат. Его поведение одинаково в любой системе, будь то Windows, Linux или macOS (с установленным Docker).✅ Разделение GUI и CLI
Docker используется только для CLI. Это упрощает образ, делает его минимальным и не тянет GUI-библиотеки.
🛠 Структура Dockerfile
В проекте используется Dockerfile.cli:
FROM debian:bookworm-slim
COPY dotplus /usr/local/bin/dotplus
ENTRYPOINT ["dotplus"]Это минимальный образ (на базе slim-дистрибутива Debian), в который помещается только собранный бинарник dotplus. Никаких дополнительных зависимостей, библиотек или окружения не требуется.
⚙️ Интеграция в CI
Сборка Docker-образа происходит автоматически, после компиляции CLI:
- name: Build Docker image
run: |
docker build -f docker/Dockerfile.cli -t ghcr.io/nigdanil/dotplus:latest .
docker push ghcr.io/nigdanil/dotplus:latestDocker-образ публикуется в Docker Hub, откуда его может скачать любой пользователь:
docker pull nigdanil/dotplus-cli:latest🚀 Как использовать Docker-версию DotPlus
Пример запуска CLI внутри Docker:
docker run --rm -v $(pwd):/out ghcr.io/nigdanil/dotplus:latest \
--text "Docker test" --format qrcode --output /out/code.pngОбъяснение:
--rm— удаляет контейнер после завершения-v $(pwd):/out— монтирует текущую папку внутрь контейнера для вывода результата--text,--format,--output— аргументы CLI DotPlus
Таким образом, можно использовать DotPlus в любом CI, на сервере, на macOS или даже в WSL — не устанавливая ничего, кроме Docker.
💻 Запуск DotPlus через Docker на Windows (.bat-файлы)
👉 Для пользователей Windows подготовлены удобные .bat-скрипты, которые вызывают CLI DotPlus внутри Docker-контейнера. Это позволяет запускать генерацию QR и штрихкодов без установки зависимостей.
📄 run-qr.bat — генерация QR-кодов
@echo off
REM Генерация QR-кодов из CSV через Docker
docker run --rm -v "%cd%\examples:/examples" nigdanil/dotplus-cli:1.0.0 ^
--mode qr ^
--csv "/examples/magnit/data/qr/magnit.csv" ^
--logo "/examples/magnit/logo/v1.png" ^
--output "/examples/magnit/img/qr" ^
--cols 3 ^
--rows 3 ^
--qr-size 150 ^
--font-size 24 ^
--font-color "#000000"
pause📄 run-barcode.bat — генерация EAN-13 штрихкодов
@echo off
REM Генерация штрихкодов EAN-13 из CSV через Docker
docker run --rm -v "%cd%\examples:/examples" nigdanil/dotplus-cli:1.0.0 ^
--mode barcode ^
--csv "/examples/magnit/data/barcode/magnit-barcodes-EAN-13.csv" ^
--output "/examples/magnit/img/barcode" ^
--barcode-type EAN-13 ^
--cols 3 ^
--rows 4 ^
--width 300 ^
--height 100 ^
--font-size 22 ^
--label-height 40 ^
--offset-y 10 ^
--spacing-x 20 ^
--spacing-y 20
pause📂 Структура проекта для скриптов
D:\dotplus-windows\
├── examples\
├── run-qr.bat
└── run-barcode.bat📌 Скрипты монтируют папку examples внутрь контейнера и сохраняют результат в удобное место. Всё, что нужно — это установленный Docker.
✅ Почему это удобно?
Не нужно устанавливать
Rust, зависимости или самdotplusРаботает на любой машине с Docker
Можно интегрировать в автоматизацию, скрипты, CI/CD
📌 Что удалось благодаря Docker
Проблема | Решение через Docker |
Кросс-сборка в CI |
|
Использование без установки | Образ с CLI доступен публично |
Интеграция в shell-скрипты и пайплайны | CLI можно вызывать из любого скрипта |
Минимизация зависимости | Образ содержит только |
✅ Вывод: Docker стал неотъемлемой частью инфраструктуры DotPlus. Он используется и в процессе сборки, и как самостоятельный способ запуска CLI. Это позволяет дистрибутировать инструмент в любую среду — будь то сервер, CI/CD или чужой компьютер без установки зависимостей.
📜 Лицензия DotPlus: от исходников к закрытому дистрибутиву
В первой версии DotPlus проект поставлялся с открытым кодом. Однако с релизом стабильных версий и запуском сборок под Linux, стало ясно: пора пересмотреть подход к лицензированию. Причин этому — несколько, и они связаны как с техническими, так и с юридическими и практическими аспектами.
В результате было принято решение:
📌 Перейти на бесплатную, но проприетарную лицензию.
❓ Почему так?
Вот ключевые причины:
Минимизация рисков форков и переиспользования бренда
Когда проект становится узнаваемым, велик риск "серых" клонов, которые мог��т нарушать философию продукта или использовать имя DotPlus без разрешения.Снижение нагрузки на поддержку
Когда код открыт, пользователи часто создают собственные сборки, вносят изменения и потом задают вопросы, не относящиеся к официальной версии.Защита бизнес-модели и эксклюзивных алгоритмов
DotPlus использует внутренние техники вставки логотипов, оптимизации QR, компактного вывода и т. д. Их защита — ключ к качеству конечного продукта.Фокус на стабильных бинарниках, а не на доработках со стороны сообщества
Вся сборка и дистрибуция централизованы — это позволяет гарантировать качество и одинаковое поведение на всех системах.
✅ Что разрешено по новой лицензии?
🔓 Бесплатное использование для любых целей — как в личных, так и в коммерческих проектах
📦 Распространение неизменённых бинарников
👥 Использование в организациях, автоматизации, CI/CD и т. п.
❌ Что запрещено?
🚫 Изучение, анализ, декомпиляция и модификация бинарников
🚫 Распространение модифицированных версий
🚫 Попытки восстановить или раскрыть исходный код
📁 Как распространяется DotPlus сейчас?
✅ Только в виде бинарников (
.exe,.deb,.rpm,.tar.gz)✅ Через официальный GitHub Releases и Docker Registry
📄 Лицензионное соглашение (фрагмент)
Тип лицензии: Бесплатное ПО (проприетарное)
Исходный код: не распространяется
Использование: разрешено для личного и коммерческого применения
Обратная разработка: строго запрещена
Распространение: допустимо только в виде неизменённых бинарников с включением лицензионного соглашения
Авторские права: исходный код и все права на него остаются за автором
⚠️ Почему это всё равно честно?
Несмотря на закрытую лицензию, DotPlus остаётся:
полностью бесплатным;
стабильным и регулярно обновляемым;
совместимым с Linux, Windows, Docker;
понятным и удобным инструментом, который не требует онлайн-доступа или регистрации.
Более того, пользователь всё ещё получает CLI-инструмент, GUI-приложение и все опции (включая CSV, логотипы, экспорт) без ограничений функциональности.
✅ Вывод: лицензия DotPlus теперь закрытая, но прозрачная. Программа остаётся бесплатной, распространяется в виде готовых бинарников и полностью пригодна для реального применения — без страха перед юридическими подводными камнями.
📈 Итоги и планы развития DotPlus
DotPlus прошёл большой путь от простой Windows-программы до полноценного кроссплатформенного инструмента с поддержкой CLI, GUI, Docker и релизами под Linux. Этот этап развития был посвящён тому, чтобы сделать проект устойчивым, универсальным и легко доставляемым в любой среде.
✅ Что реализовано
Возможность | Статус | Комментарий |
🖥 GUI для Windows и Linux | ✅ Готово | На базе |
🧾 CLI-интерфейс | ✅ Готово | Генерация QR/штрихкодов через параметры |
📦 DEB и RPM-пакеты | ✅ В релизах | Для всех популярных дистрибутивов |
🐳 Docker-образ | ✅ Опубликован | Поддержка запуска без установки |
🔄 CI/CD-сборка и релизы | ✅ Автоматизировано | Публикация в GitHub Releases + GHCR |
🔐 Проприетарная лицензия | ✅ Введена | Бесплатно, без исходников, с разрешением на использование |
🛠 Технические особенности
Используется
crossдля мультиархитектурной сборки (x86_64, ARMv7, AArch64)Автоматическая генерация
.debи.rpmчерез скриптtools/generate.shCI/CD на GitHub Actions, один YAML управляет всем пайплайном
Распространение Docker-образа через Docker Hub:
docker pull nigdanil/dotplus-cli:latest🔮 Что в планах?
Вот направления, над которыми планируется работать в следующих релизах:
План | Статус | Комментарий |
📄 Экспорт в PDF и SVG | 🔜 В процессе | Для векторной печати и типографий |
🌐 Web-версия на WASM | 🔜 Исследуется | Возможность запуска в браузере без сервера |
📄 Поддержка больших CSV | 🔜 Планируется | Пакетная генерация с логами и ошибками |
🔄 Автообновление для GUI | 🔜 Будет | Особенно для Windows-версии |
⚙️ Расширение CLI | 🔜 Постепенно | Больше форматов, управление шаблонами |
🔔 Интеграция уведомлений | 🔜 Через | Пока опциональная фича |
🤝 Обратная связь и участие
Если вам не хватает какой-то функции, формат не поддерживается, или вы хотите предложить идею — открывайте issue на GitHub:
📌 https://github.com/nigdanil/dotplus
✅ Финальный вывод
DotPlus стал стабильным, мощным и универсальным инструментом для генерации QR и штрихкодов.
Поддержка разных архитектур, нативные пакеты, Docker и офлайн-режим делают его отличным выбором для всех — от домашних пользователей до CI-инфраструктур.
Программа продолжит развиваться. Спасибо всем, кто использует, тестирует и даёт обратную связь.