aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc/module.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/cc/module.cxx')
-rw-r--r--libbuild2/cc/module.cxx165
1 files changed, 93 insertions, 72 deletions
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index c930d49..cf6c6e4 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -11,10 +11,7 @@
#include <libbuild2/bin/target.hxx>
-#include <libbuild2/cc/target.hxx> // pc*
-
#include <libbuild2/config/utility.hxx>
-#include <libbuild2/install/utility.hxx>
#include <libbuild2/cc/guess.hxx>
@@ -30,6 +27,8 @@ namespace build2
{
tracer trace (x, "guess_init");
+ context& ctx (rs.ctx);
+
bool cc_loaded (cast_false<bool> (rs["cc.core.guess.loaded"]));
// Adjust module priority (compiler). Also order cc module before us
@@ -41,7 +40,10 @@ namespace build2
config::save_module (rs, x, 250);
- auto& vp (rs.var_pool ());
+ // All the variables we enter are qualified so go straight for the
+ // public variable pool.
+ //
+ auto& vp (rs.var_pool (true /* public */));
// Must already exist.
//
@@ -55,7 +57,7 @@ namespace build2
// config.x
//
- strings mode;
+ strings omode; // Original mode.
{
// Normally we will have a persistent configuration and computing the
// default value every time will be a waste. So try without a default
@@ -139,21 +141,34 @@ namespace build2
fail << "invalid path '" << s << "' in " << config_x;
}
- mode.assign (++v.begin (), v.end ());
+ omode.assign (++v.begin (), v.end ());
// Save original path/mode in *.config.path/mode.
//
rs.assign (x_c_path) = xc;
- rs.assign (x_c_mode) = mode;
+ rs.assign (x_c_mode) = omode;
+
+ // Merge the configured mode options into user-specified (which must
+ // be done before loading the *.guess module).
+ //
+ // In particular, this ability to specify the compiler mode in a
+ // buildfile is useful in embedded development where the project may
+ // need to hardcode things like -target, -nostdinc, etc.
+ //
+ const strings& mode (cast<strings> (rs.assign (x_mode) += omode));
// Figure out which compiler we are dealing with, its target, etc.
//
// Note that we could allow guess() to modify mode to support
// imaginary options (such as /MACHINE for cl.exe). Though it's not
// clear what cc.mode would contain (original or modified). Note that
- // we are now folding *.std options into mode options.
+ // we are now adding *.std options into mode options.
+ //
+ // @@ But can't the language standard options alter things like search
+ // directories?
//
x_info = &build2::cc::guess (
+ ctx,
x, x_lang,
rs.root_extra->environment_checksum,
move (xc),
@@ -180,7 +195,8 @@ namespace build2
if (config_sub)
{
- ct = run<string> (3,
+ ct = run<string> (ctx,
+ 3,
*config_sub,
xi.target.c_str (),
[] (string& l, bool) {return move (l);});
@@ -218,9 +234,10 @@ namespace build2
// Assign values to variables that describe the compiler.
//
+ // Note: x_mode is dealt with above.
+ //
rs.assign (x_path) = process_path_ex (
xi.path, x_name, xi.checksum, env_checksum);
- const strings& xm (cast<strings> (rs.assign (x_mode) = move (mode)));
rs.assign (x_id) = xi.id.string ();
rs.assign (x_id_type) = to_string (xi.id.type);
@@ -265,9 +282,9 @@ namespace build2
//
if (!cc_loaded)
{
- // Prepare configuration hints.
+ // Prepare configuration hints (pretend it belongs to root scope).
//
- variable_map h (rs.ctx);
+ variable_map h (rs);
// Note that all these variables have already been registered.
//
@@ -278,8 +295,8 @@ namespace build2
if (!xi.pattern.empty ())
h.assign ("config.cc.pattern") = xi.pattern;
- if (!xm.empty ())
- h.assign ("config.cc.mode") = xm;
+ if (!omode.empty ())
+ h.assign ("config.cc.mode") = move (omode);
h.assign (c_runtime) = xi.runtime;
h.assign (c_stdlib) = xi.c_stdlib;
@@ -350,6 +367,8 @@ namespace build2
# ifdef __APPLE__
static const dir_path a_usr_inc (
"/Library/Developer/CommandLineTools/SDKs/MacOSX*.sdk/usr/include");
+ static const dir_path a_usr_lib (
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX*.sdk/usr/lib");
# endif
#endif
@@ -376,7 +395,9 @@ namespace build2
//
if (!cast_false<bool> (rs["cc.core.config.loaded"]))
{
- variable_map h (rs.ctx);
+ // Prepare configuration hints (pretend it belongs to root scope).
+ //
+ variable_map h (rs);
if (!xi.bin_pattern.empty ())
h.assign ("config.bin.pattern") = xi.bin_pattern;
@@ -602,10 +623,10 @@ namespace build2
switch (xi.class_)
{
case compiler_class::gcc:
- lib_dirs = gcc_library_search_dirs (xi.path, rs);
+ lib_dirs = gcc_library_search_dirs (xi, rs);
break;
case compiler_class::msvc:
- lib_dirs = msvc_library_search_dirs (xi.path, rs);
+ lib_dirs = msvc_library_search_dirs (xi, rs);
break;
}
}
@@ -619,10 +640,10 @@ namespace build2
switch (xi.class_)
{
case compiler_class::gcc:
- hdr_dirs = gcc_header_search_dirs (xi.path, rs);
+ hdr_dirs = gcc_header_search_dirs (xi, rs);
break;
case compiler_class::msvc:
- hdr_dirs = msvc_header_search_dirs (xi.path, rs);
+ hdr_dirs = msvc_header_search_dirs (xi, rs);
break;
}
}
@@ -640,8 +661,8 @@ namespace build2
sys_hdr_dirs_mode = hdr_dirs.second;
sys_mod_dirs_mode = mod_dirs ? mod_dirs->second : 0;
- sys_lib_dirs_extra = lib_dirs.first.size ();
- sys_hdr_dirs_extra = hdr_dirs.first.size ();
+ sys_lib_dirs_extra = 0;
+ sys_hdr_dirs_extra = 0;
#ifndef _WIN32
// Add /usr/local/{include,lib}. We definitely shouldn't do this if we
@@ -657,11 +678,11 @@ namespace build2
// on the next invocation.
//
{
- auto& is (hdr_dirs.first);
+ auto& hs (hdr_dirs.first);
auto& ls (lib_dirs.first);
- bool ui (find (is.begin (), is.end (), usr_inc) != is.end ());
- bool uli (find (is.begin (), is.end (), usr_loc_inc) != is.end ());
+ bool ui (find (hs.begin (), hs.end (), usr_inc) != hs.end ());
+ bool uli (find (hs.begin (), hs.end (), usr_loc_inc) != hs.end ());
#ifdef __APPLE__
// On Mac OS starting from 10.14 there is no longer /usr/include.
@@ -684,15 +705,28 @@ namespace build2
//
// Is Apple's /usr/include.
//
- if (!ui && !uli)
+ // Also, it appears neither Clang nor GCC report MacOSX*.sdk/usr/lib
+ // with -print-search-dirs but they do search in there. So we add it
+ // to our list if we see MacOSX*.sdk/usr/include.
+ //
+ auto aui (find_if (hs.begin (), hs.end (),
+ [] (const dir_path& d)
+ {
+ return path_match (d, a_usr_inc);
+ }));
+
+ if (aui != hs.end ())
{
- for (const dir_path& d: is)
+ if (!ui)
+ ui = true;
+
+ if (find_if (ls.begin (), ls.end (),
+ [] (const dir_path& d)
+ {
+ return path_match (d, a_usr_lib);
+ }) == ls.end ())
{
- if (path_match (d, a_usr_inc))
- {
- ui = true;
- break;
- }
+ ls.push_back (aui->directory () /= "lib");
}
}
#endif
@@ -700,18 +734,29 @@ namespace build2
{
bool ull (find (ls.begin (), ls.end (), usr_loc_lib) != ls.end ());
- // Many platforms don't search in /usr/local/lib by default (but do
- // for headers in /usr/local/include). So add it as the last option.
+ // Many platforms don't search in /usr/local/lib by default but do
+ // for headers in /usr/local/include.
+ //
+ // Note that customarily /usr/local/include is searched before
+ // /usr/include so we add /usr/local/lib before built-in entries
+ // (there isn't really a way to add it after since all we can do is
+ // specify it with -L).
//
if (!ull && exists (usr_loc_lib, true /* ignore_error */))
- ls.push_back (usr_loc_lib);
+ {
+ ls.insert (ls.begin () + sys_lib_dirs_mode, usr_loc_lib);
+ ++sys_lib_dirs_extra;
+ }
// FreeBSD is at least consistent: it searches in neither. Quoting
// its wiki: "FreeBSD can't even find libraries that it installed."
// So let's help it a bit.
//
if (!uli && exists (usr_loc_inc, true /* ignore_error */))
- is.push_back (usr_loc_inc);
+ {
+ hs.insert (hs.begin () + sys_hdr_dirs_mode, usr_loc_inc);
+ ++sys_hdr_dirs_extra;
+ }
}
}
#endif
@@ -815,8 +860,11 @@ namespace build2
dr << "\n hdr dirs";
for (size_t i (0); i != incs.size (); ++i)
{
- if (i == sys_hdr_dirs_extra)
+ if ((sys_hdr_dirs_mode != 0 && i == sys_hdr_dirs_mode) ||
+ (sys_hdr_dirs_extra != 0 &&
+ i == sys_hdr_dirs_extra + sys_hdr_dirs_mode))
dr << "\n --";
+
dr << "\n " << incs[i];
}
}
@@ -826,8 +874,11 @@ namespace build2
dr << "\n lib dirs";
for (size_t i (0); i != libs.size (); ++i)
{
- if (i == sys_lib_dirs_extra)
+ if ((sys_lib_dirs_mode != 0 && i == sys_lib_dirs_mode) ||
+ (sys_lib_dirs_extra != 0 &&
+ i == sys_lib_dirs_extra + sys_lib_dirs_mode))
dr << "\n --";
+
dr << "\n " << libs[i];
}
}
@@ -948,40 +999,7 @@ namespace build2
// Register target types and configure their "installability".
//
- bool install_loaded (cast_false<bool> (rs["install.loaded"]));
-
- {
- using namespace install;
-
- rs.insert_target_type (x_src);
-
- auto insert_hdr = [&rs, install_loaded] (const target_type& tt)
- {
- rs.insert_target_type (tt);
-
- // Install headers into install.include.
- //
- if (install_loaded)
- install_path (rs, tt, dir_path ("include"));
- };
-
- // Note: module (x_mod) is in x_hdr.
- //
- for (const target_type* const* ht (x_hdr); *ht != nullptr; ++ht)
- insert_hdr (**ht);
-
- // Also register the C header for C-derived languages.
- //
- if (*x_hdr != &h::static_type)
- insert_hdr (h::static_type);
-
- rs.insert_target_type<pc> ();
- rs.insert_target_type<pca> ();
- rs.insert_target_type<pcs> ();
-
- if (install_loaded)
- install_path<pc> (rs, dir_path ("pkgconfig"));
- }
+ load_module (rs, rs, (string (x) += ".types"), loc);
// Register rules.
//
@@ -1079,8 +1097,11 @@ namespace build2
// them in case they depend on stuff that we need to install (see the
// install rule implementations for details).
//
- if (install_loaded)
+ if (cast_false<bool> (rs["install.loaded"]))
{
+ // Note: we rely quite heavily in these rule implementations that
+ // these are the only target types they are registered for.
+
const install_rule& ir (*this);
r.insert<exe> (perform_install_id, x_install, ir);