# ************************************************************************** # * (C)opyright 2026 by Ruben Carlo Benante * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU General Public License as published by * # * the Free Software Foundation, either version 3 of the License, or * # * (at your option) any later version. * # * * # * This program is distributed in the hope that it will be useful, * # * but WITHOUT ANY WARRANTY; without even the implied warranty of * # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * # * GNU General Public License for more details. * # * * # * You should have received a copy of the GNU General Public License * # * along with this program. If not, see http://www.gnu.org/licenses/. * # * * # * Contact author at: * # * Ruben Carlo Benante * # * rcb@beco.cc * # ************************************************************************** # Makefile for logsdu - build the extension for Firefox and Chrome. # # Usage: # make # everything: build and package both browsers # make firefox # build Firefox only -> build/firefox/ # make chrome # build Chrome only -> build/chrome/ # make test # run the unit tests # make smoke # check the background bundle works as a service worker # make xpi # package Firefox -> dist/logsdu--firefox.xpi # make crx # package Chrome -> dist/logsdu--chrome.zip # make packages # both of the above (same as plain "make") # make clean # remove build/, dist/ and stray packages # make distclean # clean, plus node_modules/ # # build// holds the unpacked extension for one browser; the two targets # never share a directory, so neither can be left stale by the other. dist/ # holds the packages meant to be published, and is kept out of build/ so that # packaging never tries to include its own output. # # Dependencies are installed with pnpm, never npm: # corepack pnpm install # # Load the unpacked build while developing: # Firefox about:debugging -> This Firefox -> Load Temporary Add-on -> # build/firefox/manifest.json (dropped when Firefox restarts) # Chrome chrome://extensions -> Developer mode -> Load unpacked -> # build/chrome/ # # Publishing: # Firefox upload dist/*-firefox.xpi at addons.mozilla.org # Chrome upload dist/*-chrome.zip at chrome.google.com/webstore/devconsole # # Every package filename names its browser. The two are not interchangeable -- # they differ in the manifest's background key -- and uploading the wrong one # fails in ways that are not obvious from the error. EXT_ID := logsdu VERSION := $(shell node -p "require('./package.json').version") FIREFOX_DIR := build/firefox CHROME_DIR := build/chrome DIST := dist XPI := $(DIST)/$(EXT_ID)-$(VERSION)-firefox.xpi CRX := $(DIST)/$(EXT_ID)-$(VERSION)-chrome.zip .PHONY: all firefox chrome typecheck test smoke xpi crx packages clean \ distclean check-deps # The default does the lot: build both browsers and package both. Packaging is # only a zip of a directory that was going to be built anyway, so making it the # default costs nothing and means dist/ is never quietly out of date with src/. all: packages # Unit tests for the pure logic: the input formatters and the decision that # says whether a page load may press "Entrar". Run straight through Node's # built-in runner and type stripping, so there is no test framework to install. test: node --test "src/**/*.test.ts" # Runs the built background bundle in a service-worker-shaped sandbox, which # is where a Chrome-only breakage would otherwise hide until runtime. The # bundle is identical for both targets, so checking one covers both. smoke: chrome node tools/sw-smoke.mjs $(CHROME_DIR)/background.js # Typecheck once. Both build targets depend on it rather than each running tsc, # which halves the work when building both. # # Calls the local toolchain directly, so this works regardless of how pnpm is # provided (corepack vs standalone). Run "corepack pnpm install" first. typecheck: check-deps node_modules/.bin/tsc -noEmit -skipLibCheck firefox: typecheck node esbuild.config.mjs production @echo "Firefox build: $(CURDIR)/$(FIREFOX_DIR)" # The same sources with Chrome's manifest. Firefox and Chrome disagree on the # background key and on the gecko block, so the manifest is generated per # target rather than forked. chrome: typecheck TARGET=chrome node esbuild.config.mjs production @echo @echo "Chrome build: $(CURDIR)/$(CHROME_DIR)" @echo "Load it with chrome://extensions -> Developer mode -> Load unpacked." @echo "Select the folder itself; Chrome wants the directory holding manifest.json." @echo # An .xpi is just a zip of the extension directory, with the manifest at the # top level rather than inside a wrapper folder. xpi: firefox @mkdir -p $(DIST) rm -f $(XPI) cd $(FIREFOX_DIR) && zip -qr $(CURDIR)/$(XPI) . @echo @echo "Built: $(CURDIR)/$(XPI)" @echo @echo "This file is UNSIGNED. Two ways to use it:" @echo @echo " Publish -- upload it at addons.mozilla.org/developers/addon/submit/" @echo " Listed add-ons are signed once review approves them; unlisted" @echo " ones are signed straight away." @echo @echo " Install locally -- only on ESR, Developer Edition or Nightly:" @echo " 1. about:config -> xpinstall.signatures.required = false" @echo " 2. about:addons -> gear icon -> Install Add-on From File" @echo " 3. paste this path into the file picker:" @echo " $(CURDIR)/$(XPI)" @echo # The Chrome Web Store takes a plain zip, and does the packing into .crx itself. crx: chrome @mkdir -p $(DIST) rm -f $(CRX) cd $(CHROME_DIR) && zip -qr $(CURDIR)/$(CRX) . @echo @echo "Built: $(CURDIR)/$(CRX)" @echo "Upload it at chrome.google.com/webstore/devconsole" @echo # Both packages. Order no longer matters: each target has its own directory. packages: xpi crx # Removes everything the build produces, including packages from earlier # versions, whose filenames carry their own version number and so are never # overwritten by a later build. dist/ is tracked in git, so a clean shows the # packages as deleted until the next "make packages" puts them back. clean: rm -rf build $(DIST) rm -f $(EXT_ID)-*.xpi $(EXT_ID)-*.zip find . -name '*.map' -not -path './node_modules/*' -delete @echo "Removed build/, $(DIST)/ and any stray packages." # Everything clean removes, plus the installed dependencies. Recover with # "corepack pnpm install" -- never with npm, see the note in README.md. distclean: clean rm -rf node_modules @echo "Removed node_modules/. Run: corepack pnpm install" # Fail with a useful message rather than a confusing "tsc: not found". check-deps: @test -x node_modules/.bin/tsc || { \ echo "ERROR: dependencies are not installed."; \ echo "Run: corepack pnpm install (do NOT use npm install in this tree)"; \ exit 1; \ }