190 lines
5.8 KiB
Bash
Executable File
190 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
|
PREFIX=${PREFIX:-"$HOME/.local"}
|
|
BUILD_DIR=${BUILD_DIR:-"$ROOT/build"}
|
|
INSTALL_DEPS=0
|
|
ACTIVATE=0
|
|
ASSUME_YES=0
|
|
MINIMUM_RUST=1.87.0
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: scripts/install.sh [options]
|
|
|
|
Options:
|
|
--deps Offer to install missing build dependencies
|
|
--no-deps Do not install dependencies (default)
|
|
--activate Activate Lumen in the running Plasma session
|
|
--no-activate Build and install only (default)
|
|
--yes, -y Assume yes for dependency installation prompts
|
|
--help Show this help
|
|
|
|
Environment:
|
|
PREFIX Installation prefix (default: ~/.local)
|
|
BUILD_DIR Build directory (default: <source>/build)
|
|
LUMEN_STATE_DIR Activation backups and logs (default: PREFIX/share/lumen-wallpaper)
|
|
EOF
|
|
}
|
|
|
|
log() {
|
|
printf 'Lumen installer: %s\n' "$*"
|
|
}
|
|
|
|
fail() {
|
|
printf 'Lumen installer: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
while (($#)); do
|
|
case "$1" in
|
|
--deps) INSTALL_DEPS=1 ;;
|
|
--no-deps) INSTALL_DEPS=0 ;;
|
|
--activate) ACTIVATE=1 ;;
|
|
--no-activate) ACTIVATE=0 ;;
|
|
--yes|-y) ASSUME_YES=1 ;;
|
|
--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*) fail "Unknown option: $1" ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
confirm() {
|
|
local prompt=$1
|
|
local answer
|
|
if ((ASSUME_YES)); then
|
|
return 0
|
|
fi
|
|
if [[ ! -t 0 ]]; then
|
|
return 1
|
|
fi
|
|
read -r -p "$prompt [y/N] " answer
|
|
[[ $answer == y || $answer == Y || $answer == yes || $answer == YES ]]
|
|
}
|
|
|
|
rust_version_ok() {
|
|
command -v rustc >/dev/null 2>&1 || return 1
|
|
local version
|
|
version=$(rustc --version 2>/dev/null | awk '{print $2}')
|
|
[[ -n $version ]] || return 1
|
|
printf '%s\n%s\n' "$MINIMUM_RUST" "$version" | sort -V -C
|
|
}
|
|
|
|
ecm_available() {
|
|
local probe_dir
|
|
probe_dir=$(mktemp -d "${TMPDIR:-/tmp}/lumen-ecm-probe.XXXXXX")
|
|
if (cd "$probe_dir" && cmake --find-package \
|
|
-DNAME=ECM -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST \
|
|
>/dev/null 2>&1); then
|
|
rm -rf -- "$probe_dir"
|
|
return 0
|
|
fi
|
|
rm -rf -- "$probe_dir"
|
|
return 1
|
|
}
|
|
|
|
dependencies_ready() {
|
|
local command_name
|
|
for command_name in cmake ninja c++ cargo rustc pkg-config; do
|
|
command -v "$command_name" >/dev/null 2>&1 || return 1
|
|
done
|
|
rust_version_ok || return 1
|
|
pkg-config --exists Qt6Core Qt6Gui Qt6Qml Qt6Quick || return 1
|
|
ecm_available || return 1
|
|
}
|
|
|
|
run_as_root() {
|
|
if ((EUID == 0)); then
|
|
"$@"
|
|
else
|
|
command -v sudo >/dev/null 2>&1 || fail "sudo is required for system packages"
|
|
sudo "$@"
|
|
fi
|
|
}
|
|
|
|
install_dependencies() {
|
|
if dependencies_ready; then
|
|
log "Build dependencies are already available"
|
|
return
|
|
fi
|
|
((INSTALL_DEPS)) || return
|
|
confirm "Install missing build dependencies with the system package manager?" \
|
|
|| fail "Build dependencies are required; install them manually or rerun with --deps"
|
|
|
|
if command -v dnf >/dev/null 2>&1; then
|
|
run_as_root dnf install -y \
|
|
gcc-c++ cargo rustc cmake ninja-build extra-cmake-modules pkgconf-pkg-config curl \
|
|
qt6-qtbase-devel qt6-qtdeclarative-devel vulkan-loader-devel vulkan-headers \
|
|
kf6-kirigami plasma-workspace
|
|
elif command -v apt-get >/dev/null 2>&1; then
|
|
run_as_root apt-get update
|
|
run_as_root apt-get install -y \
|
|
build-essential cargo rustc cmake ninja-build extra-cmake-modules pkg-config curl \
|
|
qt6-base-dev qt6-declarative-dev libvulkan-dev \
|
|
qml6-module-org-kde-kirigami plasma-workspace
|
|
elif command -v pacman >/dev/null 2>&1; then
|
|
run_as_root pacman -Sy --needed --noconfirm \
|
|
base-devel cargo cmake ninja extra-cmake-modules pkgconf curl \
|
|
qt6-base qt6-declarative vulkan-headers kirigami plasma-workspace
|
|
else
|
|
fail "Unsupported package manager. Install CMake, Ninja, a C++ compiler, Rust, Qt6, ECM, Vulkan, Kirigami, and Plasma Workspace manually"
|
|
fi
|
|
}
|
|
|
|
ensure_rust() {
|
|
if rust_version_ok; then
|
|
return
|
|
fi
|
|
((INSTALL_DEPS)) || return
|
|
confirm "Rust $MINIMUM_RUST or newer is required. Install/update it with rustup in your home directory?" \
|
|
|| fail "Rust $MINIMUM_RUST or newer is required"
|
|
|
|
if command -v rustup >/dev/null 2>&1; then
|
|
rustup toolchain install stable --profile minimal
|
|
else
|
|
command -v curl >/dev/null 2>&1 || fail "curl is required to download rustup"
|
|
local rustup_script
|
|
rustup_script=$(mktemp "${TMPDIR:-/tmp}/lumen-rustup.XXXXXX")
|
|
curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs -o "$rustup_script"
|
|
sh "$rustup_script" -y --profile minimal --no-modify-path
|
|
rm -f -- "$rustup_script"
|
|
fi
|
|
export PATH="$HOME/.cargo/bin:$PATH"
|
|
export RUSTUP_TOOLCHAIN=stable
|
|
rust_version_ok || fail "The Rust toolchain is still older than $MINIMUM_RUST"
|
|
}
|
|
|
|
preflight() {
|
|
local command_name
|
|
for command_name in cmake ninja c++ cargo rustc pkg-config; do
|
|
command -v "$command_name" >/dev/null 2>&1 \
|
|
|| fail "Missing required command: $command_name"
|
|
done
|
|
rust_version_ok || fail "Rust $MINIMUM_RUST or newer is required"
|
|
pkg-config --exists Qt6Core Qt6Gui Qt6Qml Qt6Quick \
|
|
|| fail "Qt6 development packages are required"
|
|
ecm_available || fail "Extra CMake Modules (ECM) are required"
|
|
}
|
|
|
|
install_dependencies
|
|
ensure_rust
|
|
preflight
|
|
|
|
cmake -S "$ROOT" -B "$BUILD_DIR" -G Ninja \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_INSTALL_PREFIX="$PREFIX"
|
|
cmake --build "$BUILD_DIR"
|
|
cmake --install "$BUILD_DIR"
|
|
|
|
log "Installed Lumen Wallpaper to $PREFIX"
|
|
if ((ACTIVATE)); then
|
|
BUILD_DIR=${LUMEN_STATE_DIR:-"$PREFIX/share/lumen-wallpaper"} \
|
|
"$ROOT/scripts/activate.sh"
|
|
else
|
|
log "Activate it with scripts/activate.sh or choose Lumen Wallpaper in KDE settings"
|
|
fi
|