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