From 798ce0f9e6c1a6eb54dea1bd9b29c4786629c4d4 Mon Sep 17 00:00:00 2001 From: Jon Crussell Date: Wed, 31 Dec 2025 15:16:50 -0800 Subject: [PATCH 1/2] Enhance Makefile with improved portability and dependency handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds shell configuration for consistent behavior across distributions, implements conditional compilation based on available tools (xgettext, msgfmt), improves metadata generation, adds dependency checking, and enhances user feedback during the build process. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- Makefile | 84 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index f9ecee2..9bfe287 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,16 @@ -UUID = "forge@jmmaranan.com" +UUID = forge@jmmaranan.com INSTALL_PATH = $(HOME)/.local/share/gnome-shell/extensions/$(UUID) MSGSRC = $(wildcard po/*.po) -.PHONY: all clean install schemas uninstall enable disable log debug patchcss +# Shell configuration - explicitly use bash for portability across distros +SHELL := /bin/bash +.SHELLFLAGS := -eo pipefail -c + +# Tool detection (using bash-specific &> redirect) +HAS_XGETTEXT := $(shell command -v xgettext &>/dev/null && echo yes || echo no) +HAS_MSGFMT := $(shell command -v msgfmt &>/dev/null && echo yes || echo no) + +.PHONY: all clean install schemas uninstall enable disable log debug patchcss check-deps all: build install enable restart @@ -19,12 +27,24 @@ schemas/gschemas.compiled: schemas/*.gschema.xml patchcss: # TODO: add the script to update css tag when delivering theme.js + metadata: - echo "export const developers = Object.entries([" > lib/prefs/metadata.js - git shortlog -sne || echo "" >> lib/prefs/metadata.js - awk -i inplace '!/dependabot|noreply/' lib/prefs/metadata.js - sed -i 's/^[[:space:]]*[0-9]*[[:space:]]*\(.*\) <\(.*\)>/ {name:"\1", email:"\2"},/g' lib/prefs/metadata.js - echo "].reduce((acc, x) => ({ ...acc, [x.email]: acc[x.email] ?? x.name }), {})).map(([email, name]) => name + ' <' + email + '>')" >> lib/prefs/metadata.js + @echo "Generating developer metadata..." + @echo "export const developers = [" > lib/prefs/metadata.js + @git shortlog -sne --all \ + | (grep -vE 'dependabot|noreply' || true) \ + | awk '{ \ + email = $$NF; \ + if (email in seen) next; \ + seen[email] = 1; \ + name = ""; \ + for (i = 2; i < NF; i++) { \ + name = name (i == 2 ? "" : " ") $$i; \ + } \ + gsub(/"/, "\\\"", name); \ + printf " \"%s %s\",\n", name, email; \ + }' >> lib/prefs/metadata.js + @echo "];" >> lib/prefs/metadata.js build: clean metadata.json schemas compilemsgs metadata rm -rf temp @@ -39,10 +59,12 @@ build: clean metadata.json schemas compilemsgs metadata cp LICENSE temp mkdir -p temp/locale for msg in $(MSGSRC:.po=.mo); do \ - msgf=temp/locale/`basename $$msg .mo`; \ - mkdir -p $$msgf; \ - mkdir -p $$msgf/LC_MESSAGES; \ - cp $$msg $$msgf/LC_MESSAGES/forge.mo; \ + if [ -f $$msg ]; then \ + msgf=temp/locale/`basename $$msg .mo`; \ + mkdir -p $$msgf; \ + mkdir -p $$msgf/LC_MESSAGES; \ + cp $$msg $$msgf/LC_MESSAGES/forge.mo; \ + fi; \ done; ./po/%.mo: ./po/%.po @@ -54,22 +76,52 @@ debug: potfile: ./po/forge.pot +# Conditional potfile generation based on xgettext availability +ifeq ($(HAS_XGETTEXT),yes) ./po/forge.pot: metadata ./prefs.js ./extension.js ./lib/**/*.js mkdir -p po xgettext --from-code=UTF-8 --output=po/forge.pot --package-name "Forge" ./prefs.js ./extension.js ./lib/**/*.js - +else +./po/forge.pot: + @echo "WARNING: xgettext not found, skipping pot file generation" + @echo "Install gettext package for translation support" + @mkdir -p po + @touch ./po/forge.pot +endif + +# Conditional compilation of messages based on msgfmt availability +ifeq ($(HAS_MSGFMT),yes) compilemsgs: potfile $(MSGSRC:.po=.mo) for msg in $(MSGSRC); do \ msgmerge -U $$msg ./po/forge.pot; \ done; +else +compilemsgs: + @echo "WARNING: msgfmt not found, skipping translation compilation" + @echo "Install gettext package for translation support" +endif clean: - rm -f lib/prefs/metadata.js - rm "$(UUID).zip" || echo "Nothing to delete" + rm -f lib/prefs/metadata.js "$(UUID).zip" rm -rf temp schemas/gschemas.compiled +check-deps: + @echo "Checking build dependencies..." + @command -v glib-compile-schemas &>/dev/null || (echo "ERROR: glib-compile-schemas not found. Install glib2-devel or libglib2.0-dev" && exit 1) + @command -v git &>/dev/null || (echo "ERROR: git not found" && exit 1) + @command -v zip &>/dev/null || echo "WARNING: zip not found, 'make dist' will fail" + @command -v xgettext &>/dev/null || echo "WARNING: xgettext not found, translations will be skipped" + @command -v msgfmt &>/dev/null || echo "WARNING: msgfmt not found, translations will be skipped" + @echo "All required dependencies found!" + enable: - gnome-extensions enable "$(UUID)" + @if gnome-extensions list | grep -q "^$(UUID)$$"; then \ + gnome-extensions enable "$(UUID)" && echo "Extension enabled successfully"; \ + else \ + echo "WARNING: Extension not detected by GNOME Shell yet"; \ + echo "On Wayland: Log out and log back in, then run 'make enable'"; \ + echo "On X11: Press Alt+F2, type 'r', press Enter, then run 'make enable'"; \ + fi disable: gnome-extensions disable "$(UUID)" || echo "Nothing to disable" @@ -115,7 +167,7 @@ test-nested: horizontal-line WAYLAND_DISPLAY=wayland-forge \ dbus-run-session -- gnome-shell --nested --wayland --wayland-display=wayland-forge -# Usage: +# Usage: # make test-open & # make test-open CMD=gnome-text-editor # make test-open CMD=gnome-terminal ARGS='--app-id app.x' From 1f531d00dcc7209a8fcbd97ee258263e78535953 Mon Sep 17 00:00:00 2001 From: Jon Crussell Date: Thu, 8 Jan 2026 20:32:20 -0800 Subject: [PATCH 2/2] Address PR review feedback for Makefile portability - Restore quotes around UUID variable - Use POSIX /bin/sh instead of /bin/bash for better portability - Replace bash-specific &> redirects with POSIX >/dev/null 2>&1 - Fix awk script to use POSIX-compatible parsing (index/substr) - Quote shell variables in loops to prevent injection - Move msgfmt pattern rule inside HAS_MSGFMT conditional - Use grep -Fqx for fixed-string matching in enable target - Clarify check-deps message about optional dependencies Co-Authored-By: Claude Opus 4.5 --- Makefile | 68 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 9bfe287..ddbc332 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ -UUID = forge@jmmaranan.com +UUID = "forge@jmmaranan.com" INSTALL_PATH = $(HOME)/.local/share/gnome-shell/extensions/$(UUID) MSGSRC = $(wildcard po/*.po) -# Shell configuration - explicitly use bash for portability across distros -SHELL := /bin/bash -.SHELLFLAGS := -eo pipefail -c +# Shell configuration - use POSIX /bin/sh for better portability +SHELL := /bin/sh +.SHELLFLAGS := -ec -# Tool detection (using bash-specific &> redirect) -HAS_XGETTEXT := $(shell command -v xgettext &>/dev/null && echo yes || echo no) -HAS_MSGFMT := $(shell command -v msgfmt &>/dev/null && echo yes || echo no) +# Tool detection (using POSIX redirection) +HAS_XGETTEXT := $(shell command -v xgettext >/dev/null 2>&1 && echo yes || echo no) +HAS_MSGFMT := $(shell command -v msgfmt >/dev/null 2>&1 && echo yes || echo no) .PHONY: all clean install schemas uninstall enable disable log debug patchcss check-deps @@ -33,16 +33,17 @@ metadata: @echo "export const developers = [" > lib/prefs/metadata.js @git shortlog -sne --all \ | (grep -vE 'dependabot|noreply' || true) \ - | awk '{ \ - email = $$NF; \ - if (email in seen) next; \ - seen[email] = 1; \ - name = ""; \ - for (i = 2; i < NF; i++) { \ - name = name (i == 2 ? "" : " ") $$i; \ - } \ + | awk -F'\t' '{ \ + rest = $$2; \ + n = index(rest, " <"); \ + if (n == 0) next; \ + name = substr(rest, 1, n - 1); \ + email_part = substr(rest, n + 2); \ + gsub(/>$$/, "", email_part); \ + if (email_part in seen) next; \ + seen[email_part] = 1; \ gsub(/"/, "\\\"", name); \ - printf " \"%s %s\",\n", name, email; \ + printf " \"%s <%s>\",\n", name, email_part; \ }' >> lib/prefs/metadata.js @echo "];" >> lib/prefs/metadata.js @@ -59,17 +60,15 @@ build: clean metadata.json schemas compilemsgs metadata cp LICENSE temp mkdir -p temp/locale for msg in $(MSGSRC:.po=.mo); do \ - if [ -f $$msg ]; then \ - msgf=temp/locale/`basename $$msg .mo`; \ - mkdir -p $$msgf; \ - mkdir -p $$msgf/LC_MESSAGES; \ - cp $$msg $$msgf/LC_MESSAGES/forge.mo; \ + if [ -f "$$msg" ]; then \ + msg_base="$$(basename "$$msg" .mo)"; \ + msgf="temp/locale/$$msg_base"; \ + mkdir -p "$$msgf"; \ + mkdir -p "$$msgf/LC_MESSAGES"; \ + cp "$$msg" "$$msgf/LC_MESSAGES/forge.mo"; \ fi; \ done; -./po/%.mo: ./po/%.po - msgfmt -c $< -o $@ - debug: sed -i 's/export const production = true/export const production = false/' temp/lib/shared/settings.js #sed -i 's|1.*-alpha|4999|' temp/metadata.json @@ -91,9 +90,12 @@ endif # Conditional compilation of messages based on msgfmt availability ifeq ($(HAS_MSGFMT),yes) +./po/%.mo: ./po/%.po + msgfmt -c $< -o $@ + compilemsgs: potfile $(MSGSRC:.po=.mo) for msg in $(MSGSRC); do \ - msgmerge -U $$msg ./po/forge.pot; \ + msgmerge -U "$$msg" ./po/forge.pot; \ done; else compilemsgs: @@ -107,15 +109,15 @@ clean: check-deps: @echo "Checking build dependencies..." - @command -v glib-compile-schemas &>/dev/null || (echo "ERROR: glib-compile-schemas not found. Install glib2-devel or libglib2.0-dev" && exit 1) - @command -v git &>/dev/null || (echo "ERROR: git not found" && exit 1) - @command -v zip &>/dev/null || echo "WARNING: zip not found, 'make dist' will fail" - @command -v xgettext &>/dev/null || echo "WARNING: xgettext not found, translations will be skipped" - @command -v msgfmt &>/dev/null || echo "WARNING: msgfmt not found, translations will be skipped" - @echo "All required dependencies found!" + @command -v glib-compile-schemas >/dev/null 2>&1 || (echo "ERROR: glib-compile-schemas not found. Install glib2-devel or libglib2.0-dev" && exit 1) + @command -v git >/dev/null 2>&1 || (echo "ERROR: git not found" && exit 1) + @command -v zip >/dev/null 2>&1 || echo "WARNING: zip not found, 'make dist' will fail" + @command -v xgettext >/dev/null 2>&1 || echo "WARNING: xgettext not found, translations will be skipped" + @command -v msgfmt >/dev/null 2>&1 || echo "WARNING: msgfmt not found, translations will be skipped" + @echo "All required dependencies found. Optional tools may be missing; see any warnings above." enable: - @if gnome-extensions list | grep -q "^$(UUID)$$"; then \ + @if gnome-extensions list | grep -Fqx "$(UUID)"; then \ gnome-extensions enable "$(UUID)" && echo "Extension enabled successfully"; \ else \ echo "WARNING: Extension not detected by GNOME Shell yet"; \ @@ -142,7 +144,7 @@ dist: build zip -qr "../${UUID}.zip" . restart: - if bash -c 'xprop -root &> /dev/null'; then \ + if xprop -root >/dev/null 2>&1; then \ killall -HUP gnome-shell; \ else \ gnome-session-quit --logout; \