aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/c/init.cxx9
-rw-r--r--libbuild2/cc/common.cxx66
-rw-r--r--libbuild2/cc/common.hxx28
-rw-r--r--libbuild2/cc/compile-rule.cxx42
-rw-r--r--libbuild2/cc/gcc.cxx78
-rw-r--r--libbuild2/cc/guess.cxx63
-rw-r--r--libbuild2/cc/guess.hxx10
-rw-r--r--libbuild2/cc/link-rule.cxx68
-rw-r--r--libbuild2/cc/module.cxx50
-rw-r--r--libbuild2/cc/module.hxx24
-rw-r--r--libbuild2/cc/msvc.cxx116
-rw-r--r--libbuild2/cxx/init.cxx9
12 files changed, 364 insertions, 199 deletions
diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx
index 5939d4c..c72f729 100644
--- a/libbuild2/c/init.cxx
+++ b/libbuild2/c/init.cxx
@@ -35,8 +35,7 @@ namespace build2
{
public:
explicit
- config_module (config_data&& d)
- : config_data (move (d)), cc::config_module (move (d)) {}
+ config_module (config_data&& d): cc::config_module (move (d)) {}
virtual strings
translate_std (const compiler_info&,
@@ -345,7 +344,11 @@ namespace build2
cast<dir_paths> (rs[cm.x_sys_lib_dirs]),
cast<dir_paths> (rs[cm.x_sys_inc_dirs]),
- cm.x_info->sys_mod_dirs,
+ cm.x_info->sys_mod_dirs ? &cm.x_info->sys_mod_dirs->first : nullptr,
+
+ cm.sys_lib_dirs_mode,
+ cm.sys_inc_dirs_mode,
+ cm.sys_mod_dirs_mode,
cm.sys_lib_dirs_extra,
cm.sys_inc_dirs_extra,
diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx
index 1af64c8..b949c2b 100644
--- a/libbuild2/cc/common.cxx
+++ b/libbuild2/cc/common.cxx
@@ -815,7 +815,7 @@ namespace build2
if (!usrd)
{
- usrd = extract_library_dirs (*p.scope);
+ usrd = extract_library_search_dirs (*p.scope);
// Handle automatic importing of installed build2 libraries. This is a
// mirror side of the uninstalled case that is handled via the special
@@ -1011,8 +1011,14 @@ namespace build2
return r;
}
+ void
+ gcc_extract_library_search_dirs (const strings&, dir_paths&); // gcc.cxx
+
+ void
+ msvc_extract_library_search_dirs (const strings&, dir_paths&); // msvc.cxx
+
dir_paths common::
- extract_library_dirs (const scope& bs) const
+ extract_library_search_dirs (const scope& bs) const
{
dir_paths r;
@@ -1020,58 +1026,18 @@ namespace build2
//
auto extract = [&bs, &r, this] (const value& val, const variable& var)
{
- bool msvc (tsys == "win32-msvc");
-
const auto& v (cast<strings> (val));
- for (auto i (v.begin ()), e (v.end ()); i != e; ++i)
- {
- const string& o (*i);
-
- dir_path d;
-
- try
+ auto df = make_diag_frame (
+ [&var, &bs](const diag_record& dr)
{
- if (msvc)
- {
- // /LIBPATH:<dir> (case-insensitive).
- //
- if ((o[0] == '/' || o[0] == '-') &&
- icasecmp (o.c_str () + 1, "LIBPATH:", 8) == 0)
- d = dir_path (o, 9, string::npos);
- else
- continue;
- }
- else
- {
- // -L can either be in the "-L<dir>" or "-L <dir>" form.
- //
- if (o == "-L")
- {
- if (++i == e)
- break; // Let the compiler complain.
-
- d = dir_path (*i);
- }
- else if (o.compare (0, 2, "-L") == 0)
- d = dir_path (o, 2, string::npos);
- else
- continue;
- }
- }
- catch (const invalid_path& e)
- {
- fail << "invalid directory '" << e.path << "'"
- << " in option '" << o << "'"
- << " in variable " << var
- << " for scope " << bs;
- }
+ dr << info << "in variable " << var << " for scope " << bs;
+ });
- // Ignore relative paths. Or maybe we should warn?
- //
- if (!d.relative ())
- r.push_back (move (d));
- }
+ if (tsys == "win32-msvc")
+ msvc_extract_library_search_dirs (v, r);
+ else
+ gcc_extract_library_search_dirs (v, r);
};
if (auto l = bs[c_loptions]) extract (*l, c_loptions);
diff --git a/libbuild2/cc/common.hxx b/libbuild2/cc/common.hxx
index a17442a..56dcec4 100644
--- a/libbuild2/cc/common.hxx
+++ b/libbuild2/cc/common.hxx
@@ -162,12 +162,20 @@ namespace build2
const strings* xlate_hdr; // x.translatable_headers (NULL if
// unused/empty).
- const dir_paths& sys_lib_dirs; // x.sys_lib_dirs
- const dir_paths& sys_inc_dirs; // x.sys_inc_dirs
- const optional<dir_paths>& sys_mod_dirs; // compiler_info::sys_mod_dirs
+ // The order of sys_*_dirs is the mode entries first, followed by the
+ // compiler built-in entries, and finished off with any extra entries
+ // (e.g., fallback directories such as /usr/local/*).
+ //
+ const dir_paths& sys_lib_dirs; // x.sys_lib_dirs
+ const dir_paths& sys_inc_dirs; // x.sys_inc_dirs
+ const dir_paths* sys_mod_dirs; // compiler_info::sys_mod_dirs
+
+ size_t sys_lib_dirs_mode; // Number of leading mode entries (0 if none).
+ size_t sys_inc_dirs_mode;
+ size_t sys_mod_dirs_mode;
- size_t sys_lib_dirs_extra; // First extra path (size if none).
- size_t sys_inc_dirs_extra; // First extra path (size if none).
+ size_t sys_lib_dirs_extra; // First trailing extra entry (size if none).
+ size_t sys_inc_dirs_extra;
const target_type& x_src; // Source target type (c{}, cxx{}).
const target_type* x_mod; // Module target type (mxx{}), if any.
@@ -214,9 +222,9 @@ namespace build2
bool fs,
const dir_paths& sld,
const dir_paths& sid,
- const optional<dir_paths>& smd,
- size_t sle,
- size_t sie,
+ const dir_paths* smd,
+ size_t slm, size_t sim, size_t smm,
+ size_t sle, size_t sie,
const target_type& src,
const target_type* mod,
const target_type* const* hdr,
@@ -235,6 +243,8 @@ namespace build2
symexport (fs),
xlate_hdr (nullptr),
sys_lib_dirs (sld), sys_inc_dirs (sid), sys_mod_dirs (smd),
+ sys_lib_dirs_mode (slm), sys_inc_dirs_mode (sim),
+ sys_mod_dirs_mode (smm),
sys_lib_dirs_extra (sle), sys_inc_dirs_extra (sie),
x_src (src), x_mod (mod), x_hdr (hdr), x_inc (inc) {}
};
@@ -324,7 +334,7 @@ namespace build2
}
dir_paths
- extract_library_dirs (const scope&) const;
+ extract_library_search_dirs (const scope&) const;
// Alternative search logic for VC (msvc.cxx).
//
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index de35ad5..6d4321a 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -192,12 +192,19 @@ namespace build2
{
assert (sys_inc_dirs_extra <= sys_inc_dirs.size ());
- auto b (sys_inc_dirs.begin ());
- auto m (b + sys_inc_dirs_extra);
+ // Note that the mode options are added as part of cmode.
+ //
+ auto b (sys_inc_dirs.begin () + sys_inc_dirs_mode);
+ auto m (sys_inc_dirs.begin () + sys_inc_dirs_extra);
auto e (sys_inc_dirs.end ());
+ // Note: starting from 15.6, MSVC gained /external:I option though it
+ // doesn't seem to affect the order, only "system-ness".
+ //
append_option_values (
- args, cclass == compiler_class::msvc ? "/I" : "-I",
+ args,
+ cclass == compiler_class::gcc ? "-idirafter" :
+ cclass == compiler_class::msvc ? "/I" : "-I",
m, e,
[] (const dir_path& d) {return d.string ().c_str ();});
@@ -866,10 +873,6 @@ namespace build2
// Hash *.export.poptions from prerequisite libraries.
//
append_lib_options (bs, cs, a, t, li);
-
- // Extra system header dirs (last).
- //
- append_sys_inc_options (cs);
}
append_options (cs, t, c_coptions);
@@ -886,6 +889,9 @@ namespace build2
append_options (cs, cmode);
+ if (md.pp != preprocessed::all)
+ append_sys_inc_options (cs); // Extra system header dirs (last).
+
if (dd.expect (cs.string ()) != nullptr)
l4 ([&]{trace << "options mismatch forcing update of " << t;});
}
@@ -2933,10 +2939,6 @@ namespace build2
}
}
- // Extra system header dirs (last).
- //
- append_sys_inc_options (args);
-
if (md.symexport)
append_symexport_options (args, t);
@@ -2980,6 +2982,7 @@ namespace build2
args.push_back ("/nologo");
append_options (args, cmode);
+ append_sys_inc_options (args); // Extra system header dirs (last).
// See perform_update() for details on overriding the default
// exceptions and runtime.
@@ -3036,6 +3039,7 @@ namespace build2
}
append_options (args, cmode);
+ append_sys_inc_options (args); // Extra system header dirs (last).
// Setup the dynamic module mapper if needed.
//
@@ -4080,8 +4084,6 @@ namespace build2
append_lib_options (t.base_scope (), args, a, t, li);
- append_sys_inc_options (args);
-
if (md.symexport)
append_symexport_options (args, t);
@@ -4112,6 +4114,7 @@ namespace build2
args.push_back ("/nologo");
append_options (args, cmode);
+ append_sys_inc_options (args);
if (x_lang == lang::cxx && !find_option_prefix ("/EH", args))
args.push_back ("/EHsc");
@@ -4147,6 +4150,7 @@ namespace build2
}
append_options (args, cmode);
+ append_sys_inc_options (args);
args.push_back ("-E");
append_lang_options (args, md);
@@ -5595,7 +5599,7 @@ namespace build2
{
// Add the VC's default directory (should be only one).
//
- if (sys_mod_dirs && !sys_mod_dirs->empty ())
+ if (sys_mod_dirs != nullptr && !sys_mod_dirs->empty ())
{
args.push_back ("/module:stdIfcDir");
args.push_back (sys_mod_dirs->front ().string ().c_str ());
@@ -5693,10 +5697,6 @@ namespace build2
//
append_lib_options (bs, args, a, t, li);
- // Extra system header dirs (last).
- //
- append_sys_inc_options (args);
-
if (md.symexport)
append_symexport_options (args, t);
}
@@ -5726,6 +5726,9 @@ namespace build2
append_options (args, cmode);
+ if (md.pp != preprocessed::all)
+ append_sys_inc_options (args); // Extra system header dirs (last).
+
// While we want to keep the low-level build as "pure" as possible,
// the two misguided defaults, exceptions and runtime, just have to be
// fixed. Otherwise the default build is pretty much unusable. But we
@@ -5889,6 +5892,9 @@ namespace build2
append_options (args, cmode);
+ if (md.pp != preprocessed::all)
+ append_sys_inc_options (args); // Extra system header dirs (last).
+
append_header_options (env, args, header_args, a, t, md, md.dd);
append_module_options (env, args, module_args, a, t, md, md.dd);
diff --git a/libbuild2/cc/gcc.cxx b/libbuild2/cc/gcc.cxx
index 91a04f6..5d84f85 100644
--- a/libbuild2/cc/gcc.cxx
+++ b/libbuild2/cc/gcc.cxx
@@ -23,17 +23,61 @@ namespace build2
{
using namespace bin;
+ void
+ gcc_extract_library_search_dirs (const strings& v, dir_paths& r)
+ {
+ for (auto i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ const string& o (*i);
+
+ dir_path d;
+ try
+ {
+ // -L can either be in the "-L<dir>" or "-L <dir>" form.
+ //
+ if (o == "-L")
+ {
+ if (++i == e)
+ break; // Let the compiler complain.
+
+ d = dir_path (*i);
+ }
+ else if (o.compare (0, 2, "-L") == 0)
+ d = dir_path (o, 2, string::npos);
+ else
+ continue;
+ }
+ catch (const invalid_path& e)
+ {
+ fail << "invalid directory '" << e.path << "'" << " in option '"
+ << o << "'";
+ }
+
+ // Ignore relative paths. Or maybe we should warn?
+ //
+ if (!d.relative ())
+ r.push_back (move (d));
+ }
+ }
+
// Extract system header search paths from GCC (gcc/g++) or compatible
- // (Clang, Intel) using the -v -E </dev/null method.
+ // (Clang, Intel) using the `-v -E </dev/null` method.
+ //
+ // Note that we currently do not return an accurate number of mode paths
+ // though this information is currently not used for this compiler class.
+ // It's not even clear whether we can do this correctly since GCC will
+ // ignore an already-known system include path. Probably the only way to
+ // do this is to run the compiler twice.
//
- dir_paths config_module::
- gcc_header_search_paths (const process_path& xc, scope& rs) const
+ pair<dir_paths, size_t> config_module::
+ gcc_header_search_dirs (const process_path& xc, scope& rs) const
{
dir_paths r;
+ // Note also that any -I and similar that we may specify on the command
+ // line are factored into the output.
+ //
cstrings args {xc.recall_string ()};
- append_options (args, rs, c_coptions);
- append_options (args, rs, x_coptions);
append_options (args, tstd);
append_options (args, rs, x_mode);
@@ -154,14 +198,14 @@ namespace build2
fail << "unable to extract " << x_lang << " compiler system header "
<< "search paths";
- return r;
+ return make_pair (move (r), size_t (0));
}
// 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 (const process_path& xc, scope& rs) const
+ pair<dir_paths, size_t> config_module::
+ gcc_library_search_dirs (const process_path& xc, scope& rs) const
{
// The output of -print-search-dirs are a bunch of lines that start with
// "<name>: =" where name can be "install", "programs", or "libraries".
@@ -176,16 +220,20 @@ namespace build2
// Maybe it's time we stop playing these games and start running
// everything with LC_ALL=C? One drawback of this approach is that the
// command that we print isn't exactly how we run. Maybe print it with
- // the environment variables in front?
+ // the environment variables in front? Also there is MinGW GCC.
+ //
+ // Note also that any -L that we may specify on the command line are not
+ // factored into the output (unlike for headers above).
//
dir_paths r;
+ // Extract -L paths from the compiler mode.
+ //
+ gcc_extract_library_search_dirs (cast<strings> (rs[x_mode]), r);
+ size_t rn (r.size ());
+
cstrings args {xc.recall_string ()};
- append_options (args, rs, c_coptions);
- append_options (args, rs, x_coptions);
append_options (args, tstd);
- append_options (args, rs, x_loptions);
- append_options (args, rs, c_loptions);
append_options (args, rs, x_mode);
args.push_back ("-print-search-dirs");
args.push_back (nullptr);
@@ -267,7 +315,9 @@ namespace build2
break;
}
- return r;
+ return make_pair (move (r), rn);
}
+
+
}
}
diff --git a/libbuild2/cc/guess.cxx b/libbuild2/cc/guess.cxx
index 182a997..b63765f 100644
--- a/libbuild2/cc/guess.cxx
+++ b/libbuild2/cc/guess.cxx
@@ -1353,17 +1353,29 @@ namespace build2
<< "' to runtime version" << endf;
}
+ void
+ msvc_extract_header_search_dirs (const strings&, dir_paths&); // msvc.cxx
+
+ void
+ msvc_extract_library_search_dirs (const strings&, dir_paths&); // msvc.cxx
+
// Return the MSVC system header search paths (i.e., what the Visual
- // Studio command prompt puts into INCLUDE).
+ // Studio command prompt puts into INCLUDE) including any paths from the
+ // compiler mode and their count.
//
// Note that currently we don't add any ATL/MFC or WinRT paths (but could
// do that probably first checking if they exist/empty).
//
- static dir_paths
- msvc_inc (const msvc_info& mi)
+ static pair<dir_paths, size_t>
+ msvc_inc (const msvc_info& mi, const strings& mo)
{
dir_paths r;
+ // Extract /I paths from the compiler mode.
+ //
+ msvc_extract_header_search_dirs (mo, r);
+ size_t rn (r.size ());
+
r.push_back (dir_path (mi.msvc_dir) /= "include");
// This path structure only appeared in Platform SDK 10 (if anyone wants
@@ -1379,30 +1391,39 @@ namespace build2
r.push_back (dir_path (d) /= "um" );
}
- return r;
+ return make_pair (move (r), rn);
}
// Return the MSVC system module search paths (i.e., what the Visual
- // Studio command prompt puts into IFCPATH).
+ // Studio command prompt puts into IFCPATH) including any paths from the
+ // compiler mode and their count.
//
- static dir_paths
- msvc_mod (const msvc_info& mi, const char* cpu)
+ static pair<dir_paths, size_t>
+ msvc_mod (const msvc_info& mi, const strings&, const char* cpu)
{
+ //@@ TODO: mode.
+
dir_paths r;
r.push_back ((dir_path (mi.msvc_dir) /= "ifc") /= cpu);
- return r;
+ return make_pair (move (r), size_t (0));
}
// Return the MSVC system library search paths (i.e., what the Visual
- // Studio command prompt puts into LIB).
+ // Studio command prompt puts into LIB) including any paths from the
+ // compiler mode and their count.
//
- static dir_paths
- msvc_lib (const msvc_info& mi, const char* cpu)
+ static pair<dir_paths, size_t>
+ msvc_lib (const msvc_info& mi, const strings& mo, const char* cpu)
{
dir_paths r;
+ // Extract /LIBPATH paths from the compiler mode.
+ //
+ msvc_extract_library_search_dirs (mo, r);
+ size_t rn (r.size ());
+
r.push_back ((dir_path (mi.msvc_dir) /= "lib") /= cpu);
// This path structure only appeared in Platform SDK 10 (if anyone wants
@@ -1417,7 +1438,7 @@ namespace build2
r.push_back ((dir_path (d) /= "um" ) /= cpu);
}
- return r;
+ return make_pair (move (r), rn);
}
// Return the MSVC binutils search paths (i.e., what the Visual Studio
@@ -1452,7 +1473,7 @@ namespace build2
const path& xc,
const string* xv,
const string* xt,
- const strings&,
+ const strings& x_mo,
const strings*, const strings*,
const strings*, const strings*,
const strings*, const strings*,
@@ -1616,18 +1637,18 @@ namespace build2
// running out of the Visual Studio command prompt and will have to
// supply PATH/INCLUDE/LIB/IFCPATH equivalents ourselves.
//
- optional<dir_paths> lib_dirs;
- optional<dir_paths> inc_dirs;
- optional<dir_paths> mod_dirs;
+ optional<pair<dir_paths, size_t>> lib_dirs;
+ optional<pair<dir_paths, size_t>> inc_dirs;
+ optional<pair<dir_paths, size_t>> mod_dirs;
string bpat;
if (const msvc_info* mi = static_cast<msvc_info*> (gr.info.get ()))
{
const char* cpu (msvc_cpu (target_triplet (t).cpu));
- lib_dirs = msvc_lib (*mi, cpu);
- inc_dirs = msvc_inc (*mi);
- mod_dirs = msvc_mod (*mi, cpu);
+ lib_dirs = msvc_lib (*mi, x_mo, cpu);
+ inc_dirs = msvc_inc (*mi, x_mo);
+ mod_dirs = msvc_mod (*mi, x_mo, cpu);
bpat = msvc_bin (*mi, cpu);
}
@@ -2291,7 +2312,7 @@ namespace build2
// For Clang on Windows targeting MSVC we remap the target to match
// MSVC's.
//
- optional<dir_paths> lib_dirs;
+ optional<pair<dir_paths, size_t>> lib_dirs;
string bpat;
if (tt.system == "windows-msvc")
@@ -2333,7 +2354,7 @@ namespace build2
// to extract this from Clang and -print-search-paths would have been
// the natural way for Clang to report it. But no luck.
//
- lib_dirs = msvc_lib (mi, cpu);
+ lib_dirs = msvc_lib (mi, x_mo, cpu);
// Binutils search paths.
//
diff --git a/libbuild2/cc/guess.hxx b/libbuild2/cc/guess.hxx
index b32aaa9..97acbf9 100644
--- a/libbuild2/cc/guess.hxx
+++ b/libbuild2/cc/guess.hxx
@@ -227,12 +227,12 @@ namespace build2
string c_stdlib;
string x_stdlib;
- // System library/header/module search paths, if extracted at the guess
- // stage.
+ // System library/header/module search paths and number of leading mode
+ // entries, if extracted at the guess stage.
//
- optional<dir_paths> sys_lib_dirs;
- optional<dir_paths> sys_inc_dirs;
- optional<dir_paths> sys_mod_dirs;
+ optional<pair<dir_paths, size_t>> sys_lib_dirs;
+ optional<pair<dir_paths, size_t>> sys_inc_dirs;
+ optional<pair<dir_paths, size_t>> sys_mod_dirs;
};
// In a sense this is analagous to the language standard which we handle
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index 6969ef2..bf474e6 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -2331,39 +2331,6 @@ namespace build2
append_options (args, t, x_loptions);
append_options (args, t, c_loptions);
- // Extra system library dirs (last).
- //
- assert (sys_lib_dirs_extra <= sys_lib_dirs.size ());
-
- if (tsys == "win32-msvc")
- {
- // If we have no LIB environment variable set, then we add all of
- // them. But we want extras to come first.
- //
- auto b (sys_lib_dirs.begin ());
- auto m (b + sys_lib_dirs_extra);
- auto e (sys_lib_dirs.end ());
-
- for (auto i (m); i != e; ++i)
- sargs1.push_back ("/LIBPATH:" + i->string ());
-
- if (!getenv ("LIB"))
- {
- for (auto i (b); i != m; ++i)
- sargs1.push_back ("/LIBPATH:" + i->string ());
- }
-
- append_args (sargs1);
- }
- else
- {
- append_option_values (
- args,
- "-L",
- sys_lib_dirs.begin () + sys_lib_dirs_extra, sys_lib_dirs.end (),
- [] (const dir_path& d) {return d.string ().c_str ();});
- }
-
// Handle soname/rpath.
//
if (tclass == "windows")
@@ -2446,6 +2413,41 @@ namespace build2
if (ldc)
append_options (args, cmode);
+
+ // Extra system library dirs (last).
+ //
+ assert (sys_lib_dirs_extra <= sys_lib_dirs.size ());
+
+ if (tsys == "win32-msvc")
+ {
+ // If we have no LIB environment variable set, then we add all of
+ // them. But we want extras to come first.
+ //
+ // Note that the mode options are added as part of cmode.
+ //
+ auto b (sys_lib_dirs.begin () + sys_lib_dirs_mode);
+ auto m (sys_lib_dirs.begin () + sys_lib_dirs_extra);
+ auto e (sys_lib_dirs.end ());
+
+ for (auto i (m); i != e; ++i)
+ sargs1.push_back ("/LIBPATH:" + i->string ());
+
+ if (!getenv ("LIB"))
+ {
+ for (auto i (b); i != m; ++i)
+ sargs1.push_back ("/LIBPATH:" + i->string ());
+ }
+
+ append_args (sargs1);
+ }
+ else
+ {
+ append_option_values (
+ args,
+ "-L",
+ sys_lib_dirs.begin () + sys_lib_dirs_extra, sys_lib_dirs.end (),
+ [] (const dir_path& d) {return d.string ().c_str ();});
+ }
}
// All the options should now be in. Hash them and compare with the db.
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index 69530a2..e31519c 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -409,9 +409,9 @@ namespace build2
//
// Note that for now module search paths only come from compiler_info.
//
- dir_paths lib_dirs;
- dir_paths inc_dirs;
- const optional<dir_paths>& mod_dirs (xi.sys_mod_dirs);
+ pair<dir_paths, size_t> lib_dirs;
+ pair<dir_paths, size_t> inc_dirs;
+ const optional<pair<dir_paths, size_t>>& mod_dirs (xi.sys_mod_dirs);
if (xi.sys_lib_dirs)
lib_dirs = *xi.sys_lib_dirs;
@@ -420,10 +420,10 @@ namespace build2
switch (xi.class_)
{
case compiler_class::gcc:
- lib_dirs = gcc_library_search_paths (xi.path, rs);
+ lib_dirs = gcc_library_search_dirs (xi.path, rs);
break;
case compiler_class::msvc:
- lib_dirs = msvc_library_search_paths (xi.path, rs);
+ lib_dirs = msvc_library_search_dirs (xi.path, rs);
break;
}
}
@@ -435,16 +435,20 @@ namespace build2
switch (xi.class_)
{
case compiler_class::gcc:
- inc_dirs = gcc_header_search_paths (xi.path, rs);
+ inc_dirs = gcc_header_search_dirs (xi.path, rs);
break;
case compiler_class::msvc:
- inc_dirs = msvc_header_search_paths (xi.path, rs);
+ inc_dirs = msvc_header_search_dirs (xi.path, rs);
break;
}
}
- sys_lib_dirs_extra = lib_dirs.size ();
- sys_inc_dirs_extra = inc_dirs.size ();
+ sys_lib_dirs_mode = lib_dirs.second;
+ sys_inc_dirs_mode = inc_dirs.second;
+ sys_mod_dirs_mode = mod_dirs ? mod_dirs->second : 0;
+
+ sys_lib_dirs_extra = lib_dirs.first.size ();
+ sys_inc_dirs_extra = inc_dirs.first.size ();
#ifndef _WIN32
// Add /usr/local/{include,lib}. We definitely shouldn't do this if we
@@ -460,8 +464,8 @@ namespace build2
// on the next invocation.
//
{
- auto& is (inc_dirs);
- auto& ls (lib_dirs);
+ auto& is (inc_dirs.first);
+ auto& ls (lib_dirs.first);
bool ui (find (is.begin (), is.end (), usr_inc) != is.end ());
bool uli (find (is.begin (), is.end (), usr_loc_inc) != is.end ());
@@ -598,40 +602,44 @@ namespace build2
dr << "\n pattern " << xi.pattern;
}
- if (verb >= 3 && mod_dirs && !mod_dirs->empty ())
+ auto& mods (mod_dirs ? mod_dirs->first : dir_paths ());
+ auto& incs (inc_dirs.first);
+ auto& libs (lib_dirs.first);
+
+ if (verb >= 3 && !mods.empty ())
{
dr << "\n mod dirs";
- for (const dir_path& d: *mod_dirs)
+ for (const dir_path& d: mods)
{
dr << "\n " << d;
}
}
- if (verb >= 3 && !inc_dirs.empty ())
+ if (verb >= 3 && !incs.empty ())
{
dr << "\n inc dirs";
- for (size_t i (0); i != inc_dirs.size (); ++i)
+ for (size_t i (0); i != incs.size (); ++i)
{
if (i == sys_inc_dirs_extra)
dr << "\n --";
- dr << "\n " << inc_dirs[i];
+ dr << "\n " << incs[i];
}
}
- if (verb >= 3 && !lib_dirs.empty ())
+ if (verb >= 3 && !libs.empty ())
{
dr << "\n lib dirs";
- for (size_t i (0); i != lib_dirs.size (); ++i)
+ for (size_t i (0); i != libs.size (); ++i)
{
if (i == sys_lib_dirs_extra)
dr << "\n --";
- dr << "\n " << lib_dirs[i];
+ dr << "\n " << libs[i];
}
}
}
- rs.assign (x_sys_lib_dirs) = move (lib_dirs);
- rs.assign (x_sys_inc_dirs) = move (inc_dirs);
+ rs.assign (x_sys_lib_dirs) = move (lib_dirs.first);
+ rs.assign (x_sys_inc_dirs) = move (inc_dirs.first);
// Load cc.core.config.
//
diff --git a/libbuild2/cc/module.hxx b/libbuild2/cc/module.hxx
index 5c7b8ab..ae121ef 100644
--- a/libbuild2/cc/module.hxx
+++ b/libbuild2/cc/module.hxx
@@ -26,7 +26,7 @@ namespace build2
struct compiler_info;
class LIBBUILD2_CC_SYMEXPORT config_module: public build2::module,
- public virtual config_data
+ public config_data
{
public:
explicit
@@ -55,27 +55,31 @@ namespace build2
const compiler_info* x_info;
- // Temporary storage for data::sys_*_dirs_extra.
+ // Temporary storage for data::sys_*_dirs_*.
//
+ size_t sys_lib_dirs_mode;
+ size_t sys_inc_dirs_mode;
+ size_t sys_mod_dirs_mode;
+
size_t sys_lib_dirs_extra;
size_t sys_inc_dirs_extra;
private:
// Defined in gcc.cxx.
//
- dir_paths
- gcc_header_search_paths (const process_path&, scope&) const;
+ pair<dir_paths, size_t>
+ gcc_header_search_dirs (const process_path&, scope&) const;
- dir_paths
- gcc_library_search_paths (const process_path&, scope&) const;
+ pair<dir_paths, size_t>
+ gcc_library_search_dirs (const process_path&, scope&) const;
// Defined in msvc.cxx.
//
- dir_paths
- msvc_header_search_paths (const process_path&, scope&) const;
+ pair<dir_paths, size_t>
+ msvc_header_search_dirs (const process_path&, scope&) const;
- dir_paths
- msvc_library_search_paths (const process_path&, scope&) const;
+ pair<dir_paths, size_t>
+ msvc_library_search_dirs (const process_path&, scope&) const;
private:
bool new_; // See guess() and init() for details.
diff --git a/libbuild2/cc/msvc.cxx b/libbuild2/cc/msvc.cxx
index ce54964..4e40bd4 100644
--- a/libbuild2/cc/msvc.cxx
+++ b/libbuild2/cc/msvc.cxx
@@ -214,43 +214,135 @@ namespace build2
}
}
+ void
+ msvc_extract_header_search_dirs (const strings& v, dir_paths& r)
+ {
+ for (auto i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ const string& o (*i);
+
+ dir_path d;
+ try
+ {
+ // -I can either be in the "-Ifoo" or "-I foo" form. For VC it can
+ // also be /I.
+ //
+ if (o.size () > 1 && (o[0] == '-' || o[0] == '/') && o[1] == 'I')
+ {
+ if (o.size () == 2)
+ {
+ if (++i == e)
+ break; // Let the compiler complain.
+
+ d = dir_path (*i);
+ }
+ else
+ d = dir_path (o, 2, string::npos);
+ }
+ else
+ continue;
+ }
+ catch (const invalid_path& e)
+ {
+ fail << "invalid directory '" << e.path << "'" << " in option '"
+ << o << "'";
+ }
+
+ // Ignore relative paths. Or maybe we should warn?
+ //
+ if (!d.relative ())
+ r.push_back (move (d));
+ }
+ }
+
+ void
+ msvc_extract_library_search_dirs (const strings& v, dir_paths& r)
+ {
+ for (auto i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ const string& o (*i);
+
+ dir_path d;
+ try
+ {
+ // /LIBPATH:<dir> (case-insensitive).
+ //
+ if ((o[0] == '/' || o[0] == '-') &&
+ icasecmp (o.c_str () + 1, "LIBPATH:", 8) == 0)
+ d = dir_path (o, 9, string::npos);
+ else
+ continue;
+ }
+ catch (const invalid_path& e)
+ {
+ fail << "invalid directory '" << e.path << "'" << " in option '"
+ << o << "'";
+ }
+
+ // Ignore relative paths. Or maybe we should warn?
+ //
+ if (!d.relative ())
+ r.push_back (move (d));
+ }
+ }
+
// Extract system header search paths from MSVC.
//
- dir_paths config_module::
- msvc_header_search_paths (const process_path&, scope&) const
+ pair<dir_paths, size_t> config_module::
+ msvc_header_search_dirs (const process_path&, scope& rs) const
{
// The compiler doesn't seem to have any built-in paths and all of them
// either come from the INCLUDE environment variable or are specified
- // explicitly on the command line.
+ // explicitly on the command line (we now do this if running out of the
+ // command prompt; see guess).
// @@ VC: how are we going to do this? E.g., cl-14 does this internally.
- // cl.exe /Be prints INCLUDE.
+ // cl.exe /Be prints INCLUDE. One advantage of going through the
+ // compiler is that it may be a wrapper (like our msvc-linux). Note
+ // also that we will still have to incorporate mode options. And this
+ // is not used for Clang targeting MSVC.
//
// Should we actually bother? INCLUDE is normally used for system
// headers and its highly unlikely we will see an imported library
// that lists one of those directories in pkg-config Cflags value.
- // Let's wait and see.
+ // So the only benefit is to be able to print them. Let's wait and
+ // see.
+
+ // Extract -I paths from the compiler mode.
//
- return dir_paths ();
+ dir_paths r;
+ msvc_extract_header_search_dirs (cast<strings> (rs[x_mode]), r);
+ size_t rn (r.size ());
+
+ return make_pair (move (r), rn);
}
// Extract system library search paths from MSVC.
//
- dir_paths config_module::
- msvc_library_search_paths (const process_path&, scope&) const
+ pair<dir_paths, size_t> config_module::
+ msvc_library_search_dirs (const process_path&, scope& rs) const
{
// The linker 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 the command line.
+ // explicitly on the command line (we now do this if running out of the
+ // command prompt; see guess).
// @@ VC: how are we going to do this? E.g., cl-14 does this internally.
- // cl.exe /Be prints LIB.
+ // cl.exe /Be prints LIB. See above for further discussion.
//
// Should we actually bother? LIB is normally used for system
// libraries and its highly unlikely we will see an explicit import
- // for a library from one of those directories. Let's wait and see.
+ // for a library from one of those directories. So the only benefit
+ // is to be able to print them. Let's wait and see.
//
- return dir_paths ();
+
+ // Extract /LIBPATH paths from the compiler mode.
+ //
+ dir_paths r;
+ msvc_extract_library_search_dirs (cast<strings> (rs[x_mode]), r);
+ size_t rn (r.size ());
+
+ return make_pair (move (r), rn);
}
// Inspect the file and determine if it is static or import library.
diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx
index 719a88a..e44b6fe 100644
--- a/libbuild2/cxx/init.cxx
+++ b/libbuild2/cxx/init.cxx
@@ -36,8 +36,7 @@ namespace build2
{
public:
explicit
- config_module (config_data&& d)
- : config_data (move (d)), cc::config_module (move (d)) {}
+ config_module (config_data&& d): cc::config_module (move (d)) {}
virtual strings
translate_std (const compiler_info&,
@@ -612,7 +611,11 @@ namespace build2
cast<dir_paths> (rs[cm.x_sys_lib_dirs]),
cast<dir_paths> (rs[cm.x_sys_inc_dirs]),
- cm.x_info->sys_mod_dirs,
+ cm.x_info->sys_mod_dirs ? &cm.x_info->sys_mod_dirs->first : nullptr,
+
+ cm.sys_lib_dirs_mode,
+ cm.sys_inc_dirs_mode,
+ cm.sys_mod_dirs_mode,
cm.sys_lib_dirs_extra,
cm.sys_inc_dirs_extra,