Since we started our unannounced project we've been using Premake. As the author Jason Perkins describes it, Premake is "powerfully simple build configuration". Premake is not a build system that will figure out build dependencies and then go build your executable; it just generates project and makefiles by using Lua scripting.

So one might wonder why bother with it when you can do that with Visual Studio configuration and property sheets? Platforms supported by Visual Studio are not the only ones we care about, nor do we like changing XML configuration settings in Visual Studio. Configuration settings are easy to mess up; especially in teams where not everyone is aware of what settings should be set for which project and which configuration. When adding multiple platforms, even just those platforms supported by Visual Studio, it gets messy with all possible combinations. That's where Premake shines.

Alt text

We have split our project into different categories; 3rd party libraries, engine, game and tools. There are four project solutions, four targets platforms and three different builds for engine and game. Obviously this would difficult to manage manually. For example, to change one compiler setting for the game we would have to do it multiple times, which is very error prone. With Premake we have to change it only at one place and regenerate the project files. We have a common premake file which defines common build settings that must be consistent across 3rd party libraries and applications. Then a premake file for each solution and each project. Project premakes are short and the least interesting. A common file defines all target directories for the build, functions for copying libraries after build, platform include and library directories, defines, etc. This way everything can be rebuilt with identical settings in order to avoid any incompatibilites. In the begining we weren't sure if we should switch all our runtime 3rd party libraries to premake. We were building them separately with their own build systems and configurations. The idea of doing it was pretty scary, but then we tried (with the exception of Qt framework) to switch to Premake scripts and the process went smoothly and we're happy with it. There are a few 3rd party libraries that we're going to integrate in following weeks which have scary build systems. By 'scary' I mean custom build systems built with Perl, batch files and makefiles combined. But we'll try to switch that to premake as well.

So far we've only had a few issues with it. The main and most annoying problem is not being able to setup build output for custom build steps. This causes our custom build step to sometimes be rebuilt even if it is not neccessary. It's only one auto generated file and it doesn't slow down the process much. The other issue, which is more cosmetic, is the lack of an exclude from the build option. There is 'exclude' script which will exclude file from build and project file. Ideally 'excludefrombuild' option would still include the files into project files but flag them to skip build for specific platform. As workaround around this issue we keep all our files for all platforms in one solution and without an exclude from build option, files have to be #ifdefed for specific platform to avoid breaking build with platform specific code. These are not big issues and we hope they will be fixed soon, or we will fix them once we have more time to contribute to this project.

Before starting with Premake we knew of similar tools for generating project files, such as Badger Config, CMake, and Gyp. We haven't spent significant time exploring these alternatives. We're pretty happy with the scope of Premake and the feature set it offers for the time being. In the future if we find Premake limiting we might look reconsider other options, but we are certain we never will go back to manually editing project files.

Premake is awesome and we love it! If you haven't tried it, give it a try!

Premake Quick Start

Premake Scripting Reference