Merge remote-tracking branch 'refs/remotes/premake/master'

This commit is contained in:
Lynix 2017-04-02 15:39:03 +02:00
commit 00aa7e3673
68 changed files with 8196 additions and 73 deletions

15
.gitmodules vendored
View File

@ -1,15 +0,0 @@
[submodule "modules/xcode"]
path = modules/xcode
url = https://github.com/premake/premake-xcode.git
[submodule "modules/monodevelop"]
path = modules/monodevelop
url = https://github.com/premake/premake-monodevelop.git
[submodule "modules/codelite"]
path = modules/codelite
url = https://github.com/premake/premake-codelite.git
[submodule "modules/d"]
path = modules/d
url = https://github.com/premake/premake-dlang.git
[submodule "modules/raw"]
path = modules/raw
url = https://github.com/premake/premake-raw.git

View File

@ -5,6 +5,14 @@
See https://github.com/premake/premake-core/wiki/What's-New-in-5.0
for the complete list of changes from the Premake 4.x series.
Since 5.0-alpha9:
* New: `symbols()`, replaces and extends flags {"Symbols"}
* New: `symbolspath()` to specify location of symbol database
* New: `table.shallowcopy()`
* New: `vectorextensions` value "IA32"
* Fix: --start-group/--end-group now only enclose project libraries
Since 5.0-alpha8:
* New: `buildcustomizations()` imports custom .props files for VS

View File

@ -23,6 +23,8 @@ Patch contributors:
Damien Courtois <https://github.com/dcourtois>
* module loading fixes
* bug fixes
David Ely <https://github.com/megaeels>
* symbols() API and flag deprecation
Gabi Davar <gabi.davar@discretix.com>
* added file.directory to token environment
João Matos (joao@tritao.eu)
@ -37,6 +39,8 @@ Patch contributors:
* path.join() fixes
Mark Chandler <https://bitbucket.org/mchandler_blizzard>
* prevent self-linking
Matthew Endsley <https://github.com/mendsley>
* File matching improvements
Mark Sararu <mark.sararu@gmail.com>
* Makefile bug fixes
Mihai Sebea <http://twitter.com/mihai_sebea>

View File

