Makefile
author Oleksandr Gavenko <gavenkoa@gmail.com>
Wed, 17 Nov 2021 00:47:50 +0200
changeset 1326 e691a9d173a0
parent 1322 59b94ff17754
child 1327 d2c3b60decaf
permissions -rw-r--r--
New dialogs & correction for "What/Why does that matter?" https://ell.stackexchange.com/questions/73061/difference-between-what-does-that-matter-and-why-does-that-matter

# To build dictionary you need to install:
#
#    $ sudo apt-get install dictfmt
#
# Available target:
#
#   all         build dictionaries
#   install     install dictionaries, so they been available in stardict, may require root permission
#   uninstall   remove dictionaries, they been unavailable in stardict, may require root permission
#
# You can override such variables in Makefile.config:
#
#   SF_USER     SourceForge user name.
#   prefix      Prefix to install path.

################################################################
# Standard GNU Makefile settings.

SHELL = /bin/bash
export PATH := /bin:/usr/bin:${PATH}

# Disable built in pattern rules.
MAKEFLAGS += -r
# Disable built in variables.
MAKEFLAGS += -R
# Disable built in suffix rules.
.SUFFIXES:
# Delete target file if command fails.
.DELETE_ON_ERROR:
# Default target.
.DEFAULT_GOAL = help

################################################################
# Determine platform/environment.

host_os = unix
ifneq '' '$(COMSPEC)'
  ifneq '' '$(WINDIR)'
    # Probably under Windows.
    host_os = windows
    ifneq '' '$(wildcard /etc/setup/*cygwin*)'
      # Probably under Cygwin.
      host_os = cygwin
    endif
  endif
endif

ifneq '' '$(wildcard /etc/wsl.conf)'
  is_wsl := yes
endif

################################################################
# Build script definitions.

BUILD_SCRIPTS := $(firstword $(MAKEFILE_LIST))

ifneq '' '$(wildcard Makefile.config)'
  include Makefile.config
  BUILD_SCRIPTS += Makefile.config
endif

################################################################
# Version extracting/generation.

VER_FILE := VERSION

# Prevent making distribution with wrong version.
ifneq '' '$(filter deploy% release% dist%,$(MAKECMDGOALS))'
  ifeq '' '$(MAKE_RESTARTS)'
    $(shell rm -f $(VER_FILE))
  endif
endif

# Here are vmajor and vminor. Look README section "Versioning rules."
-include $(VER_FILE)

$(VER_FILE): | $(dir $(VER_FILE))
	\
[ -d .hg/ ] || { echo We miss VERSION file!!; exit 0; }; \
vtagdist=$$(hg log -r . --template '{latesttagdistance}'); \
vatrelease=$$([ $$vtagdist -le 1 ] && echo yes || echo no); \
vtag=$$(hg log -r . --template '{latesttag}'); \
vmajor=$${vtag#v}; \
vmajor=$${vmajor%%.*}; \
vminor=$${vtag#*.}; \
vrev=$$(hg id -i); \
visclean=$$(case $$vrev in *+) echo no;; *) echo yes;; esac); \
vrev=$${vrev%+}; \
{ \
echo "vrev=$$vrev"; \
echo "vtag=$$vtag"; \
echo "vtagdist=$$vtagdist"; \
echo "visclean=$$visclean"; \
echo "vatrelease=$$vatrelease"; \
echo "vmajor=$$vmajor"; \
echo "vminor=$$vminor"; \
} >$@

################################################################
# Build tools definition/switches.

INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644

RST_WARNING_FLAGS := --halt warning
RST_FLAGS := --strip-comments
RST_FLAGS += $(RST_WARNING_FLAGS)

RST2HTML := rst2html
ifeq '$(host_os)' 'cygwin'
  RST2HTML := rst2html.py
endif
RST2HTML_RENDER_FLAGS := --strip-comments --embed-stylesheet --no-xml-declaration --math-output=HTML --initial-header-level=2
RST2HTML_FLAGS := $(RST_FLAGS) $(RST2HTML_RENDER_FLAGS)

LATEX2PDF := pdflatex

PYTHON ?= python3

ifeq '$(ANKI_PY_DIR)' ''
  ANKI_PY_DIR := /usr/share/anki
endif

ADB := adb
ifeq 'yes' '$(is_wsl)'
  ADB := adb.exe
endif

################################################################
# Install paths.

ifeq '$(origin prefix)' 'undefined'
  ifeq '$(shell id -u)' '0'
    prefix = /usr/local
  else
    prefix = $(HOME)/usr
  endif
endif
datarootdir := $(prefix)/share
datadir := $(datarootdir)/dictd
elispdir := $(datarootdir)/emacs/site-lisp

################################################################
# Project dirs/files.

pkgname = gadict
fullpkgname = $(pkgname)-$(vmajor).$(vminor)

PY_FILES := $(wildcard py/gadict*.py)

GADICT_FILES := $(sort $(wildcard *.gadict))

C5_FILES := $(patsubst %.gadict,dist/dictd/%.c5,$(GADICT_FILES))
ALL_C5_FILES := $(C5_FILES) dist/dictd/gadict_en-ru.c5 dist/dictd/gadict_en-uk.c5
PNG_FILES := $(patsubst %.gadict,dist/dictd/%.png,$(GADICT_FILES))
DICT_FILES := $(C5_FILES:.c5=.dict)
DICTDZ_FILES := $(C5_FILES:.c5=.dict.dz)
INDEX_FILES := $(C5_FILES:.c5=.index)

