xref: /freebsd/release/packages/generate-ucl.lua (revision cb2887746f8b9dd4ad6b1e757cdc053a08b25a2e)
1#!/usr/libexec/flua
2
3--[[ usage:
4generare-ucl.lua [<variablename> <variablevalue>]... <sourceucl> <destucl>
5
6Build a package's UCL configuration by loading the template UCL file
7<sourceucl>, replacing any $VARIABLES in the UCL based on the provided
8variables, then writing the result to <destucl>.
9]]--
10
11local ucl = require("ucl")
12
13-- Give subpackages a special comment and description suffix to indicate what
14-- they contain, so e.g. "foo-man" has " (manual pages)" appended to its
15-- comment.  This avoids having to create a separate ucl files for every
16-- subpackage just to set this.
17--
18-- Note that this is not a key table because the order of the pattern matches
19-- is important.
20pkg_suffixes = {
21	{
22		"%-dev%-lib32$", "(32-bit development files)",
23		"This package contains development files for compiling "..
24		"32-bit applications on a 64-bit host."
25	},
26	{
27		"%-dbg%-lib32$", "(32-bit debugging symbols)",
28		"This package contains 32-bit external debugging symbols "..
29		"for use with a source-level debugger.",
30	},
31	{
32		"%-man%-lib32$", "(32-bit manual pages)",
33		"This package contains the online manual pages for 32-bit "..
34		"components on a 64-bit host.",
35	},
36	{
37		"%-lib32$", "(32-bit libraries)",
38		"This package contains 32-bit libraries for running 32-bit "..
39		"applications on a 64-bit host.",
40	},
41	{
42		"%-lib$", "(libraries)",
43		"This package contains runtime shared libraries.",
44	},
45	{
46		"%-dev$", "(development files)",
47		"This package contains development files for "..
48		"compiling applications."
49	},
50	{
51		"%-man$", "(manual pages)",
52		"This package contains the online manual pages."
53	},
54	{
55		"%-dbg$", "(debugging symbols)",
56		"This package contains external debugging symbols for use "..
57		"with a source-level debugger.",
58	},
59}
60
61-- A list of packages which don't get the automatic suffix handling,
62-- e.g. -man packages with no corresponding base package.
63local no_suffix_pkgs = {
64	["kernel-man"] = true,
65}
66
67function add_suffixes(obj)
68	local pkgname = obj["name"]
69
70	for _,pattern in pairs(pkg_suffixes) do
71		if pkgname:match(pattern[1]) ~= nil then
72			obj["comment"] = obj["comment"] .. " " .. pattern[2]
73			obj["desc"] = obj["desc"] .. "\n\n" .. pattern[3]
74			return
75		end
76	end
77end
78
79-- Hardcode a list of packages which don't get the automatic pkggenname
80-- dependency because the base package doesn't exist.  We should have a better
81-- way to handle this.
82local no_gen_deps = {
83	["libcompat-dev"] = true,
84	["libcompat-dev-lib32"] = true,
85	["libcompat-man"] = true,
86	["libcompiler_rt-dev"] = true,
87	["libcompiler_rt-dev-lib32"] = true,
88	["liby-dev"] = true,
89	["liby-dev-lib32"] = true,
90	["kernel-man"] = true,
91}
92
93-- Return true if the package 'pkgname' should have a dependency on the package
94-- pkggenname.
95function add_gen_dep(pkgname, pkggenname)
96	if pkgname == pkggenname then
97		return false
98	end
99	if pkgname == nil or pkggenname == nil then
100		return false
101	end
102	if no_gen_deps[pkgname] ~= nil then
103		return false
104	end
105	if pkgname:match("%-lib$") ~= nil then
106		return false
107	end
108	if pkggenname == "kernel" then
109		return false
110	end
111
112	return true
113end
114
115local pkgname = nil
116local pkggenname = nil
117local pkgprefix = nil
118local pkgversion = nil
119
120-- This parser is the output UCL we want to build.
121local parser = ucl.parser()
122
123-- Set any $VARIABLES from the command line in the parser.  This causes ucl to
124-- automatically replace them when we load the source ucl.
125if #arg < 2 or #arg % 2 ~= 0 then
126	io.stderr:write(arg[0] .. ": expected an even number of arguments, got " .. #arg)
127	os.exit(1)
128end
129
130for i = 2, #arg - 2, 2 do
131	local varname = arg[i - 1]
132	local varvalue = arg[i]
133
134	if varname == "PKGNAME" and #varvalue > 0 then
135		pkgname = varvalue
136	elseif varname == "PKGGENNAME" and #varvalue > 0 then
137		pkggenname = varvalue
138	elseif varname == "VERSION" and #varvalue > 0 then
139		pkgversion = varvalue
140	elseif varname == "PKG_NAME_PREFIX" and #varvalue > 0 then
141		pkgprefix = varvalue
142	end
143
144	parser:register_variable(varname, varvalue)
145end
146
147-- Load the source ucl file.
148local res,err = parser:parse_file(arg[#arg - 1])
149if not res then
150	io.stderr:write(arg[0] .. ": fail to parse("..arg[#arg - 1].."): "..err)
151	os.exit(1)
152end
153
154local obj = parser:get_object()
155
156-- If pkgname is different from pkggenname, add a dependency on pkggenname.
157-- This means that e.g. -dev packages depend on their respective base package.
158if add_gen_dep(pkgname, pkggenname) then
159	if obj["deps"] == nil then
160		obj["deps"] = {}
161	end
162	obj["deps"][pkggenname] = {
163		["version"] = pkgversion,
164		["origin"] = "base"
165	}
166end
167
168-- If PKG_NAME_PREFIX is provided, rewrite the names of dependency packages.
169-- We can't do this in UCL since variable substitution doesn't work in array
170-- keys.
171if pkgprefix ~= nil and obj["deps"] ~= nil then
172	newdeps = {}
173	for dep, opts in pairs(obj["deps"]) do
174		local newdep = pkgprefix .. "-" .. dep
175		newdeps[newdep] = opts
176	end
177	obj["deps"] = newdeps
178end
179
180-- Add comment and desc suffix.
181if no_suffix_pkgs[pkgname] == nil then
182	add_suffixes(obj)
183end
184
185-- Write the output file.
186local f,err = io.open(arg[#arg], "w")
187if not f then
188	io.stderr:write(arg[0] .. ": fail to open("..arg[#arg].."): ".. err)
189	os.exit(1)
190end
191
192f:write(ucl.to_format(obj, 'ucl', true))
193f:close()
194