143 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Raku
		
	
	
	
	
	
			
		
		
	
	
			143 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 -O"
 | 
						|
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"},
 | 
						|
}
 |