GAPHRASE_FILES := $(wildcard *.gaphrase)
GADIALOG_FILES := $(wildcard *.gadialog)

SRS_TAB_FILES := $(patsubst %.gadict,dist/srs/%.tab.txt,$(GADICT_FILES))
SRS_ANKI_FILES := \
  $(patsubst %.gadict,dist/anki/%.apkg,$(GADICT_FILES)) \
  $(patsubst %.gaphrase,dist/anki/%.apkg,$(GAPHRASE_FILES)) \
  $(patsubst %.gadialog,dist/anki/%.apkg,$(GADIALOG_FILES))

DICT_HTML_FILES := \
  $(patsubst %.gadict,dist/html/%.html,$(GADICT_FILES)) \
  dist/html/gadialog.html

RST_TMPL_FILE = dist/misc/rst.tmpl
RST_CSS_FILE = www/tmpl/rst.css

RST_FILES := $(wildcard www/*.rst)
RST_HTML_FILES := $(patsubst www/%.rst,dist/www/%.html,$(RST_FILES))

INDEX_HTML_FILE := dist/www/index.html

STAT_MISSING_FILE := dist/misc/MISSING.rst
STAT_RST_FILE := dist/misc/STAT.rst
STAT_HTML_FILE := dist/www/STAT.html

WWW_HTML_FILES := $(RST_HTML_FILES) $(INDEX_HTML_FILE) $(STAT_HTML_FILE)

LOGO_FILE := www/logo.svg
LOGO_DIM := 32x32 48x48 64x64
LOGO_PNG_FILES := $(patsubst %,dist/misc/logo-%.png,$(LOGO_DIM))
FAVICON := dist/www/favicon.png

EL_FILES := $(wildcard misc/*.el)

DISTREL_TARBALLS = dist/$(fullpkgname).zip # dist/$(fullpkgname).tar.gz
DISTSRC_TARBALLS = dist/$(fullpkgname)_src.zip # dist/$(fullpkgname)_src.tar.gz

################################################################
# Install/uninstall targets.

.PHONY: install
install: install-dict install-emacs

.PHONY: install-dict
install-dict: $(DICTDZ_FILES) $(INDEX_FILES) $(PNG_FILES)
	mkdir -p $(datadir)
	for f in $(DICTDZ_FILES) $(INDEX_FILES) $(PNG_FILES); do \
		$(INSTALL_DATA) $$f $(datadir); \
	done

.PHONY: install-emacs install-el
install-el: install-emacs
install-emacs:
	mkdir -p $(elispdir)
	$(INSTALL_DATA) $(EL_FILES) $(elispdir)
	emacs -batch -f batch-byte-compile $(patsubst %,$(elispdir)/%,$(notdir $(EL_FILES)))

.PHONY: uninstall
uninstall:
	for f in $(notdir $(DICTDZ_FILES) $(INDEX_FILES) $(PNG_FILES)); do \
		rm -f $(datadir)/$$f; \
	done
	rm -f $(patsubst %,$(elispdir)/%,$(notdir $(EL_FILES))) $(patsubst %.el,$(elispdir)/%.elc,$(notdir $(EL_FILES)))

.PHONY: upload-anki-android
upload-anki-android: $(SRS_ANKI_FILES)
	\
for f in $(SRS_ANKI_FILES); do \
  $(ADB) push $$f /sdcard/AnkiDroid/; \
done

################################################################
# Deploy/release targets.

SF_USER ?= gavenkoa

# Release require Anki Python modules, dictd utilities and graphicsmagick (for icon):
#   $ sudo apt install anki dictfmt dictzip graphicsmagick

#   $ apt-cyg install GraphicsMagick

# First time you deploy to SourceForge (sf) you need manually login to:
#   $ sftp $(SF_USER),$(pkgname)@web.sourceforge.net
#   $ sftp $(SF_USER),$(pkgname)@frs.sourceforge.net
#   $ hg push ssh://$(SF_USER)@hg.code.sf.net/p/gadict/code
# as it asks for accepting server public key.

.PHONY: deploy
deploy: deploy2defun deploy2sf

.PHONY: deploy-src deploy-hg
deploy-src deploy-hg: deploy2defun-hg deploy2sf-hg

.PHONY: deploy-html
deploy-html: deploy2defun-html deploy2sf-html

.PHONY: deploy-www
deploy-www: deploy2defun-www deploy2sf-www

.PHONY: release
release: release2defun release2sf

.PHONY: release2defun
release2defun: validate-release deploy2defun

.PHONY: release2sf
release2sf: validate-release deploy2sf


DEFUN_USER ?= user
DEFUN_HG_SRV ?= hg.defun.work
DEFUN_HG_DIR ?= /srv/hg/gadict
DEFUN_WWW_SRV ?= defun.work
DEFUN_WWW_DIR ?= /srv/www/gadict
DEFUN_REL_DIR ?= /srv/www/gadict/download

.PHONY: deploy2defun-full
deploy2defun-full: deploy2defun deploy2defun-voa

.PHONY: deploy2defun
deploy2defun: deploy2defun-www deploy2defun-dist deploy2defun-hg deploy2defun-html

.PHONY: deploy2defun-hg
deploy2defun-hg:
	hg push ssh://$(DEFUN_USER)@$(DEFUN_HG_SRV)/$(DEFUN_HG_DIR) || [ $$? = 1 ]

.PHONY: deploy2defun-www
deploy2defun-www: $(WWW_HTML_FILES) $(FAVICON)
	( \
echo 'cd $(DEFUN_WWW_DIR)'; \
for f in $(WWW_HTML_FILES) $(FAVICON); do \
  n=$${f##*/}; \
  echo "put $$f $$n"; \
  echo "chmod 644 $$n"; \
