set dotenv-load # Configuration ################################################################ app_name := "map" channel := "unstable" builddir := "_build" distdir := "_dist" vendordir := "_vendor" flatpakdir := "_flatpak" repodir := "_repo" clean_images := "" # Derived Values --------------------------------------------------------------- architecture := arch() version := `grep -m1 -o "[^_]version: '[^']*'" meson.build | awk -F"'" '{print $2}'` filename := f"{{app_name}}-{{architecture}}-{{channel}}" # Packaging -------------------------------------------------------------------- linuxdeploy_url := "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-" + `uname -m` + ".AppImage" linuxdeploy := ".cache/linuxdeploy.AppImage" flatpak_cargo_generator := home_directory() / "projects/vendor/flatpak-builder-tools/cargo" # Build Containers ------------------------------------------------------------- fedora_versions := "fedora43 fedora44 fedora-rawhide" debian_versions := "trixie forky sid" appimage_container := "trixie" all_containers := f"arch {{fedora_versions}} {{debian_versions}}" container_image_prefix := "map-build" # Build ######################################################################## # Setup the meson build directory. setup: meson setup {{builddir}} # Compile the project using meson build: setup meson compile -C {{builddir}} # Create a dist tarball with meson dist: setup meson dist -C {{builddir}} --no-tests --allow-dirty # Code Quality ################################################################# # Run tests test: cargo test # Run tests with a coverage report coverage: cargo tarpaulin # Format the source code and fix fixable code quality issues format: cargo fmt && cargo clippy --fix # Check the source code for lint and code quality issues lint: cargo fmt -- --check && cargo clippy # Internationalization / Localization ########################################## # Find translatable strings in the source and create a reference in POTFILES find_translatable_files: find ./src -not -path '*/.*' -type f -name "*.rs" -exec grep -l "tr!(\"\|gettext" {} \; | sed 's|^\./||' | sort > po/POTFILES find ./data -not -path '*/.*' -name "*.in.in" -type f | sed 's|^\./||' | sort >> po/POTFILES # Extract the strings into the POT file extract_strings: find_translatable_files xgettext --files-from=po/POTFILES --output=po/systems.tranquil.Map.pot --from-code=UTF-8 --add-comments --keyword='tr!' # Containers ################################################################### # Builds the container specified by name build-container name: {{ if clean_images != "" { "podman system prune -af" } else { "" } }} @echo "=== Building container image: {{container_image_prefix}}:{{name}} ===" podman build -t {{container_image_prefix}}:{{name}} build-containers/{{name}} # Builds all containers build-containers: {{ if clean_images != "" { "podman system prune -af" } else { "" } }} for container in {{all_containers}}; do podman build -t "{{container_image_prefix}}:$container" "build-containers/$container"; done # Packaging #################################################################### # Updates the cargo-sources.json update_flatpak_dependencies: cd {{flatpak_cargo_generator}} && `poetry env activate` && python3 flatpak-cargo-generator.py {{justfile_directory()}}/Cargo.lock -o {{justfile_directory()}}/build-aux/flatpak/cargo-sources.json && deactivate # Builds a flatpak and exports the .flatpak file package-flatpak: _ensure-distdir update_flatpak_dependencies flatpak-builder --force-clean --user --install-deps-from=flathub --repo={{repodir}} --install {{flatpakdir}} ./build-aux/flatpak/systems.tranquil.Map.yml flatpak build-bundle {{repodir}} {{distdir}}/{{filename}}.flatpak systems.tranquil.Map _fetch-linuxdeploy: @mkdir -p .cache @test -f {{linuxdeploy}} || curl -L -o {{linuxdeploy}} {{linuxdeploy_url}} @chmod +x {{linuxdeploy}} # Builds an AppImage package-appimage: _ensure-distdir (build-container appimage_container) dist _fetch-linuxdeploy && (_clean-image appimage_container) #!/usr/bin/env bash echo "=== Building AppImage ===" staging="$(mktemp -d)" tar -xJf "{{builddir}}/meson-dist/map-{{version}}.tar.xz" -C "${staging}/" cp {{linuxdeploy}} "${staging}/linuxdeploy.AppImage" just _run-in-podman {{container_image_prefix}} "${staging}" {{appimage_container}} " cd /build/map-{{version}} meson setup --prefix=/usr {{builddir}} meson compile -C {{builddir}} DESTDIR=/build/appdir meson install -C {{builddir}} cd /build APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=true /build/linuxdeploy.AppImage \ --appdir=/build/appdir --output=appimage \ --desktop-file=/build/appdir/usr/share/applications/systems.tranquil.Map.desktop \ --icon-file=/build/appdir/usr/share/icons/hicolor/scalable/apps/systems.tranquil.Map.svg mkdir -p /build/out mv /build/Map*.AppImage /build/out/ " mv "${staging}/out/"*.AppImage "{{distdir}}/{{app_name}}-{{architecture}}-{{channel}}.AppImage" rm -rf "${staging}" # Builds an arch .pkg.tar.gz package-arch: _ensure-distdir (build-container "arch") dist && (_clean-image "arch") #!/usr/bin/env bash echo "=== Building Arch package ({{architecture}}) ===" staging="$(mktemp -d)" cp {{builddir}}/meson-dist/map-{{version}}.tar.xz "${staging}/" cp build-aux/arch/PKGBUILD "${staging}/" just _run-in-podman {{container_image_prefix}} "${staging}" arch " mkdir -p /tmp/pkg cp /build/*.tar.xz /tmp/pkg cp /build/PKGBUILD /tmp/pkg chown -R builder:builder /tmp/pkg su builder -c 'cd /tmp/pkg && PKGEXT=.pkg.tar.gz makepkg -f' mkdir -p /build/out cp /tmp/pkg/map-{{version}}-1-{{architecture}}.pkg.tar.gz /build/out/ " cp "${staging}/out/"*.pkg.tar.gz "{{distdir}}/{{app_name}}-{{architecture}}-{{channel}}-arch.pkg.tar.gz" rm -rf "${staging}" # Build .rpm for the given distro package-rpm distro: _ensure-distdir (build-container distro) dist vendor && (_clean-image distro) #!/usr/bin/env bash echo "=== Building RPM for {{distro}} ({{architecture}}) ===" staging="$(mktemp -d)" cp {{builddir}}/meson-dist/map-{{version}}.tar.xz "${staging}/" cp -r {{vendordir}} "${staging}/vendor" tar -cJf "${staging}/map-{{version}}-vendor.tar.xz" -C "${staging}" vendor rm -rf "${staging}/vendor" cp build-aux/rpm/map.spec "${staging}/" just _run-in-podman {{container_image_prefix}} "${staging}" {{distro}} " mkdir -p ~/rpmbuild/{SOURCES,SPECS} cp /build/map-*.tar.xz ~/rpmbuild/SOURCES/ cp /build/map.spec ~/rpmbuild/SPECS/ rpmbuild -bb ~/rpmbuild/SPECS/map.spec mkdir -p /build/out cp ~/rpmbuild/RPMS/{{architecture}}/map-{{version}}-1.*.rpm /build/out/ " cp "${staging}/out/"*.rpm "{{distdir}}/{{app_name}}-{{architecture}}-{{channel}}-{{distro}}.rpm" rm -rf "${staging}" # Build .deb for the given distro package-deb distro: _ensure-distdir (build-container distro) dist && (_clean-image distro) #!/usr/bin/env bash echo "=== Building DEB for {{distro}} ({{architecture}}) ===" staging="$(mktemp -d)" cp {{builddir}}/meson-dist/map-{{version}}.tar.xz "${staging}/{{app_name}}_{{version}}.orig.tar.xz" tar -xJf "${staging}/{{app_name}}_{{version}}.orig.tar.xz" -C "${staging}" mkdir -p "${staging}/{{app_name}}-{{version}}" cp -r build-aux/debian "${staging}/{{app_name}}-{{version}}/debian" just _run-in-podman {{container_image_prefix}} "${staging}" {{distro}} " cd /build/{{app_name}}-{{version}} dpkg-buildpackage -us -uc -b mkdir -p /build/out cp /build/{{app_name}}_{{version}}*_*.deb /build/out/ " cp "${staging}/out/"*.deb "{{distdir}}/{{app_name}}-{{architecture}}-{{channel}}-{{distro}}.deb" rm -rf "${staging}" # Build .rpm for every supported distro package-rpm-all: for distro in {{fedora_versions}}; do just clean_images={{clean_images}} channel={{channel}} package-rpm "$distro"; done # Build .deb for every supported distro package-deb-all: for distro in {{debian_versions}}; do just clean_images={{clean_images}} channel={{channel}} package-deb "$distro"; done # Build all distributable packages package: package-flatpak package-appimage package-arch package-rpm-all package-deb-all # Distribution ################################################################# # Sign and upload flatpak distribute-flatpak: (_sign-and-upload f"{{distdir}}/{{filename}}.flatpak") # Sign and upload AppImage distribute-appimage: (_sign-and-upload f"{{distdir}}/{{filename}}.AppImage") # Sign and upload arch .pkg.tar.gz distribute-arch: (_sign-and-upload f"{{distdir}}/{{filename}}-arch.pkg.tar.gz") # Sign and upload .rpm files distribute-rpm: for distro in {{fedora_versions}}; do just channel={{channel}} _distribute-rpm "$distro"; done # Sign and upload .deb files distribute-deb: for distro in {{debian_versions}}; do just channel={{channel}} _distribute-deb "$distro"; done # Sign and upload all distributable packages distribute: distribute-flatpak distribute-appimage distribute-arch distribute-rpm distribute-deb _distribute-rpm distro: (_sign-and-upload f"{{distdir}}/{{filename}}-{{distro}}.rpm") _distribute-deb distro: (_sign-and-upload f"{{distdir}}/{{filename}}-{{distro}}.deb") # Release ###################################################################### # Creates, signs and uploads all distributable packages release: package distribute # CI/CD ######################################################################## # Intended to run in CI. Lints and releases. ci: lint #!/usr/bin/env bash if [[ "$GIT_REF" == "refs/heads/main" ]]; then just clean_images=1 flatpak_cargo_generator=$FLATPAK_CARGO_GENERATOR release elif [[ "$GIT_REF" == refs/tags/* ]]; then just clean_images=1 flatpak_cargo_generator=$FLATPAK_CARGO_GENERATOR channel="${GIT_REF#refs/tags/}" release else echo "Not in CI environment." fi # Local Install ################################################################ # Locally installs install: build meson install -C {{builddir}} uninstall: ninja -C {{builddir}} uninstall # Utility Tasks ################################################################ # Vendor the rust dependencies vendor: cargo vendor {{vendordir}} >/dev/null mkdir -p .cargo # Syncs versions of different files to the meson.build sync-versions: #!/usr/bin/env bash echo "Using version from meson.build: {{version}}" # Rust Cargo.toml echo -ne "\tUpdating: Cargo.toml" sed -i "s/^version = \"[^\"]*\"$/version = \"{{version}}\"/" Cargo.toml echo -e "\r\tUpdated: Cargo.toml " # Arch PKGBUILD echo -ne "\tUpdating: PKGBUILD" sed -i "s/^pkgver=.*$/pkgver={{version}}/" build-aux/arch/PKGBUILD echo -e "\r\tUpdated: PKGBUILD " # Fedora RPM Spec echo -ne "\tUpdating: map.spec" sed -i "s/^Version: .*$/Version: {{version}}/" build-aux/rpm/map.spec echo -e "\r\tUpdated: map.spec " # Internal Tasks ############################################################### # Cleans images if the flag is set (eg. for low-storage environments) _clean-image image: {{ if clean_images != "" { f"podman rmi {{container_image_prefix}}:{{image}}" } else { "" } }} # Ensures distdir exists _ensure-distdir: @mkdir -p {{distdir}} # Signs a file _sign file channel platform: #!/usr/bin/env bash comment="Version: {{channel}}, File: {{file_name(file)}} Built on: {{datetime('%Y-%m-%d %H:%M')}}, Platform: {{platform}}" if [ -f ~/.minisign/minisign.pass ]; then cat ~/.minisign/minisign.pass | minisign -Sm "{{file}}" -t "${comment}" else minisign -Sm "{{file}}" -t "${comment}" fi # Uploads a file and its signature. _upload file: rsync -avz {{file}}.minisig $DISTRIBUTION_HOST:$DISTRIBUTION_PATH rsync -avz {{file}} $DISTRIBUTION_HOST:$DISTRIBUTION_PATH # Sign and upload a file. _sign-and-upload file: (_sign file channel architecture) (_upload file) # Generic Podman Runner: Run a build script inside a container _run-in-podman prefix staging tag commands: podman run --rm -v "{{staging}}:/build:Z" \ {{prefix}}:{{tag}} \ bash -c "{{commands}}"