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
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
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.
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
Open a Window
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
local ui = require "ui"
ui.info("Hello world !")
Now compile it :
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
rtc -w hello.lua
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 ?
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 .
. 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 ?
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.