# [ʞ] makefile
#  ~ lexi hale <lexi@hale.su>
#  🄯 AGPLv3
#  ? this script performs the tasks necessary to produce a mostly
#    standalone cortav executable from the source files in the
#    repository. it assumes the presence of the following tools
#    in $SHELL or in $PATH:
#
#     * which    * cat
#     * mkdir    * echo
#     * install  * lua
#     * luac     * sh
#
#    if any are not present, the build will fail, although a missing
#    `which` can be worked around by specifying the paths to lua, luac,
#    and `sh` directly
#
#    to create a truly standalone cortav binary, build the target
#    $(build)/cortav.bin - this will wrap the cortav bytecode in a C
#    shim and produce a binary executable. depending on your needs,
#    you may want to link lua statically or as a shared library.
#    to do this, you'll need to set the variable lua-prefix to the
#    location of your lua build. if you have lua installed systemwide,
#    this will probably be something like `lua-lib-prefix=/usr/lib`,
#    or on Nix `lua-lib-prefix=$(nix path-info lua5_3)/lib`. normally
#    however if you're building a standalone binary, you probably don't
#    have lua installed systemwide, so you'll want to set this to the
#    directory where liblua.a is to be found.
#
#    note that the standalone build script assumes you're using a
#    relatively standard cc, not something like msvc. if your cc
#    doesn't accept options like -l -x -o then you'll have to build
#    the binary by hand, sorry. but if you want to contribute a build
#    script to the repository, i'll happily take merge requests :)

lua != which lua
luac != which luac
sh != which sh

#sterilize the operating theatre
lua += -E

extens = $(wildcard ext/*.lua)
extens-names ?= $(basename $(notdir $(extens)))
rendrs = $(wildcard render/*.lua)
rendrs-names ?= $(basename $(notdir $(rendrs)))
binds = $(wildcard bind/*.c)
binds-names ?= $(basename $(notdir $(binds)))

build = build
executable = cortav
default-format-flags = -m html:width 40em

prefix = $(HOME)/.local
bin-prefix = $(prefix)/bin

lua-standalone = $(if $(lua-lib-prefix),$(lua-lib-prefix)/liblua.a,-llua)
lua-bindeps = -lm -ldl

ifneq ($(filter net,$(binds-names)),)
    lua-bindeps += -lcurl
endif

ifneq ($(luac-broken),)
    comp-lua = $(if $(debug),,env strip=1) $(lua) tool/luac.lua $1 $(if $2,>$2)
else
    comp-lua = $(luac) $(if $(debug),,-s) -o $(if $2,$2,-) $1
endif

# by default, we fetch and parse information about encodings we
# support so that cortav can do fancy things like format math
# equations by character class (e.g. italicizing variables)
# this is not necessary for parsing the format, and can be
# disabled by blanking the encoding-data list when building
# ($ make encoding-data=)
encoding-data = 1
encoding-data-ucs = $(build)/unicode.txt
encoding-data-ucs-url = https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt

encoding-files = $(if $(encoding-data),$(build)/ucstbls.lc,)

# "standalone" bytecode file that can be run directly as a script
$(build)/$(executable): $(build)/$(executable).lc
	echo '#!$(lua)' > $@
	cat $< >>$@
	chmod +x $@

# raw bytecode without shebang header, must be run as `lua cortav.lc`
$(build)/$(executable).lc: sirsem.lua $(encoding-files) cortav.lua $(rendrs) $(extens) cli.lua | $(build)/
	@echo ' » building with extensions $(extens-names)'
	@echo ' » building with renderers $(rendrs-names)'
	$(call comp-lua,$^,$@)

# true standalone binary, wraps bytecode file and (optionally) lua
$(build)/$(executable).bin: $(build)/$(executable).lc tool/makeshim.lua $(binds)
	$(lua) tool/makeshim.lua $< "" $(binds-names) |\
		$(CC) -s -o$@ -xc - -xnone $(binds) $(lua-standalone) $(lua-bindeps)

# loadable lua modules for binds, mainly useful for testing
$(build)/bind/%.so: bind/%.c bind/bind.h | $(build)/bind/
	$(CC) -fPIC -shared -g -o$@ $<

$(build)/cortav.html: cortav.ct $(build)/$(executable) | $(build)/
	$(build)/$(executable) $< -o $@ -m render:format html -y html:fossil-uv

.PHONY: syncdoc
syncdoc: $(build)/cortav.html
	fossil uv add $< --as cortav.html
	fossil uv sync --all

# clean is written in overly cautious fashion to minimize damage,
# just in case it ever gets invoked in a bad way (e.g. build=/)
.PHONY: clean
clean:
	rm -f $(build)/*.{html,lc,sh,txt,desktop} \
	      $(build)/$(executable){,.bin} \
	      $(build)/bind
	rmdir $(build)

$(build)/%.sh: desk/%.sh | $(build)/
	echo >$@ "#!$(sh)"
	echo >>$@ 'cortav_exec="$(bin-prefix)/$(executable)"'
	echo >>$@ 'cortav_flags="$${ct_format_flags-$(default-format-flags)}"'
	cat $< >> $@
	chmod +x $@

$(build)/velartrill-cortav-view.desktop: desk/cortav-view.desktop
	cp $< $@
	echo "Exec=$(bin-prefix)/cortav-view.sh" >>$@

%/:
	mkdir -p $@

$(build)/unicode.txt: | $(build)/
	curl $(encoding-data-ucs-url) > $@
$(build)/ucstbls.lc: $(encoding-data-ucs) tool/ucs.lua | $(build)/
	$(lua) tool/ucs.lua $< >$@

.PHONY: install
install: $(build)/cortav $(build)/cortav-view.sh $(build)/velartrill-cortav-view.desktop | $(bin-prefix)/
	install $(build)/$(executable)  $(bin-prefix)
	install $(build)/cortav-view.sh $(bin-prefix)
	xdg-mime         install desk/velartrill-cortav.xml
	xdg-desktop-menu install $(build)/velartrill-cortav-view.desktop
	xdg-mime         default velartrill-cortav-view.desktop text/x-cortav

.PHONY: excise
excise: $(build)/velartrill-cortav-view.desktop
	xdg-mime         uninstall desk/velartrill-cortav.xml
	xdg-desktop-menu uninstall $(build)/velartrill-cortav-view.desktop
	rm $(bin-prefix)/$(executable)
	rm $(bin-prefix)/cortav-view.sh

.PHONY: wipe
wipe: excise clean