@ -1,6 +1,6 @@
# PREMAKE 5 (core)
* Linux : [![Build Status](https://travis-ci.org/premake/premake-core.svg?branch=master)](https://travis-ci.org/premake/premake-core)
* Windows: [![Build status](https://ci.appveyor.com/api/projects/status/lc9g332y2lqvel8h?svg=true)](https://ci.appveyor.com/project/PremakeOrganization/premake-core)
<img src="https://github.com/premake/premake-core/wiki/linux-widget.jpeg" width="24" height="24"/> [![Build Status](https://travis-ci.org/premake/premake-core.svg?branch=master)](https://travis-ci.org/premake/premake-core)
<img src="https://github.com/premake/premake-core/wiki/windows-widget.jpeg" width="24" height="24"/> [![Build status](https://ci.appveyor.com/api/projects/status/lc9g332y2lqvel8h?svg=true)](https://ci.appveyor.com/project/PremakeOrganization/premake-core)
<img src="http://premake.github.io/premake-logo.png" width="200" height="200" />

@ -1 +0,0 @@
Subproject commit c72dbdf9e0db9f6673410ef07cad1e5e8fcbefaf

View File

@ -0,0 +1,13 @@
Premake extension to support the [CodeLite](http://www.codelite.org/) IDE
### Features ###
* Support for C/C++ language projects
### Usage ###
Simply generate your project using the `codelite` action:
```bash
premake5 codelite
```
and open the generated project file in CodeLite.

View File

@ -0,0 +1,6 @@
return {
"_preload.lua",
"codelite.lua",
"codelite_workspace.lua",
"codelite_project.lua",
}

View File

@ -0,0 +1,57 @@
--
-- Name: codelite/_preload.lua
-- Purpose: Define the CodeLite action.
-- Author: Ryan Pusztai
-- Modified by: Andrea Zanellato
-- Andrew Gough
-- Manu Evans
-- Created: 2013/05/06
-- Copyright: (c) 2008-2015 Jason Perkins and the Premake project
--
local p = premake
newaction
{
-- Metadata for the command line and help system
trigger = "codelite",
shortname = "CodeLite",
description = "Generate CodeLite project files",
-- The capabilities of this action
valid_kinds = { "ConsoleApp", "WindowedApp", "Makefile", "SharedLib", "StaticLib", "Utility" },
valid_languages = { "C", "C++" },
valid_tools = {
cc = { "gcc", "clang", "msc" }
},
-- Workspace and project generation logic
onWorkspace = function(wks)
p.modules.codelite.generateWorkspace(wks)
end,
onProject = function(prj)
p.modules.codelite.generateProject(prj)
end,
onCleanWorkspace = function(wks)
p.modules.codelite.cleanWorkspace(wks)
end,
onCleanProject = function(prj)
p.modules.codelite.cleanProject(prj)
end,
onCleanTarget = function(prj)
p.modules.codelite.cleanTarget(prj)
end,
}
--
-- Decide when the full module should be loaded.
--
return function(cfg)
return (_ACTION == "codelite")
end

75
modules/codelite/codelite.lua Executable file
View File

@ -0,0 +1,75 @@
--
-- Name: codelite/codelite.lua
-- Purpose: Define the CodeLite action(s).
-- Author: Ryan Pusztai
-- Modified by: Andrea Zanellato
-- Andrew Gough
-- Manu Evans
-- Created: 2013/05/06
-- Copyright: (c) 2008-2015 Jason Perkins and the Premake project
--
local p = premake
p.modules.codelite = {}
p.modules.codelite._VERSION = p._VERSION
local codelite = p.modules.codelite
local project = p.project
function codelite.cfgname(cfg)
local cfgname = cfg.buildcfg
if codelite.workspace.multiplePlatforms then
cfgname = string.format("%s|%s", cfg.platform, cfg.buildcfg)
end
return cfgname
end
function codelite.esc(value)
local result = value:gsub('"', '\\&quot;')
result = result:gsub('<', '&lt;')
result = result:gsub('>', '&gt;')
return result
end
function codelite.generateWorkspace(wks)
p.eol("\r\n")
p.indent(" ")
p.escaper(codelite.esc)
p.generate(wks, ".workspace", codelite.workspace.generate)
end
function codelite.generateProject(prj)
p.eol("\r\n")
p.indent(" ")
p.escaper(codelite.esc)
if project.iscpp(prj) then
p.generate(prj, ".project", codelite.project.generate)
end
end
function codelite.cleanWorkspace(wks)
p.clean.file(wks, wks.name .. ".workspace")
p.clean.file(wks, wks.name .. "_wsp.mk")
p.clean.file(wks, wks.name .. ".tags")
p.clean.file(wks, ".clang")
end
function codelite.cleanProject(prj)
p.clean.file(prj, prj.name .. ".project")
p.clean.file(prj, prj.name .. ".mk")
p.clean.file(prj, prj.name .. ".list")
p.clean.file(prj, prj.name .. ".out")
end
function codelite.cleanTarget(prj)
-- TODO..
end
include("codelite_workspace.lua")
include("codelite_project.lua")
return codelite

View File

@ -0,0 +1,455 @@
--
-- Name: codelite/codelite_project.lua
-- Purpose: Generate a CodeLite C/C++ project file.
-- Author: Ryan Pusztai
-- Modified by: Andrea Zanellato
-- Manu Evans
-- Created: 2013/05/06
-- Copyright: (c) 2008-2015 Jason Perkins and the Premake project
--
local p = premake
local tree = p.tree
local project = p.project
local config = p.config
local codelite = p.modules.codelite
codelite.project = {}
local m = codelite.project
function codelite.getLinks(cfg)
-- System libraries are undecorated, add the required extension
return config.getlinks(cfg, "system", "fullpath")
end
function codelite.getSiblingLinks(cfg)
-- If we need sibling projects to be listed explicitly, add them on
return config.getlinks(cfg, "siblings", "fullpath")
end
m.elements = {}
m.ctools = {
gcc = "gnu gcc",
clang = "clang",
msc = "Visual C++",
}
m.cxxtools = {
gcc = "gnu g++",
clang = "clang++",
msc = "Visual C++",
}
function m.getcompilername(cfg)
local tool = _OPTIONS.cc or cfg.toolset or p.CLANG
local toolset = p.tools[tool]
if not toolset then
error("Invalid toolset '" + (_OPTIONS.cc or cfg.toolset) + "'")
end
if cfg.language == "C" then
return m.ctools[tool]
elseif cfg.language == "C++" then
return m.cxxtools[tool]
end
end
function m.getcompiler(cfg)
local toolset = p.tools[_OPTIONS.cc or cfg.toolset or p.CLANG]
if not toolset then
error("Invalid toolset '" + (_OPTIONS.cc or cfg.toolset) + "'")
end
return toolset
end
local function configuration_iscustombuild(cfg)
return cfg and (cfg.kind == p.MAKEFILE) and (#cfg.buildcommands > 0)
end
local function configuration_isfilelist(cfg)
return cfg and (cfg.buildaction == "None") and not configuration_iscustombuild(cfg)
end
local function configuration_needresoptions(cfg)
return cfg and config.findfile(cfg, ".rc") and not configuration_iscustombuild(cfg)
end
m.internalTypeMap = {
ConsoleApp = "Console",
WindowedApp = "Console",
Makefile = "",
SharedLib = "Library",
StaticLib = "Library"
}
function m.header(prj)
_p('<?xml version="1.0" encoding="UTF-8"?>')
local type = m.internalTypeMap[prj.kind] or ""
_x('<CodeLite_Project Name="%s" InternalType="%s">', prj.name, type)
end
function m.plugins(prj)
-- _p(1, '<Plugins>')
-- <Plugin Name="CMakePlugin">
-- <Plugin Name="qmake">
-- _p(1, '</Plugins>')
_p(1, '<Plugins/>')
end
function m.description(prj)
_p(1, '<Description/>')
-- TODO: ...
end
function m.files(prj)
local tr = project.getsourcetree(prj)
tree.traverse(tr, {
-- folders are handled at the internal nodes
onbranchenter = function(node, depth)
_p(depth, '<VirtualDirectory Name="%s">', node.name)
end,
onbranchexit = function(node, depth)
_p(depth, '</VirtualDirectory>')
end,
-- source files are handled at the leaves
onleaf = function(node, depth)
local excludesFromBuild = {}
for cfg in project.eachconfig(prj) do
local cfgname = codelite.cfgname(cfg)
local fcfg = p.fileconfig.getconfig(node, cfg)
if not fcfg or fcfg.flags.ExcludeFromBuild then
table.insert(excludesFromBuild, cfgname)
end
end
if #excludesFromBuild > 0 then
_p(depth, '<File Name="%s" ExcludeProjConfig="%s" />', node.relpath, table.concat(excludesFromBuild, ';'))
else
_p(depth, '<File Name="%s"/>', node.relpath)
end
end,
}, false, 1)
end
function m.dependencies(prj)
-- TODO: dependencies don't emit a line for each config if there aren't any...
-- _p(1, '<Dependencies/>')
local dependencies = project.getdependencies(prj)
for cfg in project.eachconfig(prj) do
cfgname = codelite.cfgname(cfg)
if #dependencies > 0 then
_p(1, '<Dependencies Name="%s">', cfgname)
for _, dependency in ipairs(dependencies) do
_p(2, '<Project Name="%s"/>', dependency.name)
end
_p(1, '</Dependencies>')
else
_p(1, '<Dependencies Name="%s"/>', cfgname)
end
end
end
function m.global_compiler(prj)
_p(3, '<Compiler Options="" C_Options="" Assembler="">')
_p(4, '<IncludePath Value="."/>')
_p(3, '</Compiler>')
end
function m.global_linker(prj)
_p(3, '<Linker Options="">')
_p(4, '<LibraryPath Value="."/>')
_p(3, '</Linker>')
end
function m.global_resourceCompiler(prj)
_p(3, '<ResourceCompiler Options=""/>')
end
m.elements.globalSettings = function(prj)
return {
m.global_compiler,
m.global_linker,
m.global_resourceCompiler,
}
end
function m.compiler(cfg)
if configuration_iscustombuild(cfg) or configuration_isfilelist(cfg) then
_p(3, '<Compiler Required="no"/>')
return
end
local toolset = m.getcompiler(cfg)
local cxxflags = table.concat(table.join(toolset.getcflags(cfg), toolset.getcxxflags(cfg), cfg.buildoptions), ";")
local cflags = table.concat(table.join(toolset.getcflags(cfg), cfg.buildoptions), ";")
local asmflags = ""
local pch = ""
_x(3, '<Compiler Options="%s" C_Options="%s" Assembler="%s" Required="yes" PreCompiledHeader="%s" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">', cxxflags, cflags, asmflags, pch)
for _, includedir in ipairs(cfg.includedirs) do
_x(4, '<IncludePath Value="%s"/>', project.getrelative(cfg.project, includedir))
end
for _, define in ipairs(cfg.defines) do
_x(4, '<Preprocessor Value="%s"/>', p.esc(define))
end
_p(3, '</Compiler>')
end
function m.linker(cfg)
if configuration_iscustombuild(cfg) or configuration_isfilelist(cfg) then
_p(3, '<Linker Required="no"/>')
return
end
local toolset = m.getcompiler(cfg)
local flags = table.join(toolset.getldflags(cfg), cfg.linkoptions)
local withdeps = table.join(flags, codelite.getSiblingLinks(cfg))
local ldflags = table.concat(withdeps, ";")
_x(3, '<Linker Required="yes" Options="%s">', ldflags)
if #cfg.libdirs > 0 then
local libdirs = project.getrelative(cfg.project, cfg.libdirs)
for _, libpath in ipairs(libdirs) do
_x(4, '<LibraryPath Value="%s" />', libpath)
end
end
local links = codelite.getLinks(cfg)
for _, libname in ipairs(links) do
_x(4, '<Library Value="%s" />', libname)
end
_p(3, '</Linker>')
end
function m.resourceCompiler(cfg)
if not configuration_needresoptions(cfg) then
_p(3, '<ResourceCompiler Options="" Required="no"/>')
return
end
local toolset = m.getcompiler(cfg)
local defines = table.implode(toolset.getdefines(table.join(cfg.defines, cfg.resdefines)), "", ";", "")
local options = table.concat(cfg.resoptions, ";")
_x(3, '<ResourceCompiler Options="%s%s" Required="yes">', defines, options)
for _, includepath in ipairs(table.join(cfg.includedirs, cfg.resincludedirs)) do
_x(4, '<IncludePath Value="%s"/>', project.getrelative(cfg.project, includepath))
end
_p(3, '</ResourceCompiler>')
end
function m.general(cfg)
if configuration_isfilelist(cfg) then
_p(3, '<General IntermediateDirectory="." WorkingDirectory="." PauseExecWhenProcTerminates="no"/>')
return
end
local prj = cfg.project
local isExe = prj.kind == "WindowedApp" or prj.kind == "ConsoleApp"
local targetpath = project.getrelative(prj, cfg.buildtarget.directory)
local objdir = project.getrelative(prj, cfg.objdir)
local targetname = project.getrelative(prj, cfg.buildtarget.abspath)
local command = iif(isExe, targetname, "")
local cmdargs = iif(isExe, table.concat(cfg.debugargs, " "), "") -- TODO: should this be debugargs instead?
local useseparatedebugargs = "no"
local debugargs = ""
local workingdir = iif(isExe, project.getrelative(prj, cfg.debugdir), "")
local pauseexec = iif(prj.kind == "ConsoleApp", "yes", "no")
local isguiprogram = iif(prj.kind == "WindowedApp", "yes", "no")
local isenabled = iif(cfg.flags.ExcludeFromBuild, "no", "yes")
_x(3, '<General OutputFile="%s" IntermediateDirectory="%s" Command="%s" CommandArguments="%s" UseSeparateDebugArgs="%s" DebugArguments="%s" WorkingDirectory="%s" PauseExecWhenProcTerminates="%s" IsGUIProgram="%s" IsEnabled="%s"/>',
targetname, objdir, command, cmdargs, useseparatedebugargs, debugargs, workingdir, pauseexec, isguiprogram, isenabled)
end
function m.environment(cfg)
_p(3, '<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">')
local variables = ""
_x(4, '<![CDATA[%s]]>', variables)
_p(3, '</Environment>')
end
function m.debugger(cfg)
_p(3, '<Debugger IsRemote="%s" RemoteHostName="%s" RemoteHostPort="%s" DebuggerPath="" IsExtended="%s">', iif(cfg.debugremotehost, "yes", "no"), cfg.debugremotehost or "", iif(cfg.debugport, tostring(cfg.debugport), ""), iif(cfg.debugextendedprotocol, "yes", "no"))
if #cfg.debugsearchpaths > 0 then
_p(4, '<DebuggerSearchPaths>%s</DebuggerSearchPaths>', table.concat(premake.esc(project.getrelative(cfg.project, cfg.debugsearchpaths)), "\n"))
else
_p(4, '<DebuggerSearchPaths/>')
end
if #cfg.debugconnectcommands > 0 then
_p(4, '<PostConnectCommands>%s</PostConnectCommands>', table.concat(premake.esc(cfg.debugconnectcommands), "\n"))
else
_p(4, '<PostConnectCommands/>')
end
if #cfg.debugstartupcommands > 0 then
_p(4, '<StartupCommands>%s</StartupCommands>', table.concat(premake.esc(cfg.debugstartupcommands), "\n"))
else
_p(4, '<StartupCommands/>')
end
_p(3, '</Debugger>')
end
function m.preBuild(cfg)
if #cfg.prebuildcommands > 0 then
_p(3, '<PreBuild>')
for _, commands in ipairs(cfg.prebuildcommands) do
_x(4, '<Command Enabled="yes">%s</Command>',
p.esc(commands))
end
_p(3, '</PreBuild>')
end
end
function m.postBuild(cfg)
if #cfg.postbuildcommands > 0 then
_p(3, '<PostBuild>')
for _, commands in ipairs(cfg.postbuildcommands) do
_x(4, '<Command Enabled="yes">%s</Command>',
p.esc(commands))
end
_p(3, '</PostBuild>')
end
end
function m.customBuild(cfg)
if not configuration_iscustombuild(cfg) then
_p(3, '<CustomBuild Enabled="no"/>')
return
end
local build = table.implode(cfg.buildcommands,"","","")
local clean = table.implode(cfg.cleancommands,"","","")
local rebuild = table.implode(cfg.rebuildcommands,"","","")
_p(3, '<CustomBuild Enabled="yes">')
_x(4, '<BuildCommand>%s</BuildCommand>', build)
_x(4, '<CleanCommand>%s</CleanCommand>', clean)
_x(4, '<RebuildCommand>%s</RebuildCommand>', rebuild)
_p(4, '<PreprocessFileCommand></PreprocessFileCommand>')
_p(4, '<SingleFileCommand></SingleFileCommand>')
_p(4, '<MakefileGenerationCommand></MakefileGenerationCommand>')
_p(4, '<ThirdPartyToolName></ThirdPartyToolName>')
_p(4, '<WorkingDirectory></WorkingDirectory>')
_p(3, '</CustomBuild>')
end
function m.additionalRules(cfg)
if configuration_iscustombuild(cfg) then
_p(3, '<AdditionalRules/>')
return
end
_p(3, '<AdditionalRules>')
_p(4, '<CustomPostBuild/>')
_p(4, '<CustomPreBuild/>')
_p(3, '</AdditionalRules>')
end
function m.completion(cfg)
_p(3, '<Completion EnableCpp11="%s" EnableCpp14="%s">', iif(cfg.flags["C++11"], "yes", "no"), iif(cfg.flags["C++14"], "yes", "no"))
_p(4, '<ClangCmpFlagsC/>')
_p(4, '<ClangCmpFlags/>')
_p(4, '<ClangPP/>') -- TODO: we might want to set special code completion macros...?
_p(4, '<SearchPaths/>') -- TODO: search paths for code completion?
_p(3, '</Completion>')
end
m.elements.settings = function(cfg)
return {
m.compiler,
m.linker,
m.resourceCompiler,
m.general,
m.environment,
m.debugger,
m.preBuild,
m.postBuild,
m.customBuild,
m.additionalRules,
m.completion,
}
end
m.types =
{
ConsoleApp = "Executable",
Makefile = "",
SharedLib = "Dynamic Library",
StaticLib = "Static Library",
WindowedApp = "Executable",
Utility = "",
}
m.debuggers =
{
Default = "GNU gdb debugger",
GDB = "GNU gdb debugger",
LLDB = "LLDB Debugger",
}
function m.settings(prj)
_p(1, '<Settings Type="%s">', m.types[prj.kind] or "")
_p(2, '<GlobalSettings>')
p.callArray(m.elements.globalSettings, prj)
_p(2, '</GlobalSettings>')
for cfg in project.eachconfig(prj) do
local cfgname = codelite.cfgname(cfg)
local compiler = m.getcompilername(cfg)
local debugger = m.debuggers[cfg.debugger] or m.debuggers.Default
local type = m.types[cfg.kind]
_x(2, '<Configuration Name="%s" CompilerType="%s" DebuggerType="%s" Type="%s" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">', cfgname, compiler, debugger, type)
p.callArray(m.elements.settings, cfg)
_p(2, '</Configuration>')
end
_p(1, '</Settings>')
end
m.elements.project = function(prj)
return {
m.header,
m.plugins,
m.description,
m.files,
m.dependencies,
m.settings,
}
end
--
-- Project: Generate the CodeLite project file.
--
function m.generate(prj)
p.utf8()
p.callArray(m.elements.project, prj)
_p('</CodeLite_Project>')
end

View File

@ -0,0 +1,97 @@
--
-- Name: codelite/codelite_workspace.lua
-- Purpose: Generate a CodeLite workspace.
-- Author: Ryan Pusztai
-- Modified by: Andrea Zanellato
-- Manu Evans
-- Created: 2013/05/06
-- Copyright: (c) 2008-2015 Jason Perkins and the Premake project
--
local p = premake
local project = p.project
local workspace = p.workspace
local tree = p.tree
local codelite = p.modules.codelite
codelite.workspace = {}
local m = codelite.workspace
--
-- Generate a CodeLite workspace
--
function m.generate(wks)
p.utf8()
--
-- Header
--
_p('<?xml version="1.0" encoding="UTF-8"?>')
local tagsdb = ""
-- local tagsdb = "./" .. wks.name .. ".tags"
_p('<CodeLite_Workspace Name="%s" Database="%s" SWTLW="No">', wks.name, tagsdb)
--
-- Project list
--
local tr = workspace.grouptree(wks)
tree.traverse(tr, {
onleaf = function(n)
local prj = n.project
-- Build a relative path from the workspace file to the project file
local prjpath = p.filename(prj, ".project")
prjpath = path.getrelative(prj.workspace.location, prjpath)
local active = iif(prj.name == wks.startproject, ' Active="Yes"', '')
_x(1, '<Project Name="%s" Path="%s"%s/>', prj.name, prjpath, active)
end,
onbranch = function(n)
-- TODO: not sure what situation this appears...?
-- premake5.lua emit's one of these for 'contrib', which is a top-level folder with the zip projects
end,
})
--
-- Configurations
--
-- count the number of platforms
local platformsPresent = {}
local numPlatforms = 0
for cfg in workspace.eachconfig(wks) do
local platform = cfg.platform
if platform and not platformsPresent[platform] then
numPlatforms = numPlatforms + 1
platformsPresent[platform] = true
end
end
if numPlatforms >= 2 then
codelite.workspace.multiplePlatforms = true
end
-- for each workspace config
_p(1, '<BuildMatrix>')
for cfg in workspace.eachconfig(wks) do
local cfgname = codelite.cfgname(cfg)
_p(2, '<WorkspaceConfiguration Name="%s" Selected="yes">', cfgname)
local tr = workspace.grouptree(wks)
tree.traverse(tr, {
onleaf = function(n)
local prj = n.project
_p(3, '<Project Name="%s" ConfigName="%s"/>', prj.name, cfgname)
end
})
_p(2, '</WorkspaceConfiguration>')
end
_p(1, '</BuildMatrix>')
_p('</CodeLite_Workspace>')
end

View File

@ -0,0 +1,7 @@
require ("codelite")
return {
"test_codelite_workspace.lua",
"test_codelite_project.lua",
"test_codelite_config.lua",
}

View File

@ -0,0 +1,235 @@
---
-- codelite/tests/test_codelite_config.lua
-- Automated test suite for CodeLite project generation.
-- Copyright (c) 2015 Manu Evans and the Premake project
---
local suite = test.declare("codelite_cproj_config")
local codelite = premake.modules.codelite
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, cfg
function suite.setup()
premake.action.set("codelite")
premake.indent(" ")
wks, prj = test.createWorkspace()
end
local function prepare()
cfg = test.getconfig(prj, "Debug")
end
function suite.OnProjectCfg_Compiler()
prepare()
codelite.project.compiler(cfg)
test.capture [[
<Compiler Options="" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">
</Compiler>
]]
end
function suite.OnProjectCfg_Flags()
optimize "Debug"
exceptionhandling "Off"
rtti "Off"
pic "On"
symbols "On"
flags { "NoBufferSecurityCheck", "C++11" }
buildoptions { "-opt1", "-opt2" }
prepare()
codelite.project.compiler(cfg)
test.capture [[
<Compiler Options="-O0;-fPIC;-g;-fno-exceptions;-fno-stack-protector;-std=c++11;-fno-rtti;-opt1;-opt2" C_Options="-O0;-fPIC;-g;-opt1;-opt2" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">
</Compiler>
]]
end
function suite.OnProjectCfg_Includes()
includedirs { "dir/", "dir2" }
prepare()
codelite.project.compiler(cfg)
test.capture [[
<Compiler Options="" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">
<IncludePath Value="dir"/>
<IncludePath Value="dir2"/>
</Compiler>
]]
end
function suite.OnProjectCfg_Defines()
defines { "TEST", "DEF" }
prepare()
codelite.project.compiler(cfg)
test.capture [[
<Compiler Options="" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">
<Preprocessor Value="TEST"/>
<Preprocessor Value="DEF"/>
</Compiler>
]]
end
function suite.OnProjectCfg_Linker()
prepare()
codelite.project.linker(cfg)
test.capture [[
<Linker Required="yes" Options="">
</Linker>
]]
end
function suite.OnProjectCfg_LibPath()
libdirs { "test/", "test2" }
prepare()
codelite.project.linker(cfg)
test.capture [[
<Linker Required="yes" Options="">
<LibraryPath Value="test" />
<LibraryPath Value="test2" />
</Linker>
]]
end
function suite.OnProjectCfg_Libs()
links { "lib", "lib2" }
prepare()
codelite.project.linker(cfg)
test.capture [[
<Linker Required="yes" Options="">
<Library Value="lib" />
<Library Value="lib2" />
</Linker>
]]
end
-- TODO: test sibling lib project links
function suite.OnProjectCfg_ResCompiler()
prepare()
codelite.project.resourceCompiler(cfg)
test.capture [[
<ResourceCompiler Options="" Required="no"/>
]]
end
function suite.OnProjectCfg_ResInclude()
files { "x.rc" }
resincludedirs { "dir/" }
prepare()
codelite.project.resourceCompiler(cfg)
test.capture [[
<ResourceCompiler Options="" Required="yes">
<IncludePath Value="dir"/>
</ResourceCompiler>
]]
end
function suite.OnProjectCfg_General()
system "Windows"
prepare()
codelite.project.general(cfg)
test.capture [[
<General OutputFile="bin/Debug/MyProject.exe" IntermediateDirectory="obj/Debug" Command="bin/Debug/MyProject.exe" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
]]
end
function suite.OnProjectCfg_Environment()
prepare()
codelite.project.environment(cfg)
test.capture(
' <Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">\n' ..
' <![CDATA[]]>\n' ..
' </Environment>'
)
end
function suite.OnProjectCfg_Debugger()
prepare()
codelite.project.debugger(cfg)
test.capture [[
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
<DebuggerSearchPaths/>
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
]]
end
function suite.OnProjectCfg_DebuggerOpts()
debugremotehost "localhost"
debugport(2345)
debugextendedprotocol(true)
debugsearchpaths { "search/", "path" }
debugconnectcommands { "connectcmd1", "cmd2" }
debugstartupcommands { "startcmd1", "cmd2" }
prepare()
codelite.project.debugger(cfg)
test.capture [[
<Debugger IsRemote="yes" RemoteHostName="localhost" RemoteHostPort="2345" DebuggerPath="" IsExtended="yes">
<DebuggerSearchPaths>search
path</DebuggerSearchPaths>
<PostConnectCommands>connectcmd1
cmd2</PostConnectCommands>
<StartupCommands>startcmd1
cmd2</StartupCommands>
</Debugger>
]]
end
function suite.OnProject_PreBuild()
prebuildcommands { "cmd0", "cmd1" }
prepare()
codelite.project.preBuild(prj)
test.capture [[
<PreBuild>
<Command Enabled="yes">cmd0</Command>
<Command Enabled="yes">cmd1</Command>
</PreBuild>
]]
end
function suite.OnProject_PreBuild()
postbuildcommands { "cmd0", "cmd1" }
prepare()
codelite.project.postBuild(prj)
test.capture [[
<PostBuild>
<Command Enabled="yes">cmd0</Command>
<Command Enabled="yes">cmd1</Command>
</PostBuild>
]]
end
-- TODO: test custom build
function suite.OnProject_AdditionalRules()
prepare()
codelite.project.additionalRules(prj)
test.capture [[
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
]]
end
function suite.OnProject_Completion()
flags { "C++11" }
prepare()
codelite.project.completion(prj)
test.capture [[
<Completion EnableCpp11="yes" EnableCpp14="no">
<ClangCmpFlagsC/>
<ClangCmpFlags/>
<ClangPP/>
<SearchPaths/>
</Completion>
]]
end

View File

@ -0,0 +1,100 @@
---
-- codelite/tests/test_codelite_project.lua
-- Automated test suite for CodeLite project generation.
-- Copyright (c) 2015 Manu Evans and the Premake project
---
local suite = test.declare("codelite_cproj")
local codelite = premake.modules.codelite
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj
function suite.setup()
premake.action.set("codelite")
premake.indent(" ")
wks = test.createWorkspace()
end
local function prepare()
wks = premake.oven.bakeWorkspace(wks)
prj = test.getproject(wks, 1)
end
function suite.OnProject_Header()
prepare()
codelite.project.header(prj)
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Project Name="MyProject" InternalType="Console">
]]
end
function suite.OnProject_Header_Windowed()
kind "WindowedApp"
prepare()
codelite.project.header(prj)
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Project Name="MyProject" InternalType="Console">
]]
end
function suite.OnProject_Header_Shared()
kind "SharedLib"
prepare()
codelite.project.header(prj)
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Project Name="MyProject" InternalType="Library">
]]
end
function suite.OnProject_Plugins()
prepare()
codelite.project.plugins(prj)
test.capture [[
<Plugins/>
]]
end
function suite.OnProject_Description()
prepare()
codelite.project.description(prj)
test.capture [[
<Description/>
]]
end
function suite.OnProject_Dependencies()
prepare()
codelite.project.dependencies(prj)
test.capture [[
<Dependencies Name="Debug"/>
<Dependencies Name="Release"/>
]]
end
-- TODO: dependencies with actual dependencies...
-- GlobalSettings is currently constants, so we'll just test it here
function suite.OnProject_Settings()
prepare()
codelite.project.settings(prj)
test.capture [[
<Settings Type="Executable">
<GlobalSettings>
<Compiler Options="" C_Options="" Assembler="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
<ResourceCompiler Options=""/>
</GlobalSettings>
]]
end

View File

@ -0,0 +1,131 @@
---
-- codelite/tests/test_codelite_workspace.lua
-- Validate generation for CodeLite workspaces.
-- Author Manu Evans
-- Copyright (c) 2015 Manu Evans and the Premake project
---
local suite = test.declare("codelite_workspace")
local codelite = premake.modules.codelite
--
-- Setup
--
local wks, prj
function suite.setup()
premake.action.set("codelite")
premake.indent(" ")
wks = test.createWorkspace()
end
local function prepare()
wks = test.getWorkspace(wks)
codelite.workspace.generate(wks)
end
--
-- Check the basic structure of a workspace.
--
function suite.onEmptyWorkspace()
wks.projects = {}
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Workspace Name="MyWorkspace" Database="" SWTLW="No">
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>
]]
end
function suite.onDefaultWorkspace()
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Workspace Name="MyWorkspace" Database="" SWTLW="No">
<Project Name="MyProject" Path="MyProject.project"/>
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
<Project Name="MyProject" ConfigName="Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
<Project Name="MyProject" ConfigName="Release"/>
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>
]]
end
function suite.onMultipleProjects()
test.createproject(wks)
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Workspace Name="MyWorkspace" Database="" SWTLW="No">
<Project Name="MyProject" Path="MyProject.project"/>
<Project Name="MyProject2" Path="MyProject2.project"/>
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
<Project Name="MyProject" ConfigName="Debug"/>
<Project Name="MyProject2" ConfigName="Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
<Project Name="MyProject" ConfigName="Release"/>
<Project Name="MyProject2" ConfigName="Release"/>
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>
]]
end
--
-- Projects should include relative path from workspace.
--
function suite.onNestedProjectPath()
location "MyProject"
prepare()
test.capture([[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Workspace Name="MyWorkspace" Database="" SWTLW="No">
<Project Name="MyProject" Path="MyProject/MyProject.project"/>
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
<Project Name="MyProject" ConfigName="Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
<Project Name="MyProject" ConfigName="Release"/>
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>
]])
end
function suite.onExternalProjectPath()
location "../MyProject"
prepare()
test.capture([[
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Workspace Name="MyWorkspace" Database="" SWTLW="No">
<Project Name="MyProject" Path="../MyProject/MyProject.project"/>
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
<Project Name="MyProject" ConfigName="Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
<Project Name="MyProject" ConfigName="Release"/>
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>
]])
end