done; \
echo 'quit'; \
) | sftp -b - $(DEFUN_USER)@$(DEFUN_WWW_SRV)

.PHONY: deploy2defun-dist
deploy2defun-dist: $(DISTREL_TARBALLS) $(DISTSRC_TARBALLS)
	( \
echo "-mkdir $(DEFUN_REL_DIR)"; \
echo "-mkdir $(DEFUN_REL_DIR)/v$(vmajor).$(vminor)"; \
echo "cd $(DEFUN_REL_DIR)/v$(vmajor).$(vminor)"; \
for f in $(DISTREL_TARBALLS) $(DISTSRC_TARBALLS); do \
  n=$${f##*/}; \
  echo "put $$f $$n"; \
  echo "chmod 644 $$n"; \
done; \
) | sftp -b - $(DEFUN_USER)@$(DEFUN_WWW_SRV)

.PHONY: deploy2defun-html
deploy2defun-html: $(DICT_HTML_FILES)
	( \
echo 'cd $(DEFUN_WWW_DIR)'; \
for f in $(DICT_HTML_FILES); do \
  n=$${f##*/}; \
  echo "put $$f $$n"; \
  echo "chmod 644 $$n"; \
done; \
echo 'quit'; \
) | sftp -b - $(DEFUN_USER)@$(DEFUN_WWW_SRV)

.PHONY: deploy2sf-full
deploy2sf-full: deploy2sf deploy2sf-voa

.PHONY: deploy2sf
deploy2sf: deploy2sf-www deploy2sf-dist deploy2sf-hg deploy2sf-html

.PHONY: deploy2sf-hg
deploy2sf-hg:
	hg push ssh://$(SF_USER)@hg.code.sf.net/p/$(pkgname)/code || [ $$? = 1 ]

# Will be accessed via http://$(pkgname).sourceforge.net
.PHONY: deploy2sf-www
deploy2sf-www: $(WWW_HTML_FILES) $(FAVICON)
	( echo 'cd htdocs'; \
for f in $(WWW_HTML_FILES) $(FAVICON); do \
  n=$${f##*/}; \
  echo "put $$f $$n"; \
  echo "chmod 644 $$n"; \
done; \
echo 'quit'; \
) | sftp -b - $(SF_USER),$(pkgname)@web.sourceforge.net

.PHONY: deploy2sf-dist
deploy2sf-dist: $(DISTREL_TARBALLS) $(DISTSRC_TARBALLS)
	( echo 'cd /home/frs/project/$(shell v=$(pkgname); echo $${v:0:1}/$${v:0:2})/$(pkgname)'; \
echo "put  www/README.rst"; \
echo "chmod 644 README.rst"; \
echo "-mkdir v$(vmajor).$(vminor)"; \
echo "cd v$(vmajor).$(vminor)"; \
for f in $(DISTREL_TARBALLS) $(DISTSRC_TARBALLS); do \
  n=$${f##*/}; \
  echo "put $$f $$n"; \
  echo "chmod 644 $$n"; \
done; \
echo 'quit'; \
) | sftp -b - $(SF_USER),$(pkgname)@frs.sourceforge.net

.PHONY: deploy2sf-html
deploy2sf-html: $(DICT_HTML_FILES)
	( echo 'cd htdocs'; \
for f in $(DICT_HTML_FILES); do \
  n=$${f##*/}; \
  echo "put $$f $$n"; \
  echo "chmod 644 $$n"; \
done; \
echo 'quit'; \
) | sftp -b - $(SF_USER),$(pkgname)@web.sourceforge.net

.PHONY: validate-release
validate-release:
	\
case ${visclean} in \
  no) echo "Local changes found. Build stop."; \
    exit 1;; \
esac
	\
case $(vatrelease) in \
  no) echo "We are not at release. Build stop."; \
    exit 1;; \
esac

################################################################
# Printed VOA dictionary isn't going to change so there is no need to require
# LaTeX in built environment to make releases.

.PHONY: deploy-voa
deploy-voa: deploy2defun-voa deploy2sf-voa

.PHONY: deploy2defun-voa
deploy2defun-voa: voa
	( \
echo 'cd $(DEFUN_WWW_DIR)'; \
echo "put dist/pdf/voa-special.pdf"; \
echo "chmod 644 voa-special.pdf"; \
echo 'quit'; \
) | sftp -b - $(DEFUN_USER)@$(DEFUN_WWW_SRV)

.PHONY: deploy2sf-voa
deploy2sf-voa: voa
	( \
echo 'cd htdocs'; \
echo "put dist/pdf/voa-special.pdf"; \
echo "chmod 644 voa-special.pdf"; \
echo 'quit'; \
) | sftp -b - $(SF_USER),$(pkgname)@web.sourceforge.net

################################################################
# Dist targets.

.PHONY: dist
dist: dist-rel dist-src

.PHONY: dist-rel
dist-rel: $(DISTREL_TARBALLS)

DISTREL_DICTDZ_FILES := $(patsubst %,dist/$(fullpkgname)/dictd/%,$(notdir $(DICTDZ_FILES)))
DISTREL_INDEX_FILES := $(patsubst %,dist/$(fullpkgname)/dictd/%,$(notdir $(INDEX_FILES)))
DISTREL_RST_FILES := $(patsubst %,dist/$(fullpkgname)/doc/txt/%,$(notdir $(RST_FILES)))
DISTREL_WWW_HTML_FILES := $(patsubst %,dist/$(fullpkgname)/doc/html/%,$(notdir $(RST_HTML_FILES)))
DISTREL_SRS_TAB_FILES := $(patsubst %,dist/$(fullpkgname)/srs/%,$(notdir $(SRS_TAB_FILES)))
DISTREL_SRS_ANKI_FILES := $(patsubst %,dist/$(fullpkgname)/anki/%,$(notdir $(SRS_ANKI_FILES)))

DISTREL_DEP := $(DISTREL_DICTDZ_FILES) $(DISTREL_INDEX_FILES) $(DISTREL_SRS_ANKI_FILES) $(DISTREL_RST_FILES) $(DISTREL_WWW_HTML_FILES) $(BUILD_SCRIPTS)

dist/$(fullpkgname).tar.gz: $(DISTREL_DEP)
	rm -rf $@
	tar zcf $@ -C dist/ $(fullpkgname)

dist/$(fullpkgname).zip: $(DISTREL_DEP)
	rm -rf $@
	cd $(dir $@) && zip -r $(notdir $@) $(fullpkgname)

$(DISTREL_DICTDZ_FILES) $(DISTREL_INDEX_FILES): dist/$(fullpkgname)/dictd/%: dist/dictd/% | dist/$(fullpkgname)/dictd/
	cp $< $@

$(DISTREL_SRS_TAB_FILES): dist/$(fullpkgname)/srs/%: dist/srs/% | dist/$(fullpkgname)/srs/
	cp $< $@

$(DISTREL_SRS_ANKI_FILES): dist/$(fullpkgname)/anki/%: dist/anki/% | dist/$(fullpkgname)/anki/
	cp $< $@

$(DISTREL_RST_FILES): dist/$(fullpkgname)/doc/txt/%: www/% | dist/$(fullpkgname)/doc/txt/
	cp $< $@

$(DISTREL_WWW_HTML_FILES): dist/$(fullpkgname)/doc/html/%: dist/www/% | dist/$(fullpkgname)/doc/html/
	cp $< $@

$(patsubst %,dist/$(fullpkgname)/%, dictd/ srs/ anki/ doc/txt/ doc/html/):
	mkdir -p $@

.PHONY: dist-src
dist-src: $(DISTSRC_TARBALLS)

DISTSRC_GADICT_FILES := $(patsubst %,dist/$(fullpkgname)_src/%,$(GADICT_FILES))
DISTSRC_GAPHRASE_FILES := $(patsubst %,dist/$(fullpkgname)_src/%,$(GAPHRASE_FILES))
DISTSRC_GADIALOG_FILES := $(patsubst %,dist/$(fullpkgname)_src/%,$(GADIALOG_FILES))
DISTSRC_PY_FILES := $(patsubst %,dist/$(fullpkgname)_src/py/%,$(notdir $(PY_FILES)))
DISTSRC_RST_FILES := $(patsubst %,dist/$(fullpkgname)_src/www/%,$(notdir $(RST_FILES)))
DISTSRC_TMPL_FILES := $(patsubst %,dist/$(fullpkgname)_src/www/tmpl/%, rst.css rst.tmpl.in)
DISTSRC_BUILD_SCRIPTS := $(patsubst %,dist/$(fullpkgname)_src/%, Makefile VERSION)

dist/$(fullpkgname)_src.tar.gz: $(DISTSRC_GADICT_FILES) $(DISTSRC_GAPHRASE_FILES) $(DISTSRC_GADIALOG_FILES) \
  $(DISTSRC_PY_FILES) $(DISTSRC_RST_FILES) $(DISTSRC_TMPL_FILES) $(DISTSRC_BUILD_SCRIPTS) $(BUILD_SCRIPTS)
	rm -rf $@
	tar zcf $@ -C dist/ $(fullpkgname)_src

dist/$(fullpkgname)_src.zip: $(DISTSRC_GADICT_FILES) $(DISTSRC_GAPHRASE_FILES) $(DISTSRC_GADIALOG_FILES) \
  $(DISTSRC_PY_FILES) $(DISTSRC_RST_FILES) $(DISTSRC_TMPL_FILES) $(DISTSRC_BUILD_SCRIPTS) $(BUILD_SCRIPTS)
	rm -rf $@
	cd $(dir $@) && zip -r $(notdir $@) $(fullpkgname)_src

$(DISTSRC_GADICT_FILES) $(DISTSRC_GAPHRASE_FILES) $(DISTSRC_GADIALOG_FILES): dist/$(fullpkgname)_src/%: % | dist/$(fullpkgname)_src/
	cp $< $@

$(DISTSRC_PY_FILES): dist/$(fullpkgname)_src/py/%: py/% | dist/$(fullpkgname)_src/py/
	cp $< $@

$(DISTSRC_RST_FILES): dist/$(fullpkgname)_src/www/%: www/% | dist/$(fullpkgname)_src/www/
	cp $< $@

$(DISTSRC_TMPL_FILES): dist/$(fullpkgname)_src/www/tmpl/%: www/tmpl/% | dist/$(fullpkgname)_src/www/tmpl/
	cp $< $@

$(DISTSRC_BUILD_SCRIPTS): dist/$(fullpkgname)_src/%: % | dist/$(fullpkgname)_src/
	cp $< $@

dist/$(fullpkgname)_src/ $(patsubst %,dist/$(fullpkgname)_src/%, py/ www/ www/tmpl/):
	mkdir -p $@

################################################################
# Word frequency statistic.

define FREQ_MACRO
$(1)_OPT += -freq:$(2):$(3)=$(4)
$(1)_DEP += $(4)
endef

# For gadict_voa.
$(eval $(call FREQ_MACRO,VOA_FREQLIST,freq,GSL,wordlist/gsl.freq))
$(eval $(call FREQ_MACRO,VOA_FREQLIST,freq,AWL,wordlist/awl.freq))
$(eval $(call FREQ_MACRO,VOA_FREQLIST,freq,NGSL,wordlist/ngsl.freq))
$(eval $(call FREQ_MACRO,VOA_FREQLIST,freq,NAWL,wordlist/nawl.freq))
$(eval $(call FREQ_MACRO,VOA_FREQLIST,var,BSL,wordlist/bsl.var))
$(eval $(call FREQ_MACRO,VOA_FREQLIST,var,TSL,wordlist/tsl.var))

# For other dictionaries.
$(eval $(call FREQ_MACRO,FREQLIST,freq,GSL,wordlist/gsl.freq))
$(eval $(call FREQ_MACRO,FREQLIST,freq,AWL,wordlist/awl.freq))
$(eval $(call FREQ_MACRO,FREQLIST,freq,NGSL,wordlist/ngsl.freq))
$(eval $(call FREQ_MACRO,FREQLIST,freq,NAWL,wordlist/nawl.freq))
$(eval $(call FREQ_MACRO,FREQLIST,var,VOA,dist/wordlist/voa.list))
$(eval $(call FREQ_MACRO,FREQLIST,var,BSL,wordlist/bsl.var))
$(eval $(call FREQ_MACRO,FREQLIST,var,TSL,wordlist/tsl.var))
$(eval $(call FREQ_MACRO,FREQLIST,var,KET,wordlist/ket.var))
$(eval $(call FREQ_MACRO,FREQLIST,var,PET,wordlist/pet.var))

# BNC_COCA_BASEWORD := $(wildcard wordlist/bnc+coca/basewrd[0-1]?.txt)
# FREQ_DEP += $(BNC_COCA_BASEWORD)
# FREQ_FILTER += $(patsubst %,-b:%,$(BNC_COCA_BASEWORD))

GSL_BASEWORD := $(wildcard wordlist/gsl_1000_*.var)
# FREQ_DEP += $(GSL_BASEWORD)
# FREQ_FILTER += $(patsubst %,-b:%,$(GSL_BASEWORD))
FREQ_DEP += dist/wordlist/gsl.var
FREQ_FILTER += -b:dist/wordlist/gsl.var

NGSL_BASEWORD := $(wildcard wordlist/ngsl_1000_[1-3].var wordlist/ngsl_supplemental.var)
# FREQ_DEP += $(NGSL_BASEWORD)
# FREQ_FILTER += $(patsubst %,-b:%,$(NGSL_BASEWORD))
FREQ_DEP += dist/wordlist/ngsl.var
FREQ_FILTER += -b:dist/wordlist/ngsl.var

# FAMOUS_FREQLIST := wordlist/awl.freq wordlist/gsl.freq wordlist/nawl.freq wordlist/ngsl.freq
# FREQ_FILTER += $(patsubst %,-f:%,$(FAMOUS_FREQLIST))

AWL_BASEWORD := wordlist/awl.var
FREQ_DEP += $(AWL_BASEWORD)
FREQ_FILTER += $(patsubst %,-b:%,$(AWL_BASEWORD))

NAWL_BASEWORD := wordlist/nawl.var
FREQ_DEP += $(NAWL_BASEWORD)
FREQ_FILTER += $(patsubst %,-b:%,$(NAWL_BASEWORD))

KET_BASEWORD := wordlist/ket.var
FREQ_DEP += $(KET_BASEWORD)
FREQ_FILTER += $(patsubst %,-b:%,$(KET_BASEWORD))

PET_BASEWORD := wordlist/pet.var
FREQ_DEP += $(PET_BASEWORD)
FREQ_FILTER += $(patsubst %,-b:%,$(PET_BASEWORD))

VOA_BASEWORD := dist/wordlist/voa.list
FREQ_DEP += $(VOA_BASEWORD)
FREQ_FILTER += $(patsubst %,-b:%,$(VOA_BASEWORD))

FREQ_FILTER += -12000f:wordlist/oanc.freq

.PHONY: freq
freq: dist/wordlist/gadict.list py/gadict_freq.py $(FREQ_DEP) $(BUILD_SCRIPTS)
	$(PYTHON) -B py/gadict_freq.py +b:dist/wordlist/gadict.list $(FREQ_FILTER)

.PHONY: missing
missing: missing-words missing-stat

.PHONY: missing-words
missing-words: dist/wordlist/gadict.list $(FREQ_DEP) $(BUILD_SCRIPTS)
	@echo ===== VOA =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:dist/wordlist/voa.list
	@echo ===== GSL =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +f:wordlist/gsl.freq
	@echo ===== AWL =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +f:wordlist/awl.freq
	@echo ===== NGSL =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +f:wordlist/ngsl.freq
	@echo ===== NAWL =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +f:wordlist/nawl.freq
	@echo ===== BSL =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:wordlist/bsl.var
	@echo ===== TSL =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:wordlist/tsl.var
	@echo ===== KET =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:wordlist/ket.var
	@echo ===== PET =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:wordlist/pet.var

.PHONY: missing-speakout
missing-speakout: dist/wordlist/gadict.list $(FREQ_DEP) $(BUILD_SCRIPTS)
	@echo ===== so1 =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:so1.list | tee so1.miss
	@echo ===== so2 =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:so2.list | tee so2.miss
	@echo ===== so3 =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:so3.list | tee so3.miss
	@echo ===== so4 =====
	$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list +b:so4.list | tee so4.miss

define stat-cmd
{ \
stat() { \
  lack=`$(PYTHON) -B py/gadict_freq.py -b:dist/wordlist/gadict.list $$2:$$3 | wc -l`; \
  total=`grep -v '^[ 	]' $$3 | wc -l`; \
  cover=$$((total - lack)); \
  printf "   %4s %5s %5s %4s\n" $$1 $$cover $$total $$lack; \
}; \
echo "   ==== ===== ===== ===="; \
echo "   List Cover Total Lack"; \
echo "   ==== ===== ===== ===="; \
stat VOA +b dist/wordlist/voa.list; \
stat GSL +f wordlist/gsl.freq; \
stat AWL +f wordlist/awl.freq; \
stat NGSL +f wordlist/ngsl.freq; \
stat NAWL +f wordlist/nawl.freq; \
stat BSL +b wordlist/bsl.var; \
stat TSL +b wordlist/tsl.var; \
stat KET +b wordlist/ket.var; \
stat PET +b wordlist/pet.var; \
echo "   ==== ===== ===== ===="; \
}
endef

.PHONY: missing-stat
missing-stat: dist/wordlist/gadict.list $(FREQ_DEP) $(BUILD_SCRIPTS)
	@${stat-cmd}

dist/wordlist/%.list: %.gadict py/gadict_headwords.py $(BUILD_SCRIPTS) | dist/wordlist/
	$(PYTHON) -B py/gadict_headwords.py  $< $@

dist/wordlist/gsl.var: $(GSL_BASEWORD) | dist/wordlist/
	cat $(GSL_BASEWORD) >$@

dist/wordlist/ngsl.var: $(NGSL_BASEWORD) | dist/wordlist/
	cat $(NGSL_BASEWORD) >$@

dist/wordlist/voa.list: gadict_voa.gadict py/gadict_headwords.py $(MAKEFILE_LIST) | dist/wordlist/
	$(PYTHON) -B py/gadict_headwords.py gadict_voa.gadict >$@

dist/wordlist/:
	mkdir -p $@

################################################################
# Build targets.

.PHONY: all
all: dict

.PHONY: dict dictd c5
dictd c5: dict
dict: $(DICTDZ_FILES) $(INDEX_FILES)

DICTFMT := dictfmt
#  --case-sensitive
DICTFMT_OPT := --headword-separator '; ' --break-headwords --without-headword --utf8 --allchars --columns 0

dist/dictd/%.dict dist/dictd/%.index: dist/dictd/%.c5 dist/dictd/%.c5.name dist/dictd/%.c5.url $(MAKEFILE_LIST)
	(cd dist/dictd; $(DICTFMT) $(DICTFMT_OPT)  -c5  -s "`cat $*.c5.name`" -u "`cat $*.c5.url`"  $*)  < $<

dist/dictd/%.dict.dz: dist/dictd/%.dict
	dictzip -c $< >$@

dist/dictd/%.png: %.xpm | dist/dictd/
	gm convert $< $@

GADICT_SUFFIXES := en-ru+uk en-ru en-uk voa
.SECONDARY: $(patsubst %,dist/dictd/gadict_%.c5.name,$(GADICT_SUFFIXES))
.SECONDARY: $(patsubst %,dist/dictd/gadict_%.c5.url,$(GADICT_SUFFIXES))

dist/dictd/%.c5.name dist/dictd/%.c5.url: dist/dictd/%.c5
	:

# -B  suppress __pycache__ dir

dist/dictd/gadict.c5: gadict.gadict $(FREQLIST_DEP) py/gadict.py py/gadict_c5.py $(MAKEFILE_LIST) | dist/dictd/
	LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_c5.py $(FREQLIST_OPT)  $< $@
	echo "gadict En-Ru+Uk"> dist/dictd/gadict.c5.name

dist/dictd/gadict_en-ru.c5: gadict.gadict py/gadict.py py/gadict_c5.py $(MAKEFILE_LIST) | dist/dictd/
	LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_c5.py  $< $@ -lang:ru
	echo "gadict En-Ru"> dist/dictd/gadict_en-ru.c5.name

dist/dictd/gadict_en-uk.c5: gadict.gadict py/gadict.py py/gadict_c5.py $(MAKEFILE_LIST) | dist/dictd/
	LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_c5.py  $< $@ -lang:uk
	echo "gadict En-Uk"> dist/dictd/gadict_en-uk.c5.name

dist/dictd/gadict_voa.c5: gadict_voa.gadict py/gadict.py py/gadict_c5.py $(MAKEFILE_LIST) | dist/dictd/
	LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_c5.py  $< $@ -lang:en

dist/dictd/%.c5: %.gadict py/gadict.py py/gadict_c5.py $(MAKEFILE_LIST) | dist/dictd/
	LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_c5.py  $< $@

dist/dictd/:
	mkdir -p $@

.PHONY: srs
srs: $(SRS_ANKI_FILES) $(SRS_TAB_FILES)

.PHONY: anki
anki: $(SRS_ANKI_FILES)

GADICT_DEL_FILE := $(wildcard gadict.del)
GADICT_DEL_OPT :=
ifneq '' '$(GADICT_DEL_FILE)'
  GADICT_DEL_OPT := -delfile=$(GADICT_DEL_FILE)
endif

# Specific rules (due to renames or other customization).
dist/anki/gadict.apkg: gadict.gadict $(GADICT_DEL_FILE) py/gadict.py py/gadict_srs_anki.py $(FREQLIST_DEP) $(MAKEFILE_LIST) | dist/anki/
	PYTHONPATH=$(ANKI_PY_DIR): LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_srs_anki.py -name="gadict_en-ru+uk" -rich $(GADICT_DEL_OPT) $(FREQLIST_OPT) $< $@

dist/anki/gadict_voa.apkg: gadict_voa.gadict py/gadict.py py/gadict_srs_anki.py $(VOA_FREQLIST_DEP) $(MAKEFILE_LIST) | dist/anki/
	PYTHONPATH=$(ANKI_PY_DIR): LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_srs_anki.py -name="gadict_voa" $(VOA_FREQLIST_OPT) $< $@

dist/anki/%.apkg: %.gadialog py/gadialog_srs_anki.py $(MAKEFILE_LIST) | dist/anki/
	PYTHONPATH=$(ANKI_PY_DIR): LC_ALL=en_US.utf8 $(PYTHON) -B py/gadialog_srs_anki.py -name="$*" $< $@

dist/anki/%.apkg: %.gaphrase py/gaphrase_srs_anki.py $(MAKEFILE_LIST) | dist/anki/
	PYTHONPATH=$(ANKI_PY_DIR): LC_ALL=en_US.utf8 $(PYTHON) -B py/gaphrase_srs_anki.py -name="$*" $< $@

# General rules.
dist/anki/%.apkg: %.gadict %.del py/gadict.py py/gadict_srs_anki.py $(FREQLIST_DEP) $(MAKEFILE_LIST) | dist/anki/
	PYTHONPATH=$(ANKI_PY_DIR): LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_srs_anki.py -name=$* -rich -delfile=$*.del $(FREQLIST_OPT) $< $@

dist/anki/%.apkg: %.gadict py/gadict.py py/gadict_srs_anki.py $(FREQLIST_DEP) $(MAKEFILE_LIST) | dist/anki/
	PYTHONPATH=$(ANKI_PY_DIR): LC_ALL=en_US.utf8 $(PYTHON) -B py/gadict_srs_anki.py -name=$* -rich $(FREQLIST_OPT) $< $@

.PHONY: tab
tab: $(SRS_TAB_FILES)

dist/srs/gadict.tab.txt: gadict.gadict py/gadict.py py/gadict_srs_tab.py $(MAKEFILE_LIST) | dist/srs/
	$(PYTHON) -B py/gadict_srs_tab.py  $< $@ -lang:ru,uk

dist/srs/%.tab.txt: %.gadict py/gadict.py py/gadict_srs_tab.py $(MAKEFILE_LIST) | dist/srs/
	$(PYTHON) -B py/gadict_srs_tab.py  $< $@

dist/anki/ dist/srs/:
	mkdir -p $@

.PHONY: html
html: $(DICT_HTML_FILES)

dist/html/gadict_voa.html: gadict_voa.gadict py/gadict.py py/gadict_html.py $(VOA_FREQLIST_DEP) $(MAKEFILE_LIST) | dist/html/
	$(PYTHON) -B py/gadict_html.py $(VOA_FREQLIST_OPT) $< $@

dist/html/%.html: %.gadict py/gadict.py py/gadict_html.py $(FREQLIST_DEP) $(MAKEFILE_LIST) | dist/html/
	$(PYTHON) -B py/gadict_html.py $(FREQLIST_OPT) $< $@

dist/html/gadialog.html: gadialog.gadialog py/gadialog.py py/gadialog_html.py | dist/html/
	$(PYTHON) -B py/gadialog_html.py $< $@

dist/html/:
	mkdir -p $@

################################################################
# Documentation targets.

.PHONY: docs web
docs web: www

.PHONY: www
www: $(WWW_HTML_FILES)

$(INDEX_HTML_FILE): dist/www/README.html
	cp $< $@

$(RST_HTML_FILES): dist/www/%.html: www/%.rst $(RST_CSS_FILE) $(RST_TMPL_FILE) $(BUILD_SCRIPTS) | dist/www/
	$(RST2HTML) $(RST2HTML_FLAGS) --stylesheet=$(RST_CSS_FILE) --template=$(RST_TMPL_FILE)  www/$*.rst  $@

dist/www/:
	mkdir -p $@

$(RST_TMPL_FILE): www/tmpl/rst.tmpl.in VERSION $(BUILD_SCRIPTS) | $(dir $(RST_TMPL_FILE))
	\
[[ "${visclean}" = no ]] && warn1='<b>Warning</b>: Build done with local changes!' || :; \
[[ -z "${visclean}" ]] && warn1='<b>Warning</b>: Build done without <b>VERSION</b> file!' || :; \
[[ "${vatrelease}" = no ]] && warn2='<b>Warning</b>: Build is far from latest <tt>$(vtag)</tt> release state by $(vtagdist) changes.' || :; \
sed -e "s|{date}|$$(date +%F)|" -e "s|{rev}|$$(hg id -i)|" -e "s|{warn1}|$$warn1|" -e "s|{warn2}|$$warn2|" <$< >$@

################################################################
# Article statistics.

.PHONY: stat
stat: $(STAT_HTML_FILE)

$(STAT_HTML_FILE): $(STAT_RST_FILE) $(RST_CSS_FILE) $(RST_TMPL_FILE) | $(dir $(STAT_HTML_FILE))
	$(RST2HTML) $(RST2HTML_FLAGS) --stylesheet=$(RST_CSS_FILE) --template=$(RST_TMPL_FILE)  $<  $@

$(STAT_RST_FILE): $(GADICT_FILES) $(STAT_MISSING_FILE) $(BUILD_SCRIPTS) | $(dir $(STAT_RST_FILE))
	{ \
echo '==========================='; \
echo ' gadict project statistics'; \
echo '==========================='; \
echo; \
echo '.. class:: right'; \
echo; \
echo '==================== ======== ======== ========'; \
echo '   Dictionary        Articles Meanings Examples'; \
echo '==================== ======== ======== ========'; \
total=0; \
for dic in $(GADICT_FILES); do \
  awk '\
BEGIN { art=0; tr=0; ex = 0; };\
/^__$$/{ art += 1 };\
/^(en|ru|uk)> /{ ex += 1 };\
/^(n|det|pron|adj|v|adv|prep|conj|num|int|phr|phr\.v|contr|abbr|prefix)$$/{ tr += 1 };'\
"END {printf \"%20s %8s %8s %8s\n\", \"$${dic%.gadict}\", art, tr, ex};"\
  <$$dic; \
done; \
echo '==================== ======== ======== ========'; \
echo; \
echo '.. table:: ``gadict`` coverage of famous word lists'; \
echo '   :class: right'; \
echo; \
cat  $(STAT_MISSING_FILE); \
} >$@

$(STAT_MISSING_FILE): dist/wordlist/gadict.list $(FREQ_DEP) $(BUILD_SCRIPTS) | $(dir $(STAT_MISSING_FILE))
	@echo '*' make stat
	@${stat-cmd} >$(STAT_MISSING_FILE)

dist/misc/:
	mkdir -p $@

################################################################
# Misc targets.

.PHONY: favicon
favicon: $(FAVICON)

$(FAVICON): $(LOGO_FILE) $(MAKEFILE_LIST) | $(dir $(FAVICON))
	gm convert +antialias $< -resize 16x16 $@

.PHONY: logo
logo: logo-png

.PHONY: logo-png
logo-png: $(LOGO_PNG_FILES)

# Require:
#   $ sudo apt-get install imagemagick librsvg2-bin
$(LOGO_PNG_FILES): dist/misc/logo-%.png: $(LOGO_FILE) | dist/misc/
	convert +antialias -background transparent $< -resize $* $@

.PHONY: voa
voa: dist/pdf/voa-special.pdf

dist/pdf/voa-special.pdf: misc/voa-special.tex | dist/pdf/
	$(LATEX2PDF) -output-directory dist/pdf/ $<

dist/pdf/:
	mkdir -p $@

################################################################
# Helpers targets.

.PHONY: help
help:
	@\
echo; \
echo Current configuration:; \
echo; \
sed 's=^=  =' <$(VER_FILE)
	@if [ -f Makefile.config ]; then \
		echo; \
		echo User configuration:; \
		echo; \
		sed 's=^=  =' <Makefile.config; \
	fi
	@\
echo; \
echo Supported targets:; \
echo; \
sed -n -e '/^[[:alnum:]_-]*:/{s=^\(.*\):.*=  \1=;p;}' $(BUILD_SCRIPTS)

.PHONY: todo
todo:
	grep -nH 'TODO\|XXX' $(RST_FILES) $(C5_FILES)

# Install:
#   $ sudo apt-get install python3-enchant hunspell-en-us hunspell-en-gb hunspell-en-au hunspell-en-ca
.PHONY: check
check:
	$(PYTHON) -B py/gadict_spellcheck.py gadict.gadict

################################################################
# Clean targets.

.PHONY: distclean
distclean: clean
	rm -rf $(VER_FILE)

.PHONY: clean
clean:
	rm -rf dist/