Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 169 additions & 97 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,100 +1,172 @@
SHELL = /usr/bin/bash

home: dirs preferences deps
@echo "All done, reboot is strongly recommended."

SHELL := /bin/bash

# ── home-maker ────────────────────────────────────────────────────────────────
# One Makefile to install and upgrade every tool on your dev machine.
# Supports Arch Linux (pacman/paru) and Fedora (dnf).
# Inspired by https://github.com/santhoshtr/hm

# ── detect OS ─────────────────────────────────────────────────────────────────
OS_ID := $(shell . /etc/os-release 2>/dev/null && echo $$ID || echo unknown)

# ── package group includes ────────────────────────────────────────────────────
include dev/cli.mk
include dev/langs.mk
include dev/rust.mk
include dev/fonts.mk

include desktop/apps.mk
include desktop/gnome.mk

# ── package manager commands ──────────────────────────────────────────────────
ifeq ($(OS_ID),arch)
PKG_INSTALL := sudo pacman -Syyuu --needed
AUR_INSTALL := paru -Syu --needed
else ifeq ($(OS_ID),fedora)
PKG_INSTALL := sudo dnf install -y
AUR_INSTALL := echo
else
$(warning Unknown OS '$(OS_ID)'. Defaulting to dnf.)
PKG_INSTALL := sudo dnf install -y
AUR_INSTALL := echo
endif

CARGO_INSTALL := cargo install
GO_INSTALL := go install
NPM_INSTALL := sudo npm i -g

# ── helper functions ──────────────────────────────────────────────────────────

# Split "name@version" → name and version
pkg-name = $(firstword $(subst @, ,$(1)))
pkg-version = $(word 2,$(subst @, ,$(1)))

# Use PKG_<name> override when the Make target name differs from the package
# name the manager expects (e.g. libreoffice → libreoffice-fresh on Arch).
pkg-pkgname = $(or $(PKG_$(call pkg-name,$(1))),$(call pkg-name,$(1)))

# ── target generators ─────────────────────────────────────────────────────────

define gen-pkg
.PHONY: $(call pkg-name,$(1))
$(call pkg-name,$(1)):
@echo "installing/upgrading $$@..."
@$(PKG_INSTALL) $(call pkg-pkgname,$(1))
endef

ifeq ($(OS_ID),arch)
define gen-aur
.PHONY: $(call pkg-name,$(1))
$(call pkg-name,$(1)):
@echo "installing/upgrading $$@..."
@$(AUR_INSTALL) $(call pkg-pkgname,$(1))
endef
else
define gen-aur
.PHONY: $(call pkg-name,$(1))
$(call pkg-name,$(1)):
@echo "Skipping AUR package $$@ (not available on $(OS_ID))"
endef
endif

define gen-cargo
.PHONY: $(call pkg-name,$(1))
$(call pkg-name,$(1)):
@echo "installing/upgrading $$@..."
@$(CARGO_INSTALL) $(call pkg-pkgname,$(1))
endef

define gen-go
.PHONY: $(call pkg-name,$(1))
$(call pkg-name,$(1)):
@echo "installing/upgrading $$@..."
@$(GO_INSTALL) $(call pkg-pkgname,$(1))@$(or $(call pkg-version,$(1)),latest)
endef

define gen-npm
.PHONY: $(call pkg-name,$(1))
$(call pkg-name,$(1)):
@echo "installing/upgrading $$@..."
@$(NPM_INSTALL) $(call pkg-pkgname,$(1))$(if $(call pkg-version,$(1)),@$(call pkg-version,$(1)))
endef

# ── generate targets from accumulated package lists ───────────────────────────

$(foreach p,$(PKG),$(eval $(call gen-pkg,$(p))))
$(foreach p,$(AUR),$(eval $(call gen-aur,$(p))))
$(foreach p,$(CARGO),$(eval $(call gen-cargo,$(p))))
$(foreach p,$(GO),$(eval $(call gen-go,$(p))))
$(foreach p,$(NPM),$(eval $(call gen-npm,$(p))))

# ── group targets ─────────────────────────────────────────────────────────────

.PHONY: cli
cli: build-tools fzf git cmake zsh zsh-completions neovim bash-completion man-db man-pages eza zoxide

.PHONY: langs
langs: nodejs npm go dotnet-sdk rustup dart

.PHONY: rust
rust: sccache configman gprofile cargo-cache cargo-edit

.PHONY: fonts
fonts: noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra ttf-ms-fonts