@ -1 +0,0 @@
Subproject commit e854b35cf1d0bedfe16239c27a69909996af12d0

27
modules/d/LICENSE.txt Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2013-2015 Andrew Gough, Manu Evans, and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of Premake nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

55
modules/d/README.md Normal file
View File

@ -0,0 +1,55 @@
Premake Extension to support the [D](http://dlang.org) language
### Features ###
* Support actions: gmake, vs20xx (VisualD)
* Support all compilers; DMD, LDC, GDC
* Support combined and separate compilation
### Usage ###
Simply add:
```lua
language "D"
```
to your project definition and populate with .d files.
### APIs ###
* [flags](https://github.com/premake/premake-dlang/wiki/flags)
* CodeCoverage
* Deprecated
* Documentation
* GenerateHeader
* GenerateJSON
* GenerateMap
* NoBoundsCheck
* Profile
* Quiet
* RetainPaths
* SeparateCompilation
* SymbolsLikeC
* UnitTest
* Verbose
* [versionconstants](https://github.com/premake/premake-dlang/wiki/versionconstants)
* [versionlevel](https://github.com/premake/premake-dlang/wiki/versionlevel)
* [debugconstants](https://github.com/premake/premake-dlang/wiki/debugconstants)
* [debuglevel](https://github.com/premake/premake-dlang/wiki/debuglevel)
* [docdir](https://github.com/premake/premake-dlang/wiki/docdir)
* [docname](https://github.com/premake/premake-dlang/wiki/docname)
* [headerdir](https://github.com/premake/premake-dlang/wiki/headerdir)
* [headername](https://github.com/premake/premake-dlang/wiki/headername)
### Example ###
The contents of your premake5.lua file would be:
```lua
solution "MySolution"
configurations { "release", "debug" }
project "MyDProject"
kind "ConsoleApp"
language "D"
files { "src/main.d", "src/extra.d" }
```

9
modules/d/_manifest.lua Normal file
View File

@ -0,0 +1,9 @@
return {
"_preload.lua",
"d.lua",
"actions/gmake.lua",
"actions/vstudio.lua",
"tools/dmd.lua",
"tools/gdc.lua",
"tools/ldc.lua",
}

126
modules/d/_preload.lua Normal file
View File

@ -0,0 +1,126 @@
--
-- Name: d/_preload.lua
-- Purpose: Define the D language API's.
-- Author: Manu Evans
-- Created: 2013/10/28
-- Copyright: (c) 2013-2015 Manu Evans and the Premake project
--
-- TODO:
-- MonoDevelop/Xamarin Studio has 'workspaces', which correspond to collections
-- of Premake workspaces. If premake supports multiple workspaces, we should
-- write out a workspace file...
local p = premake
local api = p.api
--
-- Register the D extension
--
p.D = "D"
api.addAllowed("language", p.D)
api.addAllowed("floatingpoint", "None")
api.addAllowed("flags", {
"CodeCoverage",
"Deprecated",
"Documentation",
"GenerateHeader",
"GenerateJSON",
"GenerateMap",
"NoBoundsCheck",
-- "PIC", // Note: this should be supported elsewhere...
"Profile",
"Quiet",
-- "Release", // Note: We infer this flag from config.isDebugBuild()
"RetainPaths",
"SeparateCompilation",
"SymbolsLikeC",
"UnitTest",
"Verbose",
})
--
-- Register some D specific properties
--
api.register {
name = "versionconstants",
scope = "config",
kind = "list:string",
tokens = true,
}
api.register {
name = "versionlevel",
scope = "config",
kind = "integer",
}
api.register {
name = "debugconstants",
scope = "config",
kind = "list:string",
tokens = true,
}
api.register {
name = "debuglevel",
scope = "config",
kind = "integer",
}
api.register {
name = "docdir",
scope = "config",
kind = "path",
tokens = true,
}
api.register {
name = "docname",
scope = "config",
kind = "string",
tokens = true,
}
api.register {
name = "headerdir",
scope = "config",
kind = "path",
tokens = true,
}
api.register {
name = "headername",
scope = "config",
kind = "string",
tokens = true,
}
--
-- Provide information for the help output
--
newoption
{
trigger = "dc",
value = "VALUE",
description = "Choose a D compiler",
allowed = {
{ "dmd", "Digital Mars (dmd)" },
{ "gdc", "GNU GDC (gdc)" },
{ "ldc", "LLVM LDC (ldc2)" },
}
}
--
-- Decide when to load the full module
--
return function (cfg)
return (cfg.language == p.D)
end

370
modules/d/actions/gmake.lua Normal file
View File

@ -0,0 +1,370 @@
--
-- d/actions/gmake.lua
-- Define the D makefile action(s).
-- Copyright (c) 2013-2015 Andrew Gough, Manu Evans, and the Premake project
--
local p = premake
local m = p.modules.d
m.make = {}
local dmake = m.make
local make = p.make
local cpp = p.make.cpp
local project = p.project
local config = p.config
local fileconfig = p.fileconfig
-- This check may be unnecessary as we only 'require' this file from d.lua
-- IFF the action already exists, however this may help if this file is
-- directly required, rather than d.lua itself.
local gmake = p.action.get( 'gmake' )
if gmake == nil then
error( "Failed to locate prequisite action 'gmake'" )
end
--
-- Patch the gmake action with the allowed tools...
--
gmake.valid_languages = table.join(gmake.valid_languages, { p.D } )
gmake.valid_tools.dc = { "dmd", "gdc", "ldc" }
function m.make.separateCompilation(prj)
local some = false
local all = true
for cfg in project.eachconfig(prj) do
if cfg.flags.SeparateCompilation then
some = true
else
all = false
end
end
return iif(all, "all", iif(some, "some", "none"))
end
--
-- Override the GMake action 'onProject' funtion to provide
-- D knowledge...
--
p.override( gmake, "onProject", function(oldfn, prj)
p.escaper(make.esc)
if project.isd(prj) then
local makefile = make.getmakefilename(prj, true)
p.generate(prj, makefile, m.make.generate)
return
end
oldfn(prj)
end)
p.override( make, "objdir", function(oldfn, cfg)
if cfg.project.language ~= "D" or cfg.flags.SeparateCompilation then
oldfn(cfg)
end
end)
p.override( make, "objDirRules", function(oldfn, prj)
if prj.language ~= "D" or m.make.separateCompilation(prj) ~= "none" then
oldfn(prj)
end
end)
---
-- Add namespace for element definition lists for p.callarray()
---
m.elements = {}
--
-- Generate a GNU make C++ project makefile, with support for the new platforms API.
--
m.elements.makefile = function(prj)
return {
make.header,
make.phonyRules,
m.make.configs,
m.make.objects, -- TODO: This is basically identical to make.cppObjects(), and should ideally be merged/shared
make.shellType,
m.make.targetRules,
make.targetDirRules,
make.objDirRules,
make.cppCleanRules, -- D clean code is identical to C/C++
make.preBuildRules,
make.preLinkRules,
m.make.dFileRules,
}
end
function m.make.generate(prj)
p.callArray(m.elements.makefile, prj)
end
function m.make.buildRule(prj)
_p('$(TARGET): $(SOURCEFILES) $(LDDEPS)')
_p('\t@echo Building %s', prj.name)
_p('\t$(SILENT) $(BUILDCMD)')
_p('\t$(POSTBUILDCMDS)')
end
function m.make.linkRule(prj)
_p('$(TARGET): $(OBJECTS) $(LDDEPS)')
_p('\t@echo Linking %s', prj.name)
_p('\t$(SILENT) $(LINKCMD)')
_p('\t$(POSTBUILDCMDS)')
end
function m.make.targetRules(prj)
local separateCompilation = m.make.separateCompilation(prj)
if separateCompilation == "all" then
m.make.linkRule(prj)
elseif separateCompilation == "none" then
m.make.buildRule(prj)
else
for cfg in project.eachconfig(prj) do
_x('ifeq ($(config),%s)', cfg.shortname)
if cfg.flags.SeparateCompilation then
m.make.linkRule(prj)
else
m.make.buildRule(prj)
end
_p('endif')
end
end
_p('')
end
function m.make.dFileRules(prj)
local separateCompilation = m.make.separateCompilation(prj)
if separateCompilation ~= "none" then
make.cppFileRules(prj)
end
end
--
-- Override the 'standard' file rule to support D source files
--
p.override(cpp, "standardFileRules", function(oldfn, prj, node)
-- D file
if path.isdfile(node.abspath) then
_x('$(OBJDIR)/%s.o: %s', node.objname, node.relpath)
_p('\t@echo $(notdir $<)')
_p('\t$(SILENT) $(DC) $(ALL_DFLAGS) $(OUTPUTFLAG) -c $<')
else
oldfn(prj, node)
end
end)
--
-- Write out the settings for a particular configuration.
--
m.elements.makeconfig = function(cfg)
return {
m.make.dTools,
make.target,
m.make.target,
make.objdir,
m.make.versions,
m.make.debug,
m.make.imports,
m.make.dFlags,
make.libs,
make.ldDeps,
make.ldFlags,
m.make.linkCmd,
make.preBuildCmds,
make.preLinkCmds,
make.postBuildCmds,
m.make.allRules,
make.settings,
}
end
function m.make.configs(prj)
for cfg in project.eachconfig(prj) do
-- identify the toolset used by this configurations (would be nicer if
-- this were computed and stored with the configuration up front)
local toolset = p.tools[_OPTIONS.dc or cfg.toolset or "dmd"]
if not toolset then
error("Invalid toolset '" + (_OPTIONS.dc or cfg.toolset) + "'")
end
_x('ifeq ($(config),%s)', cfg.shortname)
p.callArray(m.elements.makeconfig, cfg, toolset)
_p('endif')
_p('')
end
end
function m.make.dTools(cfg, toolset)
local tool = toolset.gettoolname(cfg, "dc")
if tool then
_p(' DC = %s', tool)
end
end
function m.make.target(cfg, toolset)
if cfg.flags.SeparateCompilation then
_p(' OUTPUTFLAG = %s', toolset.gettarget('"$@"'))
end
end
function m.make.versions(cfg, toolset)
_p(' VERSIONS +=%s', make.list(toolset.getversions(cfg.versionconstants, cfg.versionlevel)))
end
function m.make.debug(cfg, toolset)
_p(' DEBUG +=%s', make.list(toolset.getdebug(cfg.debugconstants, cfg.debuglevel)))
end
function m.make.imports(cfg, toolset)
local includes = p.esc(toolset.getimportdirs(cfg, cfg.includedirs))
_p(' IMPORTS +=%s', make.list(includes))
end
function m.make.dFlags(cfg, toolset)
_p(' ALL_DFLAGS += $(DFLAGS)%s $(VERSIONS) $(DEBUG) $(IMPORTS) $(ARCH)', make.list(table.join(toolset.getdflags(cfg), cfg.buildoptions)))
end
function m.make.linkCmd(cfg, toolset)
if cfg.flags.SeparateCompilation then
_p(' LINKCMD = $(DC) ' .. toolset.gettarget("$(TARGET)") .. ' $(ALL_LDFLAGS) $(LIBS) $(OBJECTS)')
-- local cc = iif(cfg.language == "C", "CC", "CXX")
-- _p(' LINKCMD = $(%s) -o $(TARGET) $(OBJECTS) $(RESOURCES) $(ARCH) $(ALL_LDFLAGS) $(LIBS)', cc)
else
_p(' BUILDCMD = $(DC) ' .. toolset.gettarget("$(TARGET)") .. ' $(ALL_DFLAGS) $(ALL_LDFLAGS) $(LIBS) $(SOURCEFILES)')
end
end
function m.make.allRules(cfg, toolset)
-- TODO: The C++ version has some special cases for OSX and Windows... check whether they should be here too?
if cfg.flags.SeparateCompilation then
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)')
else
_p('all: $(TARGETDIR) prebuild prelink $(TARGET)')
end
_p('\t@:')
-- _p('')
end
--
-- List the objects file for the project, and each configuration.
--
-- TODO: This is basically identical to make.cppObjects(), and should ideally be merged/shared
function m.make.objects(prj)
-- create lists for intermediate files, at the project level and
-- for each configuration
local root = { sourcefiles={}, objects={} }
local configs = {}
for cfg in project.eachconfig(prj) do
configs[cfg] = { sourcefiles={}, objects={} }
end
-- now walk the list of files in the project
local tr = project.getsourcetree(prj)
p.tree.traverse(tr, {
onleaf = function(node, depth)
-- figure out what configurations contain this file, and
-- if it uses custom build rules
local incfg = {}
local inall = true
local custom = false
for cfg in project.eachconfig(prj) do
local filecfg = fileconfig.getconfig(node, cfg)
if filecfg and not filecfg.flags.ExcludeFromBuild then
incfg[cfg] = filecfg
custom = fileconfig.hasCustomBuildRule(filecfg)
else
inall = false
end
end
if not custom then
-- skip files that aren't compiled
if not path.isdfile(node.abspath) then
return
end
local sourcename = node.relpath
-- TODO: assign a unique object file name to avoid collisions
local objectname = "$(OBJDIR)/" .. node.objname .. ".o"
-- if this file exists in all configurations, write it to
-- the project's list of files, else add to specific cfgs
if inall then
table.insert(root.sourcefiles, sourcename)
table.insert(root.objects, objectname)
else
for cfg in project.eachconfig(prj) do
if incfg[cfg] then
table.insert(configs[cfg].sourcefiles, sourcename)
table.insert(configs[cfg].objects, objectname)
end
end
end
else
for cfg in project.eachconfig(prj) do
local filecfg = incfg[cfg]
if filecfg then
-- if the custom build outputs an object file, add it to
-- the link step automatically to match Visual Studio
local output = project.getrelative(prj, filecfg.buildoutputs[1])
if path.isobjectfile(output) then
table.insert(configs[cfg].objects, output)
end
end
end
end
end
})
local separateCompilation = m.make.separateCompilation(prj)
-- now I can write out the lists, project level first...
function listobjects(var, list)
_p('%s \\', var)
for _, objectname in ipairs(list) do
_x('\t%s \\', objectname)
end
_p('')
end
if separateCompilation ~= "all" then
listobjects('SOURCEFILES :=', root.sourcefiles)
end
if separateCompilation ~= "none" then
listobjects('OBJECTS :=', root.objects, 'o')
end
-- ...then individual configurations, as needed
for cfg in project.eachconfig(prj) do
local files = configs[cfg]
if (#files.sourcefiles > 0 and separateCompilation ~= "all") or (#files.objects > 0 and separateCompilation ~= "none") then
_x('ifeq ($(config),%s)', cfg.shortname)
if #files.sourcefiles > 0 and separateCompilation ~= "all" then
listobjects(' SOURCEFILES +=', files.sourcefiles)
end
if #files.objects > 0 and separateCompilation ~= "none" then
listobjects(' OBJECTS +=', files.objects)
end
_p('endif')
end
end
_p('')
end

View File

@ -0,0 +1,353 @@
--
-- d/actions/vstudio.lua
-- Generate a VisualD .visualdproj project.
-- Copyright (c) 2012-2015 Manu Evans and the Premake project
--
local p = premake
local m = p.modules.d
m.visuald = {}
local vstudio = p.vstudio
local workspace = p.workspace
local project = p.project
local config = p.config
local tree = p.tree
--
-- Patch the vstudio actions with D support...
--
for k,v in pairs({ "vs2005", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015" }) do
local vs = p.action.get(v)
if vs ~= nil then
table.insert( vs.valid_languages, p.D )
vs.valid_tools.dc = { "dmd", "gdc", "ldc" }
p.override(vs, "onProject", function(oldfn, prj)
oldfn(prj)
if project.isd(prj) then
p.generate(prj, ".visualdproj", m.visuald.generate)
end
end)
end
end
--
-- Patch a bunch of other functions
--
p.override(project, "isnative", function(oldfn, prj)
return project.isd(prj) or oldfn(prj)
end)
p.override(vstudio, "projectfile", function(oldfn, prj)
if project.isd(prj) then
return p.filename(prj, ".visualdproj")
end
return oldfn(prj)
end)
p.override(vstudio, "tool", function(oldfn, prj)
if project.isd(prj) then
return "002A2DE9-8BB6-484D-9802-7E4AD4084715"
end
return oldfn(prj)
end)
--
-- Generate a Visual D project.
--
m.elements.project = function(prj)
return {
m.visuald.header,
m.visuald.globals,
m.visuald.projectConfigurations,
m.visuald.files,
}
end
function m.visuald.generate(prj)
p.eol("\r\n")
p.indent(" ")
p.callArray(m.elements.project, prj)
_p('</DProject>')
end
function m.visuald.header(prj)
-- for some reason Visual D projects don't seem to have an xml header
--_p('<?xml version="1.0" encoding="utf-8"?>')
_p('<DProject>')
end
function m.visuald.globals(prj)
_p(1,'<ProjectGuid>{%s}</ProjectGuid>', prj.uuid)
end
--
-- Write out the list of project configurations, which pairs build
-- configurations with architectures.
--
function m.visuald.projectConfigurations(prj)
-- build a list of all architectures used in this project
for cfg in project.eachconfig(prj) do
local prjPlatform = p.esc(vstudio.projectPlatform(cfg))
local slnPlatform = vstudio.solutionPlatform(cfg)
local is64bit = slnPlatform == "x64" -- TODO: this seems like a hack
_p(1,'<Config name="%s" platform="%s">', prjPlatform, slnPlatform)
_p(2,'<obj>0</obj>')
_p(2,'<link>0</link>')
local isWindows = false
local isDebug = string.find(cfg.buildcfg, 'Debug') ~= nil
local isOptimised = config.isOptimizedBuild(cfg)
if cfg.kind == p.CONSOLEAPP then
_p(2,'<lib>0</lib>')
_p(2,'<subsystem>1</subsystem>')
elseif cfg.kind == p.STATICLIB then
_p(2,'<lib>1</lib>')
_p(2,'<subsystem>0</subsystem>')
elseif cfg.kind == p.SHAREDLIB then
_p(2,'<lib>2</lib>')
_p(2,'<subsystem>0</subsystem>') -- SHOULD THIS BE '2' (windows)??
else
_p(2,'<lib>0</lib>')
_p(2,'<subsystem>2</subsystem>')
isWindows = true
end
_p(2,'<multiobj>0</multiobj>')
_p(2,'<singleFileCompilation>0</singleFileCompilation>')
_p(2,'<oneobj>0</oneobj>')
_p(2,'<trace>%s</trace>', iif(cfg.flags.Profile, '1', '0'))
_p(2,'<quiet>%s</quiet>', iif(cfg.flags.Quiet, '1', '0'))
_p(2,'<verbose>%s</verbose>', iif(cfg.flags.Verbose, '1', '0'))
_p(2,'<vtls>0</vtls>')
_p(2,'<symdebug>%s</symdebug>', iif(cfg.symbols == p.ON or cfg.flags.SymbolsLikeC, iif(cfg.flags.SymbolsLikeC, '2', '1'), '0'))
_p(2,'<optimize>%s</optimize>', iif(isOptimised, '1', '0'))
_p(2,'<cpu>0</cpu>')
_p(2,'<isX86_64>%s</isX86_64>', iif(is64bit, '1', '0'))
_p(2,'<isLinux>0</isLinux>')
_p(2,'<isOSX>0</isOSX>')
_p(2,'<isWindows>%s</isWindows>', iif(isWindows, '1', '0'))
_p(2,'<isFreeBSD>0</isFreeBSD>')
_p(2,'<isSolaris>0</isSolaris>')
_p(2,'<scheduler>0</scheduler>')
_p(2,'<useDeprecated>%s</useDeprecated>', iif(cfg.flags.Deprecated, '1', '0'))
_p(2,'<errDeprecated>0</errDeprecated>')
_p(2,'<useAssert>0</useAssert>')
_p(2,'<useInvariants>0</useInvariants>')
_p(2,'<useIn>0</useIn>')
_p(2,'<useOut>0</useOut>')
_p(2,'<useArrayBounds>0</useArrayBounds>')
_p(2,'<noboundscheck>%s</noboundscheck>', iif(cfg.flags.NoBoundsCheck, '1', '0'))
_p(2,'<useSwitchError>0</useSwitchError>')
_p(2,'<useUnitTests>%s</useUnitTests>', iif(cfg.flags.UnitTest, '1', '0'))
_p(2,'<useInline>%s</useInline>', iif(cfg.flags.Inline or isOptimised, '1', '0'))
_p(2,'<release>%s</release>', iif(cfg.flags.Release or not isDebug, '1', '0'))
_p(2,'<preservePaths>0</preservePaths>')
_p(2,'<warnings>%s</warnings>', iif(cfg.flags.FatalCompileWarnings, '1', '0'))
_p(2,'<infowarnings>%s</infowarnings>', iif(cfg.warnings and cfg.warnings ~= "Off", '1', '0'))
_p(2,'<checkProperty>0</checkProperty>')
_p(2,'<genStackFrame>0</genStackFrame>')
_p(2,'<pic>%s</pic>', iif(cfg.pic == "On", '1', '0'))
_p(2,'<cov>%s</cov>', iif(cfg.flags.CodeCoverage, '1', '0'))
_p(2,'<nofloat>%s</nofloat>', iif(cfg.floatingpoint and cfg.floatingpoint == "None", '1', '0'))
_p(2,'<Dversion>2</Dversion>')
_p(2,'<ignoreUnsupportedPragmas>0</ignoreUnsupportedPragmas>')
local compiler = { dmd="0", gdc="1", ldc="2" }
m.visuald.element(2, "compiler", compiler[_OPTIONS.dc or cfg.toolset or "dmd"])
m.visuald.element(2, "otherDMD", '0')
m.visuald.element(2, "program", '$(DMDInstallDir)windows\\bin\\dmd.exe')
m.visuald.element(2, "imppath", cfg.includedirs)
m.visuald.element(2, "fileImppath")
m.visuald.element(2, "outdir", path.translate(project.getrelative(cfg.project, cfg.buildtarget.directory)))
m.visuald.element(2, "objdir", path.translate(project.getrelative(cfg.project, cfg.objdir)))
m.visuald.element(2, "objname")
m.visuald.element(2, "libname")
m.visuald.element(2, "doDocComments", iif(cfg.flags.Documentation, '1', '0'))
m.visuald.element(2, "docdir", cfg.docdir)
m.visuald.element(2, "docname", cfg.docname)
m.visuald.element(2, "modules_ddoc")
m.visuald.element(2, "ddocfiles")
m.visuald.element(2, "doHdrGeneration", iif(cfg.flags.GenerateHeader, '1', '0'))
m.visuald.element(2, "hdrdir", cfg.headerdir)
m.visuald.element(2, "hdrname", cfg.headername)
m.visuald.element(2, "doXGeneration", iif(cfg.flags.GenerateJSON, '1', '0'))
m.visuald.element(2, "xfilename", '$(IntDir)\\$(TargetName).json')
m.visuald.element(2, "debuglevel", iif(cfg.debuglevel, tostring(cfg.debuglevel), '0'))
m.visuald.element(2, "debugids", cfg.debugconstants)
m.visuald.element(2, "versionlevel", iif(cfg.versionlevel, tostring(cfg.versionlevel), '0'))
m.visuald.element(2, "versionids", cfg.versionconstants)
_p(2,'<dump_source>0</dump_source>')
_p(2,'<mapverbosity>0</mapverbosity>')
_p(2,'<createImplib>%s</createImplib>', iif(cfg.kind ~= p.SHAREDLIB or cfg.flags.NoImportLib, '0', '1'))
_p(2,'<defaultlibname />')
_p(2,'<debuglibname />')
_p(2,'<moduleDepsFile />')
_p(2,'<run>0</run>')
_p(2,'<runargs />')
-- _p(2,'<runCv2pdb>%s</runCv2pdb>', iif(cfg.symbols == p.ON, '1', '0'))
_p(2,'<runCv2pdb>1</runCv2pdb>') -- we will just leave this always enabled, since it's ignored if no debuginfo is written
_p(2,'<pathCv2pdb>$(VisualDInstallDir)cv2pdb\\cv2pdb.exe</pathCv2pdb>')
_p(2,'<cv2pdbPre2043>0</cv2pdbPre2043>')
_p(2,'<cv2pdbNoDemangle>0</cv2pdbNoDemangle>')
_p(2,'<cv2pdbEnumType>0</cv2pdbEnumType>')
_p(2,'<cv2pdbOptions />')
_p(2,'<objfiles />')
_p(2,'<linkswitches />')
local links
local explicit = vstudio.needsExplicitLink(cfg)
-- check to see if this project uses an external toolset. If so, let the
-- toolset define the format of the links
local toolset = config.toolset(cfg)
if toolset then
links = toolset.getlinks(cfg, not explicit)
else
local scope = iif(explicit, "all", "system")
links = config.getlinks(cfg, scope, "fullpath")
end
m.visuald.element(2, "libfiles", table.concat(links, " "))
m.visuald.element(2, "libpaths", cfg.libdirs)
_p(2,'<deffile />')
_p(2,'<resfile />')
local target = config.gettargetinfo(cfg)
_p(2,'<exefile>$(OutDir)\\%s</exefile>', target.name)
_p(2,'<useStdLibPath>1</useStdLibPath>')
local runtime = 0
if not cfg.flags.OmitDefaultLibrary then
if config.isDebugBuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime, "2", "4")
else
runtime = iif(cfg.flags.StaticRuntime, "1", "3")
end
end
m.visuald.element(2, "cRuntime", runtime)
local additionalOptions
if #cfg.buildoptions > 0 then
additionalOptions = table.concat(cfg.buildoptions, " ")
end
if #cfg.linkoptions > 0 then
local linkOpts = table.implode(cfg.linkoptions, "-L", "", " ")
if additionalOptions then
additionalOptions = additionalOptions .. " " .. linkOpts
else
additionalOptions = linkOpts
end
end
m.visuald.element(2, "additionalOptions", additionalOptions)
if #cfg.prebuildcommands > 0 then
_p(2,'<preBuildCommand>%s</preBuildCommand>',p.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n")))
else
_p(2,'<preBuildCommand />')
end
if #cfg.postbuildcommands > 0 then
_p(2,'<postBuildCommand>%s</postBuildCommand>',p.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n")))
else
_p(2,'<postBuildCommand />')
end
_p(2,'<filesToClean>*.obj;*.cmd;*.build;*.json;*.dep;*.o</filesToClean>')
_p(1,'</Config>')
end
end
--
-- Write out the source file tree.
--
function m.visuald.files(prj)
_p(1,'<Folder name="%s">', prj.name)
local tr = project.getsourcetree(prj)
tree.traverse(tr, {
-- folders, virtual or otherwise, are handled at the internal nodes
onbranchenter = function(node, depth)
_p(depth, '<Folder name="%s">', node.name)
end,
onbranchexit = function(node, depth)
_p(depth, '</Folder>')
end,
-- source files are handled at the leaves
onleaf = function(node, depth)
_p(depth, '<File path="%s" />', path.translate(node.relpath))
-- _p(depth, '<File path="%s">', path.translate(node.relpath))
-- m.visuald.fileConfiguration(prj, node, depth + 1)
-- _p(depth, '</File>')
end
}, false, 2)
_p(1,'</Folder>')
end
function m.visuald.fileConfiguration(prj, node, depth)
-- maybe we'll need this in the future...
end
--
-- Output an individual project XML element.
--
function m.visuald.element(depth, name, value, ...)
local isTable = type(value) == "table"
if not value or (isTable and #value == 0) then
_p(depth, '<%s />', name)
else
if isTable then
value = p.esc(table.implode(value, "", "", ";"))
_p(depth, '<%s>%s</%s>', name, value, name)
else
if select('#',...) == 0 then
value = p.esc(value)
end
_x(depth, string.format('<%s>%s</%s>', name, value, name), ...)
end
end
end

44
modules/d/d.lua Normal file
View File

@ -0,0 +1,44 @@
--
-- d/d.lua
-- Define the D makefile action(s).
-- Copyright (c) 2013-2015 Andrew Gough, Manu Evans, and the Premake project
--
local p = premake
p.modules.d = {}
local m = p.modules.d
m._VERSION = p._VERSION
m.elements = {}
local api = p.api
--
-- Patch the project table to provide knowledge of D projects
--
function p.project.isd(prj)
return prj.language == premake.D
end
--
-- Patch the path table to provide knowledge of D file extenstions
--
function path.isdfile(fname)
return path.hasextension(fname, { ".d", ".di" })
end
--
-- Patch actions
--
include( "tools/dmd.lua" )
include( "tools/gdc.lua" )
include( "tools/ldc.lua" )
include( "actions/gmake.lua" )
include( "actions/vstudio.lua" )
return m

View File

@ -0,0 +1,9 @@
require ("d")
return {
"test_visualstudio.lua",
"test_gmake.lua",
"test_dmd.lua",
"test_gdc.lua",
"test_ldc.lua",
}

View File

@ -0,0 +1,105 @@
---
-- d/tests/test_dmd.lua
-- Automated test suite for dmd.
-- Copyright (c) 2011-2015 Manu Evans and the Premake project
---
local suite = test.declare("d_dmd")
local m = premake.modules.d
local make = premake.make
local project = premake.project
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, cfg
function suite.setup()
premake.escaper(make.esc)
wks = test.createWorkspace()
end
local function prepare_cfg(calls)
prj = premake.workspace.getproject(wks, 1)
local cfg = test.getconfig(prj, "Debug")
local toolset = premake.tools.dmd
premake.callArray(calls, cfg, toolset)
end
--
-- Check configuration generation
--
function suite.dmd_dTools()
prepare_cfg({ m.make.dTools })
test.capture [[
DC = dmd
]]
end
function suite.dmd_target()
prepare_cfg({ m.make.target })
test.capture [[
]]
end
function suite.dmd_target_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.target })
test.capture [[
OUTPUTFLAG = -of"$@"
]]
end
function suite.dmd_versions()
versionlevel (10)
versionconstants { "A", "B" }
prepare_cfg({ m.make.versions })
test.capture [[
VERSIONS += -version=A -version=B -version=10
]]
end
function suite.dmd_debug()
debuglevel (10)
debugconstants { "A", "B" }
prepare_cfg({ m.make.debug })
test.capture [[
DEBUG += -debug=A -debug=B -debug=10
]]
end
function suite.dmd_imports()
includedirs { "dir1", "dir2/" }
prepare_cfg({ m.make.imports })
test.capture [[
IMPORTS += -Idir1 -Idir2
]]
end
function suite.dmd_dFlags()
prepare_cfg({ m.make.dFlags })
test.capture [[
ALL_DFLAGS += $(DFLAGS) -release $(VERSIONS) $(DEBUG) $(IMPORTS) $(ARCH)
]]
end
function suite.dmd_linkCmd()
prepare_cfg({ m.make.linkCmd })
test.capture [[
BUILDCMD = $(DC) -of$(TARGET) $(ALL_DFLAGS) $(ALL_LDFLAGS) $(LIBS) $(SOURCEFILES)
]]
end
function suite.dmd_linkCmd_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.linkCmd })
test.capture [[
LINKCMD = $(DC) -of$(TARGET) $(ALL_LDFLAGS) $(LIBS) $(OBJECTS)
]]
end

View File

@ -0,0 +1,105 @@
---
-- d/tests/test_dmd.lua
-- Automated test suite for dmd.
-- Copyright (c) 2011-2015 Manu Evans and the Premake project
---
local suite = test.declare("d_gdc")
local m = premake.modules.d
local make = premake.make
local project = premake.project
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, cfg
function suite.setup()
premake.escaper(make.esc)
wks = test.createWorkspace()
end
local function prepare_cfg(calls)
prj = premake.workspace.getproject(wks, 1)
local cfg = test.getconfig(prj, "Debug")
local toolset = premake.tools.gdc
premake.callArray(calls, cfg, toolset)
end
--
-- Check configuration generation
--
function suite.dmd_dTools()
prepare_cfg({ m.make.dTools })
test.capture [[
DC = gdc
]]
end
function suite.dmd_target()
prepare_cfg({ m.make.target })
test.capture [[
]]
end
function suite.dmd_target_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.target })
test.capture [[
OUTPUTFLAG = -o "$@"
]]
end
function suite.dmd_versions()
versionlevel (10)
versionconstants { "A", "B" }
prepare_cfg({ m.make.versions })
test.capture [[
VERSIONS += -fversion=A -fversion=B -fversion=10
]]
end
function suite.dmd_debug()
debuglevel (10)
debugconstants { "A", "B" }
prepare_cfg({ m.make.debug })
test.capture [[
DEBUG += -fdebug=A -fdebug=B -fdebug=10
]]
end
function suite.dmd_imports()
includedirs { "dir1", "dir2/" }
prepare_cfg({ m.make.imports })
test.capture [[
IMPORTS += -Idir1 -Idir2
]]
end
function suite.dmd_dFlags()
prepare_cfg({ m.make.dFlags })
test.capture [[
ALL_DFLAGS += $(DFLAGS) -frelease $(VERSIONS) $(DEBUG) $(IMPORTS) $(ARCH)
]]
end
function suite.dmd_linkCmd()
prepare_cfg({ m.make.linkCmd })
test.capture [[
BUILDCMD = $(DC) -o $(TARGET) $(ALL_DFLAGS) $(ALL_LDFLAGS) $(LIBS) $(SOURCEFILES)
]]
end
function suite.dmd_linkCmd_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.linkCmd })
test.capture [[
LINKCMD = $(DC) -o $(TARGET) $(ALL_LDFLAGS) $(LIBS) $(OBJECTS)
]]
end

View File

@ -0,0 +1,194 @@
---
-- d/tests/test_gmake.lua
-- Automated test suite for gmake project generation.
-- Copyright (c) 2011-2015 Manu Evans and the Premake project
---
local suite = test.declare("d_make")
local m = premake.modules.d
local make = premake.make
local project = premake.project
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, cfg
function suite.setup()
premake.escaper(make.esc)
wks = test.createWorkspace()
end
local function prepare()
prj = premake.workspace.getproject(wks, 1)
end
local function prepare_cfg(calls)
prj = premake.workspace.getproject(wks, 1)
local cfg = test.getconfig(prj, "Debug")
local toolset = premake.tools.dmd
premake.callArray(calls, cfg, toolset)
end
--
-- Check project generation
--
function suite.make_targetRules()
prepare()
m.make.targetRules(prj)
test.capture [[
$(TARGET): $(SOURCEFILES) $(LDDEPS)
@echo Building MyProject
$(SILENT) $(BUILDCMD)
$(POSTBUILDCMDS)
]]
end
function suite.make_targetRules_separateCompilation()
flags { "SeparateCompilation" }
prepare()
m.make.targetRules(prj)
test.capture [[
$(TARGET): $(OBJECTS) $(LDDEPS)
@echo Linking MyProject
$(SILENT) $(LINKCMD)
$(POSTBUILDCMDS)
]]
end
function suite.make_targetRules_mixedCompilation()
configuration { "Release" }
flags { "SeparateCompilation" }
prepare()
m.make.targetRules(prj)
test.capture [[
ifeq ($(config),debug)
$(TARGET): $(SOURCEFILES) $(LDDEPS)
@echo Building MyProject
$(SILENT) $(BUILDCMD)
$(POSTBUILDCMDS)
endif
ifeq ($(config),release)
$(TARGET): $(OBJECTS) $(LDDEPS)
@echo Linking MyProject
$(SILENT) $(LINKCMD)
$(POSTBUILDCMDS)
endif
]]
end
function suite.make_fileRules()
files { "blah.d" }
prepare()
m.make.dFileRules(prj)
test.capture [[
]]
end
function suite.make_fileRules_separateCompilation()
files { "blah.d" }
flags { "SeparateCompilation" }
prepare()
m.make.dFileRules(prj)
test.capture [[
$(OBJDIR)/blah.o: blah.d
@echo $(notdir $<)
$(SILENT) $(DC) $(ALL_DFLAGS) $(OUTPUTFLAG) -c $<
]]
end
function suite.make_fileRules_mixedCompilation()
files { "blah.d" }
configuration { "Release" }
flags { "SeparateCompilation" }
prepare()
m.make.dFileRules(prj)
test.capture [[
$(OBJDIR)/blah.o: blah.d
@echo $(notdir $<)
$(SILENT) $(DC) $(ALL_DFLAGS) $(OUTPUTFLAG) -c $<
]]
end
function suite.make_objects()
files { "blah.d" }
prepare()
m.make.objects(prj)
test.capture [[
SOURCEFILES := \
blah.d \
]]
end
function suite.make_objects_separateCompilation()
files { "blah.d" }
flags { "SeparateCompilation" }
prepare()
m.make.objects(prj)
test.capture [[
OBJECTS := \
$(OBJDIR)/blah.o \
]]
end
function suite.make_objects_mixedCompilation()
files { "blah.d" }
configuration { "Release" }
flags { "SeparateCompilation" }
files { "blah2.d" }
prepare()
m.make.objects(prj)
test.capture [[
SOURCEFILES := \
blah.d \
OBJECTS := \
$(OBJDIR)/blah.o \
ifeq ($(config),release)
SOURCEFILES += \
blah2.d \
OBJECTS += \
$(OBJDIR)/blah2.o \
endif
]]
end
--
-- Check configuration generation
--
function suite.make_allRules()
prepare_cfg({ m.make.allRules })
test.capture [[
all: $(TARGETDIR) prebuild prelink $(TARGET)
@:
]]
end
function suite.make_allRules_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.allRules })
test.capture [[
all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)
@:
]]
end

View File

@ -0,0 +1,105 @@
---
-- d/tests/test_dmd.lua
-- Automated test suite for dmd.
-- Copyright (c) 2011-2015 Manu Evans and the Premake project
---
local suite = test.declare("d_ldc")
local m = premake.modules.d
local make = premake.make
local project = premake.project
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, cfg
function suite.setup()
premake.escaper(make.esc)
wks = test.createWorkspace()
end
local function prepare_cfg(calls)
prj = premake.workspace.getproject(wks, 1)
local cfg = test.getconfig(prj, "Debug")
local toolset = premake.tools.ldc
premake.callArray(calls, cfg, toolset)
end
--
-- Check configuration generation
--
function suite.dmd_dTools()
prepare_cfg({ m.make.dTools })
test.capture [[
DC = ldc2
]]
end
function suite.dmd_target()
prepare_cfg({ m.make.target })
test.capture [[
]]
end
function suite.dmd_target_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.target })
test.capture [[
OUTPUTFLAG = -of="$@"
]]
end
function suite.dmd_versions()
versionlevel (10)
versionconstants { "A", "B" }
prepare_cfg({ m.make.versions })
test.capture [[
VERSIONS += -d-version=A -d-version=B -d-version=10
]]
end
function suite.dmd_debug()
debuglevel (10)
debugconstants { "A", "B" }
prepare_cfg({ m.make.debug })
test.capture [[
DEBUG += -d-debug=A -d-debug=B -d-debug=10
]]
end
function suite.dmd_imports()
includedirs { "dir1", "dir2/" }
prepare_cfg({ m.make.imports })
test.capture [[
IMPORTS += -I=dir1 -I=dir2
]]
end
function suite.dmd_dFlags()
prepare_cfg({ m.make.dFlags })
test.capture [[
ALL_DFLAGS += $(DFLAGS) -release $(VERSIONS) $(DEBUG) $(IMPORTS) $(ARCH)
]]
end
function suite.dmd_linkCmd()
prepare_cfg({ m.make.linkCmd })
test.capture [[
BUILDCMD = $(DC) -of=$(TARGET) $(ALL_DFLAGS) $(ALL_LDFLAGS) $(LIBS) $(SOURCEFILES)
]]
end
function suite.dmd_linkCmd_separateCompilation()
flags { "SeparateCompilation" }
prepare_cfg({ m.make.linkCmd })
test.capture [[
LINKCMD = $(DC) -of=$(TARGET) $(ALL_LDFLAGS) $(LIBS) $(OBJECTS)
]]
end

View File

@ -0,0 +1,74 @@
---
-- d/tests/test_visualstudio.lua
-- Automated test suite for VisualD project generation.
-- Copyright (c) 2011-2015 Manu Evans and the Premake project
---
local suite = test.declare("visual_d")
local m = premake.modules.d
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, cfg
function suite.setup()
premake.action.set("vs2010")
-- premake.escaper(premake.vstudio.vs2005.esc)
premake.indent(" ")
wks = workspace "MyWorkspace"
configurations { "Debug", "Release" }
language "D"
kind "ConsoleApp"
end
local function prepare()
prj = project "MyProject"
end
local function prepare_cfg()
prj = project "MyProject"
cfg = test.getconfig(prj, "Debug")
end
--
-- Check sln for the proper project entry
--
function suite.slnProj()
project "MyProject"
language "D"
premake.vstudio.sln2005.reorderProjects(wks)
premake.vstudio.sln2005.projects(wks)
test.capture [[
Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "MyProject", "MyProject.visualdproj", "{42B5DBC6-AE1F-903D-F75D-41E363076E92}"
EndProject
]]
end
--
-- Project tests
--
function suite.OnProject_header()
prepare()
m.visuald.header(prj)
test.capture [[
<DProject>
]]
end
function suite.OnProject_globals()
prepare()
m.visuald.globals(prj)
test.capture [[
<ProjectGuid>{42B5DBC6-AE1F-903D-F75D-41E363076E92}</ProjectGuid>
]]
end
-- TODO: break up the project gen and make lots more tests...

376
modules/d/tools/dmd.lua Normal file
View File

@ -0,0 +1,376 @@
--
-- d/tools/dmd.lua
-- Provides dmd-specific configuration strings.
-- Copyright (c) 2013-2015 Andrew Gough, Manu Evans, and the Premake project
--
local tdmd = {}
local project = premake.project
local config = premake.config
local d = premake.modules.d
--
-- Set default tools
--
tdmd.gcc = {}
tdmd.gcc.dc = "dmd"
tdmd.optlink = {}
tdmd.optlink.dc = "dmd"
-- /////////////////////////////////////////////////////////////////////////
-- dmd + GCC toolchain
-- /////////////////////////////////////////////////////////////////////////
--
-- Return a list of LDFLAGS for a specific configuration.
--
tdmd.gcc.ldflags = {
architecture = {
x86 = { "-m32" },
x86_64 = { "-m64" },
},
kind = {
SharedLib = "-shared",
StaticLib = "-lib",
}
}
function tdmd.gcc.getldflags(cfg)
local flags = config.mapFlags(cfg, tdmd.gcc.ldflags)
return flags
end
--
-- Return a list of decorated additional libraries directories.
--
tdmd.gcc.libraryDirectories = {
architecture = {
x86 = "-L-L/usr/lib",
x86_64 = "-L-L/usr/lib64",
}
}
function tdmd.gcc.getLibraryDirectories(cfg)
local flags = config.mapFlags(cfg, tdmd.gcc.libraryDirectories)
-- Scan the list of linked libraries. If any are referenced with
-- paths, add those to the list of library search paths
for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do
table.insert(flags, '-L-L' .. project.getrelative(cfg.project, dir))
end
return flags
end
--
-- Return the list of libraries to link, decorated with flags as needed.
--
function tdmd.gcc.getlinks(cfg, systemonly)
local result = {}
local links
if not systemonly then
links = config.getlinks(cfg, "siblings", "object")
for _, link in ipairs(links) do
-- skip external project references, since I have no way
-- to know the actual output target path
if not link.project.external then
if link.kind == premake.STATICLIB then
-- Don't use "-l" flag when linking static libraries; instead use
-- path/libname.a to avoid linking a shared library of the same
-- name if one is present
table.insert(result, "-L" .. project.getrelative(cfg.project, link.linktarget.abspath))
else
table.insert(result, "-L-l" .. link.linktarget.basename)
end
end
end
end
-- The "-l" flag is fine for system libraries
links = config.getlinks(cfg, "system", "fullpath")
for _, link in ipairs(links) do
if path.isframework(link) then
table.insert(result, "-framework " .. path.getbasename(link))
elseif path.isobjectfile(link) then
table.insert(result, "-L" .. link)
else
table.insert(result, "-L-l" .. path.getbasename(link))
end
end
return result
end
-- /////////////////////////////////////////////////////////////////////////
-- tdmd + OPTLINK toolchain
-- /////////////////////////////////////////////////////////////////////////
--
-- Return a list of LDFLAGS for a specific configuration.
--
tdmd.optlink.ldflags = {
architecture = {
x86 = { "-m32" },
x86_64 = { "-m64" },
},
kind = {
SharedLib = "-shared",
StaticLib = "-lib",
}
}
function tdmd.optlink.getldflags(cfg)
local flags = config.mapFlags(cfg, tdmd.optlink.ldflags)
return flags
end
--
-- Return a list of decorated additional libraries directories.
--
function tdmd.optlink.getLibraryDirectories(cfg)
local flags = {}
-- Scan the list of linked libraries. If any are referenced with
-- paths, add those to the list of library search paths
for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do
table.insert(flags, '-Llib "' .. project.getrelative(cfg.project, dir) .. '"')
end
return flags
end
--
-- Returns a list of linker flags for library names.
--
function tdmd.optlink.getlinks(cfg)
local result = {}
local links = config.getlinks(cfg, "dependencies", "object")
for _, link in ipairs(links) do
-- skip external project references, since I have no way
-- to know the actual output target path
if not link.project.externalname then
local linkinfo = config.getlinkinfo(link)
if link.kind == premake.STATICLIB then
table.insert(result, project.getrelative(cfg.project, linkinfo.abspath))
end
end
end
-- The "-l" flag is fine for system libraries
links = config.getlinks(cfg, "system", "basename")
for _, link in ipairs(links) do
if path.isobjectfile(link) then
table.insert(result, link)
elseif path.hasextension(link, premake.systems[cfg.system].staticlib.extension) then
table.insert(result, link)
end
end
return result
end
-- /////////////////////////////////////////////////////////////////////////
-- common dmd code (either toolchain)
-- /////////////////////////////////////////////////////////////////////////
-- if we are compiling on windows, we need to specialise to OPTLINK as the linker
-- OR!!! if cfg.system ~= premake.WINDOWS then
if string.match( os.getversion().description, "Windows" ) ~= nil then
-- TODO: on windows, we may use OPTLINK or MSLINK (for Win64)...
-- printf("TODO: select proper linker for 32/64 bit code")
premake.tools.dmd = tdmd.optlink
else
premake.tools.dmd = tdmd.gcc
end
local dmd = premake.tools.dmd
--
-- Returns list of D compiler flags for a configuration.
--
dmd.dflags = {
architecture = {
x86 = "-m32",
x86_64 = "-m64",
},
flags = {
CodeCoverage = "-cov",
Deprecated = "-d",
Documentation = "-D",
FatalWarnings = "-w",
GenerateHeader = "-H",
GenerateJSON = "-X",
GenerateMap = "-map",
NoBoundsCheck = "-noboundscheck",
Profile = "-profile",
Quiet = "-quiet",
-- Release = "-release",
RetainPaths = "-op",
SymbolsLikeC = "-gc",
UnitTest = "-unittest",
Verbose = "-v",
},
floatingpoint = {
None = "-nofloat",
},
optimize = {
On = "-O -inline",
Full = "-O -inline",
Size = "-O -inline",
Speed = "-O -inline",
},
pic = {
On = "-fPIC",
},
warnings = {
Default = "-wi",
Extra = "-wi",
},
symbols = {
On = "-g",
}
}
function dmd.getdflags(cfg)
local flags = config.mapFlags(cfg, dmd.dflags)
if config.isDebugBuild(cfg) then
table.insert(flags, "-debug")
else
table.insert(flags, "-release")
end
-- TODO: When DMD gets CRT options, map StaticRuntime and DebugRuntime
if cfg.flags.Documentation then
if cfg.docname then
table.insert(flags, "-Df" .. premake.quoted(cfg.docname))
end
if cfg.docdir then
table.insert(flags, "-Dd" .. premake.quoted(cfg.docdir))
end
end
if cfg.flags.GenerateHeader then
if cfg.headername then
table.insert(flags, "-Hf" .. premake.quoted(cfg.headername))
end
if cfg.headerdir then
table.insert(flags, "-Hd" .. premake.quoted(cfg.headerdir))
end
end
return flags
end
--
-- Decorate versions for the DMD command line.
--
function dmd.getversions(versions, level)
local result = {}
for _, version in ipairs(versions) do
table.insert(result, '-version=' .. version)
end
if level then
table.insert(result, '-version=' .. level)
end
return result
end
--
-- Decorate debug constants for the DMD command line.
--
function dmd.getdebug(constants, level)
local result = {}
for _, constant in ipairs(constants) do
table.insert(result, '-debug=' .. constant)
end
if level then
table.insert(result, '-debug=' .. level)
end
return result
end
--
-- Decorate import file search paths for the DMD command line.
--
function dmd.getimportdirs(cfg, dirs)
local result = {}
for _, dir in ipairs(dirs) do
dir = project.getrelative(cfg.project, dir)
table.insert(result, '-I' .. premake.quoted(dir))
end
return result
end
--
-- Returns the target name specific to compiler
--
function dmd.gettarget(name)
return "-of" .. name
end
--
-- Returns makefile-specific configuration rules.
--
dmd.makesettings = {
}
function dmd.getmakesettings(cfg)
local settings = config.mapFlags(cfg, dmd.makesettings)
return table.concat(settings)
end
--
-- Retrieves the executable command name for a tool, based on the
-- provided configuration and the operating environment.
--
-- @param cfg
-- The configuration to query.
-- @param tool
-- The tool to fetch, one of "dc" for the D compiler, or "ar" for the static linker.
-- @return
-- The executable command name for a tool, or nil if the system's
-- default value should be used.
--
dmd.tools = {
-- dmd will probably never support any foreign architectures...?
}
function dmd.gettoolname(cfg, tool)
local names = dmd.tools[cfg.architecture] or dmd.tools[cfg.system] or {}
local name = names[tool]
return name or dmd[tool]
end

292
modules/d/tools/gdc.lua Normal file
View File

@ -0,0 +1,292 @@
--
-- d/tools/gdc.lua
-- Provides GDC-specific configuration strings.
-- Copyright (c) 2013-2015 Andrew Gough, Manu Evans, and the Premake project
--
premake.tools.gdc = { }
local gdc = premake.tools.gdc
local project = premake.project
local config = premake.config
local d = premake.modules.d
--
-- Set default tools
--
gdc.dc = "gdc"
--
-- Returns list of D compiler flags for a configuration.
--
gdc.dflags = {
architecture = {
x86 = "-m32",
x86_64 = "-m64",
},
flags = {
Deprecated = "-fdeprecated",
Documentation = "-fdoc",
FatalWarnings = "-Werror",
GenerateHeader = "-fintfc",
GenerateJSON = "-fX",
NoBoundsCheck = "-fno-bounds-check",
-- Release = "-frelease",
RetainPaths = "-op",
SymbolsLikeC = "-fdebug-c",
UnitTest = "-funittest",
Verbose = "-fd-verbose",
},
floatingpoint = {
Fast = "-ffast-math",
Strict = "-ffloat-store",
},
optimize = {
Off = "-O0",
On = "-O2 -finline-functions",
Debug = "-Og",
Full = "-O3 -finline-functions",
Size = "-Os -finline-functions",
Speed = "-O3 -finline-functions",
},
pic = {
On = "-fPIC",
},
vectorextensions = {
AVX = "-mavx",
SSE = "-msse",
SSE2 = "-msse2",
},
warnings = {
-- Off = "-w",
-- Default = "-w", -- TODO: check this...
Extra = "-Wall -Wextra",
},
symbols = {
On = "-g",
}
}
function gdc.getdflags(cfg)
local flags = config.mapFlags(cfg, gdc.dflags)
if config.isDebugBuild(cfg) then
table.insert(flags, "-fdebug")
else
table.insert(flags, "-frelease")
end
-- TODO: When DMD gets CRT options, map StaticRuntime and DebugRuntime
if cfg.flags.Documentation then
if cfg.docname then
table.insert(flags, "-fdoc-file=" .. premake.quoted(cfg.docname))
end
if cfg.docdir then
table.insert(flags, "-fdoc-dir=" .. premake.quoted(cfg.docdir))
end
end
if cfg.flags.GenerateHeader then
if cfg.headername then
table.insert(flags, "-fintfc-file=" .. premake.quoted(cfg.headername))
end
if cfg.headerdir then
table.insert(flags, "-fintfc-dir=" .. premake.quoted(cfg.headerdir))
end
end
return flags
end
--
-- Decorate versions for the DMD command line.
--
function gdc.getversions(versions, level)
local result = {}
for _, version in ipairs(versions) do
table.insert(result, '-fversion=' .. version)
end
if level then
table.insert(result, '-fversion=' .. level)
end
return result
end
--
-- Decorate debug constants for the DMD command line.
--
function gdc.getdebug(constants, level)
local result = {}
for _, constant in ipairs(constants) do
table.insert(result, '-fdebug=' .. constant)
end
if level then
table.insert(result, '-fdebug=' .. level)
end
return result
end
--
-- Decorate import file search paths for the DMD command line.
--
function gdc.getimportdirs(cfg, dirs)
local result = {}
for _, dir in ipairs(dirs) do
dir = project.getrelative(cfg.project, dir)
table.insert(result, '-I' .. premake.quoted(dir))
end
return result
end
--
-- Returns the target name specific to compiler
--
function gdc.gettarget(name)
return "-o " .. name
end
--
-- Return a list of LDFLAGS for a specific configuration.
--
gdc.ldflags = {
architecture = {
x86 = { "-m32" },
x86_64 = { "-m64" },
},
kind = {
SharedLib = function(cfg)
local r = { iif(cfg.system == premake.MACOSX, "-dynamiclib", "-shared") }
if cfg.system == "windows" and not cfg.flags.NoImportLib then
table.insert(r, '-Wl,--out-implib="' .. cfg.linktarget.relpath .. '"')
end
return r
end,
WindowedApp = function(cfg)
if cfg.system == premake.WINDOWS then return "-mwindows" end
end,
},
}
function gdc.getldflags(cfg)
local flags = config.mapFlags(cfg, gdc.ldflags)
return flags
end
--
-- Return a list of decorated additional libraries directories.
--
gdc.libraryDirectories = {
architecture = {
x86 = "-L/usr/lib",
x86_64 = "-L/usr/lib64",
}
}
function gdc.getLibraryDirectories(cfg)
local flags = config.mapFlags(cfg, gdc.libraryDirectories)
-- Scan the list of linked libraries. If any are referenced with
-- paths, add those to the list of library search paths
for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do
table.insert(flags, '-Wl,-L' .. project.getrelative(cfg.project, dir))
end
return flags
end
--
-- Return the list of libraries to link, decorated with flags as needed.
--
function gdc.getlinks(cfg, systemonly)
local result = {}
local links
if not systemonly then
links = config.getlinks(cfg, "siblings", "object")
for _, link in ipairs(links) do
-- skip external project references, since I have no way
-- to know the actual output target path
if not link.project.external then
if link.kind == premake.STATICLIB then
-- Don't use "-l" flag when linking static libraries; instead use
-- path/libname.a to avoid linking a shared library of the same
-- name if one is present
table.insert(result, "-Wl," .. project.getrelative(cfg.project, link.linktarget.abspath))
else
table.insert(result, "-Wl,-l" .. link.linktarget.basename)
end
end
end
end
-- The "-l" flag is fine for system libraries
links = config.getlinks(cfg, "system", "fullpath")
for _, link in ipairs(links) do
if path.isframework(link) then
table.insert(result, "-framework " .. path.getbasename(link))
elseif path.isobjectfile(link) then
table.insert(result, "-Wl," .. link)
else
table.insert(result, "-Wl,-l" .. path.getbasename(link))
end
end
return result
end
--
-- Returns makefile-specific configuration rules.
--
gdc.makesettings = {
}
function gdc.getmakesettings(cfg)
local settings = config.mapFlags(cfg, gdc.makesettings)
return table.concat(settings)
end
--
-- Retrieves the executable command name for a tool, based on the
-- provided configuration and the operating environment.
--
-- @param cfg
-- The configuration to query.
-- @param tool
-- The tool to fetch, one of "dc" for the D compiler, or "ar" for the static linker.
-- @return
-- The executable command name for a tool, or nil if the system's
-- default value should be used.
--
gdc.tools = {
ps3 = {
dc = "ppu-lv2-gdc",
ar = "ppu-lv2-ar",
},
}
function gdc.gettoolname(cfg, tool)
local names = gdc.tools[cfg.architecture] or gdc.tools[cfg.system] or {}
local name = names[tool]
return name or gdc[tool]
end

286
modules/d/tools/ldc.lua Normal file
View File

@ -0,0 +1,286 @@
--
-- d/tools/ldc.lua
-- Provides LDC-specific configuration strings.
-- Copyright (c) 2013-2015 Andrew Gough, Manu Evans, and the Premake project
--
premake.tools.ldc = { }
local ldc = premake.tools.ldc
local project = premake.project
local config = premake.config
local d = premake.modules.d
--
-- Set default tools
--
ldc.namestyle = "posix"
--
-- Returns list of D compiler flags for a configuration.
--
ldc.dflags = {
architecture = {
x86 = "-m32",
x86_64 = "-m64",
-- arm = "-march=arm",
-- ppc = "-march=ppc32",
-- ppc64 = "-march=ppc64",
-- spu = "-march=cellspu",
-- mips = "-march=mips", -- -march=mipsel?
},
flags = {
Deprecated = "-d",
Documentation = "-D",
FatalWarnings = "-w", -- Use LLVM flag? : "-fatal-assembler-warnings",
GenerateHeader = "-H",
GenerateJSON = "-X",
NoBoundsCheck = "-disable-boundscheck",
-- Release = "-release",
RetainPaths = "-op",
SymbolsLikeC = "-gc",
UnitTest = "-unittest",
Verbose = "-v",
},
floatingpoint = {
Fast = "-fp-contract=fast -enable-unsafe-fp-math",
-- Strict = "-ffloat-store",
},
optimize = {
Off = "-O0",
On = "-O2",
Debug = "-O0",
Full = "-O3",
Size = "-Oz",
Speed = "-O3",
},
pic = {
On = "-relocation-model=pic",
},
vectorextensions = {
AVX = "-mattr=+avx",
SSE = "-mattr=+sse",
SSE2 = "-mattr=+sse2",
},
warnings = {
Default = "-wi",
Extra = "-wi", -- TODO: is there a way to get extra warnings?
},
symbols = {
On = "-g",
}
}
function ldc.getdflags(cfg)
local flags = config.mapFlags(cfg, ldc.dflags)
if config.isDebugBuild(cfg) then
table.insert(flags, "-d-debug")
else
table.insert(flags, "-release")
end
-- TODO: When DMD gets CRT options, map StaticRuntime and DebugRuntime
if cfg.flags.Documentation then
if cfg.docname then
table.insert(flags, "-Df=" .. premake.quoted(cfg.docname))
end
if cfg.docdir then
table.insert(flags, "-Dd=" .. premake.quoted(cfg.docdir))
end
end
if cfg.flags.GenerateHeader then
if cfg.headername then
table.insert(flags, "-Hf=" .. premake.quoted(cfg.headername))
end
if cfg.headerdir then
table.insert(flags, "-Hd=" .. premake.quoted(cfg.headerdir))
end
end
return flags
end
--
-- Decorate versions for the DMD command line.
--
function ldc.getversions(versions, level)
local result = {}
for _, version in ipairs(versions) do
table.insert(result, '-d-version=' .. version)
end
if level then
table.insert(result, '-d-version=' .. level)
end
return result
end
--
-- Decorate debug constants for the DMD command line.
--
function ldc.getdebug(constants, level)
local result = {}
for _, constant in ipairs(constants) do
table.insert(result, '-d-debug=' .. constant)
end
if level then
table.insert(result, '-d-debug=' .. level)
end
return result
end
--
-- Decorate import file search paths for the DMD command line.
--
function ldc.getimportdirs(cfg, dirs)
local result = {}
for _, dir in ipairs(dirs) do
dir = project.getrelative(cfg.project, dir)
table.insert(result, '-I=' .. premake.quoted(dir))
end
return result
end
--
-- Returns the target name specific to compiler
--
function ldc.gettarget(name)
return "-of=" .. name
end
--
-- Return a list of LDFLAGS for a specific configuration.
--
ldc.ldflags = {
architecture = {
x86 = { "-m32" },
x86_64 = { "-m64" },
},
kind = {
SharedLib = "-shared",
StaticLib = "-lib",
},
}
function ldc.getldflags(cfg)
local flags = config.mapFlags(cfg, ldc.ldflags)
return flags
end
--
-- Return a list of decorated additional libraries directories.
--
ldc.libraryDirectories = {
architecture = {
x86 = "-L=-L/usr/lib",
x86_64 = "-L=-L/usr/lib64",
}
}
function ldc.getLibraryDirectories(cfg)
local flags = config.mapFlags(cfg, ldc.libraryDirectories)
-- Scan the list of linked libraries. If any are referenced with
-- paths, add those to the list of library search paths
for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do
table.insert(flags, '-L=-L' .. project.getrelative(cfg.project, dir))
end
return flags
end
--
-- Return the list of libraries to link, decorated with flags as needed.
--
function ldc.getlinks(cfg, systemonly)
local result = {}
local links
if not systemonly then
links = config.getlinks(cfg, "siblings", "object")
for _, link in ipairs(links) do
-- skip external project references, since I have no way
-- to know the actual output target path
if not link.project.external then
if link.kind == premake.STATICLIB then
-- Don't use "-l" flag when linking static libraries; instead use
-- path/libname.a to avoid linking a shared library of the same
-- name if one is present
table.insert(result, "-L=" .. project.getrelative(cfg.project, link.linktarget.abspath))
else
table.insert(result, "-L=-l" .. link.linktarget.basename)
end
end
end
end
-- The "-l" flag is fine for system libraries
links = config.getlinks(cfg, "system", "fullpath")
for _, link in ipairs(links) do
if path.isframework(link) then
table.insert(result, "-framework " .. path.getbasename(link))
elseif path.isobjectfile(link) then
table.insert(result, "-L=" .. link)
else
table.insert(result, "-L=-l" .. path.getbasename(link))
end
end
return result
end
--
-- Returns makefile-specific configuration rules.
--
ldc.makesettings = {
}
function ldc.getmakesettings(cfg)
local settings = config.mapFlags(cfg, ldc.makesettings)
return table.concat(settings)
end
--
-- Retrieves the executable command name for a tool, based on the
-- provided configuration and the operating environment.
--
-- @param cfg
-- The configuration to query.
-- @param tool
-- The tool to fetch, one of "dc" for the D compiler, or "ar" for the static linker.
-- @return
-- The executable command name for a tool, or nil if the system's
-- default value should be used.
--
ldc.tools = {
dc = "ldc2",
ar = "ar",
}
function ldc.gettoolname(cfg, tool)
return ldc.tools[tool]
end

@ -1 +0,0 @@
Subproject commit 4a9f26f9a46795cb46492f32f1814ff74c23a339

@ -1 +0,0 @@
Subproject commit 4970a7b6bdaab013b2da0de590031e2650e78950

9
modules/raw/README.md Normal file
View File

@ -0,0 +1,9 @@
Premake extension to support writing the raw lua tables.
### Usage ###
Simply generate your project using the `raw` action:
```bash
premake5 raw
```
and open the generated workspace.raw file in any text editor.

View File

@ -0,0 +1,5 @@
return {
"_preload.lua",
"raw.lua",
"raw_action.lua",
}

20
modules/raw/_preload.lua Normal file
View File

@ -0,0 +1,20 @@
newaction
{
trigger = "raw",
shortname = "Raw output",
description = "Generate raw representation of Premake structures",
valid_kinds = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib", "Makefile", "None", "Utility" },
valid_languages = { "C", "C++" },
valid_tools = { cc = { "clang" } },
onsolution = function(sln)
require('raw')
premake.generate(sln, ".raw", premake.raw.solution)
end,
}
return function(cfg)
return (_ACTION == "raw")
end

11
modules/raw/raw.lua Normal file
View File

@ -0,0 +1,11 @@
local p = premake
p.modules.raw = {}
local m = p.modules.raw
m.elements = {}
dofile("_preload.lua")
dofile("raw_action.lua")
return m

View File

@ -0,0 +1,75 @@
premake.raw = { }
local raw = premake.raw
local gvisited = { }
function raw.solution(sln)
if not gvisited[sln.global] then
gvisited[sln.global] = true
raw.printTable({ global = sln.global })
end
end
function raw.printTable(t, i)
i = i or 0
placement = raw._createPlacement(t)
raw._printTableRecursive(t, i, placement)
end
function raw._printTableRecursive(t, i, placement)
elements = { }
for k, v in pairs(t) do
table.insert(elements, { key = k, value = v })
end
table.sort(elements, function(a, b)
local n1 = type(a.key) == "number"
local n2 = type(b.key) == "number"
if n1 ~= n2 then
return n1
end
local k1 = n1 and a.key or raw._encode(a.key)
local k2 = n2 and b.key or raw._encode(b.key)
return k1 < k2
end)
for _, elem in ipairs(elements) do
p = placement[elem.value]
if p and elem.key == p.key and t == p.parent then
_p(i, "%s", raw._encode(elem.key) .. ': ' .. raw._encode(elem.value) .. ' {')
raw._printTableRecursive(elem.value, i + 1, placement)
_p(i, '} # ' .. raw._encode(elem.key))
else
_p(i, "%s", raw._encode(elem.key) .. ': ' .. raw._encode(elem.value))
end
end
end
function raw._createPlacement(tbl)
placement = { }
placementList = { tbl }
while #placementList ~= 0 do
parentList = { }
for _, parent in ipairs(placementList) do
for k, v in pairs(parent) do
if type(v) == "table" and not placement[v] then
table.insert(parentList, v)
placement[v] = {
parent = parent,
key = k
}
end
end
end
placementList = parentList
end
return placement
end
function raw._encode(v)
if type(v) == "string" then
return '"' .. v .. '"'
else
return tostring(v)
end
end

@ -1 +0,0 @@
Subproject commit 9427f3373074795b16d25d2efcc836c2a2501902

27
modules/xcode/LICENSE.TXT Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2003-2015 Jason Perkins, Mihai Sebea and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of Premake nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,7 @@
return {
"_preload.lua",
"xcode.lua",
"xcode4_workspace.lua",
"xcode_common.lua",
"xcode_project.lua",
}

View File

@ -0,0 +1,66 @@
---
-- xcode/_preload.lua
-- Define the Apple XCode actions and new APIs.
-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
---
local p = premake
--
-- Register new Xcode-specific project fields.
--
p.api.register {
name = "xcodebuildsettings",
scope = "config",
kind = "key-array",
}
p.api.register {
name = "xcodebuildresources",
scope = "config",
kind = "list",
}
--
-- Register the Xcode exporters.
--
newaction {
trigger = "xcode4",
shortname = "Apple Xcode 4",
description = "Generate Apple Xcode 4 project files",
-- Xcode always uses Mac OS X path and naming conventions
os = "macosx",
-- The capabilities of this action
valid_kinds = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib", "Makefile", "None" },
valid_languages = { "C", "C++" },
valid_tools = {
cc = { "gcc", "clang" },
},
-- Workspace and project generation logic
onWorkspace = function(wks)
p.generate(wks, ".xcworkspace/contents.xcworkspacedata", p.modules.xcode.generateWorkspace)
end,
onProject = function(prj)
p.generate(prj, ".xcodeproj/project.pbxproj", p.modules.xcode.generateProject)
end,
}
--
-- Decide when the full module should be loaded.
--
return function(cfg)
return (_ACTION == "xcode4")
end

View File

@ -0,0 +1,9 @@
require ("xcode")
return {
"test_header_footer.lua",
"test_xcode4_project.lua",
"test_xcode4_workspace.lua",
"test_xcode_dependencies.lua",
"test_xcode_project.lua",
}

View File

@ -0,0 +1,48 @@
---
-- xcode/tests/test_header.lua
-- Validate generation for Xcode workspaces.
-- Author Jason Perkins
-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
---
local suite = test.declare("xcode_header")
local xcode = premake.modules.xcode
--
-- Setup
--
local wks
function suite.setup()
wks = test.createWorkspace()
end
local function prepare()
prj = test.getproject(wks, 1)
xcode.header(prj)
xcode.footer(prj)
end
--
-- Check basic structure
--
function suite.onDefaults()
prepare()
test.capture [[
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}
]]
end

