diff options
Diffstat (limited to 'build2/cxx')
-rw-r--r-- | build2/cxx/compile.cxx | 8 | ||||
-rw-r--r-- | build2/cxx/guess | 28 | ||||
-rw-r--r-- | build2/cxx/guess.cxx | 159 | ||||
-rw-r--r-- | build2/cxx/link.cxx | 14 | ||||
-rw-r--r-- | build2/cxx/module.cxx | 17 |
5 files changed, 128 insertions, 98 deletions
diff --git a/build2/cxx/compile.cxx b/build2/cxx/compile.cxx index cf0c91c..c4e9cee 100644 --- a/build2/cxx/compile.cxx +++ b/build2/cxx/compile.cxx @@ -461,10 +461,10 @@ namespace build2 auto init_args = [&t, &s, &rs, &args, &cxx_std] () { - const string& cxx (cast<string> (rs["config.cxx"])); + const path& cxx (cast<path> (rs["config.cxx"])); const string& sys (cast<string> (rs["cxx.target.system"])); - args.push_back (cxx.c_str ()); + args.push_back (cxx.string ().c_str ()); // Add cxx.export.poptions from prerequisite libraries. Note // that here we don't need to see group members (see apply()). @@ -923,10 +923,10 @@ namespace build2 path rels (relative (s->path ())); scope& rs (t.root_scope ()); - const string& cxx (cast<string> (rs["config.cxx"])); + const path& cxx (cast<path> (rs["config.cxx"])); const string& sys (cast<string> (rs["cxx.target.system"])); - cstrings args {cxx.c_str ()}; + cstrings args {cxx.string ().c_str ()}; // Add cxx.export.poptions from prerequisite libraries. Note that // here we don't need to see group members (see apply()). diff --git a/build2/cxx/guess b/build2/cxx/guess index cd9f740..0588523 100644 --- a/build2/cxx/guess +++ b/build2/cxx/guess @@ -8,8 +8,6 @@ #include <build2/types> #include <build2/utility> -#include <build2/variable> - namespace build2 { namespace cxx @@ -62,22 +60,18 @@ namespace build2 // struct compiler_version { - std::string major; - std::string minor; - std::string patch; - std::string build; + std::string string; - // The format is always A.B[.C][-D]. + // Currently all the compilers that we support have numeric MAJOR, + // MINOR, and PATCH components and it makes sense to represent them as + // integers for easy comparison. If we meet a compiler for which this + // doesn't hold, then we will probably just set these to 0 and let the + // user deal with the string representation. // - std::string - string () const - { - std::string r (major); - r += '.'; r += minor; - if (!patch.empty ()) {r += '.'; r += patch;} - if (!build.empty ()) {r += '-'; r += build;} - return r; - } + uint64_t major; + uint64_t minor; + uint64_t patch; + std::string build; }; // C++ compiler information. @@ -106,7 +100,7 @@ namespace build2 }; compiler_info - guess (const path& cxx, lookup<const value> coptions); // @@ VAR + guess (const path& cxx, const strings* coptions); } } diff --git a/build2/cxx/guess.cxx b/build2/cxx/guess.cxx index d2f828d..ad52847 100644 --- a/build2/cxx/guess.cxx +++ b/build2/cxx/guess.cxx @@ -277,9 +277,7 @@ namespace build2 } static compiler_info - guess_gcc (const path& cxx, - lookup<const value> coptions, - guess_result&& gr) + guess_gcc (const path& cxx, const strings* coptions, guess_result&& gr) { tracer trace ("cxx::guess_gcc"); @@ -309,19 +307,27 @@ namespace build2 if (b == e) fail << "unable to extract gcc version from '" << s << "'"; + compiler_version v; + v.string.assign (s, b, string::npos); + // Split the version into components. // size_t vb (b), ve (b); - auto next = [&s, b, e, &vb, &ve] (const char* m) -> string + auto next = [&s, b, e, &vb, &ve] (const char* m) -> uint64_t { - if (!next_word (s, e, vb, ve, '.')) - fail << "unable to extract gcc " << m << " version from '" - << string (s, b, e - b) << "'"; + try + { + if (next_word (s, e, vb, ve, '.')) + return stoull (string (s, vb, ve - vb)); + } + catch (const invalid_argument&) {} + catch (const out_of_range&) {} - return string (s, vb, ve - vb); + error << "unable to extract gcc " << m << " version from '" + << string (s, b, e - b) << "'"; + throw failed (); }; - compiler_version v; v.major = next ("major"); v.minor = next ("minor"); v.patch = next ("patch"); @@ -351,7 +357,8 @@ namespace build2 // -dumpmachine (older gcc or not multi-arch). // cstrings args {cxx.string ().c_str (), "-print-multiarch"}; - append_options (args, coptions); + if (coptions != nullptr) + append_options (args, *coptions); args.push_back (nullptr); // The output of both -print-multiarch and -dumpmachine is a single line @@ -383,9 +390,7 @@ namespace build2 } static compiler_info - guess_clang (const path& cxx, - lookup<const value> coptions, - guess_result&& gr) + guess_clang (const path& cxx, const strings* coptions, guess_result&& gr) { // Extract the version. Here we will try to handle both vanilla and // Apple clang since the signature lines are fairly similar. They have @@ -425,25 +430,33 @@ namespace build2 if (b == e) fail << "unable to extract clang version from '" << s << "'"; + compiler_version v; + v.string.assign (s, b, string::npos); + // Split the version into components. // size_t vb (b), ve (b); - auto next = [&s, b, e, &vb, &ve] (const char* m) -> string + auto next = [&s, b, e, &vb, &ve] (const char* m, bool opt) -> uint64_t { - if (next_word (s, e, vb, ve, '.')) - return string (s, vb, ve - vb); + try + { + if (next_word (s, e, vb, ve, '.')) + return stoull (string (s, vb, ve - vb)); - if (m != nullptr) - fail << "unable to extract clang " << m << " version from '" - << string (s, b, e - b) << "'"; + if (opt) + return 0; + } + catch (const invalid_argument&) {} + catch (const out_of_range&) {} - return string (); + error << "unable to extract clang " << m << " version from '" + << string (s, b, e - b) << "'"; + throw failed (); }; - compiler_version v; - v.major = next ("major"); - v.minor = next ("minor"); - v.patch = next (gr.id.variant == "apple" ? nullptr : "patch"); + v.major = next ("major", false); + v.minor = next ("minor", false); + v.patch = next ("patch", gr.id.variant == "apple"); if (e != s.size ()) v.build.assign (s, e + 1, string::npos); @@ -454,7 +467,8 @@ namespace build2 // however, respects the compile options (e.g., -m32). // cstrings args {cxx.string ().c_str (), "-dumpmachine"}; - append_options (args, coptions); + if (coptions != nullptr) + append_options (args, *coptions); args.push_back (nullptr); // The output of -dumpmachine is a single line containing just the @@ -475,9 +489,7 @@ namespace build2 } static compiler_info - guess_icc (const path& cxx, - lookup<const value> coptions, - guess_result&& gr) + guess_icc (const path& cxx, const strings* coptions, guess_result&& gr) { // Extract the version. If the version has the fourth component, then // the signature line (extracted with --version) won't include it. So we @@ -513,7 +525,9 @@ namespace build2 : string (); }; - s = run<string> (cxx, "-V", f); + // The -V output is sent to STDERR. + // + s = run<string> (cxx, "-V", f, false); if (s.empty ()) fail << "unable to extract signature from " << cxx << " -V output"; @@ -553,27 +567,36 @@ namespace build2 if (b == e) fail << "unable to extract icc version from '" << s << "'"; + compiler_version v; + v.string.assign (s, b, string::npos); + // Split the version into components. // size_t vb (b), ve (b); - auto next = [&s, b, e, &vb, &ve] (const char* m) -> string + auto next = [&s, b, e, &vb, &ve] (const char* m, bool opt) -> uint64_t { - if (next_word (s, e, vb, ve, '.')) - return string (s, vb, ve - vb); + try + { + if (next_word (s, e, vb, ve, '.')) + return stoull (string (s, vb, ve - vb)); - if (m != nullptr) - fail << "unable to extract icc " << m << " version from '" - << string (s, b, e - b) << "'"; + if (opt) + return 0; + } + catch (const invalid_argument&) {} + catch (const out_of_range&) {} - return ""; + error << "unable to extract icc " << m << " version from '" + << string (s, b, e - b) << "'"; + throw failed (); }; - compiler_version v; - v.major = next ("major"); - v.minor = next ("minor"); - v.patch = next (nullptr); - if (!v.patch.empty ()) - v.build = next (nullptr); + v.major = next ("major", false); + v.minor = next ("minor", false); + v.patch = next ("patch", true); + + if (vb != ve && next_word (s, e, vb, ve, '.')) + v.build.assign (s, vb, ve - vb); if (e != s.size ()) { @@ -597,10 +620,13 @@ namespace build2 // "Intel(R)" "MIC" (-dumpmachine says: x86_64-k1om-linux) // cstrings args {cxx.string ().c_str (), "-V"}; - append_options (args, coptions); + if (coptions != nullptr) + append_options (args, *coptions); args.push_back (nullptr); - string t (run<string> (args.data (), f)); + // The -V output is sent to STDERR. + // + string t (run<string> (args.data (), f, false)); if (t.empty ()) fail << "unable to extract target architecture from " << cxx @@ -735,26 +761,33 @@ namespace build2 if (b == e) fail << "unable to extract msvc version from '" << s << "'"; + compiler_version v; + v.string.assign (s, b, e - b); + // Split the version into components. // size_t vb (b), ve (b); - auto next = [&s, b, e, &vb, &ve] (const char* m) -> string + auto next = [&s, b, e, &vb, &ve] (const char* m) -> uint64_t { - if (next_word (s, e, vb, ve, '.')) - return string (s, vb, ve - vb); - - if (m != nullptr) - fail << "unable to extract msvc " << m << " version from '" - << string (s, b, e - b) << "'"; + try + { + if (next_word (s, e, vb, ve, '.')) + return stoull (string (s, vb, ve - vb)); + } + catch (const invalid_argument&) {} + catch (const out_of_range&) {} - return ""; + error << "unable to extract msvc " << m << " version from '" + << string (s, b, e - b) << "'"; + throw failed (); }; - compiler_version v; v.major = next ("major"); v.minor = next ("minor"); v.patch = next ("patch"); - v.build = next (nullptr); + + if (next_word (s, e, vb, ve, '.')) + v.build.assign (s, vb, ve - vb); // Continue scanning for the CPU. // @@ -837,14 +870,14 @@ namespace build2 // 14.00 80/8.0 VS2005 // 13.10 71/7.1 VS2003 // - /**/ if (v.major == "19" && v.minor == "00") arch += "14.0"; - else if (v.major == "18" && v.minor == "00") arch += "12.0"; - else if (v.major == "17" && v.minor == "00") arch += "11.0"; - else if (v.major == "16" && v.minor == "00") arch += "10.0"; - else if (v.major == "15" && v.minor == "00") arch += "9.0"; - else if (v.major == "14" && v.minor == "00") arch += "8.0"; - else if (v.major == "13" && v.minor == "10") arch += "7.1"; - else fail << "unable to map msvc compiler version '" << v.string () + /**/ if (v.major == 19 && v.minor == 0) arch += "14.0"; + else if (v.major == 18 && v.minor == 0) arch += "12.0"; + else if (v.major == 17 && v.minor == 0) arch += "11.0"; + else if (v.major == 16 && v.minor == 0) arch += "10.0"; + else if (v.major == 15 && v.minor == 0) arch += "9.0"; + else if (v.major == 14 && v.minor == 0) arch += "8.0"; + else if (v.major == 13 && v.minor == 10) arch += "7.1"; + else fail << "unable to map msvc compiler version '" << v.string << "' to runtime version"; } @@ -861,7 +894,7 @@ namespace build2 } compiler_info - guess (const path& cxx, lookup<const value> coptions) + guess (const path& cxx, const strings* coptions) { string pre (pre_guess (cxx)); guess_result gr; diff --git a/build2/cxx/link.cxx b/build2/cxx/link.cxx index c0ea6d3..aa60c7e 100644 --- a/build2/cxx/link.cxx +++ b/build2/cxx/link.cxx @@ -123,7 +123,7 @@ namespace build2 cstrings args; string std_storage; - args.push_back (cast<string> (rs["config.cxx"]).c_str ()); + args.push_back (cast<path> (rs["config.cxx"]).string ().c_str ()); append_options (args, bs, "cxx.coptions"); append_std (args, bs, std_storage); append_options (args, bs, "cxx.loptions"); @@ -877,8 +877,8 @@ namespace build2 // precedence. // if (auto l = t["bin.rpath"]) - for (const string& p: cast<strings> (l)) - sargs.push_back ("-Wl,-rpath," + p); + for (const dir_path& p: cast<dir_paths> (l)) + sargs.push_back ("-Wl,-rpath," + p.string ()); // Then the paths of the shared libraries we are linking to. Unless // this is update for install, in which case we have to do something @@ -978,12 +978,12 @@ namespace build2 if (lt == type::a) { - args[0] = cast<string> (rs["config.bin.ar"]).c_str (); + args[0] = cast<path> (rs["config.bin.ar"]).string ().c_str (); args.push_back (relt.string ().c_str ()); } else { - args[0] = cast<string> (rs["config.cxx"]).c_str (); + args[0] = cast<path> (rs["config.cxx"]).string ().c_str (); args.push_back ("-o"); args.push_back (relt.string ().c_str ()); } @@ -1048,7 +1048,9 @@ namespace build2 if (ranlib) { const char* args[] = { - cast<string> (ranlib).c_str (), relt.string ().c_str (), nullptr}; + cast<path> (ranlib).string ().c_str (), + relt.string ().c_str (), + nullptr}; if (verb >= 2) print_process (args); diff --git a/build2/cxx/module.cxx b/build2/cxx/module.cxx index 18f9e53..7b0f04e 100644 --- a/build2/cxx/module.cxx +++ b/build2/cxx/module.cxx @@ -62,7 +62,7 @@ namespace build2 { auto& v (var_pool); - v.find<string> ("config.cxx"); //@@ VAR type + v.find<path> ("config.cxx"); v.find<strings> ("config.cxx.poptions"); v.find<strings> ("config.cxx.coptions"); @@ -172,12 +172,12 @@ namespace build2 // if (first) { - auto p (config::required (r, "config.cxx", "g++")); + auto p (config::required (r, "config.cxx", path ("g++"))); // Figure out which compiler we are dealing with, its target, etc. // - const path& cxx (path (cast<string> (p.first))); // @@ VAR - compiler_info ci (guess (cxx, r["cxx.coptions"])); + const path& cxx (cast<path> (p.first)); + compiler_info ci (guess (cxx, cast_null<strings> (r["cxx.coptions"]))); // If this is a new value (e.g., we are configuring), then print the // report at verbosity level 2 and up (-v). @@ -188,6 +188,7 @@ namespace build2 text << cxx << ":\n" << " id " << ci.id << "\n" + << " version " << ci.version.string << "\n" << " major " << ci.version.major << "\n" << " minor " << ci.version.minor << "\n" << " patch " << ci.version.patch << "\n" @@ -201,10 +202,10 @@ namespace build2 r.assign<string> ("cxx.id.type") = move (ci.id.type); r.assign<string> ("cxx.id.variant") = move (ci.id.variant); - r.assign<string> ("cxx.version") = ci.version.string (); - r.assign<string> ("cxx.version.major") = move (ci.version.major); - r.assign<string> ("cxx.version.minor") = move (ci.version.minor); - r.assign<string> ("cxx.version.patch") = move (ci.version.patch); + r.assign<string> ("cxx.version") = move (ci.version.string); + r.assign<uint64_t> ("cxx.version.major") = ci.version.major; + r.assign<uint64_t> ("cxx.version.minor") = ci.version.minor; + r.assign<uint64_t> ("cxx.version.patch") = ci.version.patch; r.assign<string> ("cxx.version.build") = move (ci.version.build); r.assign<string> ("cxx.signature") = move (ci.signature); |