From 8e904346350cff0453c8bcd524a40a631fc05485 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 9 Jan 2019 13:09:18 +0200 Subject: Tighten cc rules matching Specifically, make sure the rule does not match if there is a c-common prerequisites that it doesn't recognize. --- build2/cc/common.hxx | 2 +- build2/cc/link-rule.cxx | 20 +++++++++++++------- build2/cc/target.cxx | 2 +- build2/cc/target.hxx | 12 ++++++------ build2/cxx/target.cxx | 8 ++++---- build2/cxx/target.hxx | 18 +++++++++--------- 6 files changed, 34 insertions(+), 28 deletions(-) diff --git a/build2/cc/common.hxx b/build2/cc/common.hxx index dccf62e..e1b04d7 100644 --- a/build2/cc/common.hxx +++ b/build2/cc/common.hxx @@ -148,7 +148,7 @@ namespace build2 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 "header header" first and + // most likely to appear order with the "real header" first and // terminated with NULL. // const target_type* const* x_hdr; diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx index c24655a..b7ecd85 100644 --- a/build2/cc/link-rule.cxx +++ b/build2/cc/link-rule.cxx @@ -71,7 +71,8 @@ namespace build2 } // Scan prerequisites and see if we can work with what we've got. Note - // that X could be C. We handle this by always checking for X first. + // that X could be C (as in language). We handle this by always checking + // for X first. // // Note also that we treat bmi{} as obj{}. // @@ -84,9 +85,9 @@ namespace build2 if (include (a, t, p) != include_type::normal) continue; - if (p.is_a (x_src) || - (lt.library () && p.is_a (*x_hdr[0])) || // Header-only library. - (x_mod != nullptr && p.is_a (*x_mod))) + if (p.is_a (x_src) || + (x_mod != nullptr && p.is_a (*x_mod)) || + (lt.library () && x_header (p))) // Header-only library. { seen_x = seen_x || true; } @@ -127,11 +128,16 @@ namespace build2 { seen_lib = seen_lib || true; } - // If this is some other c-common source (say C++ in a C rule), then - // it will most definitely need to be compiled but we can't do that. + // If this is some other c-common header/source (say C++ in a C rule), + // 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 ()) + else if (p.is_a () && !p.is_a ()) + { + l4 ([&]{trace << "non-" << x_lang << " prerequisite " << p + << " for target " << t;}); return false; + } } if (!(seen_x || seen_c || seen_obj || seen_lib)) diff --git a/build2/cc/target.cxx b/build2/cc/target.cxx index 7039728..981f4d7 100644 --- a/build2/cc/target.cxx +++ b/build2/cc/target.cxx @@ -30,7 +30,7 @@ namespace build2 const target_type h::static_type { "h", - &file::static_type, + &cc::static_type, &target_factory, nullptr, /* fixed_extension */ &target_extension_var, diff --git a/build2/cc/target.hxx b/build2/cc/target.hxx index 4fb38cb..395c233 100644 --- a/build2/cc/target.hxx +++ b/build2/cc/target.hxx @@ -14,10 +14,10 @@ namespace build2 { namespace cc { - // This is an abstract base target for all c-common source files. We use - // this arrangement in rule matching to detect "unknown" (to this rule) - // source files that it cannot handle but should not ignore either. For - // example, a C link rule that sees a C++ source file. + // This is an abstract base target for all c-common header/source files. + // We use this arrangement during rule matching to detect "unknown" (to + // this rule) source/header files that it cannot handle but should not + // ignore either. For example, a C link rule that sees a C++ source file. // class cc: public file { @@ -32,10 +32,10 @@ namespace build2 // There is hardly a c-family compilation without a C header inclusion. // As a result, this target type is registered for any c-family module. // - class h: public file + class h: public cc { public: - using file::file; + using cc::cc; public: static const target_type static_type; diff --git a/build2/cxx/target.cxx b/build2/cxx/target.cxx index 3431bc4..bdfa609 100644 --- a/build2/cxx/target.cxx +++ b/build2/cxx/target.cxx @@ -16,7 +16,7 @@ namespace build2 const target_type hxx::static_type { "hxx", - &file::static_type, + &cc::static_type, &target_factory, nullptr, /* fixed_extension */ &target_extension_var, @@ -30,7 +30,7 @@ namespace build2 const target_type ixx::static_type { "ixx", - &file::static_type, + &cc::static_type, &target_factory, nullptr, /* fixed_extension */ &target_extension_var, @@ -44,7 +44,7 @@ namespace build2 const target_type txx::static_type { "txx", - &file::static_type, + &cc::static_type, &target_factory, nullptr, /* fixed_extension */ &target_extension_var, @@ -72,7 +72,7 @@ namespace build2 const target_type mxx::static_type { "mxx", - &file::static_type, + &cc::static_type, &target_factory, nullptr, /* fixed_extension */ &target_extension_var, diff --git a/build2/cxx/target.hxx b/build2/cxx/target.hxx index e31d311..94295d1 100644 --- a/build2/cxx/target.hxx +++ b/build2/cxx/target.hxx @@ -18,30 +18,30 @@ namespace build2 using cc::h; using cc::c; - class hxx: public file + class hxx: public cc::cc { public: - using file::file; + using cc::cc; public: static const target_type static_type; virtual const target_type& dynamic_type () const {return static_type;} }; - class ixx: public file + class ixx: public cc::cc { public: - using file::file; + using cc::cc; public: static const target_type static_type; virtual const target_type& dynamic_type () const {return static_type;} }; - class txx: public file + class txx: public cc::cc { public: - using file::file; + using cc::cc; public: static const target_type static_type; @@ -61,12 +61,12 @@ namespace build2 // The module interface unit is both like a header (e.g., we need to // install it) and like a source (we need to compile it). Plus, to // support dual use (modules/headers) it could actually be #include'd - // (and even in both cases). + // (and even in both cases e.g., by different codebases). // - class mxx: public file + class mxx: public cc::cc { public: - using file::file; + using cc::cc; public: static const target_type static_type; -- cgit v1.1