View File

@ -0,0 +1,94 @@
---
-- tests/actions/xcode/test_xcode4_project.lua
-- Automated test suite for Xcode project generation.
-- Copyright (c) 2011-2015 Jason Perkins and the Premake project
---
local suite = test.declare("xcode4_proj")
local xcode = premake.modules.xcode
--
-- Replacement for xcode.newid(). Creates a synthetic ID based on the node name,
-- its intended usage (file ID, build ID, etc.) and its place in the tree. This
-- makes it easier to tell if the right ID is being used in the right places.
--
xcode.used_ids = {}
xcode.newid = function(node, usage)
local name = node
if usage then
name = name .. ":" .. usage
end
if xcode.used_ids[name] then
local count = xcode.used_ids[name] + 1
xcode.used_ids[name] = count
name = name .. "(" .. count .. ")"
else
xcode.used_ids[name] = 1
end
return "[" .. name .. "]"
end
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local tr, wks
function suite.teardown()
tr = nil
end
function suite.setup()
_OS = "macosx"
_ACTION = "xcode4"
io.eol = "\n"
xcode.used_ids = { } -- reset the list of generated IDs
wks = test.createWorkspace()
end
local function prepare()
wks = premake.oven.bakeWorkspace(wks)
xcode.prepareWorkspace(wks)
local prj = premake.workspace.getproject(wks, 1)
tr = xcode.buildprjtree(prj)
end
---------------------------------------------------------------------------
-- XCBuildConfiguration_Project tests
---------------------------------------------------------------------------
function suite.XCBuildConfigurationProject_OnSymbols()
symbols "On"
prepare()
xcode.XCBuildConfiguration_Project(tr, tr.configs[1])
test.capture [[
[MyProject:Debug(2)] /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
CONFIGURATION_BUILD_DIR = "$(SYMROOT)";
CONFIGURATION_TEMP_DIR = "$(OBJROOT)";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
OBJROOT = obj/Debug;
ONLY_ACTIVE_ARCH = YES;
SYMROOT = bin/Debug;
};
name = Debug;
};
]]
end

