cortav  Check-in [a4a0570841]

Overview
Comment:add C wrapper to generate true standalone binary embedding cortav bytecode
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a4a0570841bbda58171c497af93a38fdc3b948b3102fb7f2d9dc2fb5bc016df7
User & Date: lexi on 2021-12-26 20:01:30
Other Links: manifest | tags
Context
2021-12-27
05:51
more tweaks, fixes, and additions than i can keep track of. major additions to documentation. spiffed up html renderer's footnotes and TOC dramatically check-in: e51980e07a user: lexi tags: trunk
2021-12-26
20:01
add C wrapper to generate true standalone binary embedding cortav bytecode check-in: a4a0570841 user: lexi tags: trunk
17:49
get math parser working check-in: d1b7d2fd5f user: lexi tags: trunk
Changes

Modified makefile from [ac8c1379b3] to [d74d07de6f].

    11     11   #     * install  * lua
    12     12   #     * luac     * sh
    13     13   #
    14     14   #    if any are not present, the build will fail, although a missing
    15     15   #    `which` can be worked around by specifying the paths to lua, luac,
    16     16   #    and `sh` directly
    17     17   #
    18         -#    eventually you will be able to set a "standalone" variable to
    19         -#    create a truly standalone binary, by embedding the binary in a
    20         -#    C program and statically linking it to lua.
           18  +#    to create a truly standalone cortav binary, build the target
           19  +#    $(build)/cortav.bin - this will wrap the cortav bytecode in a C
           20  +#    shim and produce a binary executable. depending on your needs,
           21  +#    you may want to link lua statically or as a shared library.
           22  +#    to do this, you'll need to set the variable lua-prefix to the
           23  +#    location of your lua build. if you have lua installed systemwide,
           24  +#    this will probably be something like `lua-lib-prefix=/usr/lib`,
           25  +#    or on Nix `lua-lib-prefix=$(nix path-info lua5_3)/lib`. normally
           26  +#    however if you're building a standalone binary, you probably don't
           27  +#    have lua installed systemwide, so you'll want to set this to the
           28  +#    directory where liblua.a is to be found.
           29  +#
           30  +#    note that the standalone build script assumes you're using a
           31  +#    relatively standard cc, not something like msvc. if your cc
           32  +#    doesn't accept options like -l -x -o then you'll have to build
           33  +#    the binary by hand, sorry. but if you want to contribute a build
           34  +#    script to the repository, i'll happily take merge requests :)
    21     35   
    22     36   lua != which lua
    23     37   luac != which luac
    24     38   sh != which sh
    25     39   
    26     40   extens = $(wildcard ext/*.lua)
    27     41   extens-names ?= $(basename $(notdir $(extens)))
................................................................................
    31     45   build = build
    32     46   executable = cortav
    33     47   default-format-flags = -m html:width 40em
    34     48   
    35     49   prefix = $(HOME)/.local
    36     50   bin-prefix = $(prefix)/bin
    37     51   share-prefix = $(prefix)/share/$(executable)
           52  +
           53  +lua-standalone = $(if $(lua-lib-prefix),$(lua-lib-prefix)/liblua.a,-llua)
           54  +lua-bindeps = -lm -ldl
           55  +
           56  +dbg-flags-luac = $(if $(debug),,-s)
           57  +dbg-flags-cc = $(if $(debug),-g,-s)
           58  +
           59  +# sterilize the operating theatre
           60  +export LUA_PATH=./?.lua;./?.lc
           61  +export LUA_PATH_5_3=./?.lc;./?.lua
           62  +export LUA_PATH_5_4=./?.lc;./?.lua
           63  +export LUA_INIT=
           64  +export LUA_INIT_5_3=
           65  +export LUA_INIT_5_4=
    38     66   
    39     67   # by default, we fetch and parse information about encodings we
    40     68   # support so that cortav can do fancy things like format math
    41     69   # equations by character class (e.g. italicizing variables)
    42     70   # this is not necessary for parsing the format, and can be
    43     71   # disabled by blanking the encoding-data list when building
    44     72   # ($ make encoding-data=)
    45     73   encoding-data  = ucstbls
    46     74   encoding-files = $(patsubst %,$(build)/%.lc,$(encoding-data))
    47     75   encoding-data-ucs = https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
    48     76   
    49         -$(build)/$(executable): sirsem.lua $(encoding-files) cortav.lua $(rendrs) $(extens) cli.lua | $(build)/
           77  +# "standalone" bytecode file that can be run directly as a script
           78  +$(build)/$(executable): $(build)/$(executable).ct
           79  +	echo '#!$(lua)' > $@
           80  +	cat $< >>$@
           81  +	chmod +x $@
           82  +
           83  +# raw bytecode without shebang header, must be run as `lua cortav.lc`
           84  +$(build)/$(executable).lc: sirsem.lua $(encoding-files) cortav.lua $(rendrs) $(extens) cli.lua | $(build)/
    50     85   	@echo ' » building with extensions $(extens-names)'
    51     86   	@echo ' » building with renderers $(rendrs-names)'
    52         -	echo '#!$(lua)' > $@
    53         -	luac -o - $^ >> $@
    54         -	chmod +x $@
           87  +	$(luac) $(dbg-flags-luac) -o $@ $^
           88  +
           89  +# true standalone binary, wraps bytecode file and (optionally) lua
           90  +$(build)/$(executable).bin: $(build)/$(executable).lc
           91  +	$(lua) tools/makeshim.lua $< |\
           92  +		$(CC) -o$@ -xc - -xnone $(lua-standalone) $(lua-bindeps)
    55     93   
    56     94   $(build)/cortav.html: cortav.ct $(build)/$(executable) | $(build)/
    57     95   	$(build)/$(executable) $< -o $@ -m render:format html -y html:fossil-uv
    58     96   
    59     97   .PHONY: syncdoc
    60     98   syncdoc: $(build)/cortav.html
    61     99   	fossil uv add $< --as cortav.html
    62    100   	fossil uv sync
    63    101   
          102  +# clean is written in overly cautious fashion to minimize damage,
          103  +# just in case it ever gets invoked in a bad way
    64    104   .PHONY: clean
    65    105   clean:
    66         -	rm -f $(build)/cortav $(build)/cortav.html $(build)/velartrill-cortav-view.desktop $(build)/cortav-view.sh
          106  +	rm -f $(build)/*.{html,lc,sh,txt,desktop} \
          107  +	      $(build)/$(executable){,.bin}
          108  +	rmdir $(build)
    67    109   
    68    110   $(build)/%.sh: desk/%.sh
    69    111   	echo >$@ "#!$(sh)"
    70    112   	echo >>$@ 'cortav_exec="$(bin-prefix)/$(executable)"'
    71    113   	echo >>$@ 'cortav_flags="$${ct_format_flags-$(default-format-flags)}"'
    72    114   	cat $< >> $@
    73    115   	chmod +x $@

Added tools/makeshim.lua version [3535fb21b6].

            1  +-- [ʞ] tools/makeshim.lua
            2  +--  ~ lexi hale <lexi@hale.su>
            3  +--  🄯 AGPLv3
            4  +--  ? this program creates a C source file embedding
            5  +--    cortav, for the purposes of standalone deployment
            6  +--    without a lua interpreter, or for the purposes of
            7  +--    giving cortav extra privileges
            8  +
            9  +local includes = [[
           10  +#include <lua.h>
           11  +#include <lauxlib.h>
           12  +#include <stdio.h>
           13  +#include <stddef.h>
           14  +extern int luaL_openlibs(lua_State* l);
           15  +]]
           16  +
           17  +
           18  +local main = [[
           19  +int main(int argc, char** argv) {
           20  +	lua_State* l = luaL_newstate();
           21  +	luaL_openlibs(l);
           22  +
           23  +	// pass arguments thru to lua
           24  +	lua_newtable(l);
           25  +	for(size_t i = argc; i < argc; ++i) {
           26  +		lua_pushstring(l,argv[i]);
           27  +		lua_rawseti(l, -2, i);
           28  +	}
           29  +	lua_setglobal(l, "arg");
           30  +
           31  +	// load and run our payload
           32  +	int e = luaL_loadbufferx(l, ct_bytecode, sizeof(ct_bytecode), "cortav", "b");
           33  +	if (e != LUA_OK) {
           34  +		printf("some kind of error idk fam\n");
           35  +		return -1;
           36  +	}
           37  +
           38  +	lua_call(l, 0, 0);
           39  +
           40  +	// normal termination is by the os.exit() call
           41  +	return -1;
           42  +}
           43  +]]
           44  +
           45  +local function setfile(i, dflt, mode)
           46  +	if arg[i] and arg[i] ~= '' then
           47  +		local fn = io.open(arg[i], mode)
           48  +		if fn then
           49  +			return fn
           50  +		end
           51  +		io.stderr:write('(' .. arg[0]..' fatal) cannot open file '..arg[i])
           52  +	end
           53  +	return dflt
           54  +end
           55  +
           56  +local src = setfile(1, io.stdin, "rb")
           57  +local dest = setfile(2, io.stdout, "w")
           58  +
           59  +local cstr = {}
           60  +local strtpl = 'static char ct_bytecode [%u] = {%s};'
           61  +local lines = {includes}
           62  +
           63  +local bytes = {}
           64  +
           65  +local bn = 1
           66  +local len = 0
           67  +while true do
           68  +	local byte = src:read(1)
           69  +	if not byte then break end
           70  +	local str = tostring(byte:byte(1))..','
           71  +	-- make sure our source file is parseable by
           72  +	-- a compliant C compiler
           73  +	len = len + string.len(str)
           74  +	if len >= 4096 then
           75  +		len = 0
           76  +		bytes[bn]='\n'
           77  +		bn = bn + 1
           78  +	end
           79  +	bytes[bn] = str
           80  +	bn = bn + 1
           81  +end
           82  +
           83  +table.insert(lines, strtpl:format(#bytes, table.concat(bytes)))
           84  +table.insert(lines, main)
           85  +
           86  +dest:write(table.concat(lines, '\n'))