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