1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
--!A cross-platform build utility based on Lua
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- Copyright (C) 2015-present, Xmake Open Source Community.
--
-- @author ruki
-- @file instance_deps.lua
--
-- define module
local instance_deps = instance_deps or {}
-- load modules
local option = require("base/option")
local string = require("base/string")
local table = require("base/table")
-- load deps for instance: e.g. option, instance and rule
--
-- e.g.
--
-- a.deps = b
-- b.deps = c
-- foo.deps = a d
--
-- foo.orderdeps: d -> c -> b -> a
--
-- if they're targets, their links order is reverse(orderdeps), e.g. foo: a -> b -> c -> d
--
function instance_deps.load_deps(instance, instances, deps, orderdeps, depspath, walkdep)
local plaindeps = table.wrap(instance:get("deps"))
local total = #plaindeps
for idx, _ in ipairs(plaindeps) do
-- we reverse to get the flat dependencies in order to ensure the correct linking order
-- @see https://github.com/xmake-io/xmake/issues/3144
local depname = plaindeps[total + 1 - idx]
local depinst = instances[depname]
if depinst == nil and instance.namespace then
local namespace = instance:namespace()
if namespace then
depinst = instances[namespace .. "::" .. depname]
end
end
if depinst then
local continue_walk = true
if walkdep then
continue_walk = walkdep(instance, depinst)
end
if continue_walk then
if not deps[depname] then
deps[depname] = depinst
local depspath_sub
if depspath then
for idx, name in ipairs(depspath) do
if name == depname then
local circular_deps = table.slice(depspath, idx)
table.insert(circular_deps, depname)
os.raise("circular dependency(%s) detected!", table.concat(circular_deps, ", "))
end
end
depspath_sub = table.join(depspath, depname)
end
instance_deps.load_deps(depinst, instances, deps, orderdeps, depspath_sub, walkdep)
table.insert(orderdeps, depinst)
end
end
end
end
end
-- sort the given instance with deps
function instance_deps._sort_instance(instance, instances, orderinstances, instancerefs, depspath)
if not instancerefs[instance:fullname()] then
instancerefs[instance:fullname()] = true
for _, depname in ipairs(table.wrap(instance:get("deps"))) do
local depinst = instances[depname]
if depinst == nil and instance.namespace then
local namespace = instance:namespace()
if namespace then
depinst = instances[namespace .. "::" .. depname]
end
end
if depinst then
local depspath_sub
if depspath then
for idx, name in ipairs(depspath) do
if name == depname then
local circular_deps = table.slice(depspath, idx)
table.insert(circular_deps, depname)
os.raise("circular dependency(%s) detected!", table.concat(circular_deps, ", "))
end
end
depspath_sub = table.join(depspath, depinst:fullname())
end
instance_deps._sort_instance(depinst, instances, orderinstances, instancerefs, depspath_sub)
end
end
table.insert(orderinstances, instance)
end
end
-- sort instances with deps
--
-- e.g.
--
-- a.deps = b
-- b.deps = c
-- foo.deps = a d
--
-- orderdeps: c -> b -> a -> d -> foo
function instance_deps.sort(instances)
local refs = {}
local orderinstances = {}
for _, instance in table.orderpairs(instances) do
instance_deps._sort_instance(instance, instances, orderinstances, refs, {instance:fullname()})
end
return orderinstances
end
-- return module
return instance_deps
|