aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc/msvc.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/cc/msvc.cxx')
-rw-r--r--libbuild2/cc/msvc.cxx162
1 files changed, 106 insertions, 56 deletions
diff --git a/libbuild2/cc/msvc.cxx b/libbuild2/cc/msvc.cxx
index f95cab0..d21969c 100644
--- a/libbuild2/cc/msvc.cxx
+++ b/libbuild2/cc/msvc.cxx
@@ -164,18 +164,21 @@ namespace build2
// Filter cl.exe and link.exe noise.
//
+ // Note: must be followed with the dbuf.read() call.
+ //
void
- msvc_filter_cl (ifdstream& is, const path& src)
+ msvc_filter_cl (diag_buffer& dbuf, const path& src)
+ try
{
// While it appears VC always prints the source name (event if the
// file does not exist), let's do a sanity check. Also handle the
// command line errors/warnings which come before the file name.
//
- for (string l; !eof (getline (is, l)); )
+ for (string l; !eof (getline (dbuf.is, l)); )
{
if (l != src.leaf ().string ())
{
- diag_stream_lock () << l << endl;
+ dbuf.write (l, true /* newline */);
if (msvc_sense_diag (l, 'D').first != string::npos)
continue;
@@ -184,14 +187,19 @@ namespace build2
break;
}
}
+ catch (const io_error& e)
+ {
+ fail << "unable to read from " << dbuf.args0 << " stderr: " << e;
+ }
void
- msvc_filter_link (ifdstream& is, const file& t, otype lt)
+ msvc_filter_link (diag_buffer& dbuf, const file& t, otype lt)
+ try
{
// Filter lines until we encounter something we don't recognize. We also
// have to assume the messages can be translated.
//
- for (string l; getline (is, l); )
+ for (string l; getline (dbuf.is, l); )
{
// " Creating library foo\foo.dll.lib and object foo\foo.dll.exp"
//
@@ -216,12 +224,15 @@ namespace build2
// /INCREMENTAL causes linker to sometimes issue messages but now I
// can't quite reproduce it.
- //
- diag_stream_lock () << l << endl;
+ dbuf.write (l, true /* newline */);
break;
}
}
+ catch (const io_error& e)
+ {
+ fail << "unable to read from " << dbuf.args0 << " stderr: " << e;
+ }
void
msvc_extract_header_search_dirs (const strings& v, dir_paths& r)
@@ -253,6 +264,13 @@ namespace build2
}
else
continue;
+
+ // Ignore relative paths. Or maybe we should warn?
+ //
+ if (d.relative ())
+ continue;
+
+ d.normalize ();
}
catch (const invalid_path& e)
{
@@ -260,10 +278,7 @@ namespace build2
<< o << "'";
}
- // Ignore relative paths. Or maybe we should warn?
- //
- if (!d.relative ())
- r.push_back (move (d));
+ r.push_back (move (d));
}
}
@@ -284,6 +299,13 @@ namespace build2
d = dir_path (o, 9, string::npos);
else
continue;
+
+ // Ignore relative paths. Or maybe we should warn?
+ //
+ if (d.relative ())
+ continue;
+
+ d.normalize ();
}
catch (const invalid_path& e)
{
@@ -291,10 +313,7 @@ namespace build2
<< o << "'";
}
- // Ignore relative paths. Or maybe we should warn?
- //
- if (!d.relative ())
- r.push_back (move (d));
+ r.push_back (move (d));
}
}
@@ -313,7 +332,7 @@ namespace build2
{
try
{
- r.push_back (dir_path (move (d)));
+ r.push_back (dir_path (move (d)).normalize ());
}
catch (const invalid_path&)
{
@@ -326,7 +345,7 @@ namespace build2
// Extract system header search paths from MSVC.
//
pair<dir_paths, size_t> config_module::
- msvc_header_search_dirs (const process_path&, scope& rs) const
+ msvc_header_search_dirs (const compiler_info&, scope& rs) const
{
// MSVC doesn't have any built-in paths and all of them either come from
// the INCLUDE environment variable or are specified explicitly on the
@@ -354,7 +373,7 @@ namespace build2
// Extract system library search paths from MSVC.
//
pair<dir_paths, size_t> config_module::
- msvc_library_search_dirs (const process_path&, scope& rs) const
+ msvc_library_search_dirs (const compiler_info&, scope& rs) const
{
// MSVC doesn't seem to have any built-in paths and all of them either
// come from the LIB environment variable or are specified explicitly on
@@ -379,9 +398,22 @@ namespace build2
// Inspect the file and determine if it is static or import library.
// Return otype::e if it is neither (which we quietly ignore).
//
+ static global_cache<otype> library_type_cache;
+
static otype
library_type (const process_path& ld, const path& l)
{
+ string key;
+ {
+ sha256 cs;
+ cs.append (ld.effect_string ());
+ cs.append (l.string ());
+ key = cs.string ();
+
+ if (const otype* r = library_type_cache.find (key))
+ return *r;
+ }
+
// The are several reasonably reliable methods to tell whether it is a
// static or import library. One is lib.exe /LIST -- if there aren't any
// .obj members, then it is most likely an import library (it can also
@@ -422,9 +454,9 @@ namespace build2
//
process pr (run_start (ld,
args,
- 0 /* stdin */,
- -1 /* stdout */,
- false /* error */));
+ 0 /* stdin */,
+ -1 /* stdout */,
+ 1 /* stderr (to stdout) */));
bool obj (false), dll (false);
string s;
@@ -447,14 +479,11 @@ namespace build2
// libhello\hello.lib.obj
// hello-0.1.0-a.0.19700101000000.dll
//
- // Archive member name at 746: [...]hello.dll[/][ ]*
- // Archive member name at 8C70: [...]hello.lib.obj[/][ ]*
- //
size_t n (s.size ());
for (; n != 0 && s[n - 1] == ' '; --n) ; // Skip trailing spaces.
- if (n >= 7) // At least ": X.obj" or ": X.dll".
+ if (n >= 5) // At least "X.obj" or "X.dll".
{
n -= 4; // Beginning of extension.
@@ -480,7 +509,7 @@ namespace build2
io = true;
}
- if (!run_finish_code (args, pr, s) || io)
+ if (!run_finish_code (args, pr, s, 2 /* verbosity */) || io)
{
diag_record dr;
dr << warn << "unable to detect " << l << " library type, ignoring" <<
@@ -489,23 +518,25 @@ namespace build2
return otype::e;
}
- if (obj && dll)
+ otype r;
+ if (obj != dll)
+ r = obj ? otype::a : otype::s;
+ else
{
- warn << l << " looks like hybrid static/import library, ignoring";
- return otype::e;
- }
+ if (obj && dll)
+ warn << l << " looks like hybrid static/import library, ignoring";
- if (!obj && !dll)
- {
- warn << l << " looks like empty static or import library, ignoring";
- return otype::e;
+ if (!obj && !dll)
+ warn << l << " looks like empty static or import library, ignoring";
+
+ r = otype::e;
}
- return obj ? otype::a : otype::s;
+ return library_type_cache.insert (move (key), r);
}
template <typename T>
- static T*
+ static pair<T*, bool>
msvc_search_library (const process_path& ld,
const dir_path& d,
const prerequisite_key& p,
@@ -551,20 +582,26 @@ namespace build2
//
timestamp mt (mtime (f));
- if (mt != timestamp_nonexistent && library_type (ld, f) == lt)
+ pair<T*, bool> r (nullptr, true);
+
+ if (mt != timestamp_nonexistent)
{
- // Enter the target.
- //
- T* t;
- common::insert_library (p.scope->ctx, t, name, d, ld, e, exist, trace);
- t->path_mtime (move (f), mt);
- return t;
+ if (library_type (ld, f) == lt)
+ {
+ // Enter the target.
+ //
+ common::insert_library (
+ p.scope->ctx, r.first, name, d, ld, e, exist, trace);
+ r.first->path_mtime (move (f), mt);
+ }
+ else
+ r.second = false; // Don't search for binless.
}
- return nullptr;
+ return r;
}
- liba* common::
+ pair<bin::liba*, bool> common::
msvc_search_static (const process_path& ld,
const dir_path& d,
const prerequisite_key& p,
@@ -572,14 +609,21 @@ namespace build2
{
tracer trace (x, "msvc_search_static");
- liba* r (nullptr);
+ liba* a (nullptr);
+ bool b (true);
- auto search = [&r, &ld, &d, &p, exist, &trace] (
+ auto search = [&a, &b, &ld, &d, &p, exist, &trace] (
const char* pf, const char* sf) -> bool
{
- r = msvc_search_library<liba> (
- ld, d, p, otype::a, pf, sf, exist, trace);
- return r != nullptr;
+ pair<liba*, bool> r (msvc_search_library<liba> (
+ ld, d, p, otype::a, pf, sf, exist, trace));
+
+ if (r.first != nullptr)
+ a = r.first;
+ else if (!r.second)
+ b = false;
+
+ return a != nullptr;
};
// Try:
@@ -592,10 +636,10 @@ namespace build2
search ("", "") ||
search ("lib", "") ||
search ("", "lib") ||
- search ("", "_static") ? r : nullptr;
+ search ("", "_static") ? make_pair (a, true) : make_pair (nullptr, b);
}
- libs* common::
+ pair<bin::libs*, bool> common::
msvc_search_shared (const process_path& ld,
const dir_path& d,
const prerequisite_key& pk,
@@ -606,12 +650,14 @@ namespace build2
assert (pk.scope != nullptr);
libs* s (nullptr);
+ bool b (true);
- auto search = [&s, &ld, &d, &pk, exist, &trace] (
+ auto search = [&s, &b, &ld, &d, &pk, exist, &trace] (
const char* pf, const char* sf) -> bool
{
- if (libi* i = msvc_search_library<libi> (
- ld, d, pk, otype::s, pf, sf, exist, trace))
+ pair<libi*, bool> r (msvc_search_library<libi> (
+ ld, d, pk, otype::s, pf, sf, exist, trace));
+ if (r.first != nullptr)
{
ulock l (
insert_library (
@@ -619,6 +665,8 @@ namespace build2
if (!exist)
{
+ libi* i (r.first);
+
if (l.owns_lock ())
{
s->adhoc_member = i; // We are first.
@@ -632,6 +680,8 @@ namespace build2
s->path_mtime (path (), i->mtime ());
}
}
+ else if (!r.second)
+ b = false;
return s != nullptr;
};
@@ -644,7 +694,7 @@ namespace build2
return
search ("", "") ||
search ("lib", "") ||
- search ("", "dll") ? s : nullptr;
+ search ("", "dll") ? make_pair (s, true) : make_pair (nullptr, b);
}
}
}