aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-06-12 08:33:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-06-12 08:33:28 +0200
commitce177a4b12f2fef490683e53ccc9ee8f4d3e0bd6 (patch)
tree34aae6ca8abb182fdf20a59b6ab3a08ef1e1db55
parentb01fde82ba1e70af68ac78607daf421334f60cc7 (diff)
Add workaround for Clang module import during preprocessing
-rw-r--r--build2/algorithm.cxx12
-rw-r--r--build2/cc/compile.cxx39
-rw-r--r--build2/cc/parser.cxx2
-rw-r--r--build2/cxx/init.cxx6
-rw-r--r--build2/utility.cxx26
-rw-r--r--build2/utility.hxx9
-rw-r--r--build2/utility.ixx29
7 files changed, 79 insertions, 44 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 0dca9cc..658a6cd 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -126,12 +126,12 @@ namespace build2
// Wait for the count to drop below busy if someone is already working
// on this target.
//
- // We also unlock the phase for the duration of the wait. Why? Consider
- // this scenario: we are trying to match a dir{} target whose buildfile
- // still needs to be loaded. Let's say someone else started the match
- // before us. So we wait for their completion and they wait to switch
- // the phase to load. Which would result in a deadlock unless we release
- // the phase.
+ // We also unlock the phase for the duration of the wait. Why?
+ // Consider this scenario: we are trying to match a dir{} target whose
+ // buildfile still needs to be loaded. Let's say someone else started
+ // the match before us. So we wait for their completion and they wait
+ // to switch the phase to load. Which would result in a deadlock
+ // unless we release the phase.
//
if (e >= busy)
{
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index d0fd153..31986ed 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -1286,9 +1286,18 @@ namespace build2
// Some compile options (e.g., -std, -m) affect the preprocessor.
//
+ // Currently Clang supports importing "header modules" even when in
+ // the TS mode. And "header modules" support macros which means
+ // imports have to be resolved during preprocessing. Which poses a
+ // bit of a chicken and egg problem for us. For now, the workaround
+ // is to remove the -fmodules-ts option when preprocessing. Hopefully
+ // there will be a "pure modules" mode at some point.
+ //
append_options (args, t, c_coptions);
append_options (args, t, x_coptions);
- append_options (args, tstd);
+ append_options (args, tstd,
+ tstd.size () -
+ (modules && cid == compiler_id::clang ? 1 : 0));
if (cid == compiler_id::msvc)
{
@@ -2144,34 +2153,27 @@ namespace build2
args.push_back (cpath.recall_string ());
- // Add *.export.poptions from prerequisite libraries.
- //
append_lib_options (bs, args, t, act, lo);
append_options (args, t, c_poptions);
append_options (args, t, x_poptions);
- // Extra system header dirs (last).
- //
for (const dir_path& d: sys_inc_dirs)
{
args.push_back ("-I");
args.push_back (d.string ().c_str ());
}
- // Some compile options (e.g., -std, -m) affect the preprocessor.
- //
append_options (args, t, c_coptions);
append_options (args, t, x_coptions);
- append_options (args, tstd);
+ append_options (args, tstd,
+ tstd.size () -
+ (modules && cid == compiler_id::clang ? 1 : 0));
if (cid == compiler_id::msvc)
{
args.push_back ("/nologo");
- // See perform_update() for details on overriding the default
- // exceptions and runtime.
- //
if (x_lang == lang::cxx && !find_option_prefix ("/EH", args))
args.push_back ("/EHsc");
@@ -2186,8 +2188,6 @@ namespace build2
{
if (t.is_a<objs> ())
{
- // On Darwin, Win32 -fPIC is the default.
- //
if (tclass == "linux" || tclass == "bsd")
args.push_back ("-fPIC");
}
@@ -2337,15 +2337,18 @@ namespace build2
if (!modules)
fail << "modules support not enabled or unavailable";
- // Set the cc.module_name variable if this is an interface unit. We set
- // it on the bmi{} group so we have to lock it.
+ // Set the cc.module_name variable if this is an interface unit. If we
+ // have the bmi{} group, set it there (in which case we have to lock).
//
if (tu.module_interface)
{
- target_lock l (lock (act, *t.group));
- assert (l.target != nullptr);
+ target_lock l;
+ target* x (t.group == nullptr
+ ? &t
+ : (l = lock (act, *t.group)).target);
+ assert (x != nullptr); // Should be lockable.
- if (value& v = l.target->vars.assign (c_module_name))
+ if (value& v = x->vars.assign (c_module_name))
assert (cast<string> (v) == tu.module_name);
else
v = move (tu.module_name); // Note: move.
diff --git a/build2/cc/parser.cxx b/build2/cc/parser.cxx
index 24de7ba..c3c1324 100644
--- a/build2/cc/parser.cxx
+++ b/build2/cc/parser.cxx
@@ -21,7 +21,7 @@ namespace build2
lexer l (is, name);
l_ = &l;
- translation_unit u;
+ translation_unit u {"", false, {}};
u_ = &u;
// If the source has errors then we want the compiler to issues the
diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx
index 32ba8b6..8c4249c 100644
--- a/build2/cxx/init.cxx
+++ b/build2/cxx/init.cxx
@@ -142,8 +142,8 @@ namespace build2
//
if (mj > 19 || (mj == 19 && mi >= 11))
{
- r.push_back ("/experimental:module");
r.push_back ("/D__cpp_modules=201703"); // n4647
+ r.push_back ("/experimental:module");
modules = true;
}
break;
@@ -168,10 +168,12 @@ namespace build2
// Note that we are using Apple to vanilla Clang version re-
// map from above so may need to update things there as well.
//
+ // Note: see Clang modules support hack in cc::compile.
+ //
if (mj >= 5)
{
- r.push_back ("-fmodules-ts");
r.push_back ("-D__cpp_modules=201704"); // p0629r0
+ r.push_back ("-fmodules-ts");
modules = true;
}
break;
diff --git a/build2/utility.cxx b/build2/utility.cxx
index 09a2342..2b3f785 100644
--- a/build2/utility.cxx
+++ b/build2/utility.cxx
@@ -277,34 +277,34 @@ namespace build2
}
void
- append_options (cstrings& args, const strings& sv)
+ append_options (cstrings& args, const strings& sv, size_t n)
{
- if (!sv.empty ())
+ if (n != 0)
{
- args.reserve (args.size () + sv.size ());
+ args.reserve (args.size () + n);
- for (const string& s: sv)
- args.push_back (s.c_str ());
+ for (size_t i (0); i != n; ++i)
+ args.push_back (sv[i].c_str ());
}
}
void
- append_options (strings& args, const strings& sv)
+ append_options (strings& args, const strings& sv, size_t n)
{
- if (!sv.empty ())
+ if (n != 0)
{
- args.reserve (args.size () + sv.size ());
+ args.reserve (args.size () + n);
- for (const string& s: sv)
- args.push_back (s);
+ for (size_t i (0); i != n; ++i)
+ args.push_back (sv[i]);
}
}
void
- hash_options (sha256& csum, const strings& sv)
+ hash_options (sha256& csum, const strings& sv, size_t n)
{
- for (const string& s: sv)
- csum.append (s);
+ for (size_t i (0); i != n; ++i)
+ csum.append (sv[i]);
}
bool
diff --git a/build2/utility.hxx b/build2/utility.hxx
index 5f5aa1d..4ce3407 100644
--- a/build2/utility.hxx
+++ b/build2/utility.hxx
@@ -319,6 +319,15 @@ namespace build2
void
hash_options (sha256&, const strings&);
+ void
+ append_options (cstrings&, const strings&, size_t);
+
+ void
+ append_options (strings&, const strings&, size_t);
+
+ void
+ hash_options (sha256&, const strings&, size_t);
+
// Check if a specified option is present in the variable or value. T is
// either target or scope.
//
diff --git a/build2/utility.ixx b/build2/utility.ixx
index 27db90f..7a706f8 100644
--- a/build2/utility.ixx
+++ b/build2/utility.ixx
@@ -49,6 +49,13 @@ namespace build2
template <typename T>
inline void
+ hash_options (sha256& csum, T& s, const variable& var)
+ {
+ hash_options (csum, s[var]);
+ }
+
+ template <typename T>
+ inline void
append_options (cstrings& args, T& s, const char* var)
{
append_options (args, s[var]);
@@ -63,16 +70,30 @@ namespace build2
template <typename T>
inline void
- hash_options (sha256& csum, T& s, const variable& var)
+ hash_options (sha256& csum, T& s, const char* var)
{
hash_options (csum, s[var]);
}
- template <typename T>
inline void
- hash_options (sha256& csum, T& s, const char* var)
+ append_options (cstrings& args, const strings& sv)
{
- hash_options (csum, s[var]);
+ if (size_t n = sv.size ())
+ append_options (args, sv, n);
+ }
+
+ inline void
+ append_options (strings& args, const strings& sv)
+ {
+ if (size_t n = sv.size ())
+ append_options (args, sv, n);
+ }
+
+ inline void
+ hash_options (sha256& csum, const strings& sv)
+ {
+ if (size_t n = sv.size ())
+ hash_options (csum, sv, n);
}
template <typename T>