The official Premake documentation.© 2002-2010 Jason Perkins and the Premake project.
This user guide reflects the current state of the software fairly closely, but may lag in places, or get a little ahead of the official releases in others. When in doubt, feel free to post a question over in the forums. If you spot any problems, or think something is unclear, feel free to leave a comment.
Imagine yourself the owner of an open source software project. Your users are asking for a Visual Studio 2008 solution, but you don't have Visual Studio! Or perhaps you are a cross-platform game developer struggling to keep projects, solutions, and makefiles in sync. Its a common problem for open and cross-platform projects: restrict yourself to a single, potentially sub-optimal build tool--driving away potential contributors--or manually maintain two, three, or more sets of build scripts.
Not working cross-platform? Have you ever been stuck using an old version of Visual Studio because it was too difficult to upgrade the entire team?
Or maybe you just want an easy way to reconfigure your project for different situations or environments, pulling in different source code or libraries, switches and options.
Premake is a build configuration tool. Describe your C, C++, or C# software project using a simple, easy to read syntax and let Premake generate the project files for:
Version 4.1 of Premake added experimental support for cross-compiling, targeting:
Premake allows you to manage your project configuration in one place and still support those pesky IDE-addicted Windows coders and/or cranky Linux command-line junkies. It allows you to generate project files for tools that you do not own. It saves the time that would otherwise be spent manually keeping several different toolsets in sync. And it provides an easy upgrade path as new versions of your favorite tools are released.
In addition to these project generation capabilities, Premake also provides a complete Lua scripting environment, enabling the automation of complex configuration tasks, such as setting up new source tree checkouts or creating deployment packages. These scripts will run on any platform, ending batch/shell script duplication.
Premake is a "plain old C" application, distributed as a single executable file. It is small, weighing in at around 200K. It does not require any additional libraries or runtimes to be installed, and should build and run pretty much anywhere. It is currently being tested and used on Windows, Mac OS X, Linux, and other POSIX environments. It uses only a handful of platform dependent routines (directory management, mostly). Adding support for additional toolsets and languages is straightforward. The source code is available under the BSD License. The source code is hosted on BitBucket; file downloads are hosted on SourceForge.
Learn how to compile Premake from the source code.If you downloaded a prebuilt binary package you can skip this page, which discusses how to build the Premake source code. Jump ahead to Quick Start to begin learning how to use and develop with Premake.
If you downloaded one of the official source code release packages, the project files have already been generated for you, and may be found in the build/ directory. Skip ahead to the next section to learn about the important differences between the build configurations.
Premake's Mercurial repository does not contain any project files. Instead, use an existing copy of Premake to generate the files for your particular toolset and environment.
Once you have a working Premake installed, embed the scripts by opening a console or terminal to the source code directory and running the command
premake4 embed
Now generate the project files with a command like:
premake4 gmake # for GNU makefiles using GCC premake4 vs2008 # for a Visual Studio 2008 solution
Use the --help option to see all of the available targets. You now have a solution/makefile/workspace that you can load and build.
Note that when working against the Mercurial sources it is a good idea to refresh the embedded scripts after each update.
$ hg pull -u $ premake4 embed
See Debug vs. Release Modes below for an explanation (and maybe eventually I'll think of a better way to do this).
Premake can be built in either "release" (the default) or "debug" modes. If you are using Makefiles (as opposed to an IDE), you can choose which configuration to build with the config argument:
make # build in release mode, both versions make config=debug # build in debug mode, when generated with Premake 4.x make CONFIG=Debug # build in debug mode, when generated with Premake 3.x
If you do not supply a config argument, release mode will be used. IDEs like Visual Studio provide their own mechanism for switching build configurations.
A significant portion of Premake is written in Lua. For release builds (the default) this has no impact, just build as normal and go.
When built in Debug mode, Premake will read its Lua scripts from the disk at startup, enabling compile-less code/test iterations, and therefore faster development. But it needs a little help finding the scripts. You can use the /scripts command line argument, like so:
premake4 /scripts=~/Code/premake4/src gmake
Or set a PREMAKE_PATH environment variable:
PREMAKE_PATH=~/Code/premake4/src
You need to specify the location of the Premake src/ directory, the one containing _premake_main.lua.
In release builds, Premake uses a copy of the scripts embedded into static strings: see src/host/scripts.c. If you modify any of the core Lua scripts (anything ending in .lua), you must also update these embedded strings before your changes will appear in the release mode build.
You can update these strings by using the embed action, which is part of Premake's own build script.
premake4 embed
This command embeds all of the scripts listed in _manifest.lua into src/host/scripts.c. The next release build will include the updated scripts.
The inclusion of the Lua scripts throws a wrench in things, and I certainly understand if you have questions. I'll be glad to help you out. Leave a note in the forums (the preferred approach), join the mailing list, or contact me directly. Your questions will help me improve these instructions.
A quick introduction for people who arrived here directly: Premake is a build configuration tool. It reads a description of a software project and generates the files for one of several different toolsets. By using Premake, software developers can save time and support more tools and users. Learn More.
If you don't have Premake already, you can download it now.
Premake is a small (around 200K) command line executable, delivered as a single file. Just unpack the download and place the executable on your system search path or anywhere else convenient.
The simplest Premake command is:
premake4 action
Usually you would like Premake to generate project files for a particular toolset, in which case action is one of these toolset identifiers:
| vs2010 | Visual Studio 2010 (or Express) |
|---|---|
| vs2008 | Visual Studio 2008 (or Express) |
| vs2005 | Visual Studio 2005 (or Express), SharpDevelop, or MonoDevelop |
| vs2003 | Visual Studio 2003 |
| vs2002 | Visual Studio 2002 |
| gmake | GNU Make (including Cygwin and MinGW) |
| xcode3 | Apple Xcode 3 |
| codeblocks | Code::Blocks |
| codelite | CodeLite |
You can see a complete list of actions and other options by typing:
premake4 --help
Once the files have been generated you can load the solution or workspace into your IDE and build as you normally would.
Running make with no options will build all targets using the default configuration. To build a different configuration supply the config argument:
make config=release
Most projects provide debug and release configurations; to see the available targets and configurations, type:
make help
Remove all generated binaries and intermediate files with:
make clean
Premake generated makefiles do not support a make install step. Instead, project owners are encouraged to add an install action to their Premake scripts, which has the advantage of working with any toolset on any platform. You can check for the existence of an install action by viewing the help (run premake4 --help in the project directory).
If you are having trouble building your project, start by contacting the project manager. If you are having trouble building or using Premake, visit our Support page and I'll try to help you out.
To learn how to use Premake for your own software projects see Scripting With Premake.
In this section, I'll show you how to create project scripts for Premake.
Premake is built on Lua, a powerful, fast, light-weight scripting language. Premake scripts are really Lua programs, so anything you can do in Lua can also be done in a Premake script. To this, Premake adds functions for defining solutions, projects, and configurations as well as support for common build configuration tasks. Premake also provides conventions for defining and handling command line options and actions, allowing you to build sophisticated configuration scripts.
Because of the descriptive nature of the Lua language, your build scripts will often look more like static configuration files than mini-programs. Here is an example of a fairly typical Premake script for a C++ executable. See the Premake Cookbook for more examples of common configuration tasks.
-- A solution contains projects, and defines the available configurations solution "MyApplication" configurations { "Debug", "Release" } -- A project defines one build target project "MyApplication" kind "ConsoleApp" language "C++" files { "**.h", "**.cpp" } configuration "Debug" defines { "DEBUG" } flags { "Symbols" } configuration "Release" defines { "NDEBUG" } flags { "Optimize" }
The indentation in this sample is arbitrary, this is the way I happen to like it.
The following sections of this guide will walk you through all of the features of Premake in a somewhat logical fashion. It isn't rocket science, and you probably already have the gist of it from the example above, so feel free to skip around. You can also refer to the Reference section or the Lua Reference Manual for information on a particular function or variable.
Let me start with a bit of general information that you will need to know to begin scripting.
Premake will look for a file named premake4.lua by default, much like make looks for a file named Makefile. So that's the name you want to give your project script files, generally.
You can specify a different file name using the file argument, like so:
premake4 --file=myfilename.lua
You can define your entire project in one script file if you want, or you can split up the projects into their own files, or any other organization you can dream up. Use the include() function or Lua's dofile() to link all the files together.
I personally like to use just one file for simple projects, and one-file-per-project for more complex builds.
You define your software project by calling a sequence of functions, such as solution, project, and defines. These functions set up the project state and take care of error checking and the like.
When calling a function with a single string constant for an argument, Lua allows you to drop the parenthesis that would normally appear around the argument list. So these two statements are functionally identical:
solution("MySolution") solution "MySolution"
I find the latter form a bit more readable. The same goes with a single list argument:
defines({"DEBUG", "TRACE"}) defines {"DEBUG", "TRACE"}
If you want to use a variable as an argument, or the result of a calculation, then you must use the parenthesis:
local lang = "C++" language (lang) -- need the parenthesis here location ("build/" .. _ACTION) -- and here too
Many of Premake's functions accept a list of values as a parameter. For instance, a list of source code files, or defined symbols, or build flags. When defining a list of values you need to surround them in curly brackets, Lua's syntax for a list. If you only want to set a single value, you can leave off the brackets if you like.
defines { "DEBUG", "TRACE" } -- defines multiple values defines "NDEBUG" -- defines a single value
There are also functions that only accept a single value, such as solution and project names, the project kind and language, and so on. If you try to pass a list to these function you'll get an error. These string values may be delimited with single (') or double (") quotes.
language "C++" kind 'ConsoleApp'
For more information on Lua programming, see the Lua website or Programming in Lua. If you get stuck, post a question over in the forums and I will do my best to help you out.
Starting with Premake 4.0 I am following the Visual Studio naming conventions for build components. For those of you unfamiliar with Visual Studio I will try to provide to provide the synonyms used by other toolsets; if I miss any let me know and I'll add them.
At the top level of every build is a solution, acting as a container and meta-project (other tools use the term workspace). Solutions define a common set of configurations and encapsulate one or more projects (see below). You can define build-wide settings at the solution level; these will apply to all of the projects contained by that solution.
Solutions are defined using the solution function. Most builds will need only a single solution, but you are free to create more if needed. Configurations are specified using the configurations function; see the next section for more information.
solution "MySolution" configurations { "Debug", "Release" }
The solution name, provided as a parameter to the function, is used as the file name of the generated solution file. So avoid special characters; spaces are okay.
The primary purpose of a solution is to act as a container for projects. A project lists the settings and source files needed to build one binary target. Just about every IDE uses the term "project" for this. In the world of Make, you can think of projects as a makefile for one particular library or executable; a solution is a meta-makefile that calls each project as needed.
Projects are defined using the project function. You must create a solution and list the available configurations before creating the first project.
solution "MySolution" configurations { "Debug", "Release" } project "MyProject"
The project name, like the solution name, is used as the file name for the generated project file so avoid special characters.
Each project specifies a kind which determines what kind of output is generated, such as a console or windowed executable, or a shared or static library. The kind function is used to specify this value.
Each project also specifies which programming language it uses, such as C++ or C#. The language function is used to set this value.
project "MyProject" kind "ConsoleApp" language "C++"
By default, Premake will place generated solution and project files in the same directory as the script which defined them. If your Premake script is in C:\Code\MyProject then the generated files will also be in C:\Code\MyProject.
You can change the output location using the location function.
solution "MySolution" configurations { "Debug", "Release" } location "build" project "MyProject" location "build"
The path provided for location should be specified relative to the script file. Using the example and script above, the generated files will be placed in C:\Code\MyProject\build.
You add files—source code, resources, and so on—to your project using the files function.
files { "hello.h", -- you can specify exact names "*.c", -- or use a wildcard... "**.cpp" -- ...and recurse into subdirectories }
You can use wildcards in the file patterns to match a set of files. The wildcard * will match files in one directory; the wildcard ** will match files in one directory and also recurse down into any subdirectories.
Files located in other directories should be specified relative to the script file. For example, if the script is located at myproject/build and the source files are at myproject/src, the files should be specified as
files { "../src/*.cpp" }
Paths should always use the forward slash / as a separator; Premake will translate to the appropriate platform-specific separator as needed.
Sometimes you want most, but not all, of the files in a directory. In that case, use the excludes function to mask out those few exceptions.
files { "*.c" } excludes { "a_file.c", "another_file.c" }
Excludes may also use wildcards.
files { "**.c" } excludes { "tests/*.c" }
Sometimes you may want to exclude all the files in a particular directory, but aren't sure where that directory will fall in the source tree.
files { "**.c" } excludes { "**/Win32Specific/**" }
Linking to external libraries is done with the links function.
links { "png", "zlib" }
When specifying libraries, system-specific decorations, such as prefixes or file extensions, should be omitted. Premake will synthesize the correct format based on the target platform automatically. The one exception to the rule is Mac OS X frameworks, where the file extension is required to identify it as such.
links { "Cocoa.framework" }
To link to a sibling project (a project in the same solution) use the project name. Premake will deduce the correct library path and name based on the current platform and configuration.
solution "MySolution" project "MyLibraryProject" -- ...project settings here... project "MyExecutableProject" -- ...project settings here... links { "MyLibraryProject" }
You can tell Premake where to search for libraries with the libdirs function.
libdirs { "libs", "../mylibs" }
If you need to discover the location of a library, use the os.findlib function.
libdirs { os.findlib("X11") }
A configuration is a collection of flags and options to apply to a build, including build flags, header file and library search directories, and more. Each solution defines its own list of configurations. The most common configuration set, which is usually provided by default by most IDEs, is "Debug" and "Release". Visual Studio and other IDEs provide facilities to quickly switch between configurations; Premake-generated makefiles allow the configuration to be specified with a command-line parameter.
At the solution level, specify your list of possible configurations by calling the configurations function and passing it a list of names.
solution "MySolution" configurations { "Debug", "Release" }
You are not limited to these two standard names. For instance, if your project can be built as both as both static or shared libraries, you might use this instead:
configurations { "DebugLib", "DebugDLL", "ReleaseLib", "ReleaseDLL" }
Some features of Premake, such as selecting a configuration from the command line, are easier if you avoid spaces. However, spaces are allowed in configuration names.
Premake provides a great deal of flexibility when it comes to configuring your build: you can apply settings across an entire solution, a project, or to a targeted combination of configuration and toolset. The configuration function is used to apply settings to a particular build environment.
For example, you can define a symbol across all configurations of all projects by setting it at the solution level, before any filters are enabled.
solution "MySolution" configurations { "Debug", "Release" } defines { "MY_SYMBOL" }
Or, using the configuration function, you can limit it to a particular configuration.
solution "MySolution" configurations { "Debug", "Release" } configuration "Debug" defines { "MY_SYMBOL" }
The same rules hold true at the project level.
project "MyProject" defines { "TRACE" } -- this will be applied to every configuration configuration "Debug" defines { "DEBUG" } -- this will only be applied to Debug builds
When values are supplied at multiple levels, list fields (like defines above) are concatenated while single-value fields (like language) are overridden. Project values take precedence over solution values, and will appear after the solution values in lists. Values at the same level are evaluated in the order in which they are encountered in the script.
This is just an overview of configuration filtering. For more details, including a list of the available filter keywords, see the documentation for the configuration function.
(I can see where this topic might be a bit confusing for newcomers, and I welcome suggestions for improving this text. Feel free to leave your ideas in the comments.)
Platform support is a new, experimental feature introduced in Premake 4.1. This is a potentially large area of development and it may take a few releases to get it just right. The syntax and behavior described here might change along the way.
An important caveat: I don't target multiple platforms in my own day to day work. I am relying on those of you that do, and the community at large, to help me shape this feature.
One more disclaimer: I think this page is confusing. If you've got any ideas on how I might explain it better please leave a comment. Thanks!
In addition to configurations, you can also target multiple hardware platforms, such as a 32-bit build and a 64-bit build. This is also known as cross compiling. These platforms can be quickly switched between from within your IDE, or with a command-line parameter on the generated makefile.
In addition to 32- and 64-bit builds, Premake also supports Mac OS X universal binaries, the Playstation 3, and the Xbox 360. See the platforms function documentation for a full list of supported platforms.
Unlike configurations, platforms are optional. If you don't need them, just don't call the platforms function at all, in which case the toolset's default behavior will be used.
The easiest way to target a particular platform is to supply the --platform argument to Premake. If you have a solution that builds on Windows, and you want to a binary for the Xbox 360, you would call:
premake4 --platform=xbox360 vs2005
The files generated by this call will include the default Win32 build normally present in Visual Studio solutions, plus a new set of configurations which target the Xbox 360. Assuming that you have the proper development tools installed and your software is portable enough, you can now build an Xbox 360 binary.
If you frequently target several different platforms, and want to switch between them without regenerating your project files, you can add them directly to your script. Target platforms are part of the solution, just like configurations:
solution "MySolution" configurations { "Debug", "Release" } platforms { "Native", "Universal" }
Not all tools will support all of the possible targets (currently only Visual Studio supports the Xbox 360 platform). Unsupported platforms are silently ignored; they simply will not appear in the generated build scripts.
Most toolsets require extra configuration to target multiple platforms. Premake will generate a build script with the right instructions for a 64-bit or an Xbox build, but that build will only succeed if the corresponding tools and libraries have been installed on the developer machine. GCC users may need to install the GCC multilib packages.
In addition to the cross-compiling platform targets listed above, there is a special target called native which preserves the default compiler behavior. Taking GCC as an example, Premake's x32 flag adds -m32 to the GCC command line, and the x64 flag adds -m64. The native platform, in contrast, does not add any flags to the command line and lets GCC use its default behavior to target the current platform.
Normally you would include the native platform, and list it first to make it the default.
platforms { "native", "x32", "x64" }
So if you wanted your code to "just build" on Windows or Unix, 32- or 64-bit systems, and you also wanted to allow folks to cross-compile for the Xbox 360 or Mac OS X universal binaries, you could do:
platforms { "native", "xbox360", "universal" }
Sometimes it is important to know which platform you are targeting; you might need to define specific symbols or link to different libraries. In this case, the native platform would not be included in the list.
platforms { "x32", "x64" }
Like any other configuration-specific value, platform-specific settings are set with configuration filters. If no platform is specified to the filter, the subsequent settings will apply to all platforms.
configuration { "debug" } defines "_DEBUG" -- this symbol will appear in settings for ALL platforms
If a specific platform identifier is listed, the settings will be applied only when that platform is specifically selected by the user.
configuration { "xbox360" } defines "IS_XBOX360_BUILD" -- this will only get applied when user chooses the Xbox 360 build
The platform is just another configuration axis, which you can mix and match with any other selectors. See the configuration function for more details.
configuration { "Debug", "x64" } defines "USE_64BIT_DEBUG_LIBRARY"
I am still working out how the target platforms should be represented in Premake-generated makefiles. Below is my best take so far; feedback and suggestions for improvement are very much appreciated.
In the generated makefiles, platforms and build configurations are paired up. If you defined a solution like this:
platforms { "native", "x64", "universal" }
There would be six possible configurations: debug, release, debug64, release64, debuguniv, and releaseuniv. I tried to truncate the platforms to something easy to type.
You target a specific configuration using the config argument.
make config=debug64
If the makefile is executed without any arguments, the first build configuration (in the example above, debug) will be used. For this reason, it is recommended that you put native first in the list.
Premake provides an ever-growing list of build settings that you can tweak; the following table lists some of the most common configuration tasks with a link to the corresponding function. As you can see, the flags function provides most of the features, and is a good place to start if you aren't sure how to make something go.
| Specify source code files | files, excludes |
|---|---|
| Define compiler or preprocessor symbols | defines |
| Locate include files | includedirs |
| Link against libraries, frameworks, or sibling projects | links, libdirs |
| Enable debugging information | flags |
| Optimize for size or speed | flags |
| Turn compiler or linker features on or off | flags, buildoptions, linkoptions |
| Set the name or location of the compiled target file | targetname, targetextension, targetprefix, targetdir |
For a comprehensive list of available settings and functions, see the Scripting Reference page.
If you think something should be possible and you can't figure out how to do it, feel free to post a question in the forums and someone will help you out.
Premake provides the ability to define and handle new command-line arguments from within your project script using the newaction and newoption functions.
Premake recognizes two types of arguments: actions and options.
An action indicates what Premake should do on any given run. For instance, the vs2005 action indicates that Visual Studio 2005 project files should be generated. The clean action causes all generated files to be deleted. Only one action may be specified at a time (this is different than Premake 3.x).
An option modifies the behavior of the action. For instance, the dotnet option is used to change which .NET compiler set is used in the generated files. Options can accept a value, such as --dotnet=mono or act as a flag, like --with-opengl.
From within your script, you can identify the current action with the _ACTION global variable, a string value. You can check for an option using the _OPTIONS table, which contains a list of key-value pairs. The key is the option identifier ("dotnet"), which references the command line value ("mono") or an empty string for valueless options.
-- delete a file if the clean action is running if _ACTION == "clean" then -- do something end -- use an option value in a configuration targetdir ( _OPTIONS["outdir"] )
New command-line options are created using the newoption function, passing a table which fully describes the option. This is best illustrated with some examples.
Here is an option intended to force the use of OpenGL in a 3D application. It serves as a simple flag, and does not take any value.
newoption { trigger = "with-opengl", description = "Force the use of OpenGL for rendering, regardless of platform" }
Note the commas after each key-value pair; this is required Lua syntax for a table. Once added to your script, the option will appear in the help text, and you may use the trigger as a keyword in your configuration blocks.
configuration "with-opengl" links { "opengldrv" } configuration "not with-opengl" links { "direct3ddrv" }
The next example shows an option with a fixed set of allowed values. Like the example above, it is intended to allow the user to specify a 3D API.
newoption { trigger = "gfxapi", value = "API", description = "Choose a particular 3D API for rendering", allowed = { { "opengl", "OpenGL" }, { "direct3d", "Direct3D (Windows only)" }, { "software", "Software Renderer" } } }
As before, this new option will be integrated into the help text, along with a description of each of the allowed values. Premake will check the option value at startup, and raise an error on invalid values. The value field appears in the help text, and is intended to give the user a clue about the type of value that is expected. In this case, the help text will appear like this:
--gfxapi=API Choose a particular 3D API for rendering; one of:
opengl OpenGL
direct3d Direct3D (Windows only)
software Software Renderer
Unlike the example above, you now use the value as a keyword in your configuration blocks.
configuration "opengl" links { "opengldrv" } configuration "direct3d" links { "direct3ddrv" } configuration "software" links { "softwaredrv" }
Or you could be more clever.
links { _OPTIONS["gfxapi"] .. "drv" }
In this example, you would also want to provide a default behavior for the case where no option is specified. You could place a bit of code like this anywhere in your script.
if not _OPTIONS["gfxapi"] then _OPTIONS["gfxapi"] = "opengl" end
As a last example of options, you may want to specify an option that accepts an unconstrained value, such as an output path. Just leave off the list of allowed values.
newoption { trigger = "outdir", value = "path", description = "Output directory for the compiled executable" }
Actions are defined in much the same way as options, and can be as simple as this:
newaction { trigger = "install", description = "Install the software", execute = function () -- copy files, etc. here end }
The actual code to be executed when the action if fired should be placed in the execute() function.
That's the simple version. If you are interested in developing more complex actions, for instance to add support for a new toolset, see Create a new action in the Extending Premake section.
If you are having trouble using Premake to generate build files for a particular project, your best bet is to contact the manager of the project first. They know their project better than I will, and may have seen the same problem before.
If you are having a problem with Premake, or need help with your project scripts, you have some choices.
First, check the Frequently Asked Questions. Someone may have asked the same question before.
If you haven't already, read the Documentation. If you find a problem in the documentation, leave a comment describing the problem on that page. I'll see your comment and fix it up, and the in meantime others can benefit from your input.
If you've found a bug in the software, or if you want to request a new feature please visit the Premake Trackers on SourceForge. It is a good idea to run a quick search first to make sure your issue hasn't already been reported. If not, go ahead and create a new ticket. The tracker makes sure your request gets the visibility and attention it deserves, with no chance of it slipping through the cracks.
If you just have a question you want answered, stop by the forums and start a new discussion. I try to check them daily and respond personally to most posts.
Here are answers to some of the most frequently asked questions about Premake, taken from the forums and the mailing list.
How do I control the build order of my projects?
How do I build a Universal/64-bit/Xbox binary?
Is it possible to invoke external tools?
Why is my Windows program trying to call main() instead of WinMain()?
How do I get my cool new feature/bug fix included in Premake?
There are two ways: re-order the projects in the script, and create link dependencies.
The project files generated by Premake will maintain the order of the projects as they appear in your script. So you can change the build order by rearranging the order of the projects in your script.
However, when people ask this question they are really asking how to link against a library project. In this case you want to put the library project name, not the library file name, in the list of links for the dependent project.
So if I have a library project called "MyLibrary"...
project "MyLibrary" kind "SharedLib"
...I can link against it like this.
project "MyExecutable" kind "ConsoleApp" links { "MyLibrary" }
Premake will automatically figure out the library file name and directory and create a dependency between the two projects to ensure a proper build order.
You can also use this method to create a build dependency between non-libraries. For instance, you may want to build an executable to use in the prebuild step for another project. As shown above, just put the project name in the list of links for the dependent project. Premake will recognize it as an executable and create the build dependency, but skip the link dependency.
For more information, see the description of the links function.
Supply the --platform option to Premake, and then build using the corresponding configuration.
premake4 --platform=universal gmake make config=releaseuniv clean make config=releaseuniv
Best practice is to clean before building a new platform. See Platforms for more information. This feature requires Premake 4.1 or later.
Yes, using Lua's os.execute() function. See the Lua Reference Manual for details.
Premake tries hard to make all build tools on all platforms perform as similarly as possible. So, by default, it will configure your Windows applications to call the standard main() entry point instead of the Windows-specific WinMain(). You can change this behavior by adding the WinMain build flag to your package, like so:
flags { "WinMain" }
I love code contributions! The best way is to create a patch (see Subversion's diff command) against the Subversion repository, or if that's not possible, the most recent source code release. Post it to the Patch Tracker on SourceForge—I get notified via email, and it provides a good place to discuss and track it.
If you can't figure out how to make a patch, get it to me however you can. I will do my best to make sense of it.
This section describes the functions and variables available to Premake scripts.
Premake is built on Lua, so everything in the Lua Reference Manual applies to a Premake script. Premake adds the ability to define solutions, projects, and configurations, as well as functions useful for build configuration tasks.
You may also want to check out LuaForge for a wide assortment of Lua add-on modules.
The _ACTION global variable stores the name of the action to be performed on this execution run. As an example, if this command line was used to launch Premake...
$ premake4 vs2005
...then _ACTION will be set to "vs2005". If there is no action (for instance, if the command was premake4 /help) this variable will be nil.
The _ARGS global variable stores any arguments to the current action. As an example, if this command line was used to launch Premake...
$ premake4 vs2005 alpha beta
...then _ARGS[1] will be set to "alpha" and _ARGS[2] to "beta". If there are no arguments this array will be empty.
The _OPTIONS global variable lists the current set of command line options and their values, if any. For more information, see Command Line Arguments.
The _PREMAKE_COMMAND global variable stores the full path to the Premake executable.
Introduced in Premake 4.4.
The _PREMAKE_VERSION global variable stores the current Premake version, i.e. "4.2".
The _SCRIPT global variable stores the full path of the currently executing script.
The _WORKING_DIR global variable stores the current working directory at the time Premake was launched.
Introduced in Premake 4.4.
The buildaction function specifies how a file or set of files should be treated during the compilation process. It is usually paired with a configuration filter to select a file set. If no build action is specified for a file a default action will be used, based on the file's extension.
buildaction ("action")
Build actions are currently only supported for .NET projects, and not for C or C++.
Solutions, projects, and configurations.
action is one of:
Embed all PNG image files into the target binary.
configuration "**.png" buildaction "Embed"
The buildoptions function passes arguments directly to the compiler command line without translation.
buildoptions { "options" }
If a project includes multiple calls to buildoptions the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
options is a list of compiler flags and options, specific to a particular compiler.
Use pkg-config style configuration when building on Linux with GCC. Build options are always compiler specific and should be targeted to a particular toolset.
configuration { "linux", "gmake" } buildoptions { "`wx-config --cxxflags`", "-ansi", "-pedantic" }
The configuration function limits the subsequent build settings to a particular environment.
configuration { "keywords" }
The configuration functions acts as a filter. Any settings that appear after this function in the script will be applied only in those environments that match all of the listed keywords. See below for some usage examples.
keywords is a list of identifiers (see below). If all of these identifiers are present in the current runtime environment, then the settings following the configuration call will be applied. If any of the identifiers is not the current environment the settings will be ignored.
The following table lists the available sources for keywords. Keywords are not case-sensitive.
In addition to the terms listed above, you may use the * and ** wildcards to match more than one term or file. You may also use the modifiers not and or to build more complex conditions. See the examples below for more information.
The function returns the current configuration object; see The Configuration Block below for more information on the structure of this object.
Define a new symbol which applies only to debug builds; assumes a configuration named "Debug" was defined as part of the solution.
configuration "Debug" defines { "_DEBUG" }
Define a symbol only when targeting Visual Studio 2005.
configuration "vs2005" defines { "VISUAL_STUDIO_2005" }
Wildcards can be used to match multiple terms. Define a symbol for all versions of Visual Studio.
configuration "vs*" defines { "VISUAL_STUDIO_2005" }
Add a suffix to the debug versions of libraries.
configuration { "Debug", "SharedLib or StaticLib" } targetsuffix "_d" -- ...or... configuration { "Debug", "*Lib" } targetsuffix "_d"
Although support is currently quite limited (only buildaction works so far), you may also apply settings to a particular file or set of files. This example sets the build action for all PNG image files.
configuration "*.png" buildaction "Embed"
In the case of files you may also use the ** wildcard, which will recurse into subdirectories.
configuration "**.png" buildaction "Embed"
If multiple keywords are specified, they will be treated as a logical AND. All terms must be present for the block to be applied. This example will apply the symbol only for debug builds on Mac OS X.
configuration { "debug", "macosx" } defines { "DEBUG_MACOSX" }
Multiple terms must use Lua's curly bracket list syntax.
You can use the or modifier to match against multiple, specific terms.
configuration "linux or macosx" defines { "LINUX_OR_MACOSX" }
You can also use not to apply the settings to all environments where the identifier is not set.
configuration "not windows" defines { "NOT_WINDOWS" }
Finally, you can reset the configuration filter and remove all active keywords by passing the function an empty table.
configuration {}
Each call to configuration function creates a new configuration block object. Unless you really know what you are doing, you should treat this object as read-only and use the Premake API to make any changes. The configuration block object contains the following values:
The configurations function specifies the set of build configurations, such as "Debug" and "Release", for a solution.
configurations { "names" }
A configuration encapsulates a collection of build settings, allowing the developer to easily switch between them. "Debug" and "Release" are the most common configurations, the former providing debugging information, and the latter providing optimizations.
The list of configurations must be specified before any projects are defined, and once a project has been defined the configuration list may no longer be changed.
Solutions only.
names is a list of configuration names. Spaces are allowed, but may make using certain Premake features, such as a command-line configuration selection, more difficult.
The function returns the current list of configuration names for the active solution.
Specify debug and release configurations for a solution.
solution "MySolution" configurations { "Debug", "Release" }
Add additional configurations for a dynamic link library version.
configurations { "Debug", "Release", "DebugDLL", "ReleaseDLL" }
You can retrieve the current list of configurations by calling the function with no parameters.
local cfgs = configurations()
The debugargs function specifies a list of arguments to pass to the application when run under the debugger.
debugargs { "args" }
Note that this settings is not implemented for Xcode 3, which requires a per-user configuration file in order to make it work.
In Visual Studio, this file can be overridden by a per-user configuration file (such as ProjectName.vcproj.MYDOMAIN-MYUSERNAME.user). Removing this file (which is done by Premake's clean action) will restore the default settings.
Added in Premake 4.4.
Solutions, projects, and configurations.
args is a Lua list of arguments to provide to the executable while debugging.
configuration "Debug" debugargs { "--append", "somefile.txt" }
The debugdir function sets the working directory for the integrated debugger.
debugdir "path"Note that this settings is not implemented for Xcode 3, which requires a per-user configuration file in order to make it work.
In Visual Studio, this file can be overridden by a per-user configuration file (such as ProjectName.vcproj.MYDOMAIN-MYUSERNAME.user). Removing this file (which is done by Premake's clean action) will restore the default settings.
Added in Premake 4.4.
Solutions, projects, and configurations.
path is the path to the working directory, relative to the currently executing script file.
configuration "Debug" debugdir "bin/debug"
The defines function adds preprocessor or compiler symbols to a project.
defines { "symbols" }
If a project includes multiple calls to defines the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
symbols specifies a list of symbols to be defined.
Define two new symbols in the current project.
defines { "DEBUG", "TRACE" }
Symbols may also assign values.
defines { "CALLSPEC=__dllexport" }
The deploymentoptions function passes arguments directly to the deployment tool command line without translation.
deploymentoptions { "options" }
If a project includes multiple calls to deploymentoptions the lists are concatenated, in the order in which they appear in the script.
Deployment options are currently only supported for Xbox 360 targets.
Solutions, projects, and configurations.
options is a list of deployment tools flags and options.
The excludes function removes files, added with the files function, from a project.
excludes { "file_list" }
If a project includes multiple calls to excludes the lists are concatenated.
Files may be set on the solution, project, and configuration level. However, only project-level file lists are currently supported.
file_list specifies one or more file patterns, separated by commas. File paths should be specified relative to the location of the script file. File patterns may contain the * wildcard to match against files in the current directory, or the ** wildcard to perform a recursive match.
Add all C files in a directory, and then exclude a specific file.
files { "*.c" } excludes { "a_file.c" }
Add an entire directory tree of C files, and then exclude one particular directory.
files { "**.c" } excludes { "tests/*.c" }
The files function adds files to a project.
files { "file_list" }
If a project includes multiple calls to files the lists are concatenated, in the order in which they appear in the script.
Files may be set on the solution, project, and configuration level. However, only project-level file lists are currently supported.
file_list specifies one or more file patterns, separated by commas. File paths should be specified relative to the location of the script file. File patterns may contain the * wildcard to match against files in the current directory, or the ** wildcard to perform a recursive match.
If a wildcard matches more files than you would like, you may filter the list using the excludes function.
Add two files to the current project.
files { "hello.cpp", "goodbye.cpp" }
Add all C++ files from the src/ directory to the project.
files { "src/*.cpp" }
Add all C++ files from the src/ directory, and any subdirectories.
files { "src/**.cpp" }
The flags function specifies build flags to modify the compiling or linking process.
flags { "flag_list" }
If a project includes multiple calls to flags the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
flags_list is a list of string flag names; see below for a list of valid flags. The flag values are not case-sensitive. Flags that are not supported by a particular platform or toolset are ignored.
If the existing flags are not sufficient, you can also pass tool-specific arguments directly to the compiler or linker using buildoptions and linkoptions.
A common configuration: enable debugging symbols in the Debug configuration, and optimize the Release configuration.
configuration "Debug" flags { "Symbols" } configuration "Release" flags { "Optimize" }
You can specify multiple flags.
flags { "Symbols", "ExtraWarnings", "FatalWarnings" }
The framework function selects a .NET framework version.
framework ("version")
This value currently is only applied to Visual Studio 2005 or later, and GNU makefiles using Mono. If no framework is specified the toolset default is used.
Solutions and projects.
version is one of:
Use the .NET 3.0 Framework.
framework "3.0"The iif function implements an immediate "if" clause, returning one of two possible values.
result = iif(condition, trueval, falseval)
condition is the logical condition to test. trueval is the value to return if the condition evaluates to true, falseval if the condition evaluates false.
trueval is the condition evaluates true, falseval otherwise.
result = iif(os.is("windows"), "is windows", "is not windows")
Note that all expressions are evaluated before the condition is checked; the following expression can not be implemented with an immediate if because it may try to concatenate a string value.
result = iif(x ~= nil, "x is " .. x, "x is nil")
The imageoptions function passes arguments directly to the image tool command line without translation.
imageoptions { "options" }
If a project includes multiple calls to imageoptions the lists are concatenated, in the order in which they appear in the script.
Image options are currently only supported for Xbox 360 targets.
Solutions, projects, and configurations.
options is a list of image tools flags and options.
The imagepath function sets the file name of the deployment image produced by the build.
imagepath ("path")
This value is currently only used by the Xbox 360.
Solutions, projects, and configurations.
path is the full path for the image file, relative to the currently executing script file.
The implibdir function specifies the import library output directory. Import libraries are generated for Windows DLL projects.
implibdir ("path")
By default, the generated project files will place the import library in the same directory as the compiled binary. The implibdir function allows you to change this location.
Solutions, projects, and configurations.
path is the output directory for the library, relative to the currently executing script file.
implibname
implibextension
implibprefix
implibsuffix
implibdir "../Libraries"The implibextension function specifies the import library file extension. Import libraries are generated for Windows DLL projects.
implibextension ("ext")
By default, the toolset static library file extension will be used (.lib with Windows tools, .a with GNU tools). The implibextension function allows you to change this default.
Solutions, projects, and configurations.
ext is the new file extension, including the leading dot.
implibname
implibdir
implibprefix
implibsuffix
implibextension ".mpi"The implibname function specifies the import library base file name. Import libraries are generated for Windows DLL projects.
implibname ("name")
By default, the target name will be used as the import library file name. The implibname function allows you to change this default.
Solutions, projects, and configurations.
name is the new base file name.
implibdir
implibextension
implibprefix
implibsuffix
implibname "mytarget"The implibprefix function specifies the import library file name prefix. Import libraries are generated for Windows DLL projects.
implibprefix ("prefix")
By default, the system naming convention will be used: no prefix on Windows, a prefix of "lib" (as in libMyProject.a) on other systems. The implibprefix function allows you to change this default.
Solutions, projects, and configurations.
prefix is the new file name prefix.
implibname
implibdir
implibextension
implibsuffix
implibprefix "plugin"The prefix may also be set to an empty string for no prefix.
implibprefix ""The implibsuffix function specifies a file name suffix for the import library base file name. Import libraries are generated for Windows DLL projects.
implibsuffix ("suffix")
Solutions, projects, and configurations.
suffix is the new filename suffix.
implibname
implibdir
implibprefix
implibextension
-- Add "-d" to debug versions of files configuration "Debug" implibsuffix "-d"
The include function looks for a file named premake4.lua in a specified directory, and includes it in the current script.
include "directory"This is equivalent to:
dofile "directory/premake4.lua"
This allows you to specify each project in its own premake4.lua file, and then easily include them into a solution, or multiple solutions.
directory is the path to the included directory, relative to the currently executing script file. The directory must contain a premake4.lua file, or an error will occur. If you wish to call a file other than premake4.lua, use the dofile function instead.
Any values returned by the included script are passed through to the caller.
-- runs "src/MyApplication/premake4.lua" include "src/MyApplication" -- runs "src/MyLibrary/premake4.lua" include "src/MyLibrary"
The includedirs function specifies the include file search paths.
includedirs { "paths" }
If a project includes multiple calls to includedirs the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
paths specifies a list of include file search directories. Paths should be specified relative to the currently running script file.
Define two include file search paths.
includedirs { "../lua/include", "../zlib" }
You can also use wildcards to match multiple directories. The * will match against a single directory, ** will recurse into subdirectories as well.
includedirs { "../includes/**" }
The kind function sets the kind of binary object being created by the project, such as a console or windowed application, or a shared or static library.
kind ("kind")
Solutions, projects, and configurations.
kind is the project kind identifier, and must be one of:
Set the project to generate a console executable.
kind "ConsoleApp"Set the project to generate a shared library (DLL).
kind "SharedLib"You can also set different kinds for each configuration. This is not supported by Xcode.
solution "MySolution" configurations { "DebugLib", "ReleaseLib", "DebugDLL", "ReleaseDLL" } project "MyProject" configuration "*Lib" kind "StaticLib" configuration "*DLL" kind "SharedLib"
The language function sets the programming language used by a project.
language ("lang")
Premake currently supports C, C++, and C#. Not all languages are supported by all of the generators; for instance, SharpDevelop does not (currently) support C or C++ development, and Code::Blocks does not support the .NET languages (C#, Managed C++).
Solutions and projects.
lang is the language identifier. This is a string value, set to one of C, C++, or C#. The value is not case sensitive.
Set the project language to C++.
language "C++"Set the project language to C#
language "C#"The libdirs function specifies the library search paths.
libdirs { "paths" }
Library search directories are not well supported by the .NET tools. Visual Studio will change relative paths to absolute, making it difficult to share the generated project. MonoDevelop and SharpDevelop do not support search directories at all, using only the GAC. In general, it is better to include the full (relative) path to the assembly in links instead. C/C++ projects do not have this limitation.
If a project includes multiple calls to libdirs the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
paths specifies a list of library search directories. Paths should be specified relative to the currently running script file.
Define two library file search paths.
libdirs { "../lua/libs", "../zlib" }
You can also use wildcards to match multiple directories. The * will match against a single directory, ** will recurse into subdirectories as well.
libdirs { "../libs/**" }
The linkoptions function passes arguments directly to the linker command line without translation.
linkoptions { "options" }
If a project includes multiple calls to linkoptions the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
options is a list of linker flags and options, specific to a particular linker.
Use pkg-config style configuration when building on Linux with GCC. Build options are always linker specific and should be targeted to a particular toolset.
configuration { "linux", "gmake" } linkoptions { "`wx-config --libs`" }
The links function specifies a list of libraries and projects to link against.
links { "references" }
If a project includes multiple calls to links the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
references is a list of library and project names.
When linking against another project in the same solution, specify the project name here, rather than the library name. Premake will figure out the correct library to link against for the current configuration, and will also create a dependency between the projects to ensure a proper build order.
When linking against system libraries, do not include any prefix or file extension. Premake will use the appropriate naming conventions for the current platform.
Link against some system libraries.
configuration "windows" links { "user32", "gdi32" } configuration "linux" links { "m", "png" } configuration "macosx" -- OS X frameworks need the extension to be handled properly links { "Cocoa.framework", "png" }
In a solution with two projects, link the library into the executable. Note that the project name is used to specify the link; Premake will automatically figure out the correct library file name and directory and create a project dependency.
solution "MySolution" configurations { "Debug", "Release" } language "C++" project "MyExecutable" kind "ConsoleApp" files "**.cpp" links { "MyLibrary" } project "MyLibrary" kind "SharedLib" files "**.cpp"
You may also create links between non-library projects. In this case, Premake will generate a build dependency (the linked project will build first), but not an actual link. In this example, MyProject uses a build dependency to ensure that MyTool gets built first. It then uses MyTool as part of its build process.
solution "MySolution" configurations { "Debug", "Release" } language "C++" project "MyProject" kind "ConsoleApp" files "**.cpp" links { "MyTool" } prebuildcommands { "MyTool --dosomething" } project "MyTool" kind "ConsoleApp" files "**.cpp"
The location function sets the destination directory for a generated solution or project file.
location ("path")
By default, solution and project files are generated into the same directory as the script that defines them. The location function allows you to change this location.
Solutions and projects.
path is the directory where the generated files should be stored, specified relative to the currently executing script file.
Set the destination directory for a solution. Setting the location for a project works the same way.
solution "MySolution" location "../build"
If you plan to build with multiple tools from the same source tree you might want to split up the project files by toolset. The _ACTION global variable contains the current toolset identifier, as specified on the command line. Note that Lua syntax requires parenthesis around the function parameters in this case.
location ("../build/" .. _ACTION)
The newaction function registers a new command-line action argument. For more information, see Command Line Arguments.
newaction (description)
description is a table describing the new action. It may contain the following fields:
Register a new action to install the software project.
newaction { trigger = "install", description = "Install the software", execute = function () os.copyfile("bin/debug/myprogram", "/usr/local/bin/myprogram") end }
The newoption function registers a new command-line option argument. For more information, see Command Line Arguments.
newoption (description)
description is a table describing the new option. It may contain the following fields:
Register a new option to select a rendering API for a 3D application.
newoption { trigger = "gfxapi", value = "API", description = "Choose a particular 3D API for rendering", allowed = { { "opengl", "OpenGL" }, { "direct3d", "Direct3D (Windows only)" }, { "software", "Software Renderer" } } }
The objdir function sets object and intermediate file directory for a project.
objdir ("path")
By default, object and intermediate files are stored in a directory named "obj" in the same directory as the project. The objdir function allows you to change this location.
Solutions, projects, and configurations.
path is the directory where the object and intermediate files should be stored, specified relative to the currently executing script file.
Set an object directory for a project.
project "MyProject" objdir "objects"
Set object directories per configuration.
configuration "Debug" objdir "../obj_debug" configuration "Release" objdir "../obj_release"
The os.chdir function changes the current working directory.
os.chdir("path")
path is the file system path to the new working directory.
True if successful, otherwise nil and an error message.
The os.copyfile function copies a file from one location to another.
os.copyfile("source", "destination")
Source is the file system path to the file to be copied. Destination is the path to the copy location.
True if successful, otherwise nil and an error message.
The os.findlib function scans the well-known system locations looking for a library file.
p = os.findlib("libname")
libname is name of the library to locate. It may be specified with (libX11.so) or without (X11) system-specific decorations.
The path containing the library file, if found. Otherwise, nil.
The os.get function identifies the currently targeted operating system.
id = os.get()
None.
An operating system identifier, one of bsd, linux, macosx, solaris, or windows.
if os.get() == "windows" then -- do something Windows-specific end
The os.getcwd function gets the current working directory.
cwd = os.getcwd()
None.
The current working directory.
Retrieve version information for the host operating system.
os.getversion()
Introduced in Premake 4.4, this function has not yet been implemented for all platforms. On platforms where this has not been implemented, it will return zero for all version numbers, and the platform name as the description.
A table, containing the following key-value pairs:
| majorversion | The major version number |
|---|---|
| minorversion | The minor version number |
| revision | The bug fix release or service pack number |
| description | A human-readable description of the OS version |
local ver = os.getversion() print(string.format(" %d.%d.%d (%s)", ver.majorversion, ver.minorversion, ver.revision, ver.description)) -- On Windows XP: "5.1.3 (Windows XP)" -- On OS X,: "10.6.6 (Mac OS X Snow Leopard)"
The os.is function checks the current operating system identifier against a particular value.
os.is("id")
id is one of the operating system identifiers bsd, linux, macosx, solaris, or windows.
True if the supplied ID matches the current operating system identifier, false otherwise.
The os.is64bit function determines if the host is using a 64-bit processor.
os.is64bit()
Introduced in Premake 4.4.
True if the host system has a 64-bit processor, false otherwise.
if os.is64bit() then print("This is a 64-bit system") else print("This is NOT a 64-bit system") end
The os.isdir function checks for the existence of directory.
os.isdir("path")
Path is the file system path to check.
True if a matching directory is found; false is there is no such file system path, or if the path points to a file instead of a directory.
The os.isfile function checks for the existence of file.
os.isfile("path")
Path is the file system path to check.
True if a matching file is found; false is there is no such file system path, or if the path points to a directory instead of a file.
The os.matchdirs function performs a wildcard match to locate one or more directories.
matches = os.matchdirs("pattern")
patterm is the file system path to search. It may contain single (non-recursive) or double (recursive) asterisk wildcard patterns.
A list of directories which match the specified pattern. May be empty.
matches = os.matchdirs("src/*") -- non-recursive match matches = os.matchdirs("src/**") -- recursive match matches = os.matchdirs("src/test*") -- may also match partial names
The os.matchdirs function performs a wildcard match to locate one or more directories.
matches = os.matchfiles("pattern")
patterm is the file system path to search. It may contain single (non-recursive) or double (recursive) asterisk wildcard patterns.
A list of files which match the specified pattern. May be empty.
matches = os.matchfiles("src/*.c") -- non-recursive match matches = os.matchfiles("src/**.c") -- recursive match
The os.mkdir function creates a new directory.
os.mkdir("path")
Path is the file system path to be created.
True if successful, otherwise nil and an error message.
The os.outputof function runs a shell command and returns the output.
result = os.outputof("command")
command is a shell command to run.
The output of the command.
-- Get the ID for the host processor architecture local proc = os.outputof("uname -p")
The os.pathsearch function searches a collection of paths for a particular file.
p = os.pathsearch("fname", "path1", ...)
fname is the name of the file being searched. This is followed by one or more path sets to be searched.
Path sets match the format of the PATH environment variable: a colon-delimited list of paths. On Windows, you may use a semicolon-delimited list if drive letters might be included.
The path to the directory which contains the file, if found. Otherwise, nil.
local p = os.pathsearch("mysystem.config", "./config:/usr/local/etc:/etc")
The os.rmdir function removes an existing directory as well as any files or subdirectories it contains.
os.rmdir("path")
path is the file system path to be removed.
True if successful, otherwise nil and an error message.
The os.stat function retrieves information about a file.
info = os.stat("path")
Added in Premake 4.4.
path is the filesystem path to file for which to retrieve information.
A table of values:
The os.uuid function returns a Universally Unique Identifier.
id = os.uuid()
None.
A new UUID, a string value with the format 74CFC033-FA4D-4B1E-A871-7DC48FA36769.
The path.getabsolute function converts a relative path an absolute path.
p = path.getabsolute("path")
path is the relative path to be converted. It does need to actually exist on the file system.
A new absolute path, calculated from the current working directory.
The path.getbasename function returns the base file portion of a path, with the directory and file extension removed.
p = path.getbasename("path")
path is the file system path to be split.
The base name portion of the supplied path, with any directory and file extension removed.
The path.getdirectory function returns the directory portion of a path, with any file name removed.
p = path.getdirectory("path")
path is the file system path to be split.
The directory portion of the path, with any file name removed. If the path does not include any directory information, the "." (single dot) current directory is returned.
The path.getdrive function returns the drive letter portion of a path, if present.
p = path.getdrive("path")
path is the file system path to be split.
The drive letter portion of the path, if one is specified. Otherwise, nil.
The path.getextension function returns the file extension portion of a path.
p = path.getextension("path")
path is the file system path to be split.
The file extension portion of the path, or an empty string if no extension is present.
The path.getname function returns the file name and extension, with any directory information removed.
p = path.getname("path")
path is the file system path to be split.
The file name and extension, with no directory information.
The path.getrelative function computes a relative path from one directory to another.
p = path.getrelative("src", "dest")
src is the originating directory, dest is the target directory. Both may be specified as absolute or relative.
A relative path from src to dest.
The path.isabsolute function returns true if the specified path is an absolute path.
path.isabsolute("path")
path is the file system path to check.
True if the specified path is absolute, false otherwise.
The path.iscfile function returns true if the specified path represents a C source code file, based on its file extension.
path.iscfile("path")
path is the file system path to check.
True if the path matches a well-known C file extension, false otherwise.
The path.iscppfile function returns true if the specified path represents a C++ source code file, based on its file extension.
path.iscppfile("path")
path is the file system path to check.
True if the path matches a well-known C++ file extension, false otherwise.
The path.isresourcefile function returns true if the specified path represents a Windows resource file, based on its file extension.
path.isresourcefile("path")
path is the file system path to check.
True if the path matches a well-known Windows resource file extension, false otherwise.
The path.join function joins two path portions together into a single path.
path.join("leading", "trailing")
If trailing is an absolute path, then the leading portion is ignored, and the absolute path is returned instead (see below for examples).
leading is the beginning portion of the path; trailing is the ending portion.
A merged path.
-- returns "MySolution/MyProject" p = path.join("MySolution", "MyProject") -- returns "/usr/bin", because the trailing path is absolute p = path.join("MySolution", "/usr/bin") -- tokens are assumed to be absolute; this returns "$(ProjectDir)" p = path.join("MySolution", "$(ProjectDir)")
The path.rebase function takes a relative path and makes it relative to a different location.
path.rebase("path", "oldbase", "newbase")
path is the relative path to conver. oldbase is the original base directory, from with path is relative. newbase is the new base directory, from where the resulting path should be relative.
The rebased path.
The path.translate function converts the file separators in a path.
path.translate("path", "newsep")
path is the file system path to translate. newsep is the new path separator.
If newsep is nil, the native path separator for the current environment will be used.
The translated path.
The pchheader function sets the main header file for precompiled header support.
pchheader "file"If no header file is set, the toolset default settings will be used.
Projects only.
file is the name of the header file, as it is specified in your source file #include statements.
pchheader "afxwin.h" pchsource "afxwin.cpp"
The pchsource function sets the main source file for precompiled header support. This is only used by Visual Studio.
pchsource "file"If no source file is set, the toolset default settings will be used.
Projects only.
file is the name of the source file, specified relative to the currently executing script file.
pchheader "afxwin.h" pchsource "afxwin.cpp"
Platform support is a new, experimental feature which will be introduced in Premake 4.1. The syntax and behavior described here might change as we sort out the details.
The platforms function specifies a set of target hardware platforms for a solution. This is an optional setting; if it is not provided the toolset's default behavior will be used.
platforms { "identifiers" }
Please see the Platforms section of the user guide for a lot more information on platforms and how they are used by Premake.
Solutions only.
identifiers is a list of hardware platform identifiers, and may include any of the following.
Not all platforms are supported on all systems, unsupported platforms will be silently ignored. Some targets require extra configuration of the build tools on the client machine in order to support cross-compilation.
The function returns the current list of target platforms for the active solution.
Provide a generic build that will work anywhere, as well as a Mac OS X Universal build.
solution "MySolution" configurations { "Debug", "Release" } platforms { "native", "universal" }
Provide 32- and 64-bit specific build targets. No generic build is provided, so one of these two platforms must always be used. Do this only if your software requires knowledge of the underlying architecture at build time, otherwise include "native" to provide a generic build.
solution "MySolution" configurations { "Debug", "Release" } platforms { "x32", "x64" }
You can retrieve the current list of platforms by calling the function with no parameters.
local p = platforms()
Once you have defined a list of platforms, you may use those identifiers to set up configuration filters and apply platform-specific settings.
configuration "x64" defines "IS_64BIT" -- You can also mix platforms with other configuration selectors configuration { "Debug", "x64" } defines "IS_64BIT_DEBUG"
The postbuildcommands function specifies shell commands to run after build is finished.
postbuildcommands { "commands" }
Solutions, projects, and configurations.
commands is one or more shell commands. These commands will be passed to the shell exactly as entered, including path separators and the like.
prebuildcommands
prelinkcommands
configuration "windows" postbuildcommands { "copy default.config bin\\project.config" } configuration "not windows" postbuildcommands { "cp default.config bin/project.config" }
The prebuildcommands function specifies shell commands to run before each build.
prebuildcommands { "commands" }
Solutions, projects, and configurations.
commands is one or more shell commands. These commands will be passed to the shell exactly as entered, including path separators and the like.
prelinkcommands
postbuildcommands
configuration "windows" prebuildcommands { "copy default.config bin\\project.config" } configuration "not windows" prebuildcommands { "cp default.config bin/project.config" }
The prelinkcommands function specifies shell commands to run after the source files have been compiled, but before the link step.
prelinkcommands { "commands" }
Solutions, projects, and configurations.
commands is one or more shell commands. These commands will be passed to the shell exactly as entered, including path separators and the like.
prebuildcommands
postbuildcommands
configuration "windows" prelinkcommands { "copy default.config bin\\project.config" } configuration "not windows" prelinkcommands { "cp default.config bin/project.config" }
The printf performs like its C counterpart, printing a formatted string.
printf("format", ...)
It is equivalent to this Lua code:
print(string.format(format, unpack(arg))
format is a formatting string containing C printf() style formatting codes. It is followed by a list of arguments to be substituted into the format string.
None.
The project function creates a new project and makes it active.
project ("name")
Projects contain all of the settings necessary to build a single binary target, and are synonymous with a Visual Studio project. These settings include the list of source code files, the programming language used by those files, compiler flags, include directories, and which libraries to link against.
Every project belongs to a solution.
name is a unique name for the project. If a project with the given name already exists, it is made active and returned. The project name will be used as the file name of the generated solution file.
The function returns the active project object; see The Project Object below for more information on the structure of this object.
Create a new project named "MyProject". Note that a solution must exist to contain the project. The indentation is for readability and is optional.
solution "MySolution" configuration { "Debug", "Release" } project "MyProject"
You can retrieve the currently active project object by calling project with no parameters.
local prj = project()
You can retrieve the list of projects associated with a solution using the projects field on the solution object, which may then be iterated over.
local prjs = solution().projects for i, prj in ipairs(prjs) do print(prj.name) end
Each project is represented in Lua as a table of key-value pairs. Unless you really know what you are doing, you should treat this object as read-only, and use the Premake API to make any changes.
The project object contains the following values.
The resdefines function specifies preprocessor symbols for the resource compiler.
resdefines { "symbols" }
If a project includes multiple calls to resdefines the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
symbols specifies a list of symbols to be defined.
Define two new symbols in the current project.
resdefines { "DEBUG", "TRACE" }
Symbols may also assign values.
resdefines { "CALLSPEC=__dllexport" }
The resincludedirs function specifies the include file search paths for the resource compiler.
resincludedirs { "paths" }
If a project includes multiple calls to resincludedirs the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, and configurations.
paths specifies a list of include file search directories. Paths should be specified relative to the currently running script file.
Define two include file search paths.
resincludedirs { "../lua/include", "../zlib" }
You can also use wildcards to match multiple directories. The * will match against a single directory, ** will recurse into subdirectories as well.
resincludedirs { "../includes/**" }
The resoptions function passes arguments directly to the resource compiler command line without translation.
resoptions { "options" }
If a project includes multiple calls to resoptions the lists are concatenated, in the order in which they appear in the script.
Solutions, projects, configurations
options is a list of resource compiler flags and options, specific to a particular compiler.
Use pkg-config style configuration when building on Linux with GCC. Build options are always compiler specific and should be targeted to a particular toolset.
configuration { "linux", "gmake" } resoptions { "`wx-config --cxxflags`", "-ansi", "-pedantic" }
The solution function creates a new solution and makes it active.
solution ("name")
Solutions are the top-level objects in a Premake build script, and are synonymous with a Visual Studio solution. Each solution contains one or more projects, which it turn contain the settings to generate a single binary target.
name is a unique name for the solution. If a solution with the given name already exists, it is made active and returned. The solution name will be used as the file name of the generated solution file.
The function returns the active solution object; see The Solution Object below for more information on the structure of this object.
Create a new solution named "MySolution".
solution "MySolution"You can retrieve the currently active solution object by calling solution with no parameters.
local sln = solution()
You can the global variable _SOLUTIONS to list out all of the currently defined solutions.
for i, sln in ipairs(_SOLUTIONS) do print(sln.name) end
Each solution is represented in Lua as a table of key-value pairs. Unless you really know what you are doing, you should treat this object as read-only, and use the Premake API to make any changes.
The solution object contains the following values.
The string.endswith function returns true if the given string ends with the provided sequence.
string.endswith("haystack", "needle")
haystack is the string to check. needle is the ending sequence to check against.
True if haystack ends with needle.
The string.explode function returns an array of strings, each of which is a substring of s formed by splitting on boundaries formed by pattern.
string.explode("str", "pattern")
str is the string to be split. pattern is the separator pattern at which to split; it may use Lua's pattern matching syntax.
A list of substrings.
The string.findlast function finds the last instance of a pattern within a string.
string.endswith("str", "pattern", plain)
str is the string to be searched. pattern is the pattern to search for; it may use Lua's pattern matching syntax. If plain is true, no pattern matching will be performed (faster).
The matching pattern, if found, or nil if there were no matches.
The string.startswith function returns true if the given string starts with the provided sequence.
string.startswith("haystack", "needle")
haystack is the string to check. needle is the starting sequence to check against.
True if haystack starts with needle.
The table.contains function determines if an array contains a particular value.
table.contains(arr, value)
arr is the array to test; value is the value being tested for.
True if the array contains the value, false otherwise.
The table.implode function merges an array of items into a single, formatted string.
table.implode(arr, "before", "after", "between")
arr is the array to be converted into a string. before is a string to be inserted before each item. after is a string to be inserted after each item. between is a string to be inserted between items.
The formatted string.
The targetdir function sets the destination directory for the compiled binary target.
targetdir ("path")
By default, the generated project files will place their compiled output in the same directory as the script. The targetdir function allows you to change this location.
Solutions, projects, and configurations.
path is the file system path to the directory where the compiled target file should be stored. It is specified relative to the currently executing script file.
targetname
targetextension
targetprefix
This project separates its compiled output by configuration type.
project "MyProject" configuration "Debug" targetdir "bin/debug" configuration "Release" targetdir "bin/release"
The targetextension function specifies the file extension for the compiled binary target.
targetextension ("ext")
By default, the project will use the system's normal naming conventions: .exe for Windows executables, .so for Linux shared libraries, and so on. The targetextension function allows you to change this default.
Solutions, projects, and configurations.
ext is the new file extension, including the leading dot.
targetname
targetdir
targetprefix
targetsuffix
targetextension ".zmf"The targetname function specifies the base file name for the compiled binary target.
targetname ("name")
By default, the project name will be used as the file name of the compiled binary target. A Windows executable project named "MyProject" will produce a binary named MyProject.exe. The targetname function allows you to change this default.
Solutions, projects, and configurations.
name is the new base file name.
targetdir
targetextension
targetprefix
targetsuffix
targetname "mytarget"The targetprefix function specifies the file name prefix for the compiled binary target.
targetprefix ("prefix")
By default, the system naming convention will be used: a "lib" prefix for POSIX libraries (as in libMyProject.so), and no prefix elsewhere. The targetprefix function allows you to change this default.
Solutions, projects, and configurations.
prefix is the new file name prefix.
targetname
targetdir
targetextension
targetsuffix
targetprefix "plugin"The prefix may also be set to an empty string for no prefix.
targetprefix ""The targetsuffix function specifies a file name suffix for the compiled binary target.
targetsuffix ("suffix")
Solutions, projects, and configurations.
suffix is the new filename suffix.
targetname
targetdir
targetprefix
targetextension
-- Add "-d" to debug versions of files configuration "Debug" targetsuffix "-d"
The uuid function sets the Universally Unique Identifier (UUID) for a project.
uuid ("project_uuid")
UUIDs are synonymous (for Premake's purposes) with Globally Unique Identifiers (GUID).
Premake automatically assigns a UUID to each project, which is used by the Visual Studio generators to identify the project within a solution. This UUID is essentially random and will change each time the project file is generated. If you are storing the generated Visual Studio project files in a version control system, this will create a lot of unnecessary deltas. Using the uuid function, you can assign a fixed UUID to each project which never changes, removing the randomness from the generated projects.
Projects only.
project_uuid is the UUID for the current project. It should take the form "01234567-ABCD-ABCD-ABCD-0123456789AB" (see the examples below for some real UUID values). You can use the Visual Studio guidgen tool to create new UUIDs, or this website, or run Premake once to generate Visual Studio files and copy the assigned UUIDs.
The current project UUID, or nil if no UUID has been set.
Set the UUID for a current project.
uuid "BE2461B7-236F-4278-81D3-F0D476F9A4C0"The vpaths function places files into groups or "virtual paths", rather than the default behavior of mirroring the filesystem in IDE-based projects. So you could, for instance, put all header files in a group called "Headers", no matter where they appeared in the source tree.
vpaths { ["group"] = "pattern(s)" }
Note that Lua tables do not maintain any ordering between key-value pairs, so there is no precedence between the supplied rules. That is, you can't write a rule that rewrites the results of an earlier rule, since there is no guarantee in which order the rules will run.
Added in Premake 4.4.
Virtual paths, like files, may be set on the solution, project, and configuration level. However, only project-level file lists are currently supported.
A list of key/value pairs, specified with Lua's standard syntax, which map file patterns to the group in which they should appear. See the examples below for a more complete explanation.
Place all header files into a virtual path called "Headers". Any directory information is removed, so a path such as src/lua/lua.h will appear in the IDE as Headers/lua.h.
vpaths { ["Headers"] = "**.h" }
You may also specify multiple file patterns using the table syntax.
vpaths { ["Headers"] = { "**.h", "**.hxx", "**.hpp" } }
It is also possible to include the file's path in the virtual group. Using the same example as above, this rule will appear in the IDE as Headers/src/lua/lua.h.
vpaths { ["Headers/*"] = "**.h" }
Any directory information explicitly provided in the pattern will be removed from the replacement. This rule will appear in the IDE as Headers/lua/lua.h.
vpaths { ["Headers/*"] = "src/**.h" }
You can also use virtual paths to remove extra directories from the IDE. For instance, this rule will cause the previous example to appear as lua/lua.h, removing the src part of the path from all files.
vpaths { [""] = "src" }
And of course, you can specify more than one rule at a time.
vpaths { ["Headers"] = "**.h", ["Sources/*"] = {"**.c", "**.cpp"}, ["Docs"] = "**.txt" }
A collection of how-to articles on extending and improving Premake. These are intended for folks who want to add new actions or API functions to Premake. If you just want to script your projects, have a look at Scripting with Premake instead.
This section is very much a work in progress, which I hope to gradually build up over time.
Some things you should know before you digging into the Premake internals, in no particular order:
Before you begin, you should be able to build and run the debug configuration of Premake. This will save you the trouble of embedding the scripts and recompiling with each change, and will greatly speed up development.
When you have completed your changes and are ready to roll them out, note that you must run premake4 embed and recompile in order to see your changes in the release build of Premake. Debug builds load the scripts dynamically at startup and so can skip this step.
Premake knows which scripts to load and run by reading the file src/_manifest.lua. Any new script file you create must be listed in the manifest if you want it to run. This is a common mistake; I still make it myself every once in a while.
The command premake4 embed copies all of the scripts listed in the manifest into static C buffers in the file src/host/scripts.c, which then gets compiled into the final executable. This is how I can ship a single binary, rather than the whole source tree.
There is a fairly comprehensive set of automated tests in the tests/ folder. Create a debug build of Premake and then, in this tests directory, run the command:
../bin/debug/premake4 test
Or, if you're in a POSIX environment, run the ./test shell script. I am using my own homegrown testing framework, which is defined in tests/testfx.lua. You can add new test files in tests/premake4.lua.
Lua allows the creation of namespaces (of a sort) by putting your functions into a table. This example creates a function bar in the namespace premake.foo.
premake.foo = { } function premake.foo.bar() -- do something useful end
I have begun moving all of Premake's internals into the premake namespace, but it is a work in progress.
Finally, post any questions you might have over in the forums and I will be delighted (yes, delighted) to help you out. Your questions will help me improve this documentation and Premake itself and are very much appreciated.
An action is what gets triggered when you run Premake; the command premake4 vs2008 triggers the Visual Studio 2008 action, while premake4 clean triggers the clean action.
I created an example action, available in the source code packages at src/actions/example, to help you get started. This example writes out simple "solution" and "project" files, showing how to get out the project information using the Premake APIs. The tutorial below will show you how to use these example files to get started on your own actions.
If you have any questions, ask them over in the forums and I'll try to help you out.
I keep all of the actions in src/actions, so create a new folder there with an appropriate name. Look at the other folders at that location, you'll get the idea.
Copy the files from src/actions/example to your new folder and rename them appropriately. The leading underscore on _example.lua is optional; it is a convention I use to indicate which file contains the action description (more on that below). The underscore sorts this file to the top of the list making it easy to locate. Files without the leading underscore contain the actual implementation of the action.
I'll continue to use the original file names (like _example.lua) through this explanation. Substitute in your new names.
Add your new files (and any others you create later) to the script manifest at src/_manifest.lua.
-- The master list of built-in scripts. Order is important! If you want to -- build a new script into Premake, add it to this list. return { -- core files "base/os.lua", "base/path.lua", "...and so on...", -- Clean action "actions/clean/_clean.lua", -- Your new action goes here "actions/example/_example.lua", "actions/example/example_solution.lua", "actions/example/example_project.lua", }
Order matters a little here: _example.lua defines the namespace for the action and must appear first. See the comments in that file for more information.
I've loaded up the example files, particularly the action description, to help you make sense of them. Rather than repeating all of that here, I'll just let you go browse through the files and start plugging in the code for your own actions.
If you get stuck, if something isn't clear, or you want to see a demonstration of something that isn't covered by the example drop a note in the forums and I'll try to help you out.