aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-10-25 17:18:37 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-10-25 17:44:42 +0200
commit8ababa51319753c5c697374c722bb01e845e3e68 (patch)
treec8f89bffc129d3004da232c327eb81b9a1459e77
parent59dec666d17fdd7c5394c3c081cf21381a8af07d (diff)
Redesign cc::compiler_id to make variant customizable
-rw-r--r--build2/c/init.cxx7
-rw-r--r--build2/cc/common.hxx31
-rw-r--r--build2/cc/compile-rule.cxx123
-rw-r--r--build2/cc/guess.cxx143
-rw-r--r--build2/cc/guess.hxx70
-rw-r--r--build2/cc/link-rule.cxx6
-rw-r--r--build2/cc/module.cxx2
-rw-r--r--build2/cxx/init.cxx30
-rw-r--r--build2/types.hxx1
9 files changed, 223 insertions, 190 deletions
diff --git a/build2/c/init.cxx b/build2/c/init.cxx
index 56b3f02..141c810 100644
--- a/build2/c/init.cxx
+++ b/build2/c/init.cxx
@@ -314,7 +314,8 @@ namespace build2
"c.install",
"c.uninstall",
- cm.ci_->id.value (),
+ cm.ci_->id.type,
+ cm.ci_->id.variant,
cm.ci_->class_,
cm.ci_->version.major,
cm.ci_->version.minor,
@@ -326,8 +327,8 @@ namespace build2
false, // No C modules yet.
false, // No __symexport support since no modules.
- cast<dir_paths> (rs[cm.x_sys_lib_dirs]),
- cast<dir_paths> (rs[cm.x_sys_inc_dirs]),
+ cast<dir_paths> (rs[cm.x_sys_lib_dirs]),
+ cast<dir_paths> (rs[cm.x_sys_inc_dirs]),
cm.sys_lib_dirs_extra,
cm.sys_inc_dirs_extra,
diff --git a/build2/cc/common.hxx b/build2/cc/common.hxx
index deed573..9629fa3 100644
--- a/build2/cc/common.hxx
+++ b/build2/cc/common.hxx
@@ -119,20 +119,21 @@ namespace build2
// Cached values for some commonly-used variables/values.
//
- compiler_id::value_type cid; // x.id
- compiler_class cclass; // x.class
- uint64_t cmaj; // x.version.major
- uint64_t cmin; // x.version.minor
- const process_path& cpath; // x.path
+ compiler_type ctype; // x.id.type
+ const string& cvariant; // x.id.variant
+ compiler_class cclass; // x.class
+ uint64_t cmaj; // x.version.major
+ uint64_t cmin; // x.version.minor
+ const process_path& cpath; // x.path
- const target_triplet& ctgt; // x.target
- const string& tsys; // x.target.system
- const string& tclass; // x.target.class
+ const target_triplet& ctgt; // x.target
+ const string& tsys; // x.target.system
+ const string& tclass; // x.target.class
- const strings& tstd; // Translated x_std value (options).
+ const strings& tstd; // Translated x_std value (options).
- bool modules; // x.features.modules
- bool symexport; // x.features.symexport
+ bool modules; // x.features.modules
+ bool symexport; // x.features.symexport
const dir_paths& sys_lib_dirs; // x.sys_lib_dirs
const dir_paths& sys_inc_dirs; // x.sys_inc_dirs
@@ -173,7 +174,9 @@ namespace build2
const char* link,
const char* install,
const char* uninstall,
- compiler_id::value_type id, compiler_class cl,
+ compiler_type ct,
+ const string& cv,
+ compiler_class cl,
uint64_t mj, uint64_t mi,
const process_path& path,
const target_triplet& tgt,
@@ -193,7 +196,9 @@ namespace build2
x_link (link),
x_install (install),
x_uninstall (uninstall),
- cid (id), cclass (cl), cmaj (mj), cmin (mi), cpath (path),
+ ctype (ct), cvariant (cv), cclass (cl),
+ cmaj (mj), cmin (mi),
+ cpath (path),
ctgt (tgt), tsys (ctgt.system), tclass (ctgt.class_),
tstd (std),
modules (fm),
diff --git a/build2/cc/compile-rule.cxx b/build2/cc/compile-rule.cxx
index 4431abd..d0ef61a 100644
--- a/build2/cc/compile-rule.cxx
+++ b/build2/cc/compile-rule.cxx
@@ -23,7 +23,9 @@
#include <build2/cc/module.hxx>
#include <build2/cc/utility.hxx>
-using namespace std;
+using std::exit;
+using std::strlen;
+
using namespace butl;
namespace build2
@@ -156,9 +158,9 @@ namespace build2
bool m (md.type == translation_type::module_iface);
//preprocessed p (md.pp);
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// Ignore the preprocessed value since for GCC it is handled via
// -fpreprocessed -fdirectives-only.
@@ -170,8 +172,7 @@ namespace build2
}
}
// Fall through.
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
// Clang has *-cpp-output (but not c++-module-cpp-output) and they
// handle comments and line continuations. However, currently this
@@ -185,7 +186,7 @@ namespace build2
}
}
// Fall through.
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
switch (x_lang)
{
@@ -194,7 +195,7 @@ namespace build2
}
}
// Fall through.
- case compiler_id::icc:
+ case compiler_type::icc:
{
switch (x_lang)
{
@@ -552,25 +553,24 @@ namespace build2
}
}
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
e += mod ? "nms" : o;
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
e += mod ? "pcm" : o;
break;
}
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
e += mod ? "ifc" : o;
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
{
assert (!mod);
e += o;
@@ -981,7 +981,7 @@ namespace build2
// original source (something to do with having to detect and store
// header boundaries in the .ifc files).
//
- if (cid == compiler_id::msvc)
+ if (ctype == compiler_type::msvc)
{
if (md.type == translation_type::module_iface)
psrc.second = false;
@@ -1516,9 +1516,9 @@ namespace build2
//
const char* pp (nullptr);
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// -fdirectives-only is available since GCC 4.3.0.
//
@@ -1527,8 +1527,7 @@ namespace build2
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
// -frewrite-includes is available since vanilla Clang 3.2.0.
//
@@ -1536,19 +1535,19 @@ namespace build2
// option (4.2 is based on 3.2svc so it may or may not have it and,
// no, we are not going to try to find out).
//
- if (cid == compiler_id::clang_apple
+ if (cvariant == "apple"
? (cmaj >= 5)
: (cmaj > 3 || (cmaj == 3 && cmin >= 2)))
pp = "-frewrite-includes";
break;
}
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
pp = "/C";
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
break;
}
@@ -1914,8 +1913,7 @@ namespace build2
case compiler_class::msvc: werror = "/WX"; break;
}
- bool clang (cid == compiler_id::clang ||
- cid == compiler_id::clang_apple);
+ bool clang (ctype == compiler_type::clang);
append_options (args, t, c_coptions, werror);
append_options (args, t, x_coptions, werror);
@@ -2016,7 +2014,7 @@ namespace build2
// diagnostics on the -E runs (which we do by redirecting
// stderr to stdout).
//
- if (cid == compiler_id::gcc)
+ if (ctype == compiler_type::gcc)
{
// Use the .t extension (for "temporary"; .d is taken).
//
@@ -2068,7 +2066,7 @@ namespace build2
args[i++] = src.path ().string ().c_str ();
args[i] = nullptr;
- if (cid == compiler_id::gcc)
+ if (ctype == compiler_type::gcc)
{
sense_diag = false;
}
@@ -2082,7 +2080,7 @@ namespace build2
args[i++] = pp;
args[i] = "-MF";
- if (cid == compiler_id::gcc)
+ if (ctype == compiler_type::gcc)
{
r = &drm.path;
sense_diag = true;
@@ -2980,8 +2978,7 @@ namespace build2
case compiler_class::msvc: werror = "/WX"; break;
}
- bool clang (cid == compiler_id::clang ||
- cid == compiler_id::clang_apple);
+ bool clang (ctype == compiler_type::clang);
append_options (args, t, c_coptions, werror);
append_options (args, t, x_coptions, werror);
@@ -3024,7 +3021,7 @@ namespace build2
args.push_back ("-x");
args.push_back (langopt (md));
- if (cid == compiler_id::gcc)
+ if (ctype == compiler_type::gcc)
{
args.push_back ("-fpreprocessed");
args.push_back ("-fdirectives-only");
@@ -3104,7 +3101,7 @@ namespace build2
// syntax so we use the preprequisite type to distinguish between
// interface and implementation units.
//
- if (cid == compiler_id::msvc &&
+ if (ctype == compiler_type::msvc &&
cmaj == 19 && cmin <= 11 &&
x_mod != nullptr && src.is_a (*x_mod))
{
@@ -3229,9 +3226,9 @@ namespace build2
// Save the module map for compilers that use it.
//
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// We don't need to redo this if the above hash hasn't changed and
// the database is still valid.
@@ -4067,9 +4064,9 @@ namespace build2
const module_positions& ms (md.mods);
dir_path stdifc; // See the VC case below.
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// Use the module map stored in depdb.
//
@@ -4085,8 +4082,7 @@ namespace build2
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
if (ms.start == 0)
return;
@@ -4149,7 +4145,7 @@ namespace build2
#endif
break;
}
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
if (ms.start == 0)
return;
@@ -4198,7 +4194,7 @@ namespace build2
}
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
assert (false);
}
@@ -4422,9 +4418,9 @@ namespace build2
if (mod)
{
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// Output module file is specified in the mapping file, the
// same as input.
@@ -4434,8 +4430,7 @@ namespace build2
args.push_back ("-c");
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
relm = relative (tp);
@@ -4452,8 +4447,8 @@ namespace build2
break;
}
- case compiler_id::msvc:
- case compiler_id::icc:
+ case compiler_type::msvc:
+ case compiler_type::icc:
assert (false);
}
}
@@ -4472,9 +4467,9 @@ namespace build2
// Note that the mode we select must still handle comments and line
// continuations. So some more compiler-specific voodoo.
//
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// -fdirectives-only is available since GCC 4.3.0.
//
@@ -4485,17 +4480,16 @@ namespace build2
}
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
// Clang handles comments and line continuations in the
// preprocessed source (it does not have -fpreprocessed).
//
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
break; // Compile as normal source for now.
- case compiler_id::msvc:
+ case compiler_type::msvc:
assert (false);
}
}
@@ -4530,9 +4524,9 @@ namespace build2
// This should match with how we setup preprocessing.
//
- switch (cid)
+ switch (ctype)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// The -fpreprocessed is implied by .i/.ii.
//
@@ -4541,21 +4535,20 @@ namespace build2
args.push_back ("-fdirectives-only");
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
// Note that without -x Clang will treat .i/.ii as fully
// preprocessed.
//
break;
}
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
// Nothing to do (/TP or /TC already there).
//
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
assert (false);
}
@@ -4583,7 +4576,7 @@ namespace build2
// tries to pull off something similar. For sane compilers this should
// be harmless.
//
- bool filter (cid == compiler_id::msvc);
+ bool filter (ctype == compiler_type::msvc);
process pr (cpath,
args.data (),
@@ -4631,8 +4624,7 @@ namespace build2
// Clang's module compilation requires two separate compiler
// invocations.
//
- if (mod && (cid == compiler_id::clang ||
- cid == compiler_id::clang_apple))
+ if (mod && ctype == compiler_type::clang)
{
// Remove the target file if this fails. If we don't do that, we will
// end up with a broken build that is up-to-date.
@@ -4688,15 +4680,14 @@ namespace build2
{
const file& t (xt.as<file> ());
- using id = compiler_id;
+ using ct = compiler_type;
- switch (cid)
+ switch (ctype)
{
- case id::gcc: return clean_extra (a, t, {".d", x_pext, ".t"});
- case id::clang_apple:
- case id::clang: return clean_extra (a, t, {".d", x_pext});
- case id::msvc: return clean_extra (a, t, {".d", x_pext, ".idb", ".pdb"});
- case id::icc: return clean_extra (a, t, {".d"});
+ case ct::gcc: return clean_extra (a, t, {".d", x_pext, ".t"});
+ case ct::clang: return clean_extra (a, t, {".d", x_pext});
+ case ct::msvc: return clean_extra (a, t, {".d", x_pext, ".idb", ".pdb"});
+ case ct::icc: return clean_extra (a, t, {".d"});
}
assert (false);
diff --git a/build2/cc/guess.cxx b/build2/cc/guess.cxx
index e75a6ee..4e581a7 100644
--- a/build2/cc/guess.cxx
+++ b/build2/cc/guess.cxx
@@ -15,40 +15,62 @@ namespace build2
{
namespace cc
{
- compiler_id::
- compiler_id (value_type v)
+ string
+ to_string (compiler_type t)
{
- switch (v)
+ string r;
+
+ switch (t)
{
- case clang_apple: type = "clang"; variant = "apple"; break;
- case clang: type = "clang"; break;
- case gcc: type = "gcc"; break;
- case msvc: type = "msvc"; break;
- case icc: type = "icc"; break;
+ case compiler_type::clang: r = "clang"; break;
+ case compiler_type::gcc: r = "gcc"; break;
+ case compiler_type::msvc: r = "msvc"; break;
+ case compiler_type::icc: r = "icc"; break;
}
+
+ return r;
+ }
+
+#if 0
+ compiler_id::
+ compiler_id (const std::string& t, std::string v)
+ : type (t == "gcc" ? compiler_type::gcc :
+ t == "clang" ? compiler_type::clang :
+ t == "msvc" ? compiler_type::msvc :
+ t == "icc" ? compiler_type::icc : invalid_compiler_type),
+ variant (move (v))
+ {
+ if (t == invalid_compiler_type)
+ throw invalid_argument ("invalid compiler type value '" + t + "'");
}
+#endif
- auto compiler_id::
- value () const -> value_type
+ string compiler_id::
+ string () const
{
- if (type == "gcc") return gcc;
- if (type == "clang") return variant.empty () ? clang : clang_apple;
- if (type == "msvc") return msvc;
- if (type == "icc") return icc;
+ std::string r (to_string (type));
- assert (false);
- return gcc;
+ if (!variant.empty ())
+ {
+ r += '-';
+ r += variant;
+ }
+
+ return r;
}
string
- to_string (compiler_class cl)
+ to_string (compiler_class c)
{
- switch (cl)
+ string r;
+
+ switch (c)
{
- case compiler_class::gcc: return "gcc";
- case compiler_class::msvc: return "msvc";
+ case compiler_class::gcc: r = "gcc"; break;
+ case compiler_class::msvc: r = "msvc"; break;
}
- return string (); // Never reached.
+
+ return r;
}
// Standard library detection for GCC-class compilers.
@@ -179,7 +201,7 @@ namespace build2
// example, because the compiler name is a generic 'c++'). Note that it
// only guesses the type, not the variant.
//
- static pair<string, size_t>
+ static pair<compiler_type, size_t>
pre_guess (lang xl, const path& xc)
{
tracer trace ("cc::pre_guess");
@@ -216,8 +238,9 @@ namespace build2
const char* es (nullptr); // Expected stem.
size_t p; // Executable name position.
+ using type = compiler_type;
+ using pair = std::pair<type, size_t>;
const size_t npos (string::npos);
- using pair = std::pair<string, size_t>;
switch (xl)
{
@@ -225,10 +248,10 @@ namespace build2
{
// Keep msvc last since 'cl' is very generic.
//
- if ((p = stem ("gcc")) != npos) return pair ("gcc", p);
- if ((p = stem ("clang")) != npos) return pair ("clang", p);
- if ((p = stem ("icc")) != npos) return pair ("icc", p);
- if ((p = stem ("cl")) != npos) return pair ("msvc", p);
+ if ((p = stem ("gcc")) != npos) return pair (type::gcc, p);
+ if ((p = stem ("clang")) != npos) return pair (type::clang, p);
+ if ((p = stem ("icc")) != npos) return pair (type::icc, p);
+ if ((p = stem ("cl")) != npos) return pair (type::msvc, p);
if (stem (as = "g++") != npos) es = "gcc";
else if (stem (as = "clang++") != npos) es = "clang";
@@ -242,10 +265,10 @@ namespace build2
{
// Keep msvc last since 'cl' is very generic.
//
- if ((p = stem ("g++")) != npos) return pair ("gcc", p);
- if ((p = stem ("clang++")) != npos) return pair ("clang", p);
- if ((p = stem ("icpc")) != npos) return pair ("icc", p);
- if ((p = stem ("cl")) != npos) return pair ("msvc", p);
+ if ((p = stem ("g++")) != npos) return pair (type::gcc, p);
+ if ((p = stem ("clang++")) != npos) return pair (type::clang, p);
+ if ((p = stem ("icpc")) != npos) return pair (type::icc, p);
+ if ((p = stem ("cl")) != npos) return pair (type::msvc, p);
if (stem (as = "gcc") != npos) es = "g++";
else if (stem (as = "clang") != npos) es = "clang++";
@@ -261,9 +284,9 @@ namespace build2
warn << xc << " looks like a " << o << " compiler" <<
info << "should it be '" << es << "' instead of '" << as << "'?";
- l4 ([&]{trace << "unable to guess compiler type of " << xc;});
+ l4 ([&]{trace << "unable to guess compiler type of " << xc;});
- return pair ("", string::npos);
+ return pair (invalid_compiler_type, string::npos);
}
// Guess the compiler type and variant by running it. If the pre argument
@@ -288,7 +311,7 @@ namespace build2
// Allowed to change pre if succeeds.
//
static guess_result
- guess (lang, const string& xv, const path& xc, string& pre)
+ guess (lang, const string& xv, const path& xc, compiler_type& pre)
{
tracer trace ("cc::guess");
@@ -305,6 +328,9 @@ namespace build2
xp = run_search (xc, false /* init */); // Note: cached.
}
+ using type = compiler_type;
+ const type invalid = invalid_compiler_type;
+
// Start with -v. This will cover gcc and clang.
//
// While icc also writes what may seem like something we can use to
@@ -320,7 +346,9 @@ namespace build2
// In fact, if someone renames icpc to g++, there will be no way for
// us to detect this. Oh, well, their problem.
//
- if (r.empty () && (pre.empty () || pre == "gcc" || pre == "clang"))
+ if (r.empty () && (pre == invalid ||
+ pre == type::gcc ||
+ pre == type::clang))
{
auto f = [] (string& l) -> guess_result
{
@@ -340,7 +368,7 @@ namespace build2
// gcc version 6.0.0 20160131 (experimental) (GCC)
//
if (l.compare (0, 4, "gcc ") == 0)
- return guess_result (compiler_id {"gcc", ""}, move (l));
+ return guess_result (compiler_id {type::gcc, ""}, move (l));
// The Apple clang/clang++ -v output will have a line (currently
// first) in the form:
@@ -370,7 +398,7 @@ namespace build2
if (l.compare (0, 6, "Apple ") == 0 &&
(l.compare (6, 5, "LLVM ") == 0 ||
l.compare (6, 6, "clang ") == 0))
- return guess_result (compiler_id {"clang", "apple"}, move (l));
+ return guess_result (compiler_id {type::clang, "apple"}, move (l));
// The vanilla clang/clang++ -v output will have a line (currently
// first) in the form:
@@ -385,7 +413,7 @@ namespace build2
// clang version 3.7.0 (tags/RELEASE_370/final)
//
if (l.find ("clang ") != string::npos)
- return guess_result (compiler_id {"clang", ""}, move (l));
+ return guess_result (compiler_id {type::clang, ""}, move (l));
return guess_result ();
};
@@ -411,8 +439,10 @@ namespace build2
// If this is clang-apple and pre-guess was gcc then change it so
// that we don't issue any warnings.
//
- if (r.id.type == "clang" && r.id.variant == "apple" && pre == "gcc")
- pre = "clang";
+ if (r.id.type == type::clang &&
+ r.id.variant == "apple" &&
+ pre == type::gcc)
+ pre = type::clang;
r.checksum = cs.string ();
}
@@ -420,7 +450,7 @@ namespace build2
// Next try --version to detect icc.
//
- if (r.empty () && (pre.empty () || pre == "icc"))
+ if (r.empty () && (pre == invalid || pre == type::icc))
{
auto f = [] (string& l) -> guess_result
{
@@ -435,7 +465,7 @@ namespace build2
// icc (ICC) 16.0.2 20160204
//
if (l.find (" (ICC) ") != string::npos)
- return guess_result (compiler_id {"icc", ""}, move (l));
+ return guess_result (compiler_id {type::icc, ""}, move (l));
return guess_result ();
};
@@ -446,7 +476,7 @@ namespace build2
// Finally try to run it without any options to detect msvc.
//
//
- if (r.empty () && (pre.empty () || pre == "msvc"))
+ if (r.empty () && (pre == invalid || pre == type::msvc))
{
auto f = [] (string& l) -> guess_result
{
@@ -468,7 +498,7 @@ namespace build2
//
if (l.find ("Microsoft (R)") != string::npos &&
l.find ("C/C++") != string::npos)
- return guess_result (compiler_id {"msvc", ""}, move (l));
+ return guess_result (compiler_id {type::msvc, ""}, move (l));
return guess_result ();
};
@@ -487,7 +517,7 @@ namespace build2
if (!r.empty ())
{
- if (!pre.empty () && r.id.type != pre)
+ if (pre != invalid && r.id.type != pre)
{
l4 ([&]{trace << "compiler type guess mismatch"
<< ", pre-guessed " << pre
@@ -1485,15 +1515,15 @@ namespace build2
return i->second;
}
- pair<string, size_t> pre (pre_guess (xl, xc));
- string& type (pre.first);
+ pair<compiler_type, size_t> pre (pre_guess (xl, xc));
+ compiler_type& type (pre.first);
// If we could pre-guess the type based on the excutable name, then
// try the test just for that compiler.
//
guess_result gr;
- if (!type.empty ())
+ if (type != invalid_compiler_type)
{
gr = guess (xl, xv, xc, type);
@@ -1501,7 +1531,7 @@ namespace build2
warn << xc << " looks like " << type << " but it is not" <<
info << "use " << xv << " to override";
- type.clear ();
+ type = invalid_compiler_type;
}
if (gr.empty ())
@@ -1513,36 +1543,31 @@ namespace build2
compiler_info r;
const compiler_id& id (gr.id);
- switch (id.value ())
+ switch (id.type)
{
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
- assert (id.variant.empty ());
r = guess_gcc (xl, xc,
c_po, x_po, c_co, x_co, c_lo, x_lo,
move (gr));
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
- assert (id.variant.empty () || id.variant == "apple");
r = guess_clang (xl, xc,
c_po, x_po, c_co, x_co, c_lo, x_lo,
move (gr));
break;
}
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
- assert (id.variant.empty ());
r = guess_msvc (xl, xc,
c_po, x_po, c_co, x_co, c_lo, x_lo,
move (gr));
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
{
- assert (id.variant.empty ());
r = guess_icc (xl, xc,
c_po, x_po, c_co, x_co, c_lo, x_lo,
move (gr));
diff --git a/build2/cc/guess.hxx b/build2/cc/guess.hxx
index 6e0281c..8b10b29 100644
--- a/build2/cc/guess.hxx
+++ b/build2/cc/guess.hxx
@@ -26,45 +26,53 @@ namespace build2
// msvc Microsoft cl.exe
// icc Intel icc/icpc
//
- struct compiler_id
+ // Note that the user can provide a custom id with one of the predefined
+ // types and a custom variant (say 'gcc-tasking').
+ //
+ enum class compiler_type
{
- std::string type;
- std::string variant;
+ gcc = 1, // 0 value represents invalid type.
+ clang,
+ msvc,
+ icc
+ // Update compiler_id(string) and to_string() if adding a new type.
+ };
- bool
- empty () const {return type.empty ();}
+ const compiler_type invalid_compiler_type = static_cast<compiler_type> (0);
- std::string
- string () const {return variant.empty () ? type : type + "-" + variant;}
-
- enum value_type
- {
- gcc,
- clang,
- clang_apple,
- msvc,
- icc
- };
-
- value_type
- value () const;
-
- compiler_id () = default;
- compiler_id (value_type);
- compiler_id (std::string t, std::string v)
- : type (move (t)), variant (move (v)) {}
- };
+ string
+ to_string (compiler_type);
inline ostream&
- operator<< (ostream& os, const compiler_id& id)
+ operator<< (ostream& o, const compiler_type& t)
{
- return os << id.string ();
+ return o << to_string (t);
}
+ struct compiler_id
+ {
+ compiler_type type = invalid_compiler_type;
+ std::string variant;
+
+ bool
+ empty () const {return type == invalid_compiler_type;}
+
+ std::string
+ string () const;
+
+ compiler_id ()
+ : type (invalid_compiler_type) {}
+
+ compiler_id (compiler_type t, std::string v)
+ : type (t), variant (move (v)) {}
+
+ //compiler_id (const std::string& type, std::string variant);
+ };
+
inline ostream&
- operator<< (ostream& os, const compiler_id::value_type& v)
+ operator<< (ostream& o, const compiler_id& id)
{
- return os << compiler_id (v);
+ return o << id.string ();
}
// Compiler class describes a set of compilers that follow more or less
@@ -87,9 +95,9 @@ namespace build2
to_string (compiler_class);
inline ostream&
- operator<< (ostream& os, compiler_class cl)
+ operator<< (ostream& o, compiler_class c)
{
- return os << to_string (cl);
+ return o << to_string (c);
}
// Compiler version. Here we map the various compiler version formats to
diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx
index 0ff339d..230fc6f 100644
--- a/build2/cc/link-rule.cxx
+++ b/build2/cc/link-rule.cxx
@@ -23,7 +23,9 @@
#include <build2/cc/target.hxx> // c, pc*
#include <build2/cc/utility.hxx>
-using namespace std;
+using std::map;
+using std::exit;
+
using namespace butl;
namespace build2
@@ -2143,7 +2145,7 @@ namespace build2
if (!find_option ("/INCREMENTAL", args, true))
args.push_back ("/INCREMENTAL:NO");
- if (cid == compiler_id::clang)
+ if (ctype == compiler_type::clang)
{
// According to Clang's MSVC.cpp, we shall link libcmt.lib (static
// multi-threaded runtime) unless -nostdlib or -nostartfiles is
diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx
index 76935f9..363f1d0 100644
--- a/build2/cc/module.cxx
+++ b/build2/cc/module.cxx
@@ -163,7 +163,7 @@ namespace build2
// Assign values to variables that describe the compiler.
//
rs.assign (x_id) = ci.id.string ();
- rs.assign (x_id_type) = ci.id.type;
+ rs.assign (x_id_type) = to_string (ci.id.type);
rs.assign (x_id_variant) = ci.id.variant;
rs.assign (x_class) = to_string (ci.class_);
diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx
index 2fa5dac..80a7b66 100644
--- a/build2/cxx/init.cxx
+++ b/build2/cxx/init.cxx
@@ -29,6 +29,7 @@ namespace build2
namespace cxx
{
using cc::compiler_id;
+ using cc::compiler_type;
using cc::compiler_class;
using cc::compiler_info;
@@ -52,7 +53,7 @@ namespace build2
{
strings r;
- compiler_id::value_type id (ci.id.value ());
+ compiler_type ct (ci.id.type);
compiler_class cl (ci.class_);
uint64_t mj (ci.version.major);
uint64_t mi (ci.version.minor);
@@ -81,9 +82,9 @@ namespace build2
//
const char* o (nullptr);
- switch (id)
+ switch (ct)
{
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
// VC14u3 and later has /std:c++latest.
//
@@ -92,7 +93,7 @@ namespace build2
break;
}
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
if (mj >= 8) o = "-std=c++2a"; // 20
else if (mj >= 5) o = "-std=c++1z"; // 17
@@ -101,8 +102,7 @@ namespace build2
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
// Remap Apple versions to vanilla Clang based on the following
// release point. Note that Apple no longer discloses the mapping
@@ -123,7 +123,7 @@ namespace build2
// Note that this mapping is also used to enable experimental
// features below.
//
- if (id == compiler_id::clang_apple)
+ if (ci.id.variant == "apple")
{
if (mj >= 9) {mj = 4; mi = 0;}
else if (mj == 8) {mj = 3; mi = 9;}
@@ -141,7 +141,7 @@ namespace build2
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
{
if (mj >= 17) o = "-std=c++1z"; // 17
else if (mj > 15 || (mj == 15 && p >= 3)) o = "-std=c++1y"; // 14
@@ -166,9 +166,9 @@ namespace build2
lookup l;
if (!(l = rs[v_m]) || cast<bool> (l))
{
- switch (id)
+ switch (ct)
{
- case compiler_id::msvc:
+ case compiler_type::msvc:
{
// While modules are supported in VC15u0 (19.10), there is a
// bug in separate interface/implementation unit support which
@@ -188,7 +188,7 @@ namespace build2
}
break;
}
- case compiler_id::gcc:
+ case compiler_type::gcc:
{
// Enable starting with GCC 9.0.0 (currently the c++-modules
// branch).
@@ -205,8 +205,7 @@ namespace build2
}
break;
}
- case compiler_id::clang:
- case compiler_id::clang_apple:
+ case compiler_type::clang:
{
// Enable starting with Clang 6.0.0.
//
@@ -223,7 +222,7 @@ namespace build2
}
break;
}
- case compiler_id::icc:
+ case compiler_type::icc:
break; // No modules support yet.
}
}
@@ -553,7 +552,8 @@ namespace build2
"cxx.install",
"cxx.uninstall",
- cm.ci_->id.value (),
+ cm.ci_->id.type,
+ cm.ci_->id.variant,
cm.ci_->class_,
cm.ci_->version.major,
cm.ci_->version.minor,
diff --git a/build2/types.hxx b/build2/types.hxx
index 219608c..a4aad41 100644
--- a/build2/types.hxx
+++ b/build2/types.hxx
@@ -86,6 +86,7 @@ namespace build2
using std::istream;
using std::ostream;
+ using std::endl;
// Concurrency.
//