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
|
// file : build2/cc/gcc.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#include <build2/scope>
#include <build2/target>
#include <build2/context>
#include <build2/variable>
#include <build2/filesystem>
#include <build2/diagnostics>
#include <build2/bin/target>
#include <build2/cc/types>
#include <build2/cc/module>
using namespace std;
using namespace butl;
namespace build2
{
namespace cc
{
using namespace bin;
// Extract system library search paths from GCC (gcc/g++) or compatible
// (Clang, Intel) using the -print-search-dirs option.
//
dir_paths config_module::
gcc_library_search_paths (process_path& xc, scope& rs) const
{
dir_paths r;
cstrings args;
string std; // Storage.
args.push_back (xc.recall_string ());
append_options (args, rs, c_coptions);
append_options (args, rs, x_coptions);
if (!tstd.empty ()) args.push_back (tstd.c_str ());
append_options (args, rs, c_loptions);
append_options (args, rs, x_loptions);
args.push_back ("-print-search-dirs");
args.push_back (nullptr);
if (verb >= 3)
print_process (args);
string l;
try
{
process pr (xc, args.data (), 0, -1); // Open pipe to stdout.
try
{
ifdstream is (pr.in_ofd, fdstream_mode::skip, ifdstream::badbit);
string s;
while (getline (is, s))
{
if (s.compare (0, 12, "libraries: =") == 0)
{
l.assign (s, 12, string::npos);
break;
}
}
is.close (); // Don't block.
if (!pr.wait ())
throw failed ();
}
catch (const ifdstream::failure&)
{
pr.wait ();
fail << "error reading " << x_lang << " compiler -print-search-dirs "
<< "output";
}
}
catch (const process_error& e)
{
error << "unable to execute " << args[0] << ": " << e.what ();
if (e.child ())
exit (1);
throw failed ();
}
if (l.empty ())
fail << "unable to extract " << x_lang << " compiler system library "
<< "search paths";
// Now the fun part: figuring out which delimiter is used. Normally it
// is ':' but on Windows it is ';' (or can be; who knows for sure). Also
// note that these paths are absolute (or should be). So here is what we
// are going to do: first look for ';'. If found, then that's the
// delimiter. If not found, then there are two cases: it is either a
// single Windows path or the delimiter is ':'. To distinguish these two
// cases we check if the path starts with a Windows drive.
//
char d (';');
string::size_type e (l.find (d));
if (e == string::npos &&
(l.size () < 2 || l[0] == '/' || l[1] != ':'))
{
d = ':';
e = l.find (d);
}
// Now chop it up. We already have the position of the first delimiter
// (if any).
//
for (string::size_type b (0);; e = l.find (d, (b = e + 1)))
{
r.emplace_back (l, b, (e != string::npos ? e - b : e));
r.back ().normalize ();
if (e == string::npos)
break;
}
return r;
}
}
}
|