winamp/Src/external_dependencies/openmpt-trunk/include/premake/website/docs/Coding-Conventions.md

115 lines
4.0 KiB
Markdown
Raw Permalink Normal View History

2024-09-24 12:54:57 +00:00
---
title: Coding Conventions
---
While not all of Premake's code currently follows these conventions, we are gradually nudging everything in this direction and hope to have it all done before the final 5.0 release. Knowing these conventions will make the code a little easier to read and follow.
### Tables as Namespaces
Premake tables are used as namespaces, with related functions grouped together into their own namespace table. Most of Premake's own code is placed into a table named `premake`. Code related to the project scripting API is in `premake.api`, code related to command line options in in `premake.options`, and so on.
Organizing the code in this way helps avoid collisions between similarly named functions, and generally helps to keep things tidy.
### Local Variables as Aliases
New namespaces are declared at the top of each source code file, followed by aliases for namespaces which are going to be used frequently within the source file. For example:
```lua
-- define a new namespace for the VC 2010 related code
premake.vstudio.vc2010 = {}
-- create aliases for namespaces we'll use often
local p = premake
local vstudio = p.vstudio
local project = p.project
-- and the "m" alias represents the current module being implemented
local m = p.vstudio.vc2010
```
The alias `p` is used conventionally as a shortcut for the `premake` namespace. The alias `m` is conventially used to represent the module being implemented.
Using aliases saves some keystrokes when coding. And since Premake embeds all of its scripts into the release executables, it saves on the final download size as well.
### Call Arrays
Premake's project file exporters—which write out the Visual Studio projects, makefiles, and so on—are basically big long lists of "output this, and then this, and then this". This could easily be written (and once was) as one giant function, but then it would be virtually impossible to modify its behavior.
Instead, we split up the generation of a project into many small functions, often writing out only a single line to the output. Any one of these functions can then be overridden by your own scripts or modules.
```lua
-- instead of this...
function m.outputConfig(cfg)
if #cfg.defines > 0 or vstudio.isMakefile(cfg) then
p.x('PreprocessorDefinitions="%s"', table.concat(cfg.defines, ";"))
end
if #cfg.undefines > 0 then
p.x('UndefinePreprocessorDefinitions="%s"', table.concat(cfg.undefines, ";"))
end
if cfg.rtti == p.OFF and cfg.clr == p.OFF then
p.w('RuntimeTypeInfo="false"')
elseif cfg.rtti == p.ON then
p.w('RuntimeTypeInfo="true"')
end
end
-- we do this...
function m.preprocessorDefinitions(cfg)
if #cfg.defines > 0 or vstudio.isMakefile(cfg) then
p.x('PreprocessorDefinitions="%s"', table.concat(cfg.defines, ";"))
end
end
function m.undefinePreprocessorDefinitions(cfg)
if #cfg.undefines > 0 then
p.x('UndefinePreprocessorDefinitions="%s"', table.concat(cfg.undefines, ";"))
end
end
function m.runtimeTypeInfo(cfg)
if cfg.rtti == p.OFF and cfg.clr == p.OFF then
p.w('RuntimeTypeInfo="false"')
elseif cfg.rtti == p.ON then
p.w('RuntimeTypeInfo="true"')
end
end
```
Similarly, instead of implementing the output of a particular section of the project as a function calling a long list of other functions, we put those functions into an array, and then iterate over the array. We call these "call arrays", and they allow you to inject new functions, or remove existing ones, from the array at runtime.
```lua
-- instead of this...
function m.outputConfig(cfg)
m.preprocessorDefinitions(cfg)
m.undefinePreprocessorDefinitions(cfg)
m.runtimeTypeInfo(cfg)
-- and so on...
end
-- we do this
m.elements.config = function(cfg)
return {
m.preprocessorDefinitions,
m.undefinePreprocessorDefinitions,
m.runtimeTypeInfo,
-- and so on...
}
end
function m.outputConfig(cfg)
p.callArray(m.element.config, cfg)
end
```
For an example of how to implement a new feature using these conventions, see [Overrides and Call Arrays](Overrides-and-Call-Arrays.md).