View File

@ -0,0 +1,109 @@
---
-- xcode/tests/test_xcode4_workspace.lua
-- Validate generation for Xcode workspaces.
-- Author Mihai Sebea
-- Modified by Jason Perkins
-- Copyright (c) 2014-2015 Jason Perkins and the Premake project
---
local suite = test.declare("xcode4_workspace")
local xcode = premake.modules.xcode
--
-- Setup
--
local wks, prj
function suite.setup()
_ACTION = "xcode4"
wks = test.createWorkspace()
end
local function prepare()
wks = test.getWorkspace(wks)
xcode.generateWorkspace(wks)
end
--
-- Check the basic structure of a workspace.
--
function suite.onEmptyWorkspace()
wks.projects = {}
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
</Workspace>
]]
end
function suite.onDefaultWorkspace()
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:MyProject.xcodeproj">
</FileRef>
</Workspace>
]]
end
function suite.onMultipleProjects()
test.createproject(wks)
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:MyProject.xcodeproj">
</FileRef>
<FileRef
location = "group:MyProject2.xcodeproj">
</FileRef>
</Workspace>
]]
end
--
-- Projects should include relative path from workspace.
--
function suite.onNestedProjectPath()
location "MyProject"
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:MyProject/MyProject.xcodeproj">
</FileRef>
</Workspace>
]]
end
function suite.onExternalProjectPath()
location "../MyProject"
prepare()
test.capture [[
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:../MyProject/MyProject.xcodeproj">
</FileRef>
</Workspace>
]]
end

