Skip to content
Easily build a standalone executable for any Lua program
Branch: master
Clone or download

README.adoc

Luapak

Build Status Windows Build Status LDoc

Luapak is a command-line tool that offers complete, multi-platform (Linux, macOS, and Windows), adjustable, all-in-one (yet modular) solution for building a standalone, zero-dependencies, possibly statically linked (only on Linux) executable for (almost) any Lua program. It Just Works!

  1. Resolves, builds and installs project’s Lua dependencies (declared in rockspec) from LuaRocks. Lua/C modules (aka native extensions) are built as static libraries (.a archive files), so they can be statically linked into resulting executable.[1]

  2. Resolves actually required Lua and Lua/C modules (.lua and .a files) using static code analysis of the project and its dependencies (recursively).

  3. Merges all required Lua modules into a single Lua script.

  4. Minifies the Lua script (i.e. removes unnecessary characters to shrink its size) using LuaSrcDiet.

  5. Compresses the Lua script using BriefLZ algorithm.

  6. Embeds the Lua script into a generated C wrapper.

  7. Compiles the C wrapper and links it with Lua interpreter (PUC Lua 5.1–5.3 and LuaJIT supported) and Lua/C libraries (aka native extensions) into a standalone executable.

All these steps can be run with single command luapak make <rockspec>, or separately if you need more control. You can discover available commands and their options in section Commands.

Table of Contents

Commands

luapak make

Click here to expand…
Usage: luapak make [options] [PACKAGE...]
       luapak make --help

Makes a standalone executable from Lua package(s). This is the main Luapak
command that handles entire process from installing dependencies to
compiling executable.
Options:
  -s, --entry-script=FILE         The entry point of your program, i.e. the main Lua script. If not
                                  specified and the last PACKAGE defines exactly one CLI script,
                                  then it's used.

  -e, --exclude-modules=PATTERNS  Module(s) to exclude from dependencies analysis and the
                                  generated binary. PATTERNS is one or more glob patterns matching
                                  module name in dot notation (e.g. "pl.*"). Patterns may be
                                  delimited by comma or space. This option can be also specified
                                  multiple times.

  -g, --debug                     Enable debug mode, i.e. preserve line numbers, module names and
                                  local variable names for error messages and backtraces.

  -i, --include-modules=PATTERNS  Extra module(s) to include in dependencies analysis and add to
                                  the generated binary. PATTERNS has the same format as in
                                  "--exclude-module".

      --lua-impl=NAME             The Lua implementation that should be used - "PUC" (default),
                                  or "LuaJIT". This is currently used only as a hint to find the
                                  correct library and headers when auto-detection is used
                                  (i.e. --lua-incdir or --lua-lib is not specified).

      --lua-incdir=DIR            The directory that contains Lua (or LuaJIT) headers. If not
                                  specified, luapak will look for the lua.h (and luajit.h) file
                                  inside: Luarock's LUA_INCDIR, ./vendor/lua, ./deps/lua,
                                  /usr/local/include, and /usr/include. If --lua-version is
                                  specified, then it will also try subdirectories lua and
                                  lua- of each of the named directories and verify that
                                  the found lua.h (or luajit.h) is for the specified Lua
                                  (or LuaJIT) version.

      --lua-lib=FILE              The library of Lua interpreter to include in the binary. If not
                                  specified, luapak will try to find library with version
                                  corresponding to the headers inside Luarock's LUA_LIBDIR,
                                  ./vendor/lua, ./deps/lua, /usr/local/lib, /usr/local/lib64,
                                  /usr/lib, and /usr/lib64.

      --lua-version=VERSION       The version number of Lua (or LuaJIT) headers and library to try
                                  to find (e.g. "5.3", "2.0").

  -o, --output=FILE               Output file name or path. Defaults to base name of the main
                                  script with stripped .lua extension.

  -C, --no-compress               Disable BriefLZ compression of Lua sources.

  -M, --no-minify                 Disable minification of Lua sources.

  -t, --rocks-tree=DIR            The prefix where to install required modules. Default is
                                  ".luapak" in the current directory.
  -q, --quiet                     Be quiet, i.e. print only errors.

  -v, --verbose                   Be verbose, i.e. print debug messages.

  -h, --help                      Display this help message and exit.

Environment Variables:
  AR          Archive-maintaining program; default is "ar".
  CC          Command for compiling C; default is "gcc".
  CMAKE       Command for processing CMakeLists.txt files; default is "cmake".
  CFLAGS      Extra flags to give to the C compiler; default is "-Os -fPIC".
  LD          Command for linking object files and archive files; default is "ld".
  LDFLAGS     Extra flags to give to compiler when they are supposed to invoke the linker;
              default on macOS is "-pagezero_size 10000 -image_base 100000000".
  MAKE        Command for executing Makefile; default is "make".
  RANLIB      Command for generating index to the contents of an archive; default is "ranlib".
  STRIP       Command for discarding symbols from an object file; default is "strip".

luapak analyse-deps

Click here to expand…
Usage: luapak analyse-deps [-a|-f|-m|-g] [options] FILE...
       luapak analyse-deps --help

Analyses dependency graph of Lua module(s) using static code analysis (looks
for "require" expressions).
Options:
  -a, --all                   Print all information (default).
  -f, --found                 Print only found modules.
  -m, --missing               Print only missing modules.
  -g, --ignored               Print only excluded/ignored modules.

  -e, --excludes=PATTERNS     Module(s) to exclude from the dependencies analysis. PATTERNS is one
                              or more glob patterns matching module name in dot notation
                              (e.g. "pl.*"). Patterns may be delimited by comma or space. This
                              option can be also specified multiple times.

  -n, --ignore-errors         Ignore errors from dependencies resolution (like unredable or unparseable files).

  -P, --no-pcalls             Do not analyse pcall requires.

  -W, --no-wildcards          Do not expand "wildcard" requires.

  -p, --pkg-path=PATH         The path pattern where to search for Lua and C/Lua modules instead of
                              the default path.

  -v, --verbose               Be verbose, i.e. print debug messages.

  -h, --help                  Display this help message and exit.

