From a4796d5b851dac4a546f89c282f65e320076eb10 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 27 Aug 2016 09:53:30 +0200 Subject: Clean up library export, make c and cxx modules project root only So now c and cxx modules can only be loaded in project root scope (normally root.build). Also, the c.std and cxx.std must now be set *before* loading the module to take effect. This means we won't be able to handle old buildfiles anymore but old versions of build2 should be able to handle new *.std placement. --- build2/cc/gcc.cxx | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 build2/cc/gcc.cxx (limited to 'build2/cc/gcc.cxx') diff --git a/build2/cc/gcc.cxx b/build2/cc/gcc.cxx new file mode 100644 index 0000000..a6c7448 --- /dev/null +++ b/build2/cc/gcc.cxx @@ -0,0 +1,128 @@ +// file : build2/cc/gcc.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace cc + { + using namespace bin; + + // 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 (process_path& xc, scope& rs) const + { + dir_paths r; + + cstrings args; + string std; // Storage. + + args.push_back (xc.recall_string ()); + append_options (args, rs, c_coptions); + append_options (args, rs, x_coptions); + if (!tstd.empty ()) args.push_back (tstd.c_str ()); + append_options (args, rs, c_loptions); + append_options (args, rs, x_loptions); + args.push_back ("-print-search-dirs"); + args.push_back (nullptr); + + if (verb >= 3) + print_process (args); + + string l; + try + { + process pr (xc, args.data (), 0, -1); // Open pipe to stdout. + + try + { + ifdstream is (pr.in_ofd, fdstream_mode::skip, ifdstream::badbit); + + string s; + while (getline (is, s)) + { + if (s.compare (0, 12, "libraries: =") == 0) + { + l.assign (s, 12, string::npos); + break; + } + } + + is.close (); // Don't block. + + if (!pr.wait ()) + throw failed (); + } + catch (const ifdstream::failure&) + { + pr.wait (); + fail << "error reading " << x_lang << " compiler -print-search-dirs " + << "output"; + } + } + catch (const process_error& e) + { + error << "unable to execute " << args[0] << ": " << e.what (); + + if (e.child ()) + exit (1); + + throw failed (); + } + + if (l.empty ()) + fail << "unable to extract " << x_lang << " compiler system library " + << "search paths"; + + // Now the fun part: figuring out which delimiter is used. Normally it + // is ':' but on Windows it is ';' (or can be; who knows for sure). Also + // note that these paths are absolute (or should be). So here is what we + // are going to do: first look for ';'. If found, then that's the + // delimiter. If not found, then there are two cases: it is either a + // single Windows path or the delimiter is ':'. To distinguish these two + // cases we check if the path starts with a Windows drive. + // + char d (';'); + string::size_type e (l.find (d)); + + if (e == string::npos && + (l.size () < 2 || l[0] == '/' || l[1] != ':')) + { + d = ':'; + e = l.find (d); + } + + // Now chop it up. We already have the position of the first delimiter + // (if any). + // + for (string::size_type b (0);; e = l.find (d, (b = e + 1))) + { + r.emplace_back (l, b, (e != string::npos ? e - b : e)); + r.back ().normalize (); + + if (e == string::npos) + break; + } + + return r; + } + } +} -- cgit v1.1