View File

@ -0,0 +1,317 @@
--
-- tests/actions/xcode/test_xcode_dependencies.lua
-- Automated test suite for Xcode project dependencies.
-- Copyright (c) 2009-2011 Jason Perkins and the Premake project
--
local suite = test.declare("xcode_deps")
local xcode = premake.modules.xcode
---------------------------------------------------------------------------
-- Setup/Teardown
---------------------------------------------------------------------------
local wks, prj, prj2, tr
function suite.teardown()
wks = nil
prj = nil
prj2 = nil
tr = nil
end
function suite.setup()
_ACTION = "xcode4"
xcode.used_ids = { } -- reset the list of generated IDs
wks, prj = test.createWorkspace()
links { "MyProject2" }
prj2 = test.createproject(wks)
kind "StaticLib"
configuration "Debug"
targetsuffix "-d"
end
local function prepare()
wks = premake.oven.bakeWorkspace(wks)
xcode.prepareWorkspace(wks)
local prj3 = premake.workspace.getproject(wks, 1)
--prj2 = test.getproject(wks, 2)
tr = xcode.buildprjtree(prj3)
end
---------------------------------------------------------------------------
-- PBXBuildFile tests
---------------------------------------------------------------------------
function suite.PBXBuildFile_ListsDependencyTargets_OnStaticLib()
prepare()
xcode.PBXBuildFile(tr)
test.capture [[
/* Begin PBXBuildFile section */
[libMyProject2-d.a:build] /* libMyProject2-d.a in Frameworks */ = {isa = PBXBuildFile; fileRef = [libMyProject2-d.a] /* libMyProject2-d.a */; };
/* End PBXBuildFile section */
]]
end
function suite.PBXBuildFile_ListsDependencyTargets_OnSharedLib()
kind "SharedLib"
prepare()
xcode.PBXBuildFile(tr)
test.capture [[
/* Begin PBXBuildFile section */
[libMyProject2-d.dylib:build] /* libMyProject2-d.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = [libMyProject2-d.dylib] /* libMyProject2-d.dylib */; };
/* End PBXBuildFile section */
]]
end
---------------------------------------------------------------------------
-- PBXContainerItemProxy tests
---------------------------------------------------------------------------
function suite.PBXContainerItemProxy_ListsProjectConfigs()
prepare()
xcode.PBXContainerItemProxy(tr)
test.capture [[
/* Begin PBXContainerItemProxy section */
[MyProject2.xcodeproj:prodprox] /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = [MyProject2.xcodeproj] /* MyProject2.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = [libMyProject2-d.a:product];
remoteInfo = "libMyProject2-d.a";
};
[MyProject2.xcodeproj:targprox] /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = [MyProject2.xcodeproj] /* MyProject2.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = [libMyProject2-d.a:target];
remoteInfo = "libMyProject2-d.a";
};
/* End PBXContainerItemProxy section */
]]
end
---------------------------------------------------------------------------
-- PBXFileReference tests
---------------------------------------------------------------------------
function suite.PBXFileReference_ListsDependencies()
prepare()
xcode.PBXFileReference(tr)
test.capture [[
/* Begin PBXFileReference section */
[MyProject2.xcodeproj] /* libMyProject2-d.a */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MyProject2.xcodeproj"; path = MyProject2.xcodeproj; sourceTree = SOURCE_ROOT; };
[MyProject:product] /* MyProject */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = MyProject; path = MyProject; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
]]
end
function suite.PBXFileReference_UsesRelativePaths()
prj.location = "MyProject"
prj2.location = "MyProject2"
prepare()
xcode.PBXFileReference(tr)
test.capture [[
/* Begin PBXFileReference section */
[MyProject2.xcodeproj] /* libMyProject2-d.a */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MyProject2.xcodeproj"; path = ../MyProject2.xcodeproj; sourceTree = SOURCE_ROOT; };
[MyProject:product] /* MyProject */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = MyProject; path = MyProject; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
]]
end
---------------------------------------------------------------------------
-- PBXFrameworksBuildPhase tests
---------------------------------------------------------------------------
function suite.PBXFrameworksBuildPhase_ListsDependencies_OnStaticLib()
prepare()
xcode.PBXFrameworksBuildPhase(tr)
test.capture [[
/* Begin PBXFrameworksBuildPhase section */
[MyProject:fxs] /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
[libMyProject2-d.a:build] /* libMyProject2-d.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
]]
end
function suite.PBXFrameworksBuildPhase_ListsDependencies_OnSharedLib()
kind "SharedLib"
prepare()
xcode.PBXFrameworksBuildPhase(tr)
test.capture [[
/* Begin PBXFrameworksBuildPhase section */
[MyProject:fxs] /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
[libMyProject2-d.dylib:build] /* libMyProject2-d.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
]]
end
---------------------------------------------------------------------------
-- PBXGroup tests
---------------------------------------------------------------------------
function suite.PBXGroup_ListsDependencies()
prepare()
xcode.PBXGroup(tr)
test.capture [[
/* Begin PBXGroup section */
[MyProject2.xcodeproj:prodgrp] /* Products */ = {
isa = PBXGroup;
children = (
[libMyProject2-d.a] /* libMyProject2-d.a */,
);
name = Products;
sourceTree = "<group>";
};
[MyProject] /* MyProject */ = {
isa = PBXGroup;
children = (
[Products] /* Products */,
[Projects] /* Projects */,
);
name = MyProject;
sourceTree = "<group>";
};
[Products] /* Products */ = {
isa = PBXGroup;
children = (
[MyProject:product] /* MyProject */,
);
name = Products;
sourceTree = "<group>";
};
[Projects] /* Projects */ = {
isa = PBXGroup;
children = (
[MyProject2.xcodeproj] /* MyProject2.xcodeproj */,
);
name = Projects;
sourceTree = "<group>";
};
/* End PBXGroup section */
]]
end
---------------------------------------------------------------------------
-- PBXNativeTarget tests
---------------------------------------------------------------------------
function suite.PBXNativeTarget_ListsDependencies()
prepare()
xcode.PBXNativeTarget(tr)
test.capture [[
/* Begin PBXNativeTarget section */
[MyProject:target] /* MyProject */ = {
isa = PBXNativeTarget;
buildConfigurationList = [MyProject:cfg] /* Build configuration list for PBXNativeTarget "MyProject" */;
buildPhases = (
[MyProject:rez] /* Resources */,
[MyProject:src] /* Sources */,
[MyProject:fxs] /* Frameworks */,
);
buildRules = (
);
dependencies = (
[MyProject2.xcodeproj:targdep] /* PBXTargetDependency */,
);
name = MyProject;
productInstallPath = "$(HOME)/bin";
productName = MyProject;
productReference = [MyProject:product] /* MyProject */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
]]
end
---------------------------------------------------------------------------
-- PBXProject tests
---------------------------------------------------------------------------
function suite.PBXProject_ListsDependencies()
prepare()
xcode.PBXProject(tr)
test.capture [[
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "MyProject" */;
compatibilityVersion = "Xcode 3.2";
hasScannedForEncodings = 1;
mainGroup = [MyProject] /* MyProject */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = [MyProject2.xcodeproj:prodgrp] /* Products */;
ProjectRef = [MyProject2.xcodeproj] /* MyProject2.xcodeproj */;
},
);
projectRoot = "";
targets = (
[MyProject:target] /* MyProject */,
);
};
/* End PBXProject section */
]]
end
---------------------------------------------------------------------------
-- PBXReferenceProxy tests
---------------------------------------------------------------------------
function suite.PBXReferenceProxy_ListsDependencies()
prepare()
xcode.PBXReferenceProxy(tr)
test.capture [[
/* Begin PBXReferenceProxy section */
[libMyProject2-d.a] /* libMyProject2-d.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libMyProject2-d.a";
remoteRef = [MyProject2.xcodeproj:prodprox] /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
]]
end
---------------------------------------------------------------------------
-- PBXTargetDependency tests
---------------------------------------------------------------------------
function suite.PBXTargetDependency_ListsDependencies()
prepare()
xcode.PBXTargetDependency(tr)
test.capture [[
/* Begin PBXTargetDependency section */
[MyProject2.xcodeproj:targdep] /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "libMyProject2-d.a";
targetProxy = [MyProject2.xcodeproj:targprox] /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
]]
end

