From daa35c9e4b592f055b42e482fe1398527cfdf90b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 6 Jun 2019 18:00:10 +0200 Subject: Fix cc link rule matching ambiguity wrt to C/C++ sources Considering a C header as C++ source was definitely a bad idea. --- build2/cc/common.hxx | 13 +++++++------ build2/cc/link-rule.cxx | 8 +++++--- build2/cc/module.cxx | 28 ++++++++++++++++++---------- build2/cxx/init.cxx | 1 - 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/build2/cc/common.hxx b/build2/cc/common.hxx index 19733cf..3f0f9fb 100644 --- a/build2/cc/common.hxx +++ b/build2/cc/common.hxx @@ -13,7 +13,8 @@ #include #include -#include // compiler_id +#include // compiler_id +#include // h{} namespace build2 { @@ -151,21 +152,21 @@ namespace build2 const target_type& x_src; // Source target type (c{}, cxx{}). const target_type* x_mod; // Module target type (mxx{}), if any. - // Array of target types that are considered headers. Keep them in the - // most likely to appear order with the "real header" first and - // terminated with NULL. + // Array of target types that are considered the X-language headers + // (excluding h{} except for C). Keep them in the most likely to appear + // order with the "real header" first and terminated with NULL. // const target_type* const* x_hdr; template bool - x_header (const T& t) const + x_header (const T& t, bool c_hdr = true) const { for (const target_type* const* ht (x_hdr); *ht != nullptr; ++ht) if (t.is_a (**ht)) return true; - return false; + return c_hdr && t.is_a (h::static_type); } // Array of target types that can be #include'd. Used to reverse-lookup diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx index 372d077..3b58ab7 100644 --- a/build2/cc/link-rule.cxx +++ b/build2/cc/link-rule.cxx @@ -87,12 +87,14 @@ namespace build2 if (p.is_a (x_src) || (x_mod != nullptr && p.is_a (*x_mod)) || - (lt.library () && x_header (p))) // Header-only library. + // Header-only X library (or library with C source and X header). + (lt.library () && x_header (p, false /* c_hdr */))) { seen_x = seen_x || true; } else if (p.is_a () || - (lt.library () && p.is_a ())) // Header-only library. + // Header-only C library. + (lt.library () && p.is_a ())) { seen_c = seen_c || true; } @@ -132,7 +134,7 @@ namespace build2 // then we shouldn't try to handle that (it may need to be compiled, // etc). But we assume everyone can handle a C header. // - else if (p.is_a () && !(x_header (p) || p.is_a ())) + else if (p.is_a () && !(x_header (p, true /* c_hdr */))) { l4 ([&]{trace << "non-" << x_lang << " prerequisite " << p << " for target " << t;}); diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 7527da2..14d3ceb 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -578,24 +578,32 @@ namespace build2 { using namespace install; - auto& t (rs.target_types); + auto& tts (rs.target_types); - t.insert (x_src); + tts.insert (x_src); - // Note: module (x_mod) is in x_hdr. - - for (const target_type* const* ht (x_hdr); *ht != nullptr; ++ht) + auto insert_hdr = [&rs, &tts, install_loaded] (const target_type& tt) { - t.insert (**ht); + tts.insert (tt); // Install headers into install.include. // if (install_loaded) - install_path (rs, **ht, dir_path ("include")); - } + 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); - t.insert (); - t.insert (); + tts.insert (); + tts.insert (); if (install_loaded) install_path (rs, dir_path ("pkgconfig")); diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx index ff104d3..92d5da8 100644 --- a/build2/cxx/init.cxx +++ b/build2/cxx/init.cxx @@ -526,7 +526,6 @@ namespace build2 static const target_type* const hdr[] = { &hxx::static_type, - &h::static_type, &ixx::static_type, &txx::static_type, &mxx::static_type, -- cgit v1.1