summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/genie/src/actions/ninja/ninja_solution.lua
blob: 3d1e400e553d51e88345b633334bc77348602859 (plain) (blame)
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
165
166
167
168
169
170
171
--
-- GENie - Project generator tool
-- https://github.com/bkaradzic/GENie#license
--

local ninja = premake.ninja
local p = premake
local solution = p.solution

function ninja.generate_solution(sln)
	-- create a shortcut to the compiler interface
		local cc = premake[_OPTIONS.cc]

		-- build a list of supported target platforms that also includes a generic build
		local platforms = premake.filterplatforms(sln, cc.platforms, "Native")

		-- write a header showing the build options
		_p('# %s solution makefile autogenerated by GENie', premake.action.current().shortname)
		_p('# Type "make help" for usage help')
		_p('')
		_p('NINJA=ninja')

		-- set a default configuration
		_p('ifndef config')
		_p('  config=%s', _MAKE.esc(premake.getconfigname(sln.configurations[1], platforms[1], true)))
		_p('endif')
		_p('')

		local projects = table.extract(sln.projects, "name")
		table.sort(projects)

		_p('')
		_p('.PHONY: all clean help $(PROJECTS)')
		_p('')
		_p('all:')
		if (not sln.messageskip) or (not table.contains(sln.messageskip, "SkipBuildingMessage")) then
			_p(1, '@echo "==== Building all ($(config)) ===="')
		end
		_p(1, '@${NINJA} -C ${config} all')
		_p('')

		-- write the project build rules
		for _, prj in ipairs(sln.projects) do
			local prjx = ninja.get_proxy("prj", prj)
			_p('%s:', _MAKE.esc(prj.name))
			if (not sln.messageskip) or (not table.contains(sln.messageskip, "SkipBuildingMessage")) then
				_p(1, '@echo "==== Building %s ($(config)) ===="', prj.name)
			end
			_p(1, '@${NINJA} -C ${config} %s', prj.name)
			_p('')
		end

		-- clean rules
		_p('clean:')
		_p(1, '@${NINJA} -C ${config} -t clean')
		_p('')

		-- help rule
		_p('help:')
		_p(1,'@echo "Usage: make [config=name] [target]"')
		_p(1,'@echo ""')
		_p(1,'@echo "CONFIGURATIONS:"')

		local cfgpairs = { }
		for _, platform in ipairs(platforms) do
			for _, cfgname in ipairs(sln.configurations) do
				_p(1,'@echo "   %s"', premake.getconfigname(cfgname, platform, true))
			end
		end

		_p(1,'@echo ""')
		_p(1,'@echo "TARGETS:"')
		_p(1,'@echo "   all (default)"')
		_p(1,'@echo "   clean"')

		for _, prj in ipairs(sln.projects) do
			_p(1,'@echo "   %s"', prj.name)
		end

		_p(1,'@echo ""')
		_p(1,'@echo "For more information, see https://github.com/bkaradzic/genie"')
end

-- generate solution that will call ninja for projects
	local generate

	local function getconfigs(sln, name, plat)
		local cfgs = {}
		for prj in solution.eachproject(sln) do
			prj = ninja.get_proxy("prj", prj)
			for cfg in p.eachconfig(prj, plat) do
				if cfg.name == name then
					table.insert(cfgs, cfg)
				end
			end
		end
		return cfgs
	end

	function ninja.generate_ninja_builds(sln)
		-- create a shortcut to the compiler interface
		local cc = premake[_OPTIONS.cc]

		sln.getlocation = function(cfg, plat)
			return path.join(sln.location, premake.getconfigname(cfg, plat, true))
		end

		-- build a list of supported target platforms that also includes a generic build
		local platforms = premake.filterplatforms(sln, cc.platforms, "Native")

		for _,plat in ipairs(platforms) do
			for _,name in ipairs(sln.configurations) do
				p.generate(sln, ninja.get_solution_name(sln, name, plat), function(sln)
					generate(getconfigs(sln, name, plat))
				end)
			end
		end
	end

	function ninja.get_solution_name(sln, cfg, plat)
		return path.join(sln.getlocation(cfg, plat), "build.ninja")
	end

	function generate(prjcfgs)
		local cfgs          = {}
		local cfg_start     = nil
		local cfg_first     = nil
		local cfg_first_lib = nil

		_p("# solution build file")
		_p("# generated with GENie ninja")
		_p("")

		_p("# build projects")
		for _,cfg in ipairs(prjcfgs) do
			local key  = cfg.project.name

			-- fill list of output files
			if not cfgs[key] then cfgs[key] = "" end
			cfgs[key] = cfg:getoutputfilename() .. " "

			if not cfgs["all"] then cfgs["all"] = "" end
			cfgs["all"] = cfgs["all"] .. cfg:getoutputfilename() .. " "

			-- set first configuration name
			if (cfg_start == nil) and (cfg.solution.startproject == key) then
				cfg_start = key
			end
			if (cfg_first == nil) and (cfg.kind == "ConsoleApp" or cfg.kind == "WindowedApp") then
				cfg_first = key
			end
			if (cfg_first_lib == nil) and (cfg.kind == "StaticLib" or cfg.kind == "SharedLib") then
				cfg_first_lib = key
			end

			-- include other ninja file
			_p("subninja " .. cfg:getprojectfilename())
		end

		_p("")

		_p("# targets")
		for cfg, outputs in iter.sortByKeys(cfgs) do
			_p("build " .. cfg .. ": phony " .. outputs)
		end
		_p("")

		_p("# default target")
		_p("default " .. (cfg_start or cfg_first or cfg_first_lib))
		_p("")
	end