# DWN - Desktop Window Manager
# Simple Makefile - just run 'make' to build!
# Compiler settings
CC = gcc
CFLAGS = -Wall -Wextra -O2 -I./include
LDFLAGS = -lX11 -lXext -lXinerama -lXrandr -lXft -lfontconfig -ldbus-1 -lcurl -lm -lpthread
# Directories
SRC_DIR = src
INC_DIR = include
BUILD_DIR = build
BIN_DIR = bin
# Find all source files automatically
SRCS = $(wildcard $(SRC_DIR)/*.c)
OBJS = $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
DEPS = $(OBJS:.o=.d)
# Output binary
TARGET = $(BIN_DIR)/dwn
# Installation paths
PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
DATADIR = $(PREFIX)/share
SYSCONFDIR = /etc
# Get pkg-config flags (with error handling)
PKG_CFLAGS := $(shell pkg-config --cflags x11 xext xinerama xrandr xft fontconfig dbus-1 2>/dev/null)
PKG_LIBS := $(shell pkg-config --libs x11 xext xinerama xrandr xft fontconfig dbus-1 2>/dev/null)
# Use pkg-config if available
ifneq ($(PKG_LIBS),)
LDFLAGS = $(PKG_LIBS) -lcurl -lm -lpthread
endif
ifneq ($(PKG_CFLAGS),)
CFLAGS += $(PKG_CFLAGS)
endif
# =============================================================================
# MAIN TARGETS
# =============================================================================
.PHONY: all help clean install uninstall debug run test deps check-deps
# Default target - show help if first time, otherwise build
all: check-deps $(TARGET)
@echo ""
@echo "Build successful! Binary created at: $(TARGET)"
@echo ""
@echo "Next steps:"
@echo " make run - Test DWN in a window (safe, doesn't affect your desktop)"
@echo " make install - Install DWN system-wide"
@echo ""
# Show help
help:
@echo "=============================================="
@echo " DWN - Desktop Window Manager"
@echo "=============================================="
@echo ""
@echo "QUICK START:"
@echo " make deps - Install required dependencies (Ubuntu/Debian)"
@echo " make - Build DWN"
@echo " make run - Test DWN in a safe window"
@echo " make install - Install to your system"
@echo ""
@echo "ALL COMMANDS:"
@echo " make - Build DWN (release version)"
@echo " make debug - Build with debug symbols"
@echo " make run - Test in Xephyr window (safe!)"
@echo " make install - Install to $(BINDIR)"
@echo " make uninstall- Remove from system"
@echo " make clean - Remove build files"
@echo " make deps - Install dependencies (needs sudo)"
@echo " make help - Show this help"
@echo ""
@echo "AFTER INSTALL:"
@echo " 1. Log out of your current session"
@echo " 2. At login screen, select 'DWN' as your session"
@echo " 3. Log in and enjoy!"
@echo ""
# =============================================================================
# BUILD TARGETS
# =============================================================================
# Build with debug symbols
debug: CFLAGS += -g -DDEBUG
debug: clean $(TARGET)
@echo "Debug build complete!"
# Link all object files into final binary
$(TARGET): $(OBJS) | $(BIN_DIR)
@echo "Linking..."
@$(CC) $(OBJS) -o $@ $(LDFLAGS)
# Compile each source file
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
@echo "Compiling $<..."
@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
# Create build directory
$(BUILD_DIR):
@mkdir -p $(BUILD_DIR)
# Create bin directory
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
# Include dependency files
-include $(DEPS)
# =============================================================================
# INSTALL / UNINSTALL
# =============================================================================
install: $(TARGET)
@echo "Installing DWN..."
@install -Dm755 $(TARGET) $(DESTDIR)$(BINDIR)/dwn
@install -Dm644 scripts/dwn.desktop $(DESTDIR)$(DATADIR)/xsessions/dwn.desktop
@mkdir -p $(DESTDIR)$(SYSCONFDIR)/dwn
@install -Dm644 config/config.example $(DESTDIR)$(SYSCONFDIR)/dwn/config.example
@echo ""
@echo "=============================================="
@echo " Installation complete!"
@echo "=============================================="
@echo ""
@echo "To configure DWN, run:"
@echo " mkdir -p ~/.config/dwn"
@echo " cp $(SYSCONFDIR)/dwn/config.example ~/.config/dwn/config"
@echo ""
@echo "Then log out and select 'DWN' at the login screen!"
@echo ""
uninstall:
@echo "Removing DWN..."
@rm -f $(DESTDIR)$(BINDIR)/dwn
@rm -f $(DESTDIR)$(DATADIR)/xsessions/dwn.desktop
@rm -rf $(DESTDIR)$(SYSCONFDIR)/dwn
@echo "DWN has been uninstalled."
# =============================================================================
# DEVELOPMENT / TESTING
# =============================================================================
# Test DWN in a nested X server (safe - doesn't touch your desktop)
run: $(TARGET)
@echo "Starting DWN in test mode..."
@echo "(Press Alt+Shift+Q inside the window to quit)"
Xephyr :1 -screen 1280x720 &
sleep 1
DISPLAY=:1 $(TARGET)
# Clean build files
clean:
@echo "Cleaning build files..."
@rm -rf $(BUILD_DIR) $(BIN_DIR)
@echo "Clean complete."
# =============================================================================
# DEPENDENCY MANAGEMENT
# =============================================================================
# Check if dependencies are installed
check-deps:
@command -v pkg-config >/dev/null 2>&1 || { \
echo "ERROR: pkg-config is not installed!"; \
echo "Run: make deps"; \
exit 1; \
}
@pkg-config --exists x11 2>/dev/null || { \
echo "ERROR: X11 development libraries not found!"; \
echo "Run: make deps"; \
exit 1; \
}
@pkg-config --exists dbus-1 2>/dev/null || { \
echo "ERROR: D-Bus development libraries not found!"; \
echo "Run: make deps"; \
exit 1; \
}
# Install dependencies (Ubuntu/Debian)
deps:
@echo "Installing dependencies..."
@echo "This requires sudo (administrator) access."
@echo ""
@if command -v apt >/dev/null 2>&1; then \
sudo apt update && sudo apt install -y \
build-essential \
pkg-config \
libx11-dev \
libxext-dev \
libxinerama-dev \
libxrandr-dev \
libxft-dev \
libfontconfig1-dev \
libdbus-1-dev \
libcurl4-openssl-dev \
xserver-xephyr \
dmenu; \
echo ""; \
echo "Dependencies installed successfully!"; \
echo "Now run: make"; \
elif command -v dnf >/dev/null 2>&1; then \
sudo dnf install -y \
gcc make \
pkg-config \
libX11-devel \
libXext-devel \
libXinerama-devel \
libXrandr-devel \
dbus-devel \
libcurl-devel \
xorg-x11-server-Xephyr \
dmenu; \
echo ""; \
echo "Dependencies installed successfully!"; \
echo "Now run: make"; \
elif command -v pacman >/dev/null 2>&1; then \
sudo pacman -S --needed \
base-devel \
pkg-config \
libx11 \
libxext \
libxinerama \
libxrandr \
dbus \
curl \
xorg-server-xephyr \
dmenu; \
echo ""; \
echo "Dependencies installed successfully!"; \
echo "Now run: make"; \
else \
echo "ERROR: Could not detect package manager!"; \
echo "Please install these packages manually:"; \
echo " - GCC and Make"; \
echo " - pkg-config"; \
echo " - X11, Xext, Xinerama, Xrandr development libraries"; \
echo " - D-Bus development library"; \
echo " - libcurl development library"; \
echo " - Xephyr (for testing)"; \
echo " - dmenu (for app launcher)"; \
exit 1; \
fi
# =============================================================================
# CODE QUALITY (for developers)
# =============================================================================
.PHONY: format check
format:
@echo "Formatting code..."
@clang-format -i $(SRC_DIR)/*.c $(INC_DIR)/*.h 2>/dev/null || \
echo "Note: clang-format not installed (optional)"
check:
@echo "Running static analysis..."
@cppcheck --enable=all --inconclusive -I$(INC_DIR) $(SRC_DIR) 2>/dev/null || \
echo "Note: cppcheck not installed (optional)"