2019-06-17 23:33:12 +00:00
|
|
|
-- Functions for use in targets/*
|
|
|
|
local F = {}
|
|
|
|
|
|
|
|
-- To be accessed by scripts using target_lib
|
|
|
|
local M = setmetatable({}, { __index = F })
|
|
|
|
|
|
|
|
local funcs = setmetatable({}, {
|
|
|
|
__index = function(_, k)
|
|
|
|
return F[k] or _G[k]
|
|
|
|
end,
|
2019-06-14 17:20:15 +00:00
|
|
|
})
|
2019-06-17 23:33:12 +00:00
|
|
|
|
|
|
|
local env = setmetatable({}, {
|
|
|
|
__index = function(_, k) return os.getenv(k) end
|
2019-06-14 17:20:15 +00:00
|
|
|
})
|
2019-06-17 23:33:12 +00:00
|
|
|
F.env = env
|
|
|
|
|
2019-06-14 17:20:15 +00:00
|
|
|
assert(env.GLUON_SITEDIR)
|
|
|
|
assert(env.GLUON_TARGETSDIR)
|
|
|
|
assert(env.GLUON_RELEASE)
|
2019-06-15 12:34:45 +00:00
|
|
|
assert(env.GLUON_DEPRECATED)
|
2019-06-14 17:20:15 +00:00
|
|
|
|
|
|
|
|
2020-08-15 11:59:54 +00:00
|
|
|
M.site_code = assert(
|
|
|
|
dofile('scripts/site_config.lua')('site.conf').site_code, 'site_code missing in site.conf'
|
|
|
|
)
|
2019-06-17 23:33:12 +00:00
|
|
|
M.target_packages = {}
|
|
|
|
M.configs = {}
|
|
|
|
M.devices = {}
|
|
|
|
M.images = {}
|
2019-06-14 17:20:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
local default_options = {
|
|
|
|
profile = false,
|
|
|
|
factory = '-squashfs-factory',
|
|
|
|
factory_ext = '.bin',
|
|
|
|
sysupgrade = '-squashfs-sysupgrade',
|
|
|
|
sysupgrade_ext = '.bin',
|
|
|
|
extra_images = {},
|
|
|
|
aliases = {},
|
|
|
|
manifest_aliases = {},
|
|
|
|
packages = {},
|
2020-05-03 19:35:01 +00:00
|
|
|
class = 'standard',
|
2019-06-15 12:34:45 +00:00
|
|
|
deprecated = false,
|
2019-06-14 17:20:15 +00:00
|
|
|
broken = false,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
local gluon_devices, unknown_devices = {}, {}
|
|
|
|
for dev in string.gmatch(env.GLUON_DEVICES or '', '%S+') do
|
|
|
|
gluon_devices[dev] = true
|
|
|
|
unknown_devices[dev] = true
|
|
|
|
end
|
|
|
|
|
2020-03-14 15:51:43 +00:00
|
|
|
function F.istrue(v)
|
|
|
|
return (tonumber(v) or 0) > 0
|
|
|
|
end
|
|
|
|
|
2019-06-14 17:20:15 +00:00
|
|
|
local function want_device(dev, options)
|
2020-03-14 15:51:43 +00:00
|
|
|
if options.broken and not F.istrue(env.BROKEN) then
|
2019-06-14 17:20:15 +00:00
|
|
|
return false
|
|
|
|
end
|
2019-06-15 12:34:45 +00:00
|
|
|
if options.deprecated and env.GLUON_DEPRECATED == '0' then
|
|
|
|
return false
|
|
|
|
end
|
2019-06-14 17:20:15 +00:00
|
|
|
|
|
|
|
if (env.GLUON_DEVICES or '') == '' then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
unknown_devices[dev] = nil
|
|
|
|
return gluon_devices[dev]
|
|
|
|
end
|
|
|
|
|
2019-06-15 12:34:45 +00:00
|
|
|
local full_deprecated = env.GLUON_DEPRECATED == 'full'
|
|
|
|
|
2019-06-14 17:20:15 +00:00
|
|
|
|
|
|
|
local function merge(a, b)
|
|
|
|
local ret = {}
|
|
|
|
for k, v in pairs(a) do
|
|
|
|
ret[k] = v
|
|
|
|
end
|
|
|
|
for k, v in pairs(b or {}) do
|
|
|
|
assert(ret[k] ~= nil, string.format("unknown option '%s'", k))
|
|
|
|
ret[k] = v
|
|
|
|
end
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Escapes a single argument to be used in a shell command
|
|
|
|
-- The argument is surrounded by single quotes, single quotes inside the
|
|
|
|
-- argument are replaced by '\''.
|
|
|
|
-- To allow using shell wildcards, zero bytes in the arguments are replaced
|
|
|
|
-- by unquoted asterisks.
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.escape(s)
|
2019-06-14 17:20:15 +00:00
|
|
|
s = string.gsub(s, "'", "'\\''")
|
|
|
|
s = string.gsub(s, "%z", "'*'")
|
|
|
|
return "'" .. s .. "'"
|
|
|
|
end
|
|
|
|
|
|
|
|
local function escape_command(command, raw)
|
2020-05-03 16:24:32 +00:00
|
|
|
local ret = ''
|
|
|
|
if not raw then
|
|
|
|
ret = 'exec'
|
|
|
|
end
|
2019-06-14 17:20:15 +00:00
|
|
|
for _, arg in ipairs(command) do
|
2019-06-17 23:33:12 +00:00
|
|
|
ret = ret .. ' ' .. F.escape(arg)
|
2019-06-14 17:20:15 +00:00
|
|
|
end
|
|
|
|
if raw then
|
|
|
|
ret = ret .. ' ' .. raw
|
|
|
|
end
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.exec_raw(command, may_fail)
|
2019-06-14 17:20:15 +00:00
|
|
|
local ret = os.execute(command)
|
|
|
|
assert((ret == 0) or may_fail)
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.exec(command, may_fail, raw)
|
|
|
|
return F.exec_raw(escape_command(command, raw), may_fail)
|
2019-06-14 17:20:15 +00:00
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.exec_capture_raw(command)
|
2019-06-14 17:20:15 +00:00
|
|
|
local f = io.popen(command)
|
|
|
|
assert(f)
|
|
|
|
|
|
|
|
local data = f:read('*a')
|
|
|
|
f:close()
|
|
|
|
return data
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.exec_capture(command, raw)
|
|
|
|
return F.exec_capture_raw(escape_command(command, raw))
|
2019-06-14 17:20:15 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local image_mt = {
|
|
|
|
__index = {
|
|
|
|
dest_name = function(image, name, site, release)
|
2019-06-17 23:33:12 +00:00
|
|
|
return env.GLUON_IMAGEDIR..'/'..image.subdir,
|
|
|
|
'gluon-'..(site or M.site_code)..'-'..(release or env.GLUON_RELEASE)..'-'..name..image.out_suffix..image.extension
|
2019-06-14 17:20:15 +00:00
|
|
|
end,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
local function add_image(image)
|
2020-04-24 21:09:05 +00:00
|
|
|
local device = image.image
|
|
|
|
M.images[device] = M.images[device] or {}
|
|
|
|
table.insert(M.images[device], setmetatable(image, image_mt))
|
2019-06-14 17:20:15 +00:00
|
|
|
end
|
|
|
|
|
2020-05-26 20:40:12 +00:00
|
|
|
|
|
|
|
local function format_config(k, v)
|
|
|
|
local format
|
|
|
|
if type(v) == 'string' then
|
|
|
|
format = '%s=%q'
|
|
|
|
elseif v == true then
|
|
|
|
format = '%s=y'
|
|
|
|
elseif v == nil then
|
|
|
|
format = '%s=m'
|
|
|
|
elseif v == false then
|
|
|
|
format = '# %s is not set'
|
|
|
|
else
|
|
|
|
format = '%s=%d'
|
|
|
|
end
|
2020-05-26 21:30:05 +00:00
|
|
|
return string.format(format, 'CONFIG_' .. k, v)
|
2020-05-26 20:40:12 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local config_mt = {
|
|
|
|
__index = {
|
|
|
|
format = function(config)
|
|
|
|
return format_config(config.key, config.value)
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
local function do_config(k, v, required)
|
|
|
|
M.configs[k] = setmetatable({
|
|
|
|
key = k,
|
|
|
|
value = v,
|
|
|
|
required = required,
|
|
|
|
}, config_mt)
|
|
|
|
end
|
|
|
|
|
|
|
|
function F.try_config(k, v)
|
|
|
|
do_config(k, v)
|
2019-06-17 23:33:12 +00:00
|
|
|
end
|
2019-06-14 17:20:15 +00:00
|
|
|
|
2020-05-26 20:40:12 +00:00
|
|
|
function F.config(k, v, message)
|
|
|
|
if not message then
|
|
|
|
message = string.format("unable to set '%s'", format_config(k, v))
|
|
|
|
end
|
|
|
|
do_config(k, v, message)
|
2019-06-17 23:33:12 +00:00
|
|
|
end
|
2019-06-14 17:20:15 +00:00
|
|
|
|
2020-05-26 20:40:12 +00:00
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.packages(pkgs)
|
2019-06-14 17:20:15 +00:00
|
|
|
for _, pkg in ipairs(pkgs) do
|
2019-06-17 23:33:12 +00:00
|
|
|
table.insert(M.target_packages, pkg)
|
2019-06-14 17:20:15 +00:00
|
|
|
end
|
|
|
|
end
|
2019-06-17 23:33:12 +00:00
|
|
|
M.packages = F.packages
|
2019-06-14 17:20:15 +00:00
|
|
|
|
2020-05-30 23:16:57 +00:00
|
|
|
local function as_table(v)
|
|
|
|
if type(v) == 'table' then
|
|
|
|
return v
|
|
|
|
else
|
|
|
|
return {v}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.device(image, name, options)
|
2019-06-14 17:20:15 +00:00
|
|
|
options = merge(default_options, options)
|
|
|
|
|
|
|
|
if not want_device(image, options) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
table.insert(M.devices, {
|
2019-06-14 17:20:15 +00:00
|
|
|
image = image,
|
|
|
|
name = name,
|
|
|
|
options = options,
|
|
|
|
})
|
|
|
|
|
2019-06-15 12:34:45 +00:00
|
|
|
if options.sysupgrade then
|
2019-06-14 17:20:15 +00:00
|
|
|
add_image {
|
|
|
|
image = image,
|
|
|
|
name = name,
|
2019-06-15 12:34:45 +00:00
|
|
|
subdir = 'sysupgrade',
|
|
|
|
in_suffix = options.sysupgrade,
|
|
|
|
out_suffix = '-sysupgrade',
|
|
|
|
extension = options.sysupgrade_ext,
|
2019-06-14 17:20:15 +00:00
|
|
|
aliases = options.aliases,
|
|
|
|
manifest_aliases = options.manifest_aliases,
|
|
|
|
}
|
|
|
|
end
|
2019-06-15 12:34:45 +00:00
|
|
|
|
|
|
|
if options.deprecated and not full_deprecated then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if options.factory then
|
2020-05-30 23:16:57 +00:00
|
|
|
for _, ext in ipairs(as_table(options.factory_ext)) do
|
|
|
|
add_image {
|
|
|
|
image = image,
|
|
|
|
name = name,
|
|
|
|
subdir = 'factory',
|
|
|
|
in_suffix = options.factory,
|
|
|
|
out_suffix = '',
|
|
|
|
extension = ext,
|
|
|
|
aliases = options.aliases,
|
|
|
|
}
|
|
|
|
end
|
2019-06-14 17:20:15 +00:00
|
|
|
end
|
|
|
|
for _, extra_image in ipairs(options.extra_images) do
|
|
|
|
add_image {
|
|
|
|
image = image,
|
|
|
|
name = name,
|
|
|
|
subdir = 'other',
|
|
|
|
in_suffix = extra_image[1],
|
|
|
|
out_suffix = extra_image[2],
|
|
|
|
extension = extra_image[3],
|
|
|
|
aliases = options.aliases,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.defaults(options)
|
2019-06-14 17:20:15 +00:00
|
|
|
default_options = merge(default_options, options)
|
|
|
|
end
|
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
function F.include(name)
|
|
|
|
local f = assert(loadfile(env.GLUON_TARGETSDIR .. '/' .. name))
|
|
|
|
setfenv(f, funcs)
|
|
|
|
return f()
|
|
|
|
end
|
2019-06-14 17:20:15 +00:00
|
|
|
|
2019-06-17 23:33:12 +00:00
|
|
|
|
|
|
|
function M.check_devices()
|
2019-06-14 17:20:15 +00:00
|
|
|
local device_list = {}
|
|
|
|
for device in pairs(unknown_devices) do
|
|
|
|
table.insert(device_list, device)
|
|
|
|
end
|
|
|
|
if #device_list ~= 0 then
|
|
|
|
table.sort(device_list)
|
|
|
|
io.stderr:write('Error: unknown devices given: ', table.concat(device_list, ' '), '\n')
|
|
|
|
os.exit(1)
|
|
|
|
end
|
|
|
|
end
|
2019-06-17 23:33:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
return M
|