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
|
// file : libbuild2/cc/utility.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#include <libbuild2/cc/utility.hxx>
#include <libbuild2/file.hxx>
#include <libbuild2/variable.hxx>
#include <libbuild2/algorithm.hxx> // search()
#include <libbuild2/bin/rule.hxx>
#include <libbuild2/bin/target.hxx>
using namespace std;
namespace build2
{
namespace cc
{
using namespace bin;
const dir_path module_dir ("cc");
const dir_path modules_sidebuild_dir (dir_path (module_dir) /= "modules");
lorder
link_order (const scope& bs, otype ot)
{
// Initialize to suppress 'may be used uninitialized' warning produced
// by MinGW GCC 5.4.0.
//
const char* var (nullptr);
switch (ot)
{
case otype::e: var = "bin.exe.lib"; break;
case otype::a: var = "bin.liba.lib"; break;
case otype::s: var = "bin.libs.lib"; break;
}
const auto& v (cast<strings> (bs[var]));
return v[0] == "shared"
? v.size () > 1 && v[1] == "static" ? lorder::s_a : lorder::s
: v.size () > 1 && v[1] == "shared" ? lorder::a_s : lorder::a;
}
const target*
link_member (const bin::libx& x, action a, linfo li, bool exist)
{
if (x.is_a<libul> ())
{
// For libul{} that is linked to an executable the member choice
// should be dictated by the members of lib{} this libul{} is
// "primarily" for. If both are being built, then it seems natural to
// prefer static over shared since it could be faster (but I am sure
// someone will probably want this configurable).
//
if (li.type == otype::e)
{
// Utility libraries are project-local which means the primarily
// target should be in the same project as us.
//
li.type = lib_rule::build_members (x.root_scope ()).a
? otype::a
: otype::s;
}
const target_type& tt (li.type == otype::a
? libua::static_type
: libus::static_type);
// Called by the compile rule during execute.
//
return x.ctx.phase == run_phase::match && !exist
? &search (x, tt, x.dir, x.out, x.name)
: search_existing (x.ctx, tt, x.dir, x.out, x.name);
}
else
{
assert (!exist);
const lib& l (x.as<lib> ());
// Make sure group members are resolved.
//
group_view gv (resolve_members (a, l));
assert (gv.members != nullptr);
lorder lo (li.order);
bool ls (true);
switch (lo)
{
case lorder::a:
case lorder::a_s:
ls = false; // Fall through.
case lorder::s:
case lorder::s_a:
{
if (ls ? l.s == nullptr : l.a == nullptr)
{
if (lo == lorder::a_s || lo == lorder::s_a)
ls = !ls;
else
fail << (ls ? "shared" : "static") << " variant of " << l
<< " is not available";
}
}
}
return ls ? static_cast<const target*> (l.s) : l.a;
}
}
}
}
|