File diff suppressed because it is too large Load Diff

19
modules/xcode/xcode.lua Normal file
View File

@ -0,0 +1,19 @@
---
-- xcode/xcode.lua
-- Common support code for the Apple Xcode exporters.
-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
---
local p = premake
p.modules.xcode = {}
local m = p.modules.xcode
m._VERSION = p._VERSION
m.elements = {}
include("xcode_common.lua")
include("xcode4_workspace.lua")
include("xcode_project.lua")
return m

View File

@ -0,0 +1,84 @@
---
-- xcode/xcode4_workspace.lua
-- Generate an Xcode workspace.
-- Author Mihai Sebea
-- Modified by Jason Perkins
-- Copyright (c) 2014-2015 Jason Perkins and the Premake project
---
local p = premake
local m = p.modules.xcode
---
-- Generate an Xcode contents.xcworkspacedata file.
---
m.elements.workspace = function(wks)
return {
m.xmlDeclaration,
m.workspace,
m.workspaceFileRefs,
m.workspaceTail,
}
end
function m.generateWorkspace(wks)
m.prepareWorkspace(wks)
p.callArray(m.elements.workspace, wks)
end
function m.workspace()
p.push('<Workspace')
p.w('version = "1.0">')
end
function m.workspaceTail()
-- Don't output final newline. Xcode doesn't.
premake.out('</Workspace>')
end
---
-- Generate the list of project references.
---
m.elements.workspaceFileRef = function(prj)
return {
m.workspaceLocation,
}
end
function m.workspaceFileRefs(wks)
for prj in p.workspace.eachproject(wks) do
p.push('<FileRef')
local contents = p.capture(function()
p.callArray(m.elements.workspaceFileRef, prj)
end)
p.outln(contents .. ">")
p.pop('</FileRef>')
end
end
---------------------------------------------------------------------------
--
-- Handlers for individual project elements
--
---------------------------------------------------------------------------
function m.workspaceLocation(prj)
local fname = p.filename(prj, ".xcodeproj")
fname = path.getrelative(prj.workspace.location, fname)
p.w('location = "group:%s"', fname)
end
function m.xmlDeclaration()
p.xmlUtf8(true)
end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
---
-- xcode/xcode4_project.lua
-- Generate an Xcode project file.
-- Author Jason Perkins
-- Modified by Mihai Sebea
-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
---
local p = premake
local m = p.modules.xcode
local xcode = p.modules.xcode
local project = p.project
local config = p.config
local fileconfig = p.fileconfig
local tree = p.tree
--
-- Create a tree corresponding to what is shown in the Xcode project browser
-- pane, with nodes for files and folders, resources, frameworks, and products.
--
-- @param prj
-- The project being generated.
-- @returns
-- A tree, loaded with metadata, which mirrors Xcode's view of the project.
--
function xcode.buildprjtree(prj)
local tr = project.getsourcetree(prj, nil , false)
tr.project = prj
-- create a list of build configurations and assign IDs
tr.configs = {}
for cfg in project.eachconfig(prj) do
cfg.xcode = {}
cfg.xcode.targetid = xcode.newid(prj.xcode.projectnode.name, cfg.buildcfg, "target")
cfg.xcode.projectid = xcode.newid(tr.name, cfg.buildcfg)
table.insert(tr.configs, cfg)
end
-- convert localized resources from their filesystem layout (English.lproj/MainMenu.xib)
-- to Xcode's display layout (MainMenu.xib/English).
tree.traverse(tr, {
onbranch = function(node)
if path.getextension(node.name) == ".lproj" then
local lang = path.getbasename(node.name) -- "English", "French", etc.
-- create a new language group for each file it contains
for _, filenode in ipairs(node.children) do
local grpnode = node.parent.children[filenode.name]
if not grpnode then
grpnode = tree.insert(node.parent, tree.new(filenode.name))
grpnode.kind = "vgroup"
end
-- convert the file node to a language node and add to the group
filenode.name = path.getbasename(lang)
tree.insert(grpnode, filenode)
end
-- remove this directory from the tree
tree.remove(node)
end
end
})
-- the special folder "Frameworks" lists all linked frameworks
tr.frameworks = tree.new("Frameworks")
for cfg in project.eachconfig(prj) do
for _, link in ipairs(config.getlinks(cfg, "system", "fullpath")) do
local name = path.getname(link)
if xcode.isframework(name) and not tr.frameworks.children[name] then
node = tree.insert(tr.frameworks, tree.new(name))
node.path = link
end
end
end
-- only add it to the tree if there are frameworks to link
if #tr.frameworks.children > 0 then
tree.insert(tr, tr.frameworks)
end
-- the special folder "Products" holds the target produced by the project; this
-- is populated below
tr.products = tree.insert(tr, tree.new("Products"))
-- the special folder "Projects" lists sibling project dependencies
tr.projects = tree.new("Projects")
for _, dep in ipairs(project.getdependencies(prj, "sibling", "object")) do
-- create a child node for the dependency's xcodeproj
local xcpath = xcode.getxcodeprojname(dep)
local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath)))
xcnode.path = xcpath
xcnode.project = dep
xcnode.productgroupid = xcode.newid(xcnode.name, "prodgrp")
xcnode.productproxyid = xcode.newid(xcnode.name, "prodprox")
xcnode.targetproxyid = xcode.newid(xcnode.name, "targprox")
xcnode.targetdependid = xcode.newid(xcnode.name, "targdep")
-- create a grandchild node for the dependency's link target
local lprj = premake.workspace.findproject(prj.workspace, dep.name)
local cfg = project.findClosestMatch(lprj, prj.configurations[1])
node = tree.insert(xcnode, tree.new(cfg.linktarget.name))
node.path = cfg.linktarget.fullpath
node.cfg = cfg
end
if #tr.projects.children > 0 then
tree.insert(tr, tr.projects)
end
-- Final setup
tree.traverse(tr, {
onnode = function(node)
-- assign IDs to every node in the tree
node.id = xcode.newid(node.name, nil, node.path)
node.isResource = xcode.isItemResource(prj, node)
-- assign build IDs to buildable files
if xcode.getbuildcategory(node) then
node.buildid = xcode.newid(node.name, "build", node.path)
end
-- remember key files that are needed elsewhere
if string.endswith(node.name, "Info.plist") then
tr.infoplist = node
end
end
}, true)
-- Plug in the product node into the Products folder in the tree. The node
-- was built in xcode.prepareWorkspace() in xcode_common.lua; it contains IDs
-- that are necessary for inter-project dependencies
node = tree.insert(tr.products, prj.xcode.projectnode)
node.kind = "product"
node.path = node.cfg.buildtarget.fullpath
node.cfgsection = xcode.newid(node.name, "cfg")
node.resstageid = xcode.newid(node.name, "rez")
node.sourcesid = xcode.newid(node.name, "src")
node.fxstageid = xcode.newid(node.name, "fxs")
return tr
end
---
-- Generate an Xcode .xcodeproj for a Premake project.
---
m.elements.project = function(prj)
return {
m.header,
}
end
function m.generateProject(prj)
local tr = xcode.buildprjtree(prj)
p.callArray(m.elements.project, prj)
xcode.PBXBuildFile(tr)
xcode.PBXContainerItemProxy(tr)
xcode.PBXFileReference(tr)
xcode.PBXFrameworksBuildPhase(tr)
xcode.PBXGroup(tr)
xcode.PBXNativeTarget(tr)
xcode.PBXProject(tr)
xcode.PBXReferenceProxy(tr)
xcode.PBXResourcesBuildPhase(tr)
xcode.PBXShellScriptBuildPhase(tr)
xcode.PBXSourcesBuildPhase(tr)
xcode.PBXTargetDependency(tr)
xcode.PBXVariantGroup(tr)
xcode.XCBuildConfiguration(tr)
xcode.XCBuildConfigurationList(tr)
xcode.footer(prj)
end
function m.header(prj)
p.w('// !$*UTF8*$!')
p.push('{')
p.w('archiveVersion = 1;')
p.w('classes = {')
p.w('};')
p.w('objectVersion = 46;')
p.push('objects = {')
p.w()
end
function xcode.footer(prj)
p.pop('};')
p.w('rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;')
p.pop('}')
end

