From ce177a4b12f2fef490683e53ccc9ee8f4d3e0bd6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 12 Jun 2017 08:33:28 +0200 Subject: Add workaround for Clang module import during preprocessing --- build2/algorithm.cxx | 12 ++++++------ build2/cc/compile.cxx | 39 +++++++++++++++++++++------------------ build2/cc/parser.cxx | 2 +- build2/cxx/init.cxx | 6 ++++-- build2/utility.cxx | 26 +++++++++++++------------- build2/utility.hxx | 9 +++++++++ build2/utility.ixx | 29 +++++++++++++++++++++++++---- 7 files changed, 79 insertions(+), 44 deletions(-) (limited to 'build2') 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 ()) { - // 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 (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 inline void + hash_options (sha256& csum, T& s, const variable& var) + { + hash_options (csum, s[var]); + } + + template + inline void append_options (cstrings& args, T& s, const char* var) { append_options (args, s[var]); @@ -63,16 +70,30 @@ namespace build2 template 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 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 -- cgit v1.1