Because Fennel can be used in so many different contexts, it can be difficult to know how to prepare your code so it can be used by others. Here is a selection of different methods and tips for how to work with them:
For certain kinds of programs, you don't need any fancy distribution
mechanism beyond simply running from a source checkout. In this case
it's best to simply include a copy of the standalone
script (from running
make fennel in the Fennel codebase) in your
For instance, the pengbot IRC bot can be run just by
make run in a source checkout:
run: ./fennel pengbot.fnl $(SERVER) $(PORT) $(NICK) $(CHANNEL)
If you have a standalone Fennel script that doesn't use any C
libraries, the easiest way to distribute it for others to use is to
compile it to Lua and put a
#!/usr/bin/env lua shebang at the top of
the file output. This will run on any system that already has Lua
$ echo "#!/usr/bin/env lua" > myprogram $ fennel --require-as-include --compile myprogram.fnl >> myprogram $ chmod 755 myprogram
--require-as-include flag will make it so your compiled program
includes any files required directly. It will not include transitive
requires from Lua, so you may need to directly require some of those
modules which you wouldn't otherwise need.
If you want to distribute something that works on systems that don't
already have Lua, you can compile a binary that includes Lua along
with your program using the
--compile-binary flag. You will have to
compile a separate binary for every OS+architecture you want to
support, but this can be completely standalone.
You can include a Makefile rule which fetches and compiles the version
of Lua you want to use, and cross-compiles it by setting
LUA_VERSION=5.4.2 LUA_DIR=lua-$(LUA_VERSION) $(LUA_DIR): ; curl http://www.lua.org/ftp/lua-$(LUA_VERSION).tar.gz | tar xzf /dev/stdin $(LUA_DIR)/src/liblua.a: $(LUA_DIR) ; make -C $^ myprogram: myprogram.fnl $(LUA_DIR)/src/liblua.a ./fennel --compile-binary $< $@ lua-$(LUA_VERSION)/src/liblua.a $(LUA_DIR)/src myprogram.exe: myprogram.fnl $(LUA_DIR)/src/liblua-mingw.a CC=i686-w64-mingw32-gcc ./fennel --compile-binary $< myprogram \ $(LUA_DIR)/src/liblua-mingw.a $(LUA_DIR)/src $(LUA_DIR)/src/liblua-mingw.a: $(LUA_DIR) $(MAKE) -C $(LUA_DIR)/src CC=i686-w64-mingw32-gcc \ "AR=i686-w64-mingw32-gcc -shared -o" \ "RANLIB=i686-w64-mingw32-strip --strip-unneeded" clean liblua.a mv $(LUA_DIR)/src/liblua.a $@
On a Debian-based system, the
gcc-mingw-w64-i686 package must be
installed to cross-compile Windows binaries; other OSes may provide it
under a different name.
--compile-binary method can also be used to distribute standalone
programs that use C libraries, but it's more complicated and doesn't
always work with all libraries; see the HTTP page for details.
The included Makefile can create executables for Windows, Mac OS, and
Linux-based systems as well as
.love files which are portable to any
system if you install the LÖVE framework manually. It also supports
automating publishing to itch.io, the fabulous game hosting
In this case, all the Fennel code is loaded from
.fnl files during
development, but then precompiled into
.lua code for
distribution. This allows a nice tight feedback loop during
development but doesn't involve the compiler unnecessarily later on.
TODO: someone should write this who uses luarocks!