.PHONY: apps
apps: firefox tilix libreoffice gnome-browser-connector vscode pycharm zoom

# ── top-level targets ─────────────────────────────────────────────────────────

.PHONY: dev
dev: cli langs rust

.PHONY: desktop
desktop: fonts apps gnome

.PHONY: dirs
dirs:
@echo "Creating folders"
mkdir -p ~/Projects ~/Work ~/.npm/packages/bin ~/.pub-cache/bin

preferences:
@echo "Applying gnome settings"
gsettings set org.gnome.desktop.datetime automatic-timezone true
gsettings set org.gnome.desktop.interface clock-format '12h'
gsettings set org.gnome.desktop.interface clock-show-date true
gsettings set org.gnome.desktop.interface clock-show-weekday true
gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita-dark'
gsettings set org.gnome.desktop.interface show-battery-percentage true
gsettings set org.gnome.desktop.peripherals.touchpad natural-scroll false
gsettings set org.gnome.desktop.peripherals.touchpad tap-to-click true
gsettings set org.gnome.desktop.sound allow-volume-above-100-percent true
gsettings set org.gnome.desktop.wm.keybindings show-desktop "['<Super>d']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications "['<Alt>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "['<Shift><Alt>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-windows "['<Super>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-windows-backward "['<Shift><Super>Tab']"
gsettings set org.gnome.desktop.wm.preferences button-layout ":minimize,maximize,close"

.ONESHELL:
deps:
@echo "Installing essential packages"
sudo pacman -Syyuu --needed \
base-devel \
fzf \
git \
cmake \
firefox \
tilix \
nodejs \
noto-fonts \
noto-fonts-cjk \
noto-fonts-emoji \
noto-fonts-extra \
npm \
rustup \
zsh \
zsh-completions \
neovim \
libreoffice-fresh \
bash-completion \
dart \
dotnet-sdk \
go \
man-db \
man-pages

# curl \
# --fail \
# --no-progress-meter \
# --show-error \
# --output-dir zsh \
# --remote-name-all "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/lib/{key-bindings,completion}.zsh"

@echo "Set up rust compiler & its components"
rustup toolchain install stable
rustup set profile default
cargo install sccache
export PATH=$$PATH:$$HOME/.cargo/bin
export RUSTC_WRAPPER=$(which sccache)
cargo install --locked --jobs=3 configman

@echo "Linking config files"

configman --src=. --dest=~

(
# installing AUR helper
cd /tmp
git clone https://aur.archlinux.org/paru.git
cd paru
makepkg -si
)

cargo install gprofile

paru -Syu --needed snapd chrome-gnome-shell zoom shellcheck-bin ttf-ms-fonts

# cargo install bat cargo-edit cargo-expand cargo-watch evcxr_repl exa


@echo "Installing snaps packages"
sudo systemctl enable --now snapd.socket

if [[ ! -d /snap ]]; then
sudo ln -s /var/lib/snapd/snap /snap
@echo "Creating directories..."
@mkdir -p ~/Projects ~/Work ~/.npm/packages/bin ~/.pub-cache/bin

.PHONY: link-dots
link-dots:
@echo "Linking config files..."
@configman --src=. --dest=~

.PHONY: aur-helper
aur-helper:
@if [ "$(OS_ID)" != "arch" ]; then \
echo "paru is only for Arch Linux"; exit 1; \
fi
@if ! command -v paru &>/dev/null; then \
tmpdir=$$(mktemp -d) && \
git clone https://aur.archlinux.org/paru.git "$$tmpdir/paru" && \
cd "$$tmpdir/paru" && makepkg -si && \
rm -rf "$$tmpdir"; \
else \
echo "paru is already installed"; \
fi

sleep 10s

sudo snap install code --classic
sudo snap install pycharm-community --classic
.PHONY: all
all: dirs dev desktop

.PHONY: hm
hm:
@bash "$(CURDIR)/hm.sh"

.PHONY: clean
clean:
@echo "cleaning cargo..."
@cargo-cache -a 2>/dev/null || true
@. /etc/os-release 2>/dev/null; \
if [ "$$ID" = "arch" ]; then \
echo "cleaning pacman cache..."; \
sudo pacman -Sc --noconfirm; \
elif [ "$$ID" = "fedora" ]; then \
echo "cleaning dnf cache..."; \
sudo dnf clean all; \
fi
@echo "cleaning npm..."
@npm cache clean --force 2>/dev/null || true
@echo "cleaning go..."
@go clean -cache 2>/dev/null || true
@echo "all caches cleaned"
61 changes: 61 additions & 0 deletions desktop/apps.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# desktop applications

PKG += firefox tilix

# libreoffice: 'libreoffice-fresh' on Arch, 'libreoffice' on Fedora
PKG += libreoffice
ifeq ($(OS_ID),arch)
PKG_libreoffice := libreoffice-fresh
endif

# gnome-browser-connector: AUR on Arch, official repo on Fedora
ifeq ($(OS_ID),arch)
AUR += gnome-browser-connector
else
PKG += gnome-browser-connector
endif

# snapd: AUR on Arch, official repo on Fedora
ifeq ($(OS_ID),arch)
AUR += snapd
else
PKG += snapd
endif

# VSCode — installed via snap on both distros
.PHONY: vscode
vscode: snapd-setup
@echo "installing/upgrading $@..."
@sudo snap install code --classic

# PyCharm Community — installed via snap on both distros
.PHONY: pycharm
pycharm: snapd-setup
@echo "installing/upgrading $@..."
@sudo snap install pycharm-community --classic

# zoom: AUR on Arch; direct RPM download on Fedora
ifeq ($(OS_ID),arch)
AUR += zoom
else
.PHONY: zoom
zoom:
@echo "installing/upgrading $@..."
@tmpdir=$$(mktemp -d) && \
curl -fsSL "https://zoom.us/client/latest/zoom_x86_64.rpm" \
-o "$$tmpdir/zoom.rpm" && \
sudo dnf install -y "$$tmpdir/zoom.rpm" && \
rm -rf "$$tmpdir"
endif

# snapd post-install setup (enable service, create /snap symlink)
.PHONY: snapd-setup
snapd-setup: snapd
@echo "setting up snapd..."
@sudo systemctl enable --now snapd.socket
@if [ ! -e /snap ]; then \
sudo ln -s /var/lib/snapd/snap /snap; \
fi
@echo "waiting for snapd to initialise..."
@sleep 5
@echo "snapd initialized"
20 changes: 20 additions & 0 deletions desktop/gnome.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# GNOME desktop preferences

.PHONY: gnome
gnome:
@echo "Applying GNOME settings..."
gsettings set org.gnome.desktop.datetime automatic-timezone true
gsettings set org.gnome.desktop.interface clock-format '12h'
gsettings set org.gnome.desktop.interface clock-show-date true
gsettings set org.gnome.desktop.interface clock-show-weekday true
gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita-dark'
gsettings set org.gnome.desktop.interface show-battery-percentage true
gsettings set org.gnome.desktop.peripherals.touchpad natural-scroll false
gsettings set org.gnome.desktop.peripherals.touchpad tap-to-click true
gsettings set org.gnome.desktop.sound allow-volume-above-100-percent true
gsettings set org.gnome.desktop.wm.keybindings show-desktop "['<Super>d']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications "['<Alt>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "['<Shift><Alt>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-windows "['<Super>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-windows-backward "['<Shift><Super>Tab']"
gsettings set org.gnome.desktop.wm.preferences button-layout ":minimize,maximize,close"
18 changes: 18 additions & 0 deletions dev/cli.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# core CLI tools every developer uses

PKG += fzf git cmake zsh zsh-completions neovim bash-completion man-db man-pages

CARGO += eza zoxide

# base-devel on Arch, "Development Tools" group on Fedora
.PHONY: build-tools
build-tools:
@echo "installing/upgrading $@..."
@. /etc/os-release 2>/dev/null; \
if [ "$$ID" = "arch" ]; then \
sudo pacman -Syyuu --needed base-devel; \
elif [ "$$ID" = "fedora" ]; then \
sudo dnf groupinstall -y "Development Tools"; \
else \
echo "Unsupported OS: $$ID, skipping $@"; \
fi
20 changes: 20 additions & 0 deletions dev/fonts.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# fonts

# Noto font family — package names differ between distros
PKG += noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra

ifeq ($(OS_ID),fedora)
PKG_noto-fonts := google-noto-fonts-common
PKG_noto-fonts-cjk := google-noto-cjk-fonts
PKG_noto-fonts-emoji := google-noto-emoji-fonts
PKG_noto-fonts-extra := google-noto-sans-fonts
endif

# MS fonts: AUR on Arch; not available on Fedora
ifeq ($(OS_ID),arch)
AUR += ttf-ms-fonts
else
.PHONY: ttf-ms-fonts
ttf-ms-fonts:
@echo "ttf-ms-fonts not available on $(OS_ID), skipping"
endif
Loading