xref: /freebsd/release/packages/generate-ucl.lua (revision 328110da2661a8841f12000b99fea27ceacdd5b2)
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		"%-dev$", "(development files)",
43		"This package contains development files for "..
44		"compiling applications."
45	},
46	{
47		"%-man$", "(manual pages)",
48		"This package contains the online manual pages."
49	},
50	{
51		"%-dbg$", "(debugging symbols)",
52		"This package contains external debugging symbols for use "..
53		"with a source-level debugger.",
54	},
55}
56
57-- A list of packages which don't get the automatic suffix handling,
58-- e.g. -man packages with no corresponding base package.
59local no_suffix_pkgs = {
60	["kernel-man"] = true,
61}
62
63function add_suffixes(obj)
64	local pkgname = obj["name"]
65
66	for _,pattern in pairs(pkg_suffixes) do
67		if pkgname:match(pattern[1]) ~= nil then
68			obj["comment"] = obj["comment"] .. " " .. pattern[2]
69			obj["desc"] = obj["desc"] .. "\n\n" .. pattern[3]
70			return
71		end
72	end
73end
74
75-- Hardcode a list of packages which don't get the automatic pkggenname
76-- dependency because the base package doesn't exist.  We should have a better
77-- way to handle this.
78local no_gen_deps = {
79	["libcompat-dev"] = true,
80	["libcompat-dev-lib32"] = true,
81	["libcompat-man"] = true,
82	["libcompiler_rt-dev"] = true,
83	["libcompiler_rt-dev-lib32"] = true,
84	["liby-dev"] = true,
85	["liby-dev-lib32"] = true,
86	["kernel-man"] = true,
87}
88
89-- Return true if the package 'pkgname' should have a dependency on the package
90-- pkggenname.
91function add_gen_dep(pkgname, pkggenname)
92	if pkgname == pkggenname then
93		return false
94	end
95	if pkgname == nil or pkggenname == nil then
96		return false
97	end
98	if no_gen_deps[pkgname] ~= nil then
99		return false
100	end
101	if pkggenname == "kernel" then
102		return false
103	end
104
105	return true
106end
107
108local pkgname = nil
109local pkggenname = nil
110local pkgprefix = nil
111local pkgversion = nil
112
113-- This parser is the output UCL we want to build.
114local parser = ucl.parser()
115
116-- Set any $VARIABLES from the command line in the parser.  This causes ucl to
117-- automatically replace them when we load the source ucl.
118if #arg < 2 or #arg % 2 ~= 0 then
119	io.stderr:write(arg[0] .. ": expected an even number of arguments, got " .. #arg)
120	os.exit(1)
121end
122
123for i = 2, #arg - 2, 2 do
124	local varname = arg[i - 1]
125	local varvalue = arg[i]
126
127	if varname == "PKGNAME" and #varvalue > 0 then
128		pkgname = varvalue
129	elseif varname == "PKGGENNAME" and #varvalue > 0 then
130		pkggenname = varvalue
131	elseif varname == "VERSION" and #varvalue > 0 then
132		pkgversion = varvalue
133	elseif varname == "PKG_NAME_PREFIX" and #varvalue > 0 then
134		pkgprefix = varvalue
135	end
136
137	parser:register_variable(varname, varvalue)
138end
139
140-- Load the source ucl file.
141local res,err = parser:parse_file(arg[#arg - 1])
142if not res then
143	io.stderr:write(arg[0] .. ": fail to parse("..arg[#arg - 1].."): "..err)
144	os.exit(1)
145end
146
147local obj = parser:get_object()
148
149-- If pkgname is different from pkggenname, add a dependency on pkggenname.
150-- This means that e.g. -dev packages depend on their respective base package.
151if add_gen_dep(pkgname, pkggenname) then
152	if obj["deps"] == nil then
153		obj["deps"] = {}
154	end
155	obj["deps"][pkggenname] = {
156		["version"] = pkgversion,
157		["origin"] = "base"
158	}
159end
160
161-- If PKG_NAME_PREFIX is provided, rewrite the names of dependency packages.
162-- We can't do this in UCL since variable substitution doesn't work in array
163-- keys.
164if pkgprefix ~= nil and obj["deps"] ~= nil then
165	newdeps = {}
166	for dep, opts in pairs(obj["deps"]) do
167		local newdep = pkgprefix .. "-" .. dep
168		newdeps[newdep] = opts
169	end
170	obj["deps"] = newdeps
171end
172
173-- Add comment and desc suffix.
174if no_suffix_pkgs[pkgname] == nil then
175	add_suffixes(obj)
176end
177
178-- Write the output file.
179local f,err = io.open(arg[#arg], "w")
180if not f then
181	io.stderr:write(arg[0] .. ": fail to open("..arg[#arg].."): ".. err)
182	os.exit(1)
183end
184
185f:write(ucl.to_format(obj, 'ucl', true))
186f:close()
187