From 71d9aedda0919fb22e39d6e6ce60506ceb69812e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 25 May 2017 11:32:01 +0200 Subject: Add compiler_id enum --- build2/c/init.cxx | 3 +- build2/cc/common.cxx | 10 ++-- build2/cc/common.hxx | 21 ++++---- build2/cc/compile.cxx | 136 ++++++++++++++++++++++++++++-------------------- build2/cc/guess.cxx | 12 +++++ build2/cc/guess.hxx | 15 +++++- build2/cc/link.cxx | 20 +++---- build2/cc/module.cxx | 1 + build2/cc/module.hxx | 2 + build2/cc/pkgconfig.cxx | 2 +- build2/cxx/init.cxx | 3 +- 11 files changed, 142 insertions(+), 83 deletions(-) diff --git a/build2/c/init.cxx b/build2/c/init.cxx index ebaa193..a80a4d0 100644 --- a/build2/c/init.cxx +++ b/build2/c/init.cxx @@ -238,7 +238,8 @@ namespace build2 "c.install", "c.uninstall", - cast (rs[cm.x_id]), + cm.cid, + cast (rs[cm.x_id_variant]), cast (rs[cm.x_version_major]), cast (rs[cm.x_version_minor]), cast (rs[cm.x_target]), diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx index 59feb9b..1df84c9 100644 --- a/build2/cc/common.cxx +++ b/build2/cc/common.cxx @@ -515,7 +515,7 @@ namespace build2 // const char* e (""); - if (cid == "msvc") + if (cid == compiler_id::msvc) { an = path (name); e = "lib"; @@ -543,7 +543,7 @@ namespace build2 { const char* e (""); - if (cid == "msvc") + if (cid == compiler_id::msvc) { sn = path (name); e = "dll.lib"; @@ -661,7 +661,7 @@ namespace build2 // // If we didn't find .dll.lib then we cannot assume .lib is static. // - if (!an.empty () && (s != nullptr || cid != "msvc")) + if (!an.empty () && (s != nullptr || cid != compiler_id::msvc)) { f = d; f /= an; @@ -682,7 +682,7 @@ namespace build2 // Alternative search for VC. // - if (cid == "msvc") + if (cid == compiler_id::msvc) { const scope& rs (*p.scope->root_scope ()); const process_path& ld (cast (rs["bin.ld.path"])); @@ -879,7 +879,7 @@ namespace build2 dir_path d; - if (cid == "msvc") + if (cid == compiler_id::msvc) { // /LIBPATH: (case-insensitive). // diff --git a/build2/cc/common.hxx b/build2/cc/common.hxx index bc52311..c0289d1 100644 --- a/build2/cc/common.hxx +++ b/build2/cc/common.hxx @@ -13,6 +13,7 @@ #include #include +#include // compiler_id namespace build2 { @@ -99,15 +100,17 @@ namespace build2 // Cached values for some commonly-used variables/values. // - const string& cid; // x.id - uint64_t cmaj; // x.version.major - uint64_t cmin; // x.version.minor - const target_triplet& ctg; // x.target - const string& tsys; // x.target.system - const string& tclass; // x.target.class + compiler_id::value_type cid; // x.id (no variant) + const string& cvar; // x.id.variant + uint64_t cmaj; // x.version.major + uint64_t cmin; // x.version.minor - const string& tstd; // Translated x_std value (can be empty). + const target_triplet& ctg; // x.target + const string& tsys; // x.target.system + const string& tclass; // x.target.class + + const string& tstd; // Translated x_std value (can be empty). const process_path* pkgconfig; // pkgconfig.path (can be NULL). const dir_paths& sys_lib_dirs; // x.sys_lib_dirs @@ -144,7 +147,7 @@ namespace build2 const char* link, const char* install, const char* uninstall, - const string& id, + compiler_id::value_type id, const string& var, uint64_t mj, uint64_t mi, const target_triplet& tg, const string& std, @@ -159,7 +162,7 @@ namespace build2 x_link (link), x_install (install), x_uninstall (uninstall), - cid (id), cmaj (mj), cmin (mi), + cid (id), cvar (var), cmaj (mj), cmin (mi), ctg (tg), tsys (ctg.system), tclass (ctg.class_), tstd (std), pkgconfig (pkgc), sys_lib_dirs (sld), sys_inc_dirs (sid), diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 21f7ecf..9982a91 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -954,29 +954,38 @@ namespace build2 // const char* pp (nullptr); - if (cid == "msvc") pp = "/C"; - else if (cid == "gcc") + switch (cid) { - // -fdirectives-only is available since GCC 4.3.0. - // - if (cmaj > 4 || (cmaj == 4 && cmin >= 3)) - pp = "-fdirectives-only"; - } - else if (cid == "clang") - { - // -frewrite-includes is available since Clang 3.2.0. - // - if (cmaj > 3 || (cmaj == 3 && cmin >= 2)) - pp = "-frewrite-includes"; - } - else if (cid == "clang-apple") - { - // Apple Clang 5.0 is based on LLVM 3.3svn so it should have this - // 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 (cmaj >= 5) - pp = "-frewrite-includes"; + case compiler_id::gcc: + { + // -fdirectives-only is available since GCC 4.3.0. + // + if (cmaj > 4 || (cmaj == 4 && cmin >= 3)) + pp = "-fdirectives-only"; + + break; + } + case compiler_id::clang: + { + // -frewrite-includes is available since vanilla Clang 3.2.0. + // + // Apple Clang 5.0 is based on LLVM 3.3svn so it should have this + // 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 (cvar == "" ? (cmaj > 3 || (cmaj == 3 && cmin >= 2)) : + cvar == "apple" ? (cmaj >= 5) : false) + pp = "-frewrite-includes"; + + break; + } + case compiler_id::msvc: + { + pp = "/C"; + break; + } + case compiler_id::icc: + break; } // Initialize lazily, only if required. @@ -1138,7 +1147,7 @@ namespace build2 args.push_back ("-fPIC"); } - if (cid == "msvc") + if (cid == compiler_id::msvc) { assert (pp != nullptr); @@ -1186,7 +1195,7 @@ namespace build2 // Clang's -M does not imply -w (disable warnings). We also don't // need them in the -MD case (see above) so disable for both. // - if (cid == "clang" || cid == "clang-apple") + if (cid == compiler_id::clang) args.push_back ("-w"); // Previously we used '*' as a target name but it gets expanded to @@ -1215,7 +1224,7 @@ namespace build2 // GCC is not capable of writing the dependency info to stdout. // We also need to sense the diagnostics on the -E runs. // - if (cid == "gcc") + if (cid == compiler_id::gcc) { // Use the .t extension (for "temporary"; .d is taken). // @@ -1260,7 +1269,7 @@ namespace build2 args[i + 2] = rels.string ().c_str (); args[i + 3] = nullptr; - if (cid == "gcc") + if (cid == compiler_id::gcc) { sense_diag = false; } @@ -1274,7 +1283,7 @@ namespace build2 args[i + 2] = pp; args[i + 3] = "-MF"; - if (cid == "gcc") + if (cid == compiler_id::gcc) { r = &drm.path (); sense_diag = true; @@ -1648,7 +1657,7 @@ namespace build2 args.data (), 0, -1, - cid == "msvc" ? 1 : gen ? 2 : -2); + cid == compiler_id::msvc ? 1 : gen ? 2 : -2); } else { @@ -1712,7 +1721,7 @@ namespace build2 // Parse different dependency output formats. // - if (cid == "msvc") + if (cid == compiler_id::msvc) { if (first) { @@ -1840,9 +1849,9 @@ namespace build2 // eof, this and all subsequent writes to cerr will fail (and // you won't see a thing). // - if (is.peek () != ifdstream::traits_type::eof () && - cid == "msvc" && - bad_error) + if (bad_error && + cid == compiler_id::msvc && + is.peek () != ifdstream::traits_type::eof ()) cerr << is.rdbuf (); is.close (); @@ -1990,7 +1999,7 @@ namespace build2 append_std (args); - if (cid == "msvc") + if (cid == compiler_id::msvc) { // The /F*: option variants with separate names only became available // in VS2013/12.0. Why do we bother? Because the command line suddenly @@ -2117,21 +2126,32 @@ namespace build2 // This should match with how we setup preprocessing. // - if (cid == "gcc") + switch (cid) { - // The -fpreprocessed in implied by .i/.ii. - // - args.push_back ("-fdirectives-only"); - } - else if (cid == "clang" || cid == "clang-apple") - { - // Without this Clang will treat .i/.ii as fully preprocessed. - // - args.push_back ("-x"); - args.push_back (x_name); - } - else if (cid != "msvc") // Nothing to do (/TP or /TC already there). + case compiler_id::gcc: + { + // The -fpreprocessed in implied by .i/.ii. + // + args.push_back ("-fdirectives-only"); + break; + } + case compiler_id::clang: + { + // Without this Clang will treat .i/.ii as fully preprocessed. + // + args.push_back ("-x"); + args.push_back (x_name); + break; + } + case compiler_id::msvc: + { + // Nothing to do (/TP or /TC already there). + // + break; + } + case compiler_id::icc: assert (false); + } args.push_back (rels.string ().c_str ()); args.push_back (nullptr); @@ -2157,7 +2177,7 @@ namespace build2 // tries to pull off something similar. For sane compilers this should // be harmless. // - bool filter (cid == "msvc"); + bool filter (cid == compiler_id::msvc); process pr (xc, args.data (), 0, (filter ? -1 : 2)); @@ -2213,18 +2233,22 @@ namespace build2 } target_state compile:: - perform_clean (action act, const target& xt) const + perform_clean (action a, const target& xt) const { const file& t (xt.as ()); - if (cid == "msvc") - return clean_extra (act, t, {".d", x_pext, ".idb", ".pdb"}); - else if (cid == "gcc") - return clean_extra (act, t, {".d", x_pext, ".t"}); - else if (cid == "clang" || cid == "clang-apple") - return clean_extra (act, t, {".d", x_pext}); - else - return clean_extra (act, t, {".d"}); + using id = compiler_id; + + switch (cid) + { + case id::gcc: return clean_extra (a, t, {".d", x_pext, ".t"}); + 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"}); + } + + assert (false); + return target_state::unchanged; } } } diff --git a/build2/cc/guess.cxx b/build2/cc/guess.cxx index 0569bdc..9f14661 100644 --- a/build2/cc/guess.cxx +++ b/build2/cc/guess.cxx @@ -14,6 +14,18 @@ namespace build2 { namespace cc { + auto compiler_id:: + value () const -> value_type + { + if (type == "gcc") return gcc; + if (type == "clang") return clang; + if (type == "msvc") return msvc; + if (type == "icc") return icc; + + assert (false); + return gcc; + } + // Pre-guess the compiler type based on the compiler executable name. // Return empty string if can't make a guess (for example, because the // compiler name is a generic 'c++'). Note that it only guesses the type, diff --git a/build2/cc/guess.hxx b/build2/cc/guess.hxx index dbd06e3..4d5d036 100644 --- a/build2/cc/guess.hxx +++ b/build2/cc/guess.hxx @@ -23,8 +23,8 @@ namespace build2 // gcc GCC gcc/g++ // clang Vanilla Clang clang/clang++ // clang-apple Apple Clang clang/clang++ and the gcc/g++ "alias" - // icc Intel icc/icpc // msvc Microsoft cl.exe + // icc Intel icc/icpc // struct compiler_id { @@ -36,6 +36,19 @@ namespace build2 std::string string () const {return variant.empty () ? type : type + "-" + variant;} + + // Note: does not include variant. + // + enum value_type + { + gcc, + clang, + msvc, + icc + }; + + value_type + value () const; }; inline ostream& diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index 1b2f306..e2b8275 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -355,7 +355,7 @@ namespace build2 } case otype::a: { - if (cid == "msvc") + if (cid == compiler_id::msvc) e = "lib"; else { @@ -388,8 +388,8 @@ namespace build2 // PDB // - if (lt != otype::a && - cid == "msvc" && + if (lt != otype::a && + cid == compiler_id::msvc && (find_option ("/DEBUG", t, c_loptions, true) || find_option ("/DEBUG", t, x_loptions, true))) { @@ -1140,7 +1140,9 @@ namespace build2 // const string& cs ( cast ( - rs[cid == "msvc" ? var_pool["bin.ld.checksum"] : x_checksum])); + rs[cid == compiler_id::msvc + ? var_pool["bin.ld.checksum"] + : x_checksum])); if (dd.expect (cs) != nullptr) l4 ([&]{trace << "linker mismatch forcing update of " << t;}); @@ -1169,7 +1171,7 @@ namespace build2 if (lt == otype::a) { - if (cid == "msvc") ; + if (cid == compiler_id::msvc) ; else { // If the user asked for ranlib, don't try to do its function with @@ -1181,7 +1183,7 @@ namespace build2 } else { - if (cid == "msvc") + if (cid == compiler_id::msvc) { // We are using link.exe directly so don't pass the compiler // options. @@ -1362,7 +1364,7 @@ namespace build2 { ld = &cast (rs["bin.ar.path"]); - if (cid == "msvc") + if (cid == compiler_id::msvc) { // lib.exe has /LIBPATH but it's not clear/documented what it's // used for. Perhaps for link-time code generation (/LTCG)? If @@ -1387,7 +1389,7 @@ namespace build2 case otype::e: case otype::s: { - if (cid == "msvc") + if (cid == compiler_id::msvc) { // Using link.exe directly. // @@ -1616,7 +1618,7 @@ namespace build2 // something like this) we are going to redirect stdout to stderr. For // sane compilers this should be harmless. // - bool filter (cid == "msvc" && lt != otype::a); + bool filter (cid == compiler_id::msvc && lt != otype::a); process pr (*ld, args.data (), 0, (filter ? -1 : 2)); diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 6d8c799..885d6c7 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -219,6 +219,7 @@ namespace build2 rs.assign (x_sys_lib_dirs) = move (lib_dirs); rs.assign (x_sys_inc_dirs) = move (inc_dirs); + cid = ci.id.value (); rs.assign (x_id) = ci.id.string (); rs.assign (x_id_type) = move (ci.id.type); rs.assign (x_id_variant) = move (ci.id.variant); diff --git a/build2/cc/module.hxx b/build2/cc/module.hxx index 643cf89..eaa82eb 100644 --- a/build2/cc/module.hxx +++ b/build2/cc/module.hxx @@ -40,6 +40,8 @@ namespace build2 string tstd; + compiler_id::value_type cid; + private: dir_paths gcc_library_search_paths (process_path&, scope&) const; // gcc.cxx diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx index 1b67f5f..80f418c 100644 --- a/build2/cc/pkgconfig.cxx +++ b/build2/cc/pkgconfig.cxx @@ -446,7 +446,7 @@ namespace build2 if (!lops.empty ()) { - if (cid == "msvc") + if (cid == compiler_id::msvc) { // Translate -L to /LIBPATH. // diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx index 578e617..d73f4cb 100644 --- a/build2/cxx/init.cxx +++ b/build2/cxx/init.cxx @@ -308,7 +308,8 @@ namespace build2 "cxx.install", "cxx.uninstall", - cast (rs[cm.x_id]), + cm.cid, + cast (rs[cm.x_id_variant]), cast (rs[cm.x_version_major]), cast (rs[cm.x_version_minor]), cast (rs[cm.x_target]), -- cgit v1.1