diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2018-10-25 17:18:37 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2018-10-25 17:44:42 +0200 |
commit | 8ababa51319753c5c697374c722bb01e845e3e68 (patch) | |
tree | c8f89bffc129d3004da232c327eb81b9a1459e77 | |
parent | 59dec666d17fdd7c5394c3c081cf21381a8af07d (diff) |
Redesign cc::compiler_id to make variant customizable
-rw-r--r-- | build2/c/init.cxx | 7 | ||||
-rw-r--r-- | build2/cc/common.hxx | 31 | ||||
-rw-r--r-- | build2/cc/compile-rule.cxx | 123 | ||||
-rw-r--r-- | build2/cc/guess.cxx | 143 | ||||
-rw-r--r-- | build2/cc/guess.hxx | 70 | ||||
-rw-r--r-- | build2/cc/link-rule.cxx | 6 | ||||
-rw-r--r-- | build2/cc/module.cxx | 2 | ||||
-rw-r--r-- | build2/cxx/init.cxx | 30 | ||||
-rw-r--r-- | build2/types.hxx | 1 |
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. // |