Luz#
Luz is a build system for Apple Darwin-based systems. It’s name is derived from the Spanish word for “light.” It’s meant to be a lightweight, drop in replacement for other build systems such as Dragon and Theos.
Benifits over “theos” and “dragon”#
Note: Luz is a work-in-progress project. Features will change, and bugs will be fixed. If you find a bug, please report it on the GitHub repository.
Speed#
Luz is written in pure Python, and only uses libraries that I’ve created myself in its code. This means that it’s very fast. Luz especially shines when building projects with submodules, as it can build all of the submodules in parallel. This means that building a project only takes as long as the longest build time of any of the submodules.
Below you can find a benchmark of Luz vs. Theos, using the time comparison tool hyperfine. The same tweak was built (clean) with both build systems.

Note
This benchmark was ran on a 2020 MacBook Pro with an M1 processor, 8 GB of RAM, and a 256 GB SSD.
As you can see, Luz is much faster than Theos, and is able to build the same project in less than half the time.
Source Code Structure#
Each of Luz’s modules have a different source file, which are all subclassed from a main class called Module. This allows for easy extensibility, and allows for the creation of new modules without having to modify the core of the build system.
Setup#
Installation#
To install Luz, run the following command in your terminal:
$ python -c "$(curl -fsSL https://raw.githubusercontent.com/LuzProject/luz/main/install.py)"
This will install Luz and all of its dependencies.
Options#
You can call the install script with the following options:
Option |
Type |
Description |
|
Flag |
Whether or not to install the SDKs. If this is set, you will need to install the SDKs manually. |
|
Flag |
Update Luz. (You can use |
|
String |
Ref of |
Notes#
If you are on Windows, you will need to install the Windows Subsystem for Linux (WSL). You can find instructions on how to do this here.
If you are on macOS, you will need to install Xcode and the Xcode Command Line Tools.
Commands#
Luz is a command line tool. It is used to create, build, run, and test Luz projects.
build
#
Builds a project using the LuzBuild in the working directory.
Option |
Type |
Description |
|
Flag |
Whether or not to clean the build directory before building. |
|
Flag |
Path to the directory to build. (i.e. |
|
Flag |
Add meta information to the build. (i.e. |
verify
#
Verifies the structure of luz.py
.
Option |
Type |
Description |
|
Flag |
Path to the directory to verify. (i.e. |
gen
#
Generate a project.
Option |
Type |
Description |
|
String |
The type of project to generate. ( |
Generation#
Luz comes with a built-in project generator called LuzGen
. It can be used to create a new project with the following command:
$ luz gen
This command will walk you through the steps to create a new project. First, it will ask you what kind of project you want to generate. Then, you can choose from different languages, such as Objective-C, Swift or Assembly. Finally, you enter project metadata, such as the name, author, version, etc. Below, you can find an example of how to use LuzGen
.

luzconf.py Formatting#
Luz uses a Python file to define the settings for the build. Python is used so that compile-time variables can be specified, much like a Makefile. The file is called luzconf.py
and is located in the root of your project.
LuzGen
will automatically generate a luzconf.py
file for any project that you create with it. It’s not recommended to create your own luzconf.py
, and you should only do so if you know what you’re doing.
Meta#
This is where you define the settings for the build, such as the SDK, the architectures to build for, and the clang
path.
Meta variables are defined in a class called Meta
that can be imported from luz
.
Variable |
Type |
Description |
|
Boolean |
Whether or not to build a debug version of the package. ( |
|
Boolean |
Whether or not to build a release version of the package. ( |
|
String |
SDK path to use for building. (uses |
|
String |
Prefix to use for compilation commands. ( |
|
String |
Path to |
|
String |
Path to |
|
String |
Whether or not to make a rootless DEB archive. ( |
|
String |
Command to use to compress the DEB archive. ( |
|
String |
Whether or not to pack the DEB archive. ( |
|
List |
List of architectures to build for. ( |
|
String |
Platform to build for. Can be |
|
String |
Minimum version to build for. ( |
Control#
This is where you define the settings for the control file.
Control variables are defined in a class called Control
that can be imported from luz
.
Variable |
Type |
Description |
|
String |
ID of the package. |
|
String |
Name of the package. |
|
String |
Author of the package. |
|
String |
Maintainer of the package. |
|
String |
Version of the package. |
|
String |
Section of the package. |
|
List |
Dependencies of the package. |
|
String |
Architecture of the package. |
|
String |
Description of the package. |
Additional control options can be found here.
Scripts#
This is where maintainer scripts are defined.
Scripts are defined in a class called Script
that can be imported from luz
.
Variable |
Type |
Description |
|
String |
Type of script to run. Can be |
|
String (Optional) |
Path to the script to copy. ( |
|
String (Optional) |
Content of the script to copy. ( |
Please note that either path
or content
must be specified. If both are specified, path
will be used.
Modules#
Modules are where you define the files to compile and the settings for the build.
Modules are defined in a class called Modules
that can be imported from luz
.
Variable |
Type |
Description |
|
String |
Type of module to build. ( |
|
List |
Flags to pass to |
|
List |
Flags to pass to |
|
List |
Flags to pass to the linker. |
|
String |
Optimization level to use for |
|
List |
Warnings flags to pass to |
|
List |
Entitlement flags to pass to |
|
Boolean |
Whether or not to use ARC for |
|
Boolean |
Whether or not to only compile changed files. ( |
|
List |
List of bridging headers to use for |
|
List |
List of frameworks to link against. |
|
List |
List of private frameworks to link against. |
|
List |
List of libraries to link against. |
|
Callable |
Function to run before staging. |
|
Callable |
Function to run after staging. |
Additional module options can be found here.
Submodules#
Submodules are where you define paths to directories with luz.py
files to include in your project.
Submodules are defined in a class called Submodule
that can be imported from luz
.
Variable |
Type |
Description |
|
String |
Path to the submodule. |
|
String |
Whether or not to inherit non-specified |
Example luzconf.py
#
from luz import Control, Meta, Modules, Script, Submodule
# define meta options
meta = Meta(
release=True,
archs=['arm64', 'arm64e'],
cc='/usr/bin/gcc',
swift='/usr/bin/swift',
compression='zstd',
platform='iphoneos',
sdk='~/.luz/sdks/iPhoneOS14.5.sdk',
rootless=True,
min_vers='15.0'
)
# define control options
control = Control(
id='com.jaidan.demo',
name='LuzBuildDemo',
author='Jaidan',
maintainer='Jaidan',
description='LuzBuild demo',
section='Tweaks',
version='1.0.0',
depends=['firmware (>= 15.0)', 'mobilesubstrate'],
architecture='iphoneos-arm64'
)
# define scripts
scripts = [
Script(type='postinst', path='./scripts/postinst'),
Script(type='prerm', path='./scripts/prerm')
]
# define modules
modules = [
Module(
name='TestTweak',
filter={
'bundles': ['com.apple.SpringBoard']
},
files=['Tweak.xm']
)
]
# define submodules
submodules = [
Submodule(path="./Preferences")
]