luapak build-rock

Click here to expand…
Usage: luapak build-rock [options] ROCKSPEC...
       luapak build-rock --help

Builds Lua/C module as a library archive suitable for static linking
and installs it into rocks tree.
Options:
  -C, --directory=DIR         Change directory before doing anything.

  -i, --lua-impl=NAME         The Lua implementation that should be used - "PUC" (default), or
                              "LuaJIT". This is currently used only as a hint to find the correct
                              headers when auto-detection is used (i.e. --lua-incdir unspecified).

  -I, --lua-incdir=DIR        The directory that contains Lua (or LuaJIT) headers. If not
                              specified, luapak will look for the lua.h (and luajit.h) file inside:
                              Luarock's LUA_INCDIR, ./vendor/lua, ./deps/lua, /usr/local/include,
                              and /usr/include. If --lua-version is specified, then it will also
                              try subdirectories lua and lua- of each of the
                              named directories and verify that the found lua.h (or luajit.h) is
                              for the specified Lua (or LuaJIT) version.

  -l, --lua-version=VERSION   The version number of Lua (or LuaJIT) headers and library to try
                              to find (e.g. "5.3", "2.0").

  -t, --rocks-tree=DIR        The prefix where to install Lua/C modules Default is ".luapak" in
                              the current directory.

  -v, --verbose               Be verbose, i.e. print debug messages.

  -h, --help                  Display this help message and exit.

Environment Variables:
  AR          Archive-maintaining program; default is "ar".
  CC          Command for compiling C; default is "gcc".
  CMAKE       Command for processing CMakeLists.txt files; default is "cmake".
  CFLAGS      Extra flags to give to the C compiler; default is "-Os -fPIC".
  LD          Command for linking object files and archive files; default is "ld".
  LDFLAGS     Extra flags to give to compiler when they are supposed to invoke the linker;
              default on macOS is "-pagezero_size 10000 -image_base 100000000".
  MAKE        Command for executing Makefile; default is "make".
  RANLIB      Command for generating index to the contents of an archive; default is "ranlib".

luapak merge

Click here to expand…
Usage: luapak merge [options] MODULE...
       luapak merge --help

Combines multiple Lua modules into a single file. Each module is be wrapped in
a function, or string loaded by "load" (--debug), and assigned to
"package.preload" table.
Options:
  -g, --debug               Preserve module names and line numbers in error backtraces?
  -o, --output=FILE         Where to write the generated code. Use "-" for stdout. Default is "-".
  -v, --verbose             Be verbose, i.e. print debug messages.
  -h, --help                Display this help message and exit.

luapak minify

Click here to expand…
Usage: luapak minify [options] [FILE]
       luapak minify --help

Minifies Lua source code - removes comments, unnecessary white spaces and
empty lines, shortens numbers and names of local variables.
Options:
  -l, --keep-lno              Do not affect line numbers.
  -n, --keep-names            Do not rename local variables.
  -o, --output=FILE           Where to write the output. Use "-" for stdout. Default is "-".
  -v, --verbose               Be verbose, i.e. print debug messages.
  -h, --help                  Display this help message and exit.

luapak wrapper

Click here to expand…
Usage: luapak wrapper [options] FILE [MODULE_NAME...]
       luapak wrapper --help

Wraps Lua script into a generated C file that can be compiled and linked with
Lua interpreter and Lua/C native extensions into a standalone executable.
Options:
  -C, --no-compress           Do not compress FILE using BriefLZ algorithm.
  -o, --output=FILE           Where to write the generated code; "-" for stdout. Default is "-".
  -v, --verbose               Be verbose, i.e. print debug messages.
  -h, --help                  Display this help message and exit.

What Luapak Is Not?

  • Luapak is not a transpiler from Lua to C, nor compiler to a native code. It does not save you from runtime errors in your Lua code, nor increase its performance.

Installation

Note: If you want to bootstrap development environment for running tests, read the next section.

Using LuaRocks

You can install luapak using LuaRocks (the Lua package manager):

luarocks install luapak

or to get the latest development version:

luarocks install --server=http://luarocks.org/dev luapak

Download Standalone Binary

You can also download standalone Luapak binaries for Linux, macOS and Windows from Releases.

Note: Linux binaries are statically linked with musl libc, so they should work on any Linux system.

Set Up Development Environment

  1. Clone this repository:

    git clone https://github.com/jirutka/luapak.git
    cd luapak
  2. Source file .envrc into your shell (or manually add $(pwd)/.venv/bin to your PATH):

    source .envrc
  3. Install Lua and modules for running tests into directory .venv:

    ./script/bootstrap
  4. Start hacking!

  5. Run linters:

    ./script/test

TODO

  • Write documentation into README.

  • Write integration tests.

  • Analyse usage of Lua standard modules and exclude unused from the binary.

Similar Projects

Luapak is not the first tool for packing Lua code into standalone executable, but it’s the most complete. Here’s a list of similar projects I know about, some of them served as an inspiration for Luapak.

License

This project is licensed under MIT License. For the full text of the license, see the LICENSE file.


1. Luapak includes LuaRocks package manager with rewritten builtin build backend and modified settings to build Lua/C modules as static libraries. Other backends (make, cmake, …) are not supported in the sense that Luapak cannot alter build process to produce static libraries; it’s up to the user to ensure that.
You can’t perform that action at this time.