premake/src/actions/make/_make.lua

288 lines
6.1 KiB
Lua
Raw Normal View History

--
-- _make.lua
-- Define the makefile action(s).
-- Copyright (c) 2002-2013 Jason Perkins and the Premake project
--
2012-11-27 15:08:01 +00:00
premake.make = {}
local make = premake.make
local solution = premake.solution
local project = premake.project
---
2012-04-30 20:42:03 +00:00
-- The GNU make action, with support for the new platforms API
---
2012-04-30 20:42:03 +00:00
newaction {
2012-11-27 15:08:01 +00:00
trigger = "gmake",
shortname = "GNU Make",
description = "Generate GNU makefiles for POSIX, MinGW, and Cygwin",
2012-04-30 20:42:03 +00:00
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "clang", "gcc" },
2012-04-30 20:42:03 +00:00
dotnet = { "mono", "msnet", "pnet" }
},
onsolution = function(sln)
io.esc = make.esc
2012-04-30 20:42:03 +00:00
premake.generate(sln, make.getmakefilename(sln, false), make.generate_solution)
end,
onproject = function(prj)
io.esc = make.esc
2012-04-30 20:42:03 +00:00
local makefile = make.getmakefilename(prj, true)
if project.isdotnet(prj) then
premake.generate(prj, makefile, make.cs.generate)
elseif project.iscpp(prj) then
premake.generate(prj, makefile, make.cpp.generate)
2012-04-30 20:42:03 +00:00
end
end,
2012-04-30 20:42:03 +00:00
oncleansolution = function(sln)
premake.clean.file(sln, make.getmakefilename(sln, false))
end,
2012-04-30 20:42:03 +00:00
oncleanproject = function(prj)
premake.clean.file(prj, make.getmakefilename(prj, true))
end
}
--
-- Write out the default configuration rule for a solution or project.
-- @param target
-- The solution or project object for which a makefile is being generated.
--
function make.defaultconfig(target)
-- find the right configuration iterator function for this object
local eachconfig = iif(target.project, project.eachconfig, solution.eachconfig)
local iter = eachconfig(target)
-- grab the first configuration and write the block
local cfg = iter()
if cfg then
_p('ifndef config')
_x(' config=%s', cfg.shortname)
_p('endif')
_p('')
end
end
---
-- Escape a string so it can be written to a makefile.
---
function make.esc(value)
result = value:gsub("\\", "\\\\")
result = result:gsub(" ", "\\ ")
result = result:gsub("%(", "\\%(")
result = result:gsub("%)", "\\%)")
-- leave $(...) shell replacement sequences alone
result = result:gsub("$\\%((.-)\\%)", "$%(%1%)")
return result
end
2012-04-30 20:42:03 +00:00
--
-- Get the makefile file name for a solution or a project. If this object is the
-- only one writing to a location then I can use "Makefile". If more than one object
-- writes to the same location I use name + ".make" to keep it unique.
--
function make.getmakefilename(this, searchprjs)
local count = 0
for sln in premake.solution.each() do
if sln.location == this.location then
count = count + 1
2012-04-30 20:42:03 +00:00
end
if searchprjs then
for _, prj in ipairs(sln.projects) do
2012-04-30 20:42:03 +00:00
if prj.location == this.location then
count = count + 1
end
end
end
end
2012-04-30 20:42:03 +00:00
if count == 1 then
return "Makefile"
else
return ".make"
2012-04-30 20:42:03 +00:00
end
end
--
-- Output a makefile header.
--
-- @param target
-- The solution or project object for which the makefile is being generated.
--
function make.header(target)
-- find the right configuration iterator function for this object
local kind = iif(target.project, "project", "solution")
_p('# %s %s makefile autogenerated by Premake', premake.action.current().shortname, kind)
_p('')
make.defaultconfig(target)
_p('ifndef verbose')
_p(' SILENT = @')
_p('endif')
_p('')
end
--
-- Rules for file ops based on the shell type. Can't use defines and $@ because
-- it screws up the escaping of spaces and parethesis (anyone know a solution?)
--
function make.mkdirRules(dirname)
_p('%s:', dirname)
_p('\t@echo Creating %s', dirname)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) mkdir -p %s', dirname)
_p('else')
_p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', dirname)
_p('endif')
_p('')
end
--
-- Format a list of values to be safely written as part of a variable assignment.
--
function make.list(value)
if #value > 0 then
return " " .. table.concat(value, " ")
else
return ""
end
end
2012-06-13 22:29:51 +00:00
--
-- Convert an arbitrary string (project name) to a make variable name.
--
function make.tovar(value)
value = value:gsub("[ -]", "_")
value = value:gsub("[()]", "")
return value
end
---------------------------------------------------------------------------
--
-- Handlers for the individual makefile elements that can be shared
-- between the different language projects.
2012-06-13 22:29:51 +00:00
--
---------------------------------------------------------------------------
function make.objdir(cfg)
_x(' OBJDIR = %s', project.getrelative(cfg.project, cfg.objdir))
end
function make.objDirRules(prj)
make.mkdirRules("$(OBJDIR)")
end
function make.phonyRules(prj)
_p('.PHONY: clean prebuild prelink')
_p('')
end
function make.buildCmds(cfg, event)
_p(' define %sCMDS', event:upper())
local steps = cfg[event .. "commands"]
local msg = cfg[event .. "message"]
if #steps > 0 then
msg = msg or string.format("Running %s commands", event)
_p('\t@echo %s', msg)
_p('\t%s', table.implode(steps, "", "", "\n\t"))
end
_p(' endef')
end
function make.preBuildCmds(cfg, toolset)
make.buildCmds(cfg, "prebuild")
end
function make.preBuildRules(prj)
_p('prebuild:')
_p('\t$(PREBUILDCMDS)')
_p('')
end
function make.preLinkCmds(cfg, toolset)
make.buildCmds(cfg, "prelink")
end
function make.preLinkRules(prj)
_p('prelink:')
_p('\t$(PRELINKCMDS)')
_p('')
end
function make.postBuildCmds(cfg, toolset)
make.buildCmds(cfg, "postbuild")
end
2012-06-13 22:29:51 +00:00
function make.settings(cfg, toolset)
if #cfg.makesettings > 0 then
for _, value in ipairs(cfg.makesettings) do
_p(value)
end
end
local value = toolset.getmakesettings(cfg)
if value then
_p(value)
2012-06-13 22:29:51 +00:00
end
end
2012-04-30 20:42:03 +00:00
function make.shellType()
_p('SHELLTYPE := msdos')
_p('ifeq (,$(ComSpec)$(COMSPEC))')
_p(' SHELLTYPE := posix')
_p('endif')
_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')
_p(' SHELLTYPE := posix')
_p('endif')
_p('')
end
function make.target(cfg)
_x(' TARGETDIR = %s', project.getrelative(cfg.project, cfg.buildtarget.directory))
_x(' TARGET = $(TARGETDIR)/%s', cfg.buildtarget.name)
end
function make.targetDirRules(prj)
make.mkdirRules("$(TARGETDIR)")
end