aboutsummaryrefslogtreecommitdiff
path: root/lua/cmake/variants.lua
blob: 50254c8258d0ff859444e4015bab2e046c0b3b7a (plain)
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
local config = require("cmake.config")
local utils = require("cmake.utils")

local VariantConfig = {}

VariantConfig.__index = VariantConfig

local global_variant_subs = {
	["${workspaceFolder}"] = vim.loop.cwd(),
	["${userHome}"] = vim.loop.os_homedir(),
}

local _configure_args = function(obj, build_directory)
	local args = {}
	if obj.generator then
		table.insert(args, "-G " .. '"' .. obj.generator .. '"')
	end
	table.insert(args, "-B" .. build_directory)
	if obj.buildType then
		table.insert(args, "-DCMAKE_BUILD_TYPE=" .. obj.buildType)
	end
	if obj.linkage and string.lower(obj.linkage) == "static" then
		table.insert(args, "-DCMAKE_BUILD_SHARED_LIBS=OFF")
	elseif obj.linkage and string.lower(obj.linkage) == "shared" then
		table.insert(args, "-DCMAKE_BUILD_SHARED_LIBS=ON")
	end
	for k, v in pairs(obj.settings or {}) do
		table.insert(args, "-D" .. k .. "=" .. v)
	end
	table.insert(args, "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON")
	return args
end

local _configure_command = function(obj, configure_args)
	local ret = {}
	ret.cmd = config.cmake.cmake_path
	ret.args = table.concat(configure_args, " ")
	ret.env = vim.tbl_deep_extend("keep", obj.env, config.cmake.configure_environment, config.cmake.environment)
	return ret
end

local _build_args = function(obj, build_directory)
	local args = { "--build" }
	table.insert(args, build_directory)
	if #obj.buildArgs ~= 0 then
		for _, v in ipairs(obj.buildArgs) do
			table.insert(args, v)
		end
	elseif #config.cmake.build_args ~= 0 then
		for _, v in ipairs(config.cmake.build_args) do
			table.insert(args, v)
		end
	end
	if #obj.buildToolArgs ~= 0 or #config.cmake.build_tool_args ~= 0 then
		table.insert(args, "--")
		if #obj.buildToolArgs ~= 0 then
			for _, v in ipairs(obj.buildToolArgs) do
				table.insert(args, v)
			end
		elseif #config.cmake.build_tool_args ~= 0 then
			for _, v in ipairs(config.cmake.build_tool_args) do
				table.insert(args, v)
			end
		end
	end
	return args
end

local _build_command = function(obj, build_args)
	local ret = {}
	ret.cmd = config.cmake.cmake_path
	ret.args = table.concat(build_args, " ")
	ret.env = vim.tbl_deep_extend("keep", obj.env, config.cmake.configure_environment, config.cmake.environment)
	return ret
end

function VariantConfig:new(source)
	local obj = {}
	local subs = vim.tbl_deep_extend("keep", global_variant_subs, { ["${buildType}"] = source.buildType })

	obj.name = source.short
	obj.long_name = source.long
	obj.directory = utils.substitude(config.cmake.build_directory, subs)
	local configure_args = _configure_args(source, obj.directory)
	obj.generate_command = _configure_command(source, configure_args)
	local build_args = _build_args(source, obj.directory)
	obj.build_options = {
		{
			name = source.short,
			long_name = source.long,
			command = _build_command(source, build_args),
		},
	}

	setmetatable(obj, VariantConfig)
	return obj
end

function VariantConfig.cartesian_product(sets)
	-- vim.notify("cartesian_product", vim.log.levels.INFO)
	local function collapse_result(res)
		-- vim.notify("collapse_result", vim.log.levels.INFO)
		local ret = {
			short = {},
			long = {},
			buildType = nil,
			linkage = nil,
			generator = nil,
			buildArgs = {},
			buildToolArgs = {},
			settings = {},
			env = {},
		}
		local is_default = true
		for _, v in ipairs(res) do
			if not v.default then
				is_default = false
			end
			ret.short[#ret.short + 1] = v.short
			ret.long[#ret.long + 1] = v.long
			ret.buildType = v.buildType or ret.buildType
			ret.linkage = v.linkage or ret.linkage
			ret.generator = v.generator or ret.generator
			ret.buildArgs = v.buildArgs or ret.buildArgs
			ret.buildToolArgs = v.buildToolArgs or ret.buildToolArgs
			for sname, sval in pairs(v.settings or {}) do
				ret.settings[sname] = sval
			end
			for ename, eres in pairs(v.env or {}) do
				ret.env[ename] = eres
			end
		end
		-- vim.notify(vim.inspect(ret), vim.log.levels.INFO)
		return VariantConfig:new(ret), is_default
	end
	local result = {}
	local set_count = #sets
	local function descend(depth)
		for k, v in pairs(sets[depth].choices) do
			if sets[depth].default ~= k then
				result.default = false
			end
			result[depth] = v
			result[depth].default = (k == sets[depth].default)
			if depth == set_count then
				coroutine.yield(collapse_result(result))
			else
				descend(depth + 1)
			end
		end
	end
	return coroutine.wrap(function()
		descend(1)
	end)
end

return VariantConfig