ack/first/c.pm
2006-07-23 19:56:11 +00:00

144 lines
3.3 KiB
Raku

-- pm includefile to compile *host* C programs.
-- Standard Lua boilerplate.
local io_open = io.open
local string_gsub = string.gsub
local string_gfind = string.gfind
local table_insert = table.insert
local table_getn = table.getn
local filetime = pm.filetime
-- Define some variables.
CCOMPILER = "gcc"
CC = "%CCOMPILER% %CBUILDFLAGS% %CDYNINCLUDES% %CINCLUDES% %CDEFINES% %CEXTRAFLAGS% -c -o %out% %in%"
CPROGRAM = "%CCOMPILER% %CBUILDFLAGS% %CLINKFLAGS% %CEXTRAFLAGS% -o %out% %in% %CLIBRARIES%"
CDEPENDS = "%CCOMPILER% %CBUILDFLAGS% %CDYNINCLUDES% %CINCLUDES% %CDEFINES% %CEXTRAFLAGS% -MM -MG %in% > %out%"
AR = "%RM% %out% && ar cr %out% %in% && ranlib %out%"
CBUILDFLAGS = "-g"
CINCLUDES = {}
CDEFINES = {}
CEXTRAFLAGS = ""
CLINKFLAGS = ""
CDYNINCLUDES = ""
CLIBRARIES = ""
--- Manage C file dependencies ----------------------------------------------
local dependency_cache = {}
local function load_dependency_file(fn)
local o = dependency_cache[fn]
if o then
return o
end
-- Read in the dependency file.
local f = io_open(fn)
if not f then
print("failed to open "..fn)
return nil
end
f = f:read("*a")
-- Massage the dependency file into a string containing one unescaped
-- filename per line.
f = string_gsub(f, "^.*[^\\]: *", "")
f = string_gsub(f, "\\\r?\n", "")
f = string_gsub(f, "([^\\]) +", "%1\n")
f = string_gsub(f, "\\", "")
-- Parse the string.
o = {}
for l in string_gfind(f, "[^\n]+") do
table_insert(o, l)
end
dependency_cache[fn] = o
return o
end
-- This clause specialises 'simple' to add support for smart dependencies of C
-- files.
simple_with_clike_dependencies = simple {
class = "simple_with_clike_dependencies",
makedepends = {"%CDEPENDS%"},
__init = function(self, p)
simple.__init(self, p)
-- If we're a class, don't verify.
if ((type(p) == "table") and p.class) then
return
end
-- If dynamicheaders is an object, turn it into a singleton list.
if self.dynamicheaders then
if (type(self.dynamicheaders) ~= "table") then
self:__error("doesn't know what to do with dynamicheaders, which ",
"should be a list or an object but was a ", type(self.dynamicheaders))
end
if self.dynamicheaders.class then
self.dynamicheaders = {self.dynamicheaders}
end
end
end,
__dependencies = function(self, inputs, outputs)
local obj = simple {
CDYNINCLUDES = self.CDYNINCLUDES,
command = self.makedepends,
outputs = {"%U%-%I%.d"},
unpack(inputs)
}
local o = obj:__build()
local depends = load_dependency_file(o[1])
if not depends then
self:__error("could not determine the dependencies for ",
pm.rendertable(inputs))
end
return depends
end,
__buildadditionalchildren = function(self)
self.CDYNINCLUDES = ""
if self.dynamicheaders then
for _, i in ipairs(self.dynamicheaders) do
local o = i:__build()
if o[1] then
self.CDYNINCLUDES = self.CDYNINCLUDES..' "-I'..string_gsub(o[1], "/[^/]*$", "")..'"'
end
end
end
end
}
-- These are the publically useful clauses.
cfile = simple_with_clike_dependencies {
class = "cfile",
command = {"%CC%"},
outputs = {"%U%-%I%.o"},
}
cprogram = simple {
class = "cprogram",
command = {"%CPROGRAM%"},
outputs = {"%U%-%I%"},
}
clibrary = simple {
class = "clibrary",
command = {
"%AR%"
},
outputs = {"%U%-%I%.a"},
}