Wiki

Clone wiki

premake-dev / Extending Premake

We've moved to GitHub!

The latest version of this page is now here.


Here is the quick five minute version to get things started. I (or we) will refine it as we go.

Update: I started writing up more information about the new approach, which I now calling "Modules". I will work on cleaning up and consolidating the information as I go, using that page for the user facing "how do I use a module" and this page for "how to I create a module".

Currently, Premake modules don't exist, really. I'm trying to change that. I would like to get to the point where major new features can be developed as modules and shared with the community easily, without the need to involve the core developers and modify core code. Mature or popular modules can then be integrated into the core distribution easily, as everything will be well-tested and self-contained.

Introducing Modules

Modules are simply Lua scripts. You enable them for your project by including them at the top of your script. For instance, you could use Andrew Gough's excellent D language extension (which doesn't exist yet) by simply adding this line to the top of your script:

include 'd'

But that raises questions like: were do I get the d.lua file(s)? Where do I put them? How does Premake find them? Some work has been done on searching a set of well-known system paths for includes; can someone dig up that code and document its behavior here?

Writing Modules

Create a new Lua file for your extension.

If your module depends on other modules, include those at the top of the file.

If you plan to expose functions for other modules to use, create a namespace for them.

-- include any dependencies first
include 'monodevelop'

-- define a namespace
premake.modules.d = {}
local d = premake.modules.d

-- define a function for other extensions to use
function d.doSomethingCool()
   -- do something cool
end

Now you need to deep dive the Premake source code. Find the function that you want to replace or extend. Use premake.override() to replace it. Here is an example of overriding the Visual Studio C++ preprocessor definitions element:

premake.override(premake.vstudio.vc2010, 'preprocessorDefinitions', function(base, cfg, defines)

   -- if my conditions are met, add something to the list of defines
   if cfg.flags.AddCoolness then
      defines = table.join(defines, { "COOLNESS=11" })
   end

   -- call the base implementation to output the element
   base(cfg, defines)

end)

The first argument is the namespace of the function you would like to override. The second argument is the name of the function within that namespace, as a string (this is not ideal; I'm not sure how to specify it as a function and still have it work if someone else has previously overridden it. Suggestions welcome). The last argument is the replacement function.

The replacement function will always receive the the previous implementation as the first argument, followed by the function's regular list of arguments.

Tips

  • I am still trying to figure out how extensions are going to work. Feel free to raise questions, concerns, whatever over on the forums.

  • If you find yourself copy-and-pasting code from Premake core into your extension, stop. You've found an area of code that needs to be improved. Raise the issue on the forums and we'll try to find a better way.

  • If you find your self directly accessing or modifying tables of values within Premake's core, stop. We should add an API to do that manipulation for you, or move the values into configuration blocks. Raise the issue on the forums.

Open Questions

  • How do you share the extension?

  • How are dependencies managed/communicated?

  • How are extensions unit tested?

  • How should extensions be documented?

  • When are extensions moved into the core distribution, and how is that done?

Updated