Tundra is a code build system that tries to be accurate and fast for incremental builds


Build Status

Tundra, a build system

Tundra is a high-performance code build system designed to give the best possible incremental build times even for very large software projects.

Tundra is portable and works on

  • macOS
  • Linux
  • FreeBSD
  • Windows (XP or later - binary releases require Vista/64 or later - for XP support build from source using MinGW.)

Porting to UNIX-like platforms will be very easy, porting to other platforms will take a little bit of work in a few well-defined places.

See doc/manual.asciidoc for more detailed usage information.

There is a companion Visual Studio 2012 addin that might be useful. See https://github.com/deplinenoise/tundra-vsplugin for details.


Windows installers are available for download in the releases tab.

macOS package is available via Homebrew: brew install tundra

License and Copyright

Tundra is Copyright 2010-2018 Andreas Fredriksson.

Tundra is made available under the MIT license. See the file COPYING for the complete license text. (Tundra was previously made available under the GPL license, but this hindered commercial adoption and all contributors agreed to change the license to MIT.)

Tundra uses Lua. See below for Lua's licensing terms.

Tundra includes a public domain Lua Debugger, see below.


Copyright (c) 1994-2008 Lua.org, PUC-Rio. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


Lua Debugger

Tundra includes an optional Lua CLI debugger which is public domain software written by Dave Nichols.