View File

@ -9,7 +9,7 @@ PREP
* Update CHANGES.txt and CONTRIBUTORS.txt
* Update version in src/host/premake.c and commit
* Update version in src/host/premake.h and commit
* Push release branch to GitHub; wait for CI to pass

View File

@ -6,7 +6,6 @@
return {
"xcode",
"monodevelop",
"codelite",
"d",
}

View File

@ -845,6 +845,7 @@
kind = "list:string",
tokens = true,
pathVars = true,
allowDuplicates = true,
}
api.register {
@ -861,6 +862,7 @@
kind = "list:string",
tokens = true,
pathVars = true,
allowDuplicates = true,
}
api.register {
@ -1494,4 +1496,7 @@
filter { "kind:SharedLib", "system:not Windows" }
pic "On"
filter { "system:macosx" }
toolset "clang"
filter {}

View File

@ -410,7 +410,7 @@
function make.forceInclude(cfg, toolset)
local includes = toolset.getforceincludes(cfg)
if not cfg.flags.NoPCH and cfg.pchheader then
table.insert(includes, "-include $(OBJDIR)/$(notdir $(PCH))")
table.insert(includes, 1, "-include $(OBJDIR)/$(notdir $(PCH))")
end
_x(' FORCE_INCLUDE +=%s', make.list(includes))
end
@ -445,7 +445,7 @@
if cfg.architecture == premake.UNIVERSAL then
_p(' LINKCMD = libtool -o "$@" $(OBJECTS)')
else
_p(' LINKCMD = $(AR) -rcs "$@" $(OBJECTS)')
_p(' LINKCMD = $(AR) ' .. (toolset.arargs or '-rcs') ..' "$@" $(OBJECTS)')
end
elseif cfg.kind == premake.UTILITY then
-- Empty LINKCMD for Utility (only custom build rules)

View File

@ -237,6 +237,8 @@
m.nmakeCommandLine(cfg, cfg.buildcommands, "Build")
m.nmakeCommandLine(cfg, cfg.rebuildcommands, "ReBuild")
m.nmakeCommandLine(cfg, cfg.cleancommands, "Clean")
m.nmakePreprocessorDefinitions(cfg, cfg.defines, false, nil)
m.nmakeIncludeDirs(cfg, cfg.includedirs)
p.pop('</PropertyGroup>')
end
end
@ -308,7 +310,6 @@
m.clCompileAdditionalUsingDirectories,
m.forceIncludes,
m.debugInformationFormat,
m.programDataBaseFileName,
m.optimization,
m.functionLevelLinking,
m.intrinsicFunctions,
@ -409,6 +410,7 @@
m.largeAddressAware,
m.targetMachine,
m.additionalLinkOptions,
m.programDatabaseFile,
}
end
end
@ -431,6 +433,8 @@
m.elements.lib = function(cfg, explicit)
if cfg.kind == p.STATICLIB then
return {
m.additionalDependencies,
m.additionalLibraryDirectories,
m.treatLinkerWarningAsErrors,
m.targetMachine,
m.additionalLinkOptions,
@ -1177,10 +1181,10 @@
function m.debugInformationFormat(cfg)
local value
local tool, toolVersion = p.config.toolset(cfg)
if cfg.symbols == p.ON then
if (cfg.symbols == p.ON) or (cfg.symbols == "FastLink") then
if cfg.debugformat == "c7" then
value = "OldStyle"
elseif cfg.architecture == "x86_64" or
elseif (cfg.architecture == "x86_64" and _ACTION < "vs2015") or
cfg.clr ~= p.OFF or
config.isOptimizedBuild(cfg) or
cfg.editandcontinue == p.OFF or
@ -1669,7 +1673,25 @@
m.element("NMakeOutput", nil, "$(OutDir)%s", cfg.buildtarget.name)
end
function m.nmakePreprocessorDefinitions(cfg, defines, escapeQuotes, condition)
if #defines > 0 then
defines = table.concat(defines, ";")
if escapeQuotes then
defines = defines:gsub('"', '\\"')
end
defines = p.esc(defines) .. ";$(NMakePreprocessorDefinitions)"
m.element('NMakePreprocessorDefinitions', condition, defines)
end
end
function m.nmakeIncludeDirs(cfg, includedirs)
if #includedirs > 0 then
local dirs = vstudio.path(cfg, includedirs)
if #dirs > 0 then
m.element("NMakeIncludeSearchPath", nil, "%s", table.concat(dirs, ";"))
end
end
end
function m.objectFileName(fcfg)
if fcfg.objname ~= fcfg.basename then
@ -1793,9 +1815,9 @@
end
function m.programDataBaseFileName(cfg)
function m.programDatabaseFile(cfg)
if cfg.symbolspath and cfg.symbols == p.ON and cfg.debugformat ~= "c7" then
m.element("ProgramDataBaseFileName", nil, p.project.getrelative(cfg.project, cfg.symbolspath))
m.element("ProgramDatabaseFile", nil, p.project.getrelative(cfg.project, cfg.symbolspath))
end
end

View File

@ -903,8 +903,8 @@
-- contain any other kind of data.
---
local function storeListItem(current, item)
if current[item] then
local function storeListItem(current, item, allowDuplicates)
if not allowDuplicates and current[item] then
table.remove(current, table.indexof(current, item))
end
table.insert(current, item)
@ -937,13 +937,13 @@
if type(value) == "table" then
if #value > 0 then
for i = 1, #value do
storeListItem(current, value[i])
storeListItem(current, value[i], field.allowDuplicates)
end
elseif not table.isempty(value) then
storeListItem(current, value)
storeListItem(current, value, field.allowDuplicates)
end
elseif value then
storeListItem(current, value)
storeListItem(current, value, field.allowDuplicates)
end
return current
@ -953,7 +953,7 @@
local function mergeList(field, current, value, processor)
value = value or {}
for i = 1, #value do
storeListItem(current, value[i])
storeListItem(current, value[i], field.allowDuplicates)
end
return current
end

View File

@ -16,7 +16,7 @@ int os_copyfile(lua_State* L)
#if PLATFORM_WINDOWS
z = CopyFileA(src, dst, FALSE);
#else
lua_pushfstring(L, "cp %s %s", src, dst);
lua_pushfstring(L, "cp \"%s\" \"%s\"", src, dst);
z = (system(lua_tostring(L, -1)) == 0);
#endif

View File

@ -26,7 +26,7 @@ int do_isabsolute(const char* path)
return 1;
if (isalpha(path[0]) && path[1] == ':')
return 1;
if (path[0] == '"')
if (path[0] == '"' || path[0] == '!')
return do_isabsolute(path + 1);
// $(foo) and %(foo)

View File

@ -85,6 +85,17 @@
end
--
-- Multiple of the same command should be emit.
--
function suite.onCommandTwice()
postbuildcommands { "command", "command" }
prepare()
test.capture ("<PostBuildEvent>\n\t<Command>command\r\ncommand</Command>\n</PostBuildEvent>\n")
end
--
-- Quotes should not be escaped, other special characters should.

View File

@ -621,6 +621,22 @@
]]
end
--
-- Check the handling of the editandcontinue flag.
--
function suite.debugFormat_onFastLinkBuild()
symbols "FastLink"
editandcontinue "Off"
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
]]
end
--
-- Edit-and-Continue is not supported for optimized builds.
@ -639,6 +655,7 @@
end
--
-- Edit-and-Continue is not supported for Managed builds.
--

View File

@ -155,6 +155,20 @@
]]
end
function suite.additionalDependencies_onSystemLinksStatic()
kind "StaticLib"
links { "lua", "zlib" }
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<AdditionalDependencies>lua.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
]]
end
--
-- Any system libraries specified in links() with valid extensions should
@ -171,6 +185,20 @@
]]
end
function suite.additionalDependencies_onSystemLinksExtensionsStatic()
kind "StaticLib"
links { "lua.obj", "zlib.lib" }
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<AdditionalDependencies>lua.obj;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
]]
end
--
-- Any system libraries specified in links() with multiple dots should
@ -187,6 +215,20 @@
]]
end
function suite.additionalDependencies_onSystemLinksExtensionsMultipleDotsStatic()
kind "StaticLib"
links { "lua.5.3.lib", "lua.5.4" }
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<AdditionalDependencies>lua.5.3.lib;lua.5.4.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
]]
end
--
-- Additional library directories should be specified, relative to the project.

View File

@ -114,3 +114,25 @@ command 2</NMakeBuildCommandLine>
</PropertyGroup>
]]
end
function suite.onDefines()
defines { "DEBUG", "_DEBUG" }
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeOutput>$(OutDir)MyProject</NMakeOutput>
<NMakePreprocessorDefinitions>DEBUG;_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
</PropertyGroup>
]]
end
function suite.onIncludeDirs()
includedirs { "include/lua", "include/zlib" }
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeOutput>$(OutDir)MyProject</NMakeOutput>
<NMakeIncludeSearchPath>include\lua;include\zlib</NMakeIncludeSearchPath>
</PropertyGroup>
]]
end

1
tests/base/.testDotFile Normal file
View File

@ -0,0 +1 @@
This is a test file for os.matchfiles tests.

View File

@ -105,8 +105,8 @@
end
function suite.matchfiles_OnDottedFile()
local result = os.matchfiles("../.*")
test.istrue(table.contains(result, "../.gitignore"))
local result = os.matchfiles("base/.*")
test.istrue(table.contains(result, "base/.testDotFile"))
end
function suite.matchfiles_onComboSearch()

View File

@ -14,73 +14,70 @@
local wks, prj
function suite.setup()
end
local function result(buildcfg, platform)
local cfg = test.getconfig(prj, buildcfg, platform)
return path.getrelative(os.getcwd(), cfg.objdir)
end
function suite.singleProject_noPlatforms()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
prj = project "MyProject"
end
test.isequal("obj/Debug", result("Debug"))
test.isequal("obj/Release", result("Release"))
local function prepare(buildcfg, platform)
cfg = test.getconfig(prj, buildcfg, platform)
end
function suite.singleProject_noPlatforms()
prepare("Debug")
test.isequal(path.getabsolute("obj/Debug"), cfg.objdir)
prepare("Release")
test.isequal(path.getabsolute("obj/Release"), cfg.objdir)
end
function suite.multipleProjects_noPlatforms()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
prj = project "MyProject"
project "MyProject2"
prepare("Debug")
test.createproject(wks)
test.isequal("obj/Debug/MyProject", result("Debug"))
test.isequal(path.getabsolute("obj/Debug/MyProject"), cfg.objdir)
end
function suite.singleProject_withPlatforms()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
prj = project "MyProject"
prepare("Debug", "x86")
test.isequal("obj/x86/Debug", result("Debug", "x86"))
test.isequal(path.getabsolute("obj/x86/Debug"), cfg.objdir)
end
function suite.singleProject_uniqueByTokens_noPlatforms()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
prj = project "MyProject"
objdir "obj/%{cfg.buildcfg}"
prepare("Debug")
test.isequal("obj/Debug", result("Debug"))
test.isequal(path.getabsolute("obj/Debug"), cfg.objdir)
end
function suite.singleProject_uniqueByTokens_withPlatforms()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
prj = project "MyProject"
objdir "obj/%{cfg.buildcfg}_%{cfg.platform}"
prepare("Debug", "x86")
test.isequal("obj/Debug_x86", result("Debug", "x86"))
test.isequal(path.getabsolute("obj/Debug_x86"), cfg.objdir)
end
function suite.allowOverlap_onPrefixCode()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
prj = project "MyProject"
objdir "!obj/%{cfg.buildcfg}"
prepare("Debug", "x86")
test.isequal("obj/Debug", result("Debug", "x86"))
test.isequal(path.getabsolute("obj/Debug"), cfg.objdir)
end
function suite.allowOverlap_onPrefixCode_withEnvironmentVariable()
platforms { "x86", "x86_64" }
objdir "!$(SolutionDir)/%{cfg.buildcfg}"
prepare("Debug", "x86")
test.isequal("$(SolutionDir)/Debug", cfg.objdir)
end