msimple is a simple and intuitive cross-platform toolkit for creating MSI installers.
  • C 80%
  • Lua 15.1%
  • PowerShell 2.5%
  • Makefile 1.3%
  • Shell 1.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
flipfloppy 85aa764535
All checks were successful
Build msimple / build (push) Successful in 34s
Test msimple / build (push) Successful in 13s
Fix zlib override for windows in Makefile
2026-08-13 14:02:08 +09:30
.claude/skills/add-api-function Initial commit (no working UI yet) 2026-08-12 12:00:06 +09:30
.forgejo/workflows Nevermind 2026-08-13 13:42:29 +09:30
docs Fix FileVersion inconsistencies 2026-08-13 13:10:50 +09:30
include Fix service registration issues on upgrades 2026-08-13 11:36:32 +09:30
src Fix FileVersion inconsistencies 2026-08-13 13:10:50 +09:30
tests Fix custom action issue 2026-08-12 15:41:58 +09:30
tools Initial commit (no working UI yet) 2026-08-12 12:00:06 +09:30
.gitattributes Add line ending exceptions for windows files 2026-08-13 11:39:11 +09:30
.gitignore Initial commit (no working UI yet) 2026-08-12 12:00:06 +09:30
LICENSE Initial commit (no working UI yet) 2026-08-12 12:00:06 +09:30
Makefile Fix zlib override for windows in Makefile 2026-08-13 14:02:08 +09:30
README.md Initial commit (no working UI yet) 2026-08-12 12:00:06 +09:30

msimple

A cross-platform toolkit for building MSI installers that aims to be simpler than the current tools but just as expressive. As a bonus, it's far faster and leaner than other tools. Project elements are declared in a Lua script, which msimple runs to figure out what to put in the MSI.

The result is that the instructions you give are much closer to a description of what you want the installer to do. You aren't expected to understand how MSIs work in detail to create installers that are simple to moderately advanced in complexity.

Usage

Projects are declared in lua files, like project.lua. Here's an example:

local msimple = require("msimple")

local project = msimple.new_project("My Project", "1.3.6", "B. Corp")

project:set_platform(msimple.platform.x64)
project:set_upgrade_code("{<an-upgrade-code>}")
project:set_property(msimple.property.about_url, "https://example.com")
project:install_program("MainExe", "file.exe", project:dir().."file.exe", {
    name = "My Project",
    add_to_desktop = true,
    add_to_start = true,
})
project:use_standard_ui()

project:build("installer.msi")

This script is invoked through the msimple CLI tool, which provides the underlying C API and the convenience functions in msimple.lua:

./build/msimple project.lua      # runs project.lua, which builds the .msi itself via project:build(...)

msimple will plainly log any error that occurs during the build, and will try to detect common programming mistakes that would result in weird MSI behaviour.

See docs/lua-api.md for the full Lua API reference (AI-generated, but mostly sane).

You can also run ./build/msimple dump to dump the contents of msimple.lua from the CLI tool to the current directory, for code completion and type checking.

If you need more advanced functionality than the high-level functions, you can call the bound C API directly from your project script. See msimple.lua for examples on how this works. Unlike the convenience functions, it requires an understanding of how MSIs work. Because it's in a scripting language, there's nothing stopping you from writing your own API on top of msimple, or defining functions specific to your use-case.

Building

Requires a C11 compiler, make, and zlib. Lua 5.5 is embedded via vendor/minilua.h, and the Lua bindings are embedded via tools/embed_lua.c.

make            # builds libmsimple.a, cfbtool, msimple, and tests into ./build
make windows    # cross-compiles from Linux to Windows
make test       # builds and runs the test suite

The project is cross-platform, and should build as long as you have make and POSIX utils. On Windows this requires MSYS2 or WSL (preferably MSYS2).

Architecture

msimple is (roughly speaking) composed of 4 layers:

Language Layer Primary Source Files
C CFB reader/writer cfb.h/c
C MSI database reader/writer msidb.h/c
C MSI schema reader/writer msiauthor.h/c
Lua Lua bindings msimple_native.c / msimple.lua

Each layer builds on/uses the last. The third layer is wrapped up in a convenient Lua library that can be used to produce an MSI by invoking the command-line tool.

Licensing Remarks

The vast majority of code here was generated by claude, so that's public domain. The parts that are human-authored (like this README) are licensed under MIT.

cfbtool

cfbtool is an independent tool to test reading/writing of the compound document file format the MSI database and embedded files use.

./build/cfbtool list <file.msi>
./build/cfbtool extract <file.msi> </Path/To/Stream> <outfile>
./build/cfbtool resave <file.msi> <outfile> [sector_size]   # 512, 4096, or 0=auto