diff options
Diffstat (limited to 'build2/cc/common.cxx')
-rw-r--r-- | build2/cc/common.cxx | 1031 |
1 files changed, 0 insertions, 1031 deletions
diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx deleted file mode 100644 index 4f5db4c..0000000 --- a/build2/cc/common.cxx +++ /dev/null @@ -1,1031 +0,0 @@ -// file : build2/cc/common.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build2/cc/common.hxx> - -#include <libbuild2/file.hxx> // import() -#include <libbuild2/scope.hxx> -#include <libbuild2/variable.hxx> -#include <libbuild2/algorithm.hxx> -#include <libbuild2/filesystem.hxx> -#include <libbuild2/diagnostics.hxx> - -#include <build2/cc/utility.hxx> - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace cc - { - using namespace bin; - - // Recursively process prerequisite libraries. If proc_impl returns false, - // then only process interface (*.export.libs), otherwise -- interface and - // implementation (prerequisite and from *.libs, unless overriden). - // - // Note that here we assume that an interface library is also an - // implementation (since we don't use *.export.libs in static link). We - // currently have this restriction to make sure the target in - // *.export.libs is up-to-date (which will happen automatically if it is - // listed as a prerequisite of this library). - // - // Storing a reference to library path in proc_lib is legal (it comes - // either from the target's path or from one of the *.libs variables - // neither of which should change on this run). - // - // Note that the order of processing is: - // - // 1. options - // 2. lib itself (if self is true) - // 3. dependency libs (prerequisite_targets, left to right, depth-first) - // 4. dependency libs (*.libs variables). - // - // The first argument to proc_lib is a pointer to the last element of an - // array that contains the current library dependency chain all the way to - // the library passes to process_libraries(). The first element of this - // array is NULL. - // - void common:: - process_libraries ( - action a, - const scope& top_bs, - linfo top_li, - const dir_paths& top_sysd, - const file& l, - bool la, - lflags lf, - const function<bool (const file&, - bool la)>& proc_impl, // Implementation? - const function<void (const file* const*, // Can be NULL. - const string& path, // Library path. - lflags, // Link flags. - bool sys)>& proc_lib, // True if system library. - const function<void (const file&, - const string& type, // cc.type - bool com, // cc. or x. - bool exp)>& proc_opt, // *.export. - bool self /*= false*/, // Call proc_lib on l? - small_vector<const file*, 16>* chain) const - { - small_vector<const file*, 16> chain_storage; - if (chain == nullptr) - { - chain = &chain_storage; - chain->push_back (nullptr); - } - - // See what type of library this is (C, C++, etc). Use it do decide - // which x.libs variable name to use. If it's unknown, then we only - // look into prerequisites. Note: lookup starting from rule-specific - // variables (target should already be matched). - // - const string* t (cast_null<string> (l.state[a][c_type])); - - bool impl (proc_impl && proc_impl (l, la)); - bool cc (false), same (false); - - auto& vp (top_bs.ctx.var_pool); - lookup c_e_libs; - lookup x_e_libs; - - if (t != nullptr) - { - cc = *t == "cc"; - same = !cc && *t == x; - - // The explicit export override should be set on the liba/libs{} - // target itself. Note also that we only check for *.libs. If one - // doesn't have any libraries but needs to set, say, *.loptions, then - // *.libs should be set to NULL or empty (this is why we check for - // the result being defined). - // - if (impl) - c_e_libs = l.vars[c_export_libs]; // Override. - else if (l.group != nullptr) // lib{} group. - c_e_libs = l.group->vars[c_export_libs]; - - if (!cc) - { - const variable& var (same - ? x_export_libs - : vp[*t + ".export.libs"]); - - if (impl) - x_e_libs = l.vars[var]; // Override. - else if (l.group != nullptr) // lib{} group. - x_e_libs = l.group->vars[var]; - } - - // Process options first. - // - if (proc_opt) - { - // If all we know is it's a C-common library, then in both cases we - // only look for cc.export.*. - // - if (cc) - proc_opt (l, *t, true, true); - else - { - if (impl) - { - // Interface and implementation: as discussed above, we can have - // two situations: overriden export or default export. - // - if (c_e_libs.defined () || x_e_libs.defined ()) - { - // NOTE: should this not be from l.vars rather than l? Or - // perhaps we can assume non-common values will be set on - // libs{}/liba{}. - // - proc_opt (l, *t, true, true); - proc_opt (l, *t, false, true); - } - else - { - // For default export we use the same options as were used to - // build the library. - // - proc_opt (l, *t, true, false); - proc_opt (l, *t, false, false); - } - } - else - { - // Interface: only add *.export.* (interface dependencies). - // - proc_opt (l, *t, true, true); - proc_opt (l, *t, false, true); - } - } - } - } - - // Determine if an absolute path is to a system library. Note that - // we assume both paths to be normalized. - // - auto sys = [] (const dir_paths& sysd, const string& p) -> bool - { - size_t pn (p.size ()); - - for (const dir_path& d: sysd) - { - const string& ds (d.string ()); // Can be "/", otherwise no slash. - size_t dn (ds.size ()); - - if (pn > dn && - p.compare (0, dn, ds) == 0 && - (path::traits_type::is_separator (ds[dn - 1]) || - path::traits_type::is_separator (p[dn]))) - return true; - } - - return false; - }; - - // Next process the library itself if requested. - // - if (self && proc_lib) - { - chain->push_back (&l); - - // Note that while normally the path is assigned, in case of an import - // stub the path to the DLL may not be known and so the path will be - // empty (but proc_lib() will use the import stub). - // - const path& p (l.path ()); - - bool s (t != nullptr // If cc library (matched or imported). - ? cast_false<bool> (l.vars[c_system]) - : !p.empty () && sys (top_sysd, p.string ())); - - proc_lib (&chain->back (), p.string (), lf, s); - } - - const scope& bs (t == nullptr || cc ? top_bs : l.base_scope ()); - optional<linfo> li; // Calculate lazily. - const dir_paths* sysd (nullptr); // Resolve lazily. - - // Find system search directories corresponding to this library, i.e., - // from its project and for its type (C, C++, etc). - // - auto find_sysd = [&top_sysd, t, cc, same, &bs, &sysd, this] () - { - // Use the search dirs corresponding to this library scope/type. - // - sysd = (t == nullptr || cc) - ? &top_sysd // Imported library, use importer's sysd. - : &cast<dir_paths> ( - bs.root_scope ()->vars[same - ? x_sys_lib_dirs - : bs.ctx.var_pool[*t + ".sys_lib_dirs"]]); - }; - - auto find_linfo = [top_li, t, cc, &bs, &l, &li] () - { - li = (t == nullptr || cc) - ? top_li - : link_info (bs, link_type (l).type); - }; - - // Only go into prerequisites (implementation) if instructed and we are - // not using explicit export. Otherwise, interface dependencies come - // from the lib{}:*.export.libs below. - // - if (impl && !c_e_libs.defined () && !x_e_libs.defined ()) - { - for (const prerequisite_target& pt: l.prerequisite_targets[a]) - { - // Note: adhoc prerequisites are not part of the library meta- - // information protocol. - // - if (pt == nullptr || pt.adhoc) - continue; - - bool la; - const file* f; - - if ((la = (f = pt->is_a<liba> ())) || - (la = (f = pt->is_a<libux> ())) || - ( f = pt->is_a<libs> ())) - { - if (sysd == nullptr) find_sysd (); - if (!li) find_linfo (); - - process_libraries (a, bs, *li, *sysd, - *f, la, pt.data, - proc_impl, proc_lib, proc_opt, true, chain); - } - } - } - - // Process libraries (recursively) from *.export.libs (of type names) - // handling import, etc. - // - // If it is not a C-common library, then it probably doesn't have any of - // the *.libs. - // - if (t != nullptr) - { - optional<dir_paths> usrd; // Extract lazily. - - // Determine if a "simple path" is a system library. - // - auto sys_simple = [&sysd, &sys, &find_sysd] (const string& p) -> bool - { - bool s (!path::traits_type::absolute (p)); - - if (!s) - { - if (sysd == nullptr) find_sysd (); - - s = sys (*sysd, p); - } - - return s; - }; - - auto proc_int = [&l, - &proc_impl, &proc_lib, &proc_opt, chain, - &sysd, &usrd, - &find_sysd, &find_linfo, &sys_simple, - &bs, a, &li, this] (const lookup& lu) - { - const vector<name>* ns (cast_null<vector<name>> (lu)); - if (ns == nullptr || ns->empty ()) - return; - - for (const name& n: *ns) - { - if (n.simple ()) - { - // This is something like -lpthread or shell32.lib so should be - // a valid path. But it can also be an absolute library path - // (e.g., something that may come from our .static/shared.pc - // files). - // - if (proc_lib) - proc_lib (nullptr, n.value, 0, sys_simple (n.value)); - } - else - { - // This is a potentially project-qualified target. - // - if (sysd == nullptr) find_sysd (); - if (!li) find_linfo (); - - const file& t (resolve_library (a, bs, n, *li, *sysd, usrd)); - - if (proc_lib) - { - // This can happen if the target is mentioned in *.export.libs - // (i.e., it is an interface dependency) but not in the - // library's prerequisites (i.e., it is not an implementation - // dependency). - // - // Note that we used to just check for path being assigned but - // on Windows import-installed DLLs may legally have empty - // paths. - // - if (t.mtime () == timestamp_unknown) - fail << "interface dependency " << t << " is out of date" << - info << "mentioned in *.export.libs of target " << l << - info << "is it a prerequisite of " << l << "?"; - } - - // Process it recursively. - // - // @@ Where can we get the link flags? Should we try to find - // them in the library's prerequisites? What about installed - // stuff? - // - process_libraries (a, bs, *li, *sysd, - t, t.is_a<liba> () || t.is_a<libux> (), 0, - proc_impl, proc_lib, proc_opt, true, chain); - } - } - }; - - // Process libraries from *.libs (of type strings). - // - auto proc_imp = [&proc_lib, &sys_simple] (const lookup& lu) - { - const strings* ns (cast_null<strings> (lu)); - if (ns == nullptr || ns->empty ()) - return; - - for (const string& n: *ns) - { - // This is something like -lpthread or shell32.lib so should be a - // valid path. - // - proc_lib (nullptr, n, 0, sys_simple (n)); - } - }; - - // Note: the same structure as when processing options above. - // - // If all we know is it's a C-common library, then in both cases we - // only look for cc.export.libs. - // - if (cc) - { - if (c_e_libs) proc_int (c_e_libs); - } - else - { - if (impl) - { - // Interface and implementation: as discussed above, we can have - // two situations: overriden export or default export. - // - if (c_e_libs.defined () || x_e_libs.defined ()) - { - if (c_e_libs) proc_int (c_e_libs); - if (x_e_libs) proc_int (x_e_libs); - } - else - { - // For default export we use the same options/libs as were used - // to build the library. Since libraries in (non-export) *.libs - // are not targets, we don't need to recurse. - // - if (proc_lib) - { - proc_imp (l[c_libs]); - proc_imp (l[same ? x_libs : vp[*t + ".libs"]]); - } - } - } - else - { - // Interface: only add *.export.* (interface dependencies). - // - if (c_e_libs) proc_int (c_e_libs); - if (x_e_libs) proc_int (x_e_libs); - } - } - } - - // Remove this library from the chain. - // - if (self && proc_lib) - chain->pop_back (); - } - - // The name can be an absolute or relative target name (for example, - // /tmp/libfoo/lib{foo} or ../libfoo/lib{foo}) or a project-qualified - // relative target name (e.g., libfoo%lib{foo}). - // - // Note that in case of the relative target that comes from export.libs, - // the resolution happens relative to the base scope of the target from - // which this export.libs came, which is exactly what we want. - // - // Note that the scope, search paths, and the link order should all be - // derived from the library target that mentioned this name. This way we - // will select exactly the same target as the library's matched rule and - // that's the only way to guarantee it will be up-to-date. - // - const file& common:: - resolve_library (action a, - const scope& s, - name n, - linfo li, - const dir_paths& sysd, - optional<dir_paths>& usrd) const - { - if (n.type != "lib" && n.type != "liba" && n.type != "libs") - fail << "target name " << n << " is not a library"; - - const target* xt (nullptr); - - if (!n.qualified ()) - { - // Search for an existing target with this name "as if" it was a - // prerequisite. - // - xt = search_existing (n, s); - - if (xt == nullptr) - fail << "unable to find library " << n; - } - else - { - // This is import. - // - auto rp (s.find_target_type (n, location ())); // Note: changes name. - const target_type* tt (rp.first); - optional<string>& ext (rp.second); - - if (tt == nullptr) - fail << "unknown target type '" << n.type << "' in library " << n; - - // @@ OUT: for now we assume out is undetermined, just like in - // search (name, scope). - // - dir_path out; - - prerequisite_key pk {n.proj, {tt, &n.dir, &out, &n.value, ext}, &s}; - xt = search_library_existing (a, sysd, usrd, pk); - - if (xt == nullptr) - { - if (n.qualified ()) - xt = import_existing (s.ctx, pk); - } - - if (xt == nullptr) - fail << "unable to find library " << pk; - } - - // If this is lib{}/libu*{}, pick appropriate member. - // - if (const libx* l = xt->is_a<libx> ()) - xt = link_member (*l, a, li); // Pick lib*{e,a,s}{}. - - return xt->as<file> (); - } - - // Insert a target verifying that it already exists if requested. Return - // the lock. - // - template <typename T> - ulock common:: - insert_library (context& ctx, - T*& r, - const string& name, - const dir_path& d, - optional<string> ext, - bool exist, - tracer& trace) - { - auto p (ctx.targets.insert_locked (T::static_type, - d, - dir_path (), - name, - move (ext), - true, // Implied. - trace)); - - assert (!exist || !p.second.owns_lock ()); - r = &p.first.template as<T> (); - return move (p.second); - } - - // Note that pk's scope should not be NULL (even if dir is absolute). - // - target* common:: - search_library (action act, - const dir_paths& sysd, - optional<dir_paths>& usrd, - const prerequisite_key& p, - bool exist) const - { - tracer trace (x, "search_library"); - - assert (p.scope != nullptr); - - // @@ This is hairy enough to warrant a separate implementation for - // Windows. - - // Note: since we are searching for a (presumably) installed library, - // utility libraries do not apply. - // - bool l (p.is_a<lib> ()); - const optional<string>& ext (l ? nullopt : p.tk.ext); // Only liba/libs. - - // First figure out what we need to search for. - // - const string& name (*p.tk.name); - - // liba - // - path an; - optional<string> ae; - - if (l || p.is_a<liba> ()) - { - // We are trying to find a library in the search paths extracted from - // the compiler. It would only be natural if we used the library - // prefix/extension that correspond to this compiler and/or its - // target. - // - // Unlike MinGW, VC's .lib/.dll.lib naming is by no means standard and - // we might need to search for other names. In fact, there is no - // reliable way to guess from the file name what kind of library it - // is, static or import and we will have to do deep inspection of such - // alternative names. However, if we did find .dll.lib, then we can - // assume that .lib is the static library without any deep inspection - // overhead. - // - const char* e (""); - - if (tsys == "win32-msvc") - { - an = path (name); - e = "lib"; - } - else - { - an = path ("lib" + name); - e = "a"; - } - - ae = ext ? ext : string (e); - if (!ae->empty ()) - { - an += '.'; - an += *ae; - } - } - - // libs - // - path sn; - optional<string> se; - - if (l || p.is_a<libs> ()) - { - const char* e (""); - - if (tsys == "win32-msvc") - { - sn = path (name); - e = "dll.lib"; - } - else - { - sn = path ("lib" + name); - - if (tsys == "darwin") e = "dylib"; - else if (tsys == "mingw32") e = "dll.a"; // See search code below. - else e = "so"; - } - - se = ext ? ext : string (e); - if (!se->empty ()) - { - sn += '.'; - sn += *se; - } - } - - // Now search. - // - liba* a (nullptr); - libs* s (nullptr); - - pair<path, path> pc; // pkg-config .pc file paths. - path f; // Reuse the buffer. - - auto search =[&a, &s, &pc, - &an, &ae, - &sn, &se, - &name, ext, - &p, &f, exist, &trace, this] (const dir_path& d) -> bool - { - context& ctx (p.scope->ctx); - - timestamp mt; - - // libs - // - // Look for the shared library first. The order is important for VC: - // only if we found .dll.lib can we safely assumy that just .lib is a - // static library. - // - if (!sn.empty ()) - { - f = d; - f /= sn; - mt = mtime (f); - - if (mt != timestamp_nonexistent) - { - // On Windows what we found is the import library which we need - // to make the first ad hoc member of libs{}. - // - if (tclass == "windows") - { - libi* i (nullptr); - insert_library (ctx, i, name, d, se, exist, trace); - - ulock l ( - insert_library (ctx, s, name, d, nullopt, exist, trace)); - - if (!exist) - { - if (l.owns_lock ()) - { - s->member = i; // We are first. - l.unlock (); - } - else - assert (find_adhoc_member<libi> (*s) == i); - - i->mtime (mt); - i->path (move (f)); - - // Presumably there is a DLL somewhere, we just don't know - // where (and its possible we might have to look for one if we - // decide we need to do rpath emulation for installed - // libraries as well). We will represent this as empty path - // but valid timestamp (aka "trust me, it's there"). - // - s->mtime (mt); - s->path (empty_path); - } - } - else - { - insert_library (ctx, s, name, d, se, exist, trace); - - s->mtime (mt); - s->path (move (f)); - } - } - else if (!ext && tsys == "mingw32") - { - // Above we searched for the import library (.dll.a) but if it's - // not found, then we also search for the .dll (unless the - // extension was specified explicitly) since we can link to it - // directly. Note also that the resulting libs{} would end up - // being the .dll. - // - se = string ("dll"); - f = f.base (); // Remove .a from .dll.a. - mt = mtime (f); - - if (mt != timestamp_nonexistent) - { - insert_library (ctx, s, name, d, se, exist, trace); - - s->mtime (mt); - s->path (move (f)); - } - } - } - - // liba - // - // If we didn't find .dll.lib then we cannot assume .lib is static. - // - if (!an.empty () && (s != nullptr || tsys != "win32-msvc")) - { - f = d; - f /= an; - - if ((mt = mtime (f)) != timestamp_nonexistent) - { - // Enter the target. Note that because the search paths are - // normalized, the result is automatically normalized as well. - // - // Note that this target is outside any project which we treat - // as out trees. - // - insert_library (ctx, a, name, d, ae, exist, trace); - a->mtime (mt); - a->path (move (f)); - } - } - - // Alternative search for VC. - // - if (tsys == "win32-msvc") - { - const scope& rs (*p.scope->root_scope ()); - const process_path& ld (cast<process_path> (rs["bin.ld.path"])); - - if (s == nullptr && !sn.empty ()) - s = msvc_search_shared (ld, d, p, exist); - - if (a == nullptr && !an.empty ()) - a = msvc_search_static (ld, d, p, exist); - } - - // Look for binary-less libraries via pkg-config .pc files. Note that - // it is possible we have already found one of them as binfull but the - // other is binless. - // - { - bool na (a == nullptr && !an.empty ()); // Need static. - bool ns (s == nullptr && !sn.empty ()); // Need shared. - - if (na || ns) - { - // Only consider the common .pc file if we can be sure there - // is no binfull variant. - // - pair<path, path> r ( - pkgconfig_search (d, p.proj, name, na && ns /* common */)); - - if (na && !r.first.empty ()) - { - insert_library (ctx, a, name, d, nullopt, exist, trace); - a->mtime (timestamp_unreal); - a->path (empty_path); - } - - if (ns && !r.second.empty ()) - { - insert_library (ctx, s, name, d, nullopt, exist, trace); - s->mtime (timestamp_unreal); - s->path (empty_path); - } - - // Only keep these .pc paths if we found anything via them. - // - if ((na && a != nullptr) || (ns && s != nullptr)) - pc = move (r); - } - } - - return a != nullptr || s != nullptr; - }; - - // First try user directories (i.e., -L). - // - bool sys (false); - - if (!usrd) - usrd = extract_library_dirs (*p.scope); - - const dir_path* pd (nullptr); - for (const dir_path& d: *usrd) - { - if (search (d)) - { - pd = &d; - break; - } - } - - // Next try system directories (i.e., those extracted from the compiler). - // - if (pd == nullptr) - { - for (const dir_path& d: sysd) - { - if (search (d)) - { - pd = &d; - break; - } - } - - sys = true; - } - - if (pd == nullptr) - return nullptr; - - // Enter (or find) the lib{} target group. - // - lib* lt; - insert_library ( - p.scope->ctx, lt, name, *pd, l ? p.tk.ext : nullopt, exist, trace); - - // Result. - // - target* r (l ? lt : (p.is_a<liba> () ? static_cast<target*> (a) : s)); - - // Assume the rest is already done if existing. - // - if (exist) - return r; - - // If we cannot acquire the lock then this mean the target has already - // been matched (though not clear by whom) and we assume all of this - // has already been done. - // - target_lock ll (lock (act, *lt)); - - // Set lib{} group members to indicate what's available. Note that we - // must be careful here since its possible we have already imported some - // of its members. - // - if (ll) - { - if (a != nullptr) lt->a = a; - if (s != nullptr) lt->s = s; - } - - target_lock al (a != nullptr ? lock (act, *a) : target_lock ()); - target_lock sl (s != nullptr ? lock (act, *s) : target_lock ()); - - if (!al) a = nullptr; - if (!sl) s = nullptr; - - if (a != nullptr) a->group = lt; - if (s != nullptr) s->group = lt; - - // Mark as a "cc" library (unless already marked) and set the system - // flag. - // - auto mark_cc = [sys, this] (target& t) -> bool - { - auto p (t.vars.insert (c_type)); - - if (p.second) - { - p.first.get () = string ("cc"); - - if (sys) - t.vars.assign (c_system) = true; - } - - return p.second; - }; - - // If the library already has cc.type, then assume it was either - // already imported or was matched by a rule. - // - if (a != nullptr && !mark_cc (*a)) a = nullptr; - if (s != nullptr && !mark_cc (*s)) s = nullptr; - - // Add the "using static/shared library" macro (used, for example, to - // handle DLL export). The absence of either of these macros would - // mean some other build system that cannot distinguish between the - // two (and no pkg-config information). - // - auto add_macro = [this] (target& t, const char* suffix) - { - // If there is already a value (either in cc.export or x.export), - // don't add anything: we don't want to be accumulating defines nor - // messing with custom values. And if we are adding, then use the - // generic cc.export. - // - // The only way we could already have this value is if this same - // library was also imported as a project (as opposed to installed). - // Unlikely but possible. In this case the values were set by the - // export stub and we shouldn't touch them. - // - if (!t.vars[x_export_poptions]) - { - auto p (t.vars.insert (c_export_poptions)); - - if (p.second) - { - // The "standard" macro name will be LIB<NAME>_{STATIC,SHARED}, - // where <name> is the target name. Here we want to strike a - // balance between being unique and not too noisy. - // - string d ("-DLIB"); - - d += sanitize_identifier ( - ucase (const_cast<const string&> (t.name))); - - d += '_'; - d += suffix; - - strings o; - o.push_back (move (d)); - p.first.get () = move (o); - } - } - }; - - if (ll && (a != nullptr || s != nullptr)) - { - // Try to extract library information from pkg-config. We only add the - // default macro if we could not extract more precise information. The - // idea is that in .pc files that we generate, we copy those macros - // (or custom ones) from *.export.poptions. - // - if (pc.first.empty () && pc.second.empty ()) - { - if (!pkgconfig_load (act, *p.scope, - *lt, a, s, - p.proj, name, - *pd, sysd, *usrd)) - { - if (a != nullptr) add_macro (*a, "STATIC"); - if (s != nullptr) add_macro (*s, "SHARED"); - } - } - else - pkgconfig_load (act, *p.scope, *lt, a, s, pc, *pd, sysd, *usrd); - } - - // If we have the lock (meaning this is the first time), set the - // traget's recipe to noop. Failed that we will keep re-locking it, - // updating its members, etc. - // - if (al) match_recipe (al, noop_recipe); - if (sl) match_recipe (sl, noop_recipe); - if (ll) match_recipe (ll, noop_recipe); - - return r; - } - - dir_paths common:: - extract_library_dirs (const scope& bs) const - { - dir_paths r; - - // Extract user-supplied search paths (i.e., -L, /LIBPATH). - // - auto extract = [&bs, &r, this] (const value& val, const variable& var) - { - const auto& v (cast<strings> (val)); - - for (auto i (v.begin ()), e (v.end ()); i != e; ++i) - { - const string& o (*i); - - dir_path d; - - try - { - if (cclass == compiler_class::msvc) - { - // /LIBPATH:<dir> (case-insensitive). - // - if ((o[0] == '/' || o[0] == '-') && - casecmp (o.c_str () + 1, "LIBPATH:", 8) == 0) - d = dir_path (o, 9, string::npos); - else - continue; - } - else - { - // -L can either be in the "-L<dir>" or "-L <dir>" form. - // - if (o == "-L") - { - if (++i == e) - break; // Let the compiler complain. - - d = dir_path (*i); - } - else if (o.compare (0, 2, "-L") == 0) - d = dir_path (o, 2, string::npos); - else - continue; - } - } - catch (const invalid_path& e) - { - fail << "invalid directory '" << e.path << "'" - << " in option '" << o << "'" - << " in variable " << var - << " for scope " << bs; - } - - // Ignore relative paths. Or maybe we should warn? - // - if (!d.relative ()) - r.push_back (move (d)); - } - }; - - if (auto l = bs[c_loptions]) extract (*l, c_loptions); - if (auto l = bs[x_loptions]) extract (*l, x_loptions); - - return r; - } - } -} |