The debugger was obtained from luaforge.net.

  • Rust support

    Rust support


    I would like to add Rust support to tundra but I'm not sure how to go about it. Just adding support for compiling rust files as is very easy as it's just a regular compiler.

    The thing is that Rust has it's own build/package manager called Cargo and some info can be found about it here: http://doc.crates.io/guide.html

    The way it works is that you set up a project according to some rules and allows you to depend on packages that can be downloaded when you build and such which is very convenient.

    The best way I see it would be if it would be possible to start "cargo build" for a given rust project within tundra and have tundra then link with the output in the cargo output folder (in cargo's case it ends up like target/debug/foo)

    Reading the FAQ on cargo it also states this:

    Can Cargo be used inside of make (or ninja, or ...)

    Indeed. While we intend Cargo to be useful as a standalone way to compile Rust projects at the top-level, we know that some people will want to invoke Cargo from other build tools.

    We have designed Cargo to work well in those contexts, paying attention to things like error codes and machine-readable output modes. We still have some work to do on those fronts, but using Cargo in the context of conventional scripts is something we designed for from the beginning and will continue to prioritize.


    So I feel it should be possible to allow a nice integration into Tundra but I'm unsure of how to do it.

    opened by emoon 20
  • Temporary files are getting cleaned out by tundra quicker than the tools can access them

    Temporary files are getting cleaned out by tundra quicker than the tools can access them

    I get a fair deal of this warnings, they never really seem to make a difference but they do make me wonder, is tundra cleaning up these temp files faster than the linker manage to access them or what's going on? I tried accessing the files post-build but the file did not exist. I'm a bit lost as to how approach this problem but I wanted to put up an issue about it. I'll add more info about this as I find out more about the issue.

    LINK : fatal error LNK1104: cannot open file `C:\Users\...\AppData\Local\Temp\tunFF72.tmp`
    opened by leidegre 15
  • Relicensing tundra under MIT license

    Relicensing tundra under MIT license


    In order to make it easier for tundra to be adopted, I'd like to investigate the possibility of relicensing tundra under the MIT license, so that people writing other frontends for tundra do not have to worry about the GPL requirements travelling to the frontend code.

    I've talked with @deplinenoise about it, and he supports the idea if I do the legwork of chasing down all contributors.

    This issue does that. My question to all people that have landed a PR into the tundra repo: Would you be willing to license the code you've contributed under the MIT license, so that we can make the entire repo MIT. I hope you will, tundra is an amazing build system and I'd love to be able to use it everywhere. If you do, simply replying on this issue with "I license all my contributions in the tundra repository under the MIT license" would suffice.

    Thanks, Lucas

    @leidegre @jsvennevid @jonaskje @jwtowner @uucidl @rudkx @emoon @bmharper @greatwolf @teddemunnik @mattrudder @Patuti @twoscomplement @aras-p

    opened by lucasmeijer 13
  • VS2017 C++ compiler toolset support

    VS2017 C++ compiler toolset support

    So I opted to use the vswhere tool to locate various VS 2017 installations that match certain criterias (i.e. has Visual C++ tooling). However, I've made it optional, if you specify an installation path manually it will use that instead. I found documentation regarding the usage of vswhere and have included it here.

    This is incomplete but I wanted feedback from @deplinenoise or @kayru whether you think the direction is fine.

    Also, trying to get rid of as much cruft as possible this time. Again, this is incomplete but it gets the compiler running.

    opened by leidegre 11
  • Windows XP 32-bit is not supported.

    Windows XP 32-bit is not supported.

    When running tundra from the command line, the following text is printed:

    couldn't resolve symbol InitializeConditionVariable in kernel32.dll; your windows version is not supported

    opened by petmac 11
  • Dynamic to static link

    Dynamic to static link

    Perhaps I'm just overlooking something, but how do change an ExternalLibrary that dynamically links against a .dylib (OS X) to to something that statically links agains the corresponding .a file of the same library?

    opened by PerMalmberg 10
  • Some interesting Tundra peformance numbers

    Some interesting Tundra peformance numbers

    I did some benchmarks on various build systems, Tundra included, and I'd thought I'd share my findings.

    The generated build scripts used for testing are based off Noel's Llopis' famous build scripts here.

    The environment used for testing is Win7 with an intel Q6600 quad core. Tundra 94d61aba71 built with mingw was used with optimizations enabled. Timing is measured in seconds. All build systems were performed using -j 6 parallel builds . The parameters used for script generation are: generate_libs.py root 50 100 20 5

                full build      incremental no-op   clean
    bam         100.334         0.595               1.826
    jam         120.955         1.275               0.288
    lake        106.891         63.835              47.018
    make        83.382          2.652               3.276
    make-dep    102.787         20.911              17.035
    ninja       79.248          0.686               1.575
    scons       139.074         38.641              30.825
    tundra      114.051         1.466               37.83 (*1.606)
    waf         88.124          3.088               1.638
    *ran with quiet(silent) option

    A full rebuild using tundra isn't as fast as I thought but the incremental rebuild is pretty fast. The clean operation is interesting. When used without the quiet option, clean takes 37 seconds to complete. But when ran with the silent switch where nothing gets printed, it completes in under 2 seconds.

    Note a lot of the build systems doesn't perform proper dependency checking with headers. Of the above only the following does: tundra, waf, ninja, make-dep.

    mingw32-make version 3.82.90 with parallel job support under windows was used. Note that make is done without header dep checking while make-dep has proper header dependency -- the same tool is used in both cases. It's interesting how gnu make slows down a lot when header dependency comes into the picture. I suspect file io might be the culprit.

    The bench scripts + modifications I've used can be found here.

    Thoughts and comments?

    opened by greatwolf 10
  • Tundra doesn't respect 260 path limit on windows

    Tundra doesn't respect 260 path limit on windows

    If you use relative pathes in tundra.lua it's easy to end up in situation when absolute path to obj file is longer than 260 characters. In this case tundra doesn't complain until linker stage, when linking fails because linker cannot access that object file.

    I can't find obvious workaround for this ... it's probably override function that generate path to obj files.

    opened by jimon 9
  • tundra2 breaks

    tundra2 breaks "Error List" in Visual Studio

    When building inside Visual Studio 2012 with tundra2, the IDE does not add warnings and errors to its "Error List" tab. The IDE manages to comprehend the output messages to some degree, since one can navigate the "Output" tab using Prev/Next buttons, but these items don't end up in the Error List tab. I have made sure that my Error List is not filtered at all.

    I'm busy trying to figure out what could cause this. So far the only significant difference I can see is that tundra2 emits the full source file path in the build output, whereas tundra1 emits only the relative path.

    opened by bmharper 9
  • (2.0) Figure out how to distribute and install

    (2.0) Figure out how to distribute and install

    There's VS2012 projects and a simple Makefile for the building.

    But how to make an installable package now that Lua files are not embedded and there are other executables that need to be installed as well?

    Might need a make install option that does mostly the right thing on Unix, and some sort of MSI builder for Windows.

    opened by deplinenoise 9
  • question: how to build lib standalone and as part of bigger project

    question: how to build lib standalone and as part of bigger project

    Hi, sorry to open an issue for my question.

    I have a library (with example programs) and build a standalone-version with tundra.lua and units.lua which compiles the lib and the examples in a directory. now I want to include the same repository, but as a subproject in a subfolder and include the units.lua in another tundra.lua, how can this be setup to be able to compile with the different base-directories?

    to get the idea, I have for the standalone-lib this structure: ~/sources/libA/tundra.lua <- this uses the units.lua in the same directory units.lua <- here all examples and the lib are references

    and another project: ~/sources/prgX/external_libs/libA/tundra.lua <- this one is not used in the project itself units.lua tundra.lua <- includes units.lua AND external_libs/libA/units.lua units.lua <- project-sources

    the question is: how can I set the basepath for the libA/units.lua, by setting somehow the sourcedir? (I could split the units.lua from the lib to include only the lib itself into the units.lua and let's say example.lua with the test-programs of the lib to separate the lib from the test-programs, but I still have the issue with the base-path). I could think of some way with a environment-variable you have to set as a build-base-path, but is there a better solution?

    and another (hopefully simple) question: often I have to repeat stuff like this: Env = { CPPPATH = { "include", "examples/common", .... } }, Propagate = { Env = { CPPPATH = { "include", "examples/common",

    so the propagated stuff is the same like the stuff for the lib/program itself, can this be somehow handled to write it only one time?

    for both questions here is the units.lua from the lib: https://github.com/questor/bgfx/blob/master/units.lua


    opened by questor 8
  • Added support for targets with ISPC

    Added support for targets with ISPC

    This PR adds support to specify different targets when using ISPC like this

    ISPC {
        Pass = "IspcGen",
        Source = "lanes.ispc",
        Targets = "sse4,avx2"

    When setting several targets to ISPC the compiler will generate one object file and one header for each target. The default function that one calls in this mode will do a run-time selection and call the appropriate one depending on instruction set the CPU supports. The user can chose to not use this function but instead calling function_name_<target> such as foobar_avx2 and do the detection themselves.

    Changes in this PR does a bunch of things

    • First we need to tell Tundra about the output files the compiler generates which is the meat of this change.
    • Targets is optional, so the user can chose to ignore it and use the old behavior if wanted, but to support more than on target then Targets parameter needs to be used.
    • Added Linux target to the ISPC example
    • Some minor cleanup
    • Added sse4,avx2 to the ISPC example
    opened by emoon 0
  • Precompiled headers get generated multiple times when using DefRule

    Precompiled headers get generated multiple times when using DefRule

    When adding a DefRule to my Sources list, precompiled headers seem to be created N times for each Variant declared, resulting in the same file being the output target and failing to build.

    The following tundra.lua demonstrates this using the latest v2.08 build:

    Build {
        Units = function()
            DefRule {
                Name = "ExampleGenerator",
                Pass = "ExamplePass",
                Command = "echo Building $(<) $(@) > $(@)",
                ConfigInvariant = false,
                Blueprint = {
                    Source = {Required = true, Type = "string", Help = "Input filename"},
                    OutName = {Required = true, Type = "string", Help = "Output filename"}
                Setup = function(env, data)
                    return {
                        InputFiles = {data.Source},
                        OutputFiles = {"$(OBJECTDIR)/_generated/" .. data.OutName}
            local App = Program
                Name = "App",
                PrecompiledHeader = {
                    Source = "stdafx.cpp",
                    Header = "stdafx.h",
                    Pass = "PchGen"
                Sources = {
                    ExampleGenerator {
                        Source = "example.txt",
                        OutName = "example.h"
        Passes = {
            ExamplePass = {Name = "Example Pass", BuildOrder = 1},
            PchGen = {Name = "Precompiled Header Generation", BuildOrder = 2}
        Configs = {
            Config {
                Name = "win32-msvc",
                SupportedHosts = {"windows"},
                DefaultOnHost = "windows",
                Tools = {
                    {"msvc-vs2017", TargetArch = "x86"}
        Variants = {"debug", "release", "production"}

    Logging the source_files var from x_source_list shows this clearly:

    Generating DAG for win32-msvc-release-default
    Source list
      [1] =     {
          DagCache= <nested table>
          __index= <nested table>
          Decl= <nested table>
      [2] = "stdafx.cpp",
    Generating DAG for win32-msvc-debug-default
    Source list
      [1] =     {
          DagCache= <nested table>
          __index= <nested table>
          Decl= <nested table>
      [2] = "stdafx.cpp",
      [3] = "stdafx.cpp",
    Generating DAG for win32-msvc-production-default
    Source list
      [1] =     {
          DagCache= <nested table>
          __index= <nested table>
          Decl= <nested table>
      [2] = "stdafx.cpp",
      [3] = "stdafx.cpp",
      [4] = "stdafx.cpp",
    save_dag_data: 3 bindings, 26 accessed files
    opened by trixnz 0
  • CreateProcess() errors should be shown with GetLastError()

    CreateProcess() errors should be shown with GetLastError()

    When CreateProcess() returns 0, the correct error value should be shown using GetLastError() instead of errno. errno is only c runtime and this is a WinApi function.

    opened by lundmark 0
  • Asm include scanner fails on incbin preceded by label

    Asm include scanner fails on incbin preceded by label

    This is pretty common:

    label:  incbin "somefile"

    Unfortunately Tundra's generic header scanner doesn't support this because it bails out as soon as it sees the label part.

    opened by deplinenoise 0
  • Unit Script Template Manual is outdated

    Unit Script Template Manual is outdated

    When trying to use the documentation on Unit Script Template to create my own Unit Type, it seems to fail to use the code provided.

    My definition:

    module("my_compiler", package.seeall)
    local nodegen = require "tundra.nodegen"
    local _mt = nodegen.create_eval_subclass {}
    local blueprint = {
        Sources = {
            Type = "source_list",
            Help = "List of sources",
            Required = true,
            ExtensionKey = "MY_EXTENSION",
        Name = {
            Type = "string",
            Required = true,
    function _mt:create_dag(env, data, deps)
        return env:make_node {
            Label = "MyCompiler $(@)",
            Action = "echo", --"$(MYACTION)",
            Inputs = data.Sources,
            Outputs = {},
            Dependencies = deps,
    nodegen.add_evaluator("MyCompiler", _mt, blueprint)

    But when trying to run MyCompiler then I get that when trying to create the dag, it calls the :create_dag-function where the make_node function doesn't exist.

    (attempt to call method 'make_node' (a nil value))

    It would be really awesome if there would be an example of how to get this working in the examples/directory

    opened by lundmark 2
Andreas Fredriksson
Andreas Fredriksson
CMake checks cache helper modules – for fast CI CMake builds!

cmake-checks-cache Cross platform CMake projects do platform introspection by the means of "Check" macros. Have a look at CMake's How To Write Platfor

Cristian Adam 59 Jul 7, 2022
A fast build system that encourages the creation of small, reusable modules over a variety of platforms and languages.

Buck Buck is a build tool. To see what Buck can do for you, check out the documentation at http://buck.build/. Installation Since Buck is used to buil

Facebook 8.4k Aug 10, 2022
CMake module to speed up builds.

cotire Cotire (compile time reducer) is a CMake module that speeds up the build process of CMake based build systems by fully automating techniques as

Sascha Kratky 1.3k Aug 11, 2022
Improved build system generator for CPython C, C++, Cython and Fortran extensions

scikit-build Improved build system generator for CPython C/C++/Fortran/Cython extensions. Better support is available for additional compilers, build

null 343 Aug 7, 2022
a small build system with a focus on speed

Ninja Ninja is a small build system with a focus on speed. https://ninja-build.org/ See the manual or doc/manual.asciidoc included in the distribution

null 8.4k Aug 9, 2022
muon is an implementation of the meson build system in C with minimal dependencies.

muon muon is an implementation of the meson build system in C with minimal dependencies. Non-features bug-for-bug compatibility with meson. In fact, m

Stone Tickle 40 Jul 26, 2022
A basic build system for the Skript scripting language.

skib A basic build system for the Skript scripting language. Features #include other files recursively #define preprocessor symbols and macros Usage #

Daniel 1 Jun 27, 2022
NeoWorld is a resampler using the CMake build system

NeoWorld is a resampler using the CMake build system. It's designed for utsu, OpenUTAU, and UTAU.

null 4 Jun 24, 2022
Arduino CMake Build system

Arduino Cmake Example Project This is the Cmake project settings for the Arduino platform. You can use this project as an example to develop C++ progr

Francois Campbell 55 May 23, 2022
An Enhancement Suite for the CMake Build System

A CMake Enhancement Suite Usage Look through the files in the package. Most functions will be commented and the other's usage can be inferred. All fun

Tobias Becker 397 Aug 5, 2022
Yet another post-build step and class to bring reflection to C++ enumerations.

enum_values Yet another post-build step and class to bring reflection to C++ enumerations! Fair warning: this project has not undergone much testing (

null 12 May 11, 2022
Examples of using Hunter package manager to build and run Android application.

Examples of using Hunter package manager to build and run Android application. Requirements Android NDK Go to download page and choose NDK for your pl

null 34 Mar 13, 2022
CMake and other scripts to help build process of FlyEM software

The BuildEM System The buildem repo is a modular CMake-based system that leverages CMake's ExternalProject to simplify and automate a complex build pr

null 27 Jun 9, 2022
nabs is a single-header library for writing build recipes in C++

nabs is a single-header library for writing build recipes in C++. It is directly inspired by nobuild, but with more feature (bloat) and built-in support for makefile-like dependency resolution.

zhiayang 6 May 8, 2021
curl cmake module libcurl build with msvc x86

curl-msvc Infomation curl cmake module libcurl build with MSVC10.0 arch (x86 | i386) source from https://github.com/curl/curl tags: curl-7_79_1 Usage

Jason Payne 0 May 16, 2022
Project to enable using CMake from a Maven build.

CMake-Maven-Project Introduction A Maven project for the CMake build system. It can be used by including it as a plugin within your Maven project's po

null 58 Jul 13, 2022
CMake module to enable code coverage easily and generate coverage reports with CMake targets.

CMake-codecov CMake module to enable code coverage easily and generate coverage reports with CMake targets. Include into your project To use Findcodec

HPC 77 Jul 3, 2022
A CMake addon that avoids you writing boilerplate code for resource management.

SHader INJ(I)ector SHINJI (originally SHader INJector) is a CMake addon that avoids you writing boilerplate code for resource management and exposes s

Lorenzo Rutayisire 6 Mar 21, 2022
🍩 A XMake integration in Visual Studio Code

xmake-vscode A XMake integration in Visual Studio Code Introduction A XMake integration in Visual Studio Code. You need install xmake first and a proj

xmake-io 118 Aug 4, 2022