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
134
135
|
--!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 inherit_links.lua
--
-- imports
import("private.utils.target", {alias = "target_utils"})
-- @note we cannot directly set `{interface = true}`, because it will overwrite the previous configuration
-- https://github.com/xmake-io/xmake/issues/1465
function _add_export_value(target, name, value)
local has_private = false
local private_values = target:get(name)
if private_values then
for _, v in ipairs(private_values) do
if v == value then
has_private = true
break
end
end
end
local extraconf = target:extraconf(name, value)
if has_private then
target:add(name, value, table.join(extraconf or {}, {public = true}))
else
target:add(name, value, table.join(extraconf or {}, {interface = true}))
end
end
-- export values as public/interface in target
function _add_export_values(target, name, values)
for _, value in ipairs(values) do
_add_export_value(target, name, value)
end
end
function main(target)
-- disable inherit.links for `add_deps()`?
if target:data("inherit.links") == false then
return
end
-- export target links and linkdirs
if target:is_shared() or target:is_static() then
local targetfile = target:targetfile()
-- rust maybe will disable inherit links, only inherit linkdirs
if target:data("inherit.links.deplink") ~= false then
-- we need to move target link to head
_add_export_value(target, "links", target:linkname())
local links = target:get("links", {rawref = true})
if links and type(links) == "table" and #links > 1 then
table.insert(links, 1, links[#links])
table.remove(links, #links)
end
end
local implibfile = target:artifactfile("implib")
if implibfile then
_add_export_value(target, "linkdirs", path.directory(implibfile))
else
_add_export_value(target, "linkdirs", path.directory(targetfile))
end
if target:rule("go") then
-- we need to add includedirs to support import modules for golang
_add_export_value(target, "includedirs", path.directory(targetfile))
end
if target:rule("rust") then
local cratetype = target:values("rust.cratetype")
-- only bin, lib, rlib, dylib can make use of --extern CRATE[=PATH]
if cratetype ~= "staticlib" and cratetype ~= "cdylib" then
_add_export_value(target, "frameworks", target:targetfile())
end
end
end
-- we export all links and linkdirs in self/packages/options to the parent target by default
--
-- @note we only export links for static target,
-- and we need to pass `{public = true}` to add_packages/add_links/... to export it if want to export links for shared target
--
if target:data("inherit.links.exportlinks") ~= false then
if target:is_static() or target:is_object() then
local export_values = {"rpathdirs", "frameworkdirs", "frameworks", "syslinks", "shflags"};
if target:data("inherit.links.export_static") ~= false then
local link_settings = {"linkdirs", "links", "ldflags"}
for _, link_setting in ipairs(link_settings) do
table.insert(export_values, link_setting)
end
end
for _, name in ipairs(export_values) do
local values = target_utils.get_values_from_target(target, name)
if values and #values > 0 then
_add_export_values(target, name, values)
end
end
end
end
-- export rpathdirs for all shared library
if target:is_binary() and target:policy("build.rpath") then
local targetdir = target:targetdir()
for _, dep in ipairs(target:orderdeps({inherit = true})) do
if dep:kind() == "shared" then
local rpathdir = "@loader_path"
local subdir = path.relative(path.directory(dep:targetfile()), targetdir)
if subdir and subdir ~= '.' then
rpathdir = path.join(rpathdir, subdir)
end
target:add("rpathdirs", rpathdir)
end
end
end
end
|