Compile Lua scripts to Windows executable
By Samir Tine, published on May 2023
rtc is an open source command line tool available with Luart that generates standalone executables from your Lua scripts.
Once compiled, an executable can be run on other Windows computers without the need to install Lua, facilitating the deployment of your applications.
In this tutorial, we will see how easy it is to make executables from Lua scripts, embed content, and deploy your applications on any Windows computer.
Your first executable
Create a simple hello.lua
file containing this script :
print("Hello World !")
Now, open a command line prompt, go to the folder where you just saved the file, and type the following command to invoke rtc
:
rtc hello.lua
Voila! You have just compiled your Lua script to a Windows executable hello.exe
. You can run it like any other Windows program.
In fact, by default, your compiled executable is not really standalone, it needs the Lua runtime library lua54.dll
, that can be found in the Luart bin\
folder.
If you suppress the PATH environment variable, your program hello.exe
won't execute as it won't be able to find the Lua runtime library anymore.
The hello.exe
depends on the Lua dynamic library lua54.dll
. This is called dynamic compilation.
Dynamic compilation is the standard way to run Lua, as it permits to load binary modules during runtime.
Let's go static
If you want to get ride of the lua54.dll
dependency, you can use static compilation, by using the -s
option :
rtc -s hello.lua
You can see that the new hello.exe
has a bigger size. You guess it, that's because it contains the Lua runtime library. It can now be executed without the need of the lua54.dll
library.
Static compilation may sound appealing, but it comes at a price: Binary Lua modules cannot be loaded at runtime.
Reserve this type of compilation for simple applications that do not depend on third-party binary modules.
Open a Window
By default, rtc
decide to compile executables for console or desktop depending on the file extension :
- Lua source file with a
.lua
extension are compiled for console
- Lua source file with a
.wlua
extension are compiled for desktop
Let's go further and compile our first desktop application, by saving the following file to hello.lua
:
local ui = require "ui"
ui.info("Hello world !")
Now compile it :
rtc hello.lua
If you run hello.exe
, by double clicking on it in the Windows explorer, a console window will show with an error message complaining that the ui
module is not found...
This happens because we have named our Lua source file with the .lua
extension, and rtc
compiled our file as a console application (remember that the ui
module is only available using desktop interpreter).
We have two possibilities to correct this: either rename our source file with the .wlua
extension or force rtc
to generate a desktop application. Let's use this last method with the -w
option:
rtc -w hello.lua
Running hello.exe
will show only the message box, without the console window. You just compiled your first Lua desktop application !
You are iconic
rtc
provides default applications icons for your compiled executables, depending on console/desktop applications.
You can override this default behaviour and provide your own applications icons with the -i
option. Let's use a specific icon for our previous hello.lua
desktop application :
rtc.exe -i path/to/your/icon.ico -w hello.lua
Just replace the path/to/your/icon.ico
with the path of the .ico
file to use. Rather simple !
I got this baggage with me
Now imagine that your application is made up of several Lua files in the same directory and even in subdirectories. How to package everything in the executable ?
Once again rtc
makes it easy. We just need to indicate, in addition to the main Lua source file, the directory to embed entirely in the executable. Yes, you read correctly. rtc
is able to include in the compiled executable the entire contents of a directory with all these files and subdirectories.
Let's try to compile our desktop application with its entire directory content. To do this, open a command line prompt, got to the folder where our main Lua file hello.lua
is and type the following command :
rtc.exe -w hello.lua .
The dot .
means we ask rtc
to embed the current directory with all its content inside the executable.
The embed module
But wait a minute, how to access our files once they are embedded in our executable ?
The embed
module comes to the rescue. This module is only available to compiled scripts if embedded content is found inside the executable. This module contains :
- A File object to interact with all the embedded files.
- A Zip object instance to access the compressed embedded content.
If you want to use a Lua file or a Lua binary module in the embedded content, just use the global require()
function seamlessly, without the need to extract files before.
rtc
creates inside the executable a virtual file system that contains the directory content provided by the command line.
This allows access to embedded content transparently from your Lua scripts, both for accessing files and for loading Lua modules, whether binary or not.