1--
2-- Name:        ninja_base.lua
3-- Purpose:     Define the ninja action.
4-- Author:      Stuart Carnie (stuart.carnie at gmail.com)
5--
6
7local ninja = premake.ninja
8
9function ninja.esc(value)
10	if value then
11		value = string.gsub(value, "%$", "$$") -- TODO maybe there is better way
12		value = string.gsub(value, ":", "$:")
13		value = string.gsub(value, "\n", "$\n")
14		value = string.gsub(value, " ", "$ ")
15	end
16	return value
17end
18
19-- in some cases we write file names in rule commands directly
20-- so we need to propely escape them
21function ninja.shesc(value)
22	if type(value) == "table" then
23		local result = {}
24		local n = #value
25		for i = 1, n do
26			table.insert(result, ninja.shesc(value[i]))
27		end
28		return result
29	end
30
31	if value:find(" ") then
32		return "\"" .. value .. "\""
33	end
34
35	return value
36end
37
38function ninja.list(value)
39	if #value > 0 then
40		return " " .. table.concat(value, " ")
41	else
42		return ""
43	end
44end
45
46function ninja.arglist(arg, value)
47	if #value > 0 then
48		local args = {}
49		for _, val in ipairs(value) do
50			table.insert(args, string.format("%s %s", arg, val))
51		end
52		return table.concat(args, " ")
53	else
54		return ""
55	end
56end
57
58-- generate all build files for every project configuration
59function ninja.generate_project(prj)
60	if prj.language == "Swift" then
61		ninja.generate_swift(prj)
62	else
63		ninja.generate_cpp(prj)
64	end
65end
66
67local function innerget(self, key)
68	return rawget(getmetatable(self), key) or self.__inner[key]
69end
70
71local prj_proxy = { __index = innerget }
72
73local cfg_proxy = { __index = innerget }
74
75function new_prj_proxy(prj)
76	prj = prj.project or prj
77
78	local v = { __inner = prj }
79
80	local __configs = {}
81	for key, cfg in pairs(prj.__configs) do
82		if key ~= "" then
83			__configs[key] = ninja.get_proxy("cfg", cfg)
84		else
85			__configs[key] = cfg
86		end
87	end
88	v.__configs = __configs
89
90	return setmetatable(v, prj_proxy)
91end
92
93local function rebasekeys(t, keys, old, new)
94	for _,key in ipairs(keys) do
95		t[key] = path.rebase(t[key], old, new)
96	end
97	return t
98end
99
100local function rebasearray(t, old, new)
101	local res = { }
102	for _,f in ipairs(t) do
103		table.insert(res, path.rebase(f, old, new))
104	end
105	return res
106end
107
108function new_cfg_proxy(cfg)
109	local keys = { "directory", "fullpath", "bundlepath" }
110
111	local old = cfg.location
112	local new = path.join(cfg.location, cfg.shortname)
113	local v = {
114		__inner     = cfg,
115		location    = new,
116		objectsdir  = path.rebase(cfg.objectsdir, old, new),
117		buildtarget = rebasekeys(table.deepcopy(cfg.buildtarget), keys, old, new),
118		linktarget  = rebasekeys(table.deepcopy(cfg.linktarget), keys, old, new),
119	}
120
121	v.files             = rebasearray(cfg.files, old, new)
122	v.includedirs       = rebasearray(cfg.includedirs, old, new)
123	v.libdirs       	= rebasearray(cfg.libdirs, old, new)
124	v.userincludedirs   = rebasearray(cfg.userincludedirs, old, new)
125	v.systemincludedirs = rebasearray(cfg.systemincludedirs, old, new)
126	v.swiftmodulemaps   = rebasearray(cfg.swiftmodulemaps, old, new)
127
128	return setmetatable(v, cfg_proxy)
129end
130
131function cfg_proxy:getprojectfilename(fullpath)
132	local name = self.project.name .. ".ninja"
133
134	if fullpath ~= nil then
135		return path.join(self.location, name)
136	end
137
138	return name
139end
140
141function cfg_proxy:getoutputfilename()
142	return path.join(self.buildtarget.directory, self.buildtarget.name)
143end
144
145local proxy_cache = {
146	prj = { new = new_prj_proxy },
147	cfg = { new = new_cfg_proxy },
148}
149
150function get_proxy(cache, obj)
151	if not cache[obj] then
152		cache[obj] = cache.new(obj)
153	end
154	return cache[obj]
155end
156
157function ninja.get_proxy(typ, obj)
158	if not proxy_cache[typ] then
159		error("invalid proxy type")
160	end
161
162	return get_proxy(proxy_cache[typ], obj)
163end
164
165