summaryrefslogtreecommitdiff
path: root/xmake/core/tool/builder.lua
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/core/tool/builder.lua')
-rw-r--r--xmake/core/tool/builder.lua219
1 files changed, 165 insertions, 54 deletions
diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua
index f07fc39d6..cfd3d19cf 100644
--- a/xmake/core/tool/builder.lua
+++ b/xmake/core/tool/builder.lua
@@ -125,6 +125,19 @@ function builder:_flagkinds()
return self._FLAGKINDS
end
+-- get the extra configuration from value
+function builder:_extraconf(extras, value)
+ local extra = extras
+ if extra then
+ if type(value) == "table" then
+ extra = extra[table.concat(value, "_")]
+ else
+ extra = extra[value]
+ end
+ end
+ return extra
+end
+
-- inherit flags (only for public/interface) from target deps
--
-- e.g.
@@ -241,7 +254,7 @@ function builder:_add_flags_from_target(flags, target)
-- add flags from language
targetflags = {}
- self:_add_flags_from_language(targetflags, target)
+ self:_add_flags_from_language(targetflags, {target = target})
-- add flags for the target
if target_type == "target" then
@@ -278,8 +291,20 @@ function builder:_add_flags_from_argument(flags, target, args)
end
-- add flags (named) from the language
- self:_add_flags_from_language(flags, nil, {
- target = function (name) return args[name] end,
+ self:_add_flags_from_language(flags, {linkorders = args.linkorders, linkgroups = args.linkgroups, getters = {
+ target = function (name)
+ -- we need also to get extra from arguments
+ -- @see https://github.com/xmake-io/xmake/issues/4274
+ --
+ -- e.g.
+ -- package/add_linkgroups("xxx", {group = true})
+ -- {linkgroups = , extras = {
+ -- linkgroups = {z = {group = true}}
+ -- }}
+ local values = args[name]
+ local extras = args.extras and args.extras[name]
+ return values, extras
+ end,
toolchain = function (name)
local plat, arch
if target and target.plat then
@@ -289,14 +314,20 @@ function builder:_add_flags_from_argument(flags, target, args)
arch = target:arch()
end
return platform.toolconfig(name, plat, arch)
- end})
+ end}})
end
-- add items from getter
function builder:_add_items_from_getter(items, name, opt)
- local values = opt.getter(name)
+ local values, extras = opt.getter(name)
if values then
- table.insert(items, {name = name, values = table.wrap(values), check = opt.check, multival = opt.multival, mapper = opt.mapper})
+ table.insert(items, {
+ name = name,
+ values = table.wrap(values),
+ check = opt.check,
+ multival = opt.multival,
+ mapper = opt.mapper,
+ extras = extras})
end
end
@@ -307,7 +338,12 @@ function builder:_add_items_from_config(items, name, opt)
values = path.splitenv(values)
end
if values then
- table.insert(items, {name = name, values = table.wrap(values), check = opt.check, multival = opt.multival, mapper = opt.mapper})
+ table.insert(items, {
+ name = name,
+ values = table.wrap(values),
+ check = opt.check,
+ multival = opt.multival,
+ mapper = opt.mapper})
end
end
@@ -321,7 +357,12 @@ function builder:_add_items_from_toolchain(items, name, opt)
values = platform.toolconfig(name)
end
if values then
- table.insert(items, {name = name, values = table.wrap(values), check = opt.check, multival = opt.multival, mapper = opt.mapper})
+ table.insert(items, {
+ name = name,
+ values = table.wrap(values),
+ check = opt.check,
+ multival = opt.multival,
+ mapper = opt.mapper})
end
end
@@ -333,35 +374,46 @@ function builder:_add_items_from_option(items, name, opt)
values = target:get(name)
end
if values then
- table.insert(items, {name = name, values = table.wrap(values), check = opt.check, multival = opt.multival, mapper = opt.mapper})
+ table.insert(items, {
+ name = name,
+ values = table.wrap(values),
+ check = opt.check,
+ multival = opt.multival,
+ mapper = opt.mapper})
end
end
-- add items from target
function builder:_add_items_from_target(items, name, opt)
- local values = {}
local target = opt.target
if target then
- -- get flagvalues of target with given flagname
- table.join2(values, target:get(name))
-
- -- get flagvalues of the attached options and packages
- table.join2(values, target:get_from_opts(name))
- table.join2(values, target:get_from_pkgs(name))
-
- -- get flagvalues (public or interface) of all dependent targets (contain packages/options)
- table.join2(values, target:get_from_deps(name, {interface = true}))
- end
- if values and #values > 0 then
- table.insert(items, {name = name, values = table.wrap(values), check = opt.check, multival = opt.multival, mapper = opt.mapper})
+ local result, sources = target:get_from(name, "*")
+ if result then
+ for idx, values in ipairs(result) do
+ local source = sources[idx]
+ local extras = target:extraconf_from(source, name)
+ values = table.wrap(values)
+ if values and #values > 0 then
+ table.insert(items, {
+ name = name,
+ values = values,
+ extras = extras,
+ check = opt.check,
+ multival = opt.multival,
+ mapper = opt.mapper})
+ end
+ end
+ end
end
end
-- add flags from the language
-function builder:_add_flags_from_language(flags, target, getters)
+function builder:_add_flags_from_language(flags, opt)
+ opt = opt or {}
-- get order named items
local items = {}
+ local target = opt.target
for _, flaginfo in ipairs(self:_nameflags()) do
-- get flag info
@@ -391,37 +443,57 @@ function builder:_add_flags_from_language(flags, target, getters)
-- map named flags to real flags
local mapper = self:_tool()["nf_" .. apiname]
if mapper then
- local opt = {target = target, check = checkstate, multival = multival, mapper = mapper}
- if getters then
- local getter = getters[flagscope]
+ local opt_ = {target = target, check = checkstate, multival = multival, mapper = mapper}
+ if opt.getters then
+ local getter = opt.getters[flagscope]
if getter then
- opt.getter = getter
- self:_add_items_from_getter(items, flagname, opt)
+ opt_.getter = getter
+ self:_add_items_from_getter(items, flagname, opt_)
end
elseif flagscope == "target" and target and target:type() == "target" then
- self:_add_items_from_target(items, flagname, opt)
+ self:_add_items_from_target(items, flagname, opt_)
elseif flagscope == "target" and target and target:type() == "option" then
- self:_add_items_from_option(items, flagname, opt)
+ self:_add_items_from_option(items, flagname, opt_)
elseif flagscope == "config" then
- self:_add_items_from_config(items, flagname, opt)
+ self:_add_items_from_config(items, flagname, opt_)
elseif flagscope == "toolchain" then
- self:_add_items_from_toolchain(items, flagname, opt)
+ self:_add_items_from_toolchain(items, flagname, opt_)
end
end
end
-- sort links
local kind = self:kind()
- if (kind == "ld" or kind == "sh") and target and target:type() == "target" then
- self:_sort_links_of_items(target, items)
+ if kind == "ld" or kind == "sh" then
+ local linkorders = table.wrap(opt.linkorders)
+ local linkgroups = table.wrap(opt.linkgroups)
+ if target and target:type() == "target" then
+ local values = target:get_from("linkorders", "*")
+ if values then
+ for _, value in ipairs(values) do
+ table.join2(linkorders, value)
+ end
+ end
+ values = target:get_from("linkgroups", "*")
+ if values then
+ for _, value in ipairs(values) do
+ table.join2(linkgroups, value)
+ end
+ end
+ end
+ if #linkorders > 0 or #linkgroups > 0 then
+ self:_sort_links_of_items(items, {linkorders = linkorders, linkgroups = linkgroups})
+ end
end
-- get flags from the items
for _, item in ipairs(items) do
local check = item.check
local mapper = item.mapper
+ local extras = item.extras
if item.multival then
- local results = mapper(self:_tool(), item.values, target, self:_targetkind())
+ local extra = self:_extraconf(extras, item.values)
+ local results = mapper(self:_tool(), item.values, {target = target, targetkind = self:_targetkind(), extra = extra})
for _, flag in ipairs(table.wrap(results)) do
if flag and flag ~= "" and (not check or self:has_flags(flag)) then
table.insert(flags, flag)
@@ -429,7 +501,8 @@ function builder:_add_flags_from_language(flags, target, getters)
end
else
for _, flagvalue in ipairs(item.values) do
- local flag = mapper(self:_tool(), flagvalue, target, self:_targetkind())
+ local extra = self:_extraconf(extras, flagvalue)
+ local flag = mapper(self:_tool(), flagvalue, {target = target, targetkind = self:_targetkind(), extra = extra})
if flag and flag ~= "" and (not check or self:has_flags(flag)) then
table.insert(flags, flag)
end
@@ -439,14 +512,15 @@ function builder:_add_flags_from_language(flags, target, getters)
end
-- sort links of items
-function builder:_sort_links_of_items(target, items)
+function builder:_sort_links_of_items(items, opt)
+ opt = opt or {}
local sortlinks = false
local makegroups = false
- local linkorders = table.wrap(target:get("linkorders"))
+ local linkorders = table.wrap(opt.linkorders)
if #linkorders > 0 then
sortlinks = true
end
- local linkgroups = table.wrap(target:get("linkgroups"))
+ local linkgroups = table.wrap(opt.linkgroups)
local linkgroups_set = hashset.new()
if #linkgroups > 0 then
makegroups = true
@@ -460,34 +534,54 @@ function builder:_sort_links_of_items(target, items)
-- get all links
local links = {}
local linkgroups_map = {}
+ local extras_map = {}
local link_mapper
local framework_mapper
local linkgroup_mapper
if sortlinks or makegroups then
+ local linkitems = {}
table.remove_if(items, function (_, item)
local name = item.name
local removed = false
+ if name == "links" or name == "syslinks" then
+ link_mapper = item.mapper
+ removed = true
+ table.insert(linkitems, item)
+ elseif name == "frameworks" then
+ framework_mapper = item.mapper
+ removed = true
+ table.insert(linkitems, item)
+ elseif name == "linkgroups" then
+ linkgroup_mapper = item.mapper
+ removed = true
+ table.insert(linkitems, item)
+ end
+ return removed
+ end)
+
+ -- @note table.remove_if will traverse backwards,
+ -- we need to fix the initial link order first to make sure the syslinks are in the correct order
+ linkitems = table.reverse(linkitems)
+ for _, item in ipairs(linkitems) do
+ local name = item.name
for _, value in ipairs(item.values) do
if name == "links" or name == "syslinks" then
if not linkgroups_set:has(value) then
table.insert(links, value)
end
- link_mapper = item.mapper
- removed = true
elseif name == "frameworks" then
table.insert(links, "framework::" .. value)
- framework_mapper = item.mapper
- removed = true
elseif name == "linkgroups" then
- local key = target:extraconf("linkgroups", value, "name") or tostring(value)
+ local extras = item.extras
+ local extra = self:_extraconf(extras, value)
+ local key = extra and extra.name or tostring(value)
table.insert(links, "linkgroup::" .. key)
linkgroups_map[key] = value
- linkgroup_mapper = item.mapper
- removed = true
+ extras_map[key] = extras
end
end
- return removed
- end)
+ end
+
links = table.reverse_unique(links)
end
@@ -505,12 +599,24 @@ function builder:_sort_links_of_items(target, items)
end
-- we need remove cycle in original links
-- e.g.
+ --
+ -- case1:
-- original_deps: a -> b -> c -> d -> e
-- new deps: e -> b
- -- graph: a -> b -> c -> d e (remove d -> e)
- -- /\ |
- -- | |
+ -- graph: a -> b -> c -> d e (remove d -> e, add d -> nil)
+ -- /|\ |
-- --------------
+ --
+ -- case2:
+ -- original_deps: a -> b -> c -> d -> e
+ -- new deps: b -> a
+ --
+ -- ---------
+ -- | \|/
+ -- graph: a b -> c -> d -> e (remove a -> b, add a -> c)
+ -- /|\ |
+ -- ----
+ --
local function remove_cycle_in_original_deps(f, t)
local k
local v = t
@@ -522,7 +628,11 @@ function builder:_sort_links_of_items(target, items)
end
end
if v == f and k ~= nil then
- original_deps[k] = nil
+ -- break the original from node, link to next node
+ -- e.g.
+ -- case1: d -x-> e, d -> nil, k: d, f: e
+ -- case2: a -x-> b, a -> c, k: a, f: b
+ original_deps[k] = original_deps[f]
end
end
local links_set = hashset.from(links)
@@ -559,8 +669,9 @@ function builder:_sort_links_of_items(target, items)
table.insert(items, {name = "frameworks", values = table.wrap(link), check = false, multival = false, mapper = framework_mapper})
elseif link:startswith("linkgroup::") then
local key = link:sub(12)
- local value = linkgroups_map[key]
- table.insert(items, {name = "linkgroups", values = table.wrap(value), check = false, multival = false, mapper = linkgroup_mapper})
+ local values = linkgroups_map[key]
+ local extras = extras_map[key]
+ table.insert(items, {name = "linkgroups", values = table.wrap(values), extras = extras, check = false, multival = false, mapper = linkgroup_mapper})
else
table.insert(items, {name = "links", values = table.wrap(link), check = false, multival = false, mapper = link_mapper})
end