Fennel wiki: Distribution

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:

Running from source

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 fennel Lua script (from running make fennel in the Fennel codebase) in your repository.

For instance, the pengbot IRC bot can be run just by executing make run in a source checkout:

	./fennel pengbot.fnl $(SERVER) $(PORT) $(NICK) $(CHANNEL)

Simple Scripts

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 installed.

$ echo "#!/usr/bin/env lua" > myprogram
$ fennel --require-as-include --compile myprogram.fnl >> myprogram
$ chmod 755 myprogram

The --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.

Binary executable

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 CC:

$(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.

The --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.

LÖVE (love2d)

One of the most popular uses of Fennel is to create games with the LÖVE framework. The min-love2d-fennel project skeleton provides everything you need to get started.

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 web site.

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!