From e6bb0d21f1865a389b82296823cf2ea555580a92 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 7 Jun 2019 09:43:21 +0200 Subject: Complete and normalize paths in cxx.importable_headers Also add more header unit include/import tests. --- build2/cc/module.cxx | 59 +++++++++------ tests/cc/modules/common.testscript | 8 ++- tests/cc/modules/headers.testscript | 139 +++++++++++++++++++++++++++++++++--- 3 files changed, 170 insertions(+), 36 deletions(-) diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 14d3ceb..e06ddb8 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -530,40 +530,55 @@ namespace build2 if (ih != nullptr && !ih->empty ()) { // Translate <>-style header names to absolute paths using the - // compiler's include search paths. + // compiler's include search paths. Otherwise complete and normalize + // since when searching in this list we always use the absolute and + // normalized header target path. // for (string& h: *ih) { - if (h.empty () || h.front () != '<' || h.back () != '>') + if (h.empty ()) continue; - h.pop_back (); - h.erase (0, 1); - - path f; // Reuse the buffer. - bool r (false); - for (const dir_path& d: sys_inc_dirs) + path f; + if (h.front () == '<' && h.back () == '>') { - if ((r = file_exists ((f = d, f /= h), - true /* follow_symlinks */, - true /* ignore_errors */))) + h.pop_back (); + h.erase (0, 1); + + for (const dir_path& d: sys_inc_dirs) { - h = move (f.normalize ()).string (); - break; + if (file_exists ((f = d, f /= h), + true /* follow_symlinks */, + true /* ignore_errors */)) + goto found; } - } - // What should we do if not found? While we can fail, this could - // be too drastic if, for example, the header is "optional" and - // may or may not be present/used. So for now let's restore the - // original form to aid debugging (it can't possibly match any - // absolute path). - // - if (!r) - { + // What should we do if not found? While we can fail, this could + // be too drastic if, for example, the header is "optional" and + // may or may not be present/used. So for now let's restore the + // original form to aid debugging (it can't possibly match any + // absolute path). + // h.insert (0, 1, '<'); h.push_back ('>'); + continue; + + found: + ; // Fall through. } + else + { + f = path (move (h)); + + if (f.relative ()) + f.complete (); + } + + // @@ MODHDR: should we use the more elaborate but robust + // normalize/realize scheme so the we get the same + // path? Feels right. + f.normalize (); + h = move (f).string (); } sort (ih->begin (), ih->end ()); diff --git a/tests/cc/modules/common.testscript b/tests/cc/modules/common.testscript index 4f043c9..b7501c1 100644 --- a/tests/cc/modules/common.testscript +++ b/tests/cc/modules/common.testscript @@ -12,12 +12,12 @@ using test EOI +cat <=build/root.build -cxx.std = experimental - -cxx.features.symexport = true +using in # Force modules. # +cxx.std = experimental +cxx.features.symexport = true cxx.features.modules = true using cxx @@ -32,6 +32,8 @@ hxx{*}: extension = hxx mxx{*}: extension = mxx cxx{*}: extension = cxx +cxx.poptions =+ "-I$out_root" "-I$src_root" + if ($cxx.target.class == 'windows') bmis{*}: cxx.poptions += '-DLIBFOO_EXPORT=__declspec(dllexport)' diff --git a/tests/cc/modules/headers.testscript b/tests/cc/modules/headers.testscript index d4eb919..439c919 100644 --- a/tests/cc/modules/headers.testscript +++ b/tests/cc/modules/headers.testscript @@ -19,25 +19,50 @@ inline int f () {return 1;} EOI -: import -: -ln -s ../core.hxx ./; -cat <=driver.cxx; ++cat <=base.mxx #define CORE_IN 1 - import "core.hxx"; + + #ifdef BASE_INCLUDE + // Cannot include (even if translated) in module purview. + // + module; + #include "core.hxx" + export module foo.base; + #else + export module foo.base; + #ifdef BASE_RE_EXPORT + export import "core.hxx"; + #else + import "core.hxx"; + #endif + #endif + #ifndef CORE_OUT # error macro export #endif - int main () {return f () - CORE_OUT;} + + export inline int g () {return f () - 1 /*CORE_OUT*/;} //@@ MODGCC EOI -$* test clean <=core.hxx.in + #ifdef CORE_IN + # error macro isolation + #endif + inline int f () {return 0;} EOI -: include-translation +: basics : ln -s ../core.hxx ./; -cat <=driver.cxx; +cat <=driver-imp.cxx; + #define CORE_IN 1 + import "core.hxx"; + #ifndef CORE_OUT + # error macro export + #endif + int main () {return f () - CORE_OUT;} + EOI +cat <=driver-inc.cxx; #define CORE_IN 1 #include "core.hxx" #ifndef CORE_OUT @@ -46,8 +71,100 @@ cat <=driver.cxx; int main () {return f () - CORE_OUT;} EOI $* test clean config.cxx.importable_headers="$~/core.hxx" <=driver.cxx + #define CORE_IN 1 + import foo.base; + #ifdef CORE_OUT + # error macro export + #endif + EOI + + : import + : + ln -s ../../core.hxx ../../base.mxx ./; + cat ../driver.cxx - <=driver.cxx; + int main () {return g ();} + EOI + $* test clean <=driver.cxx; + int main () {return g ();} + EOI + $* test clean config.cxx.poptions=-DBASE_INCLUDE \ + config.cxx.importable_headers="$~/core.hxx" <=driver.cxx; + int main () {return g () + (f () - 1);} + EOI + $* test clean config.cxx.poptions=-DBASE_RE_EXPORT <=driver-imp.cxx; + import ; + int main () {return f ();} + EOI +cat <=driver-inc.cxx; + #define CORE_IN 1 + #include + int main () {return f ();} + EOI +$* test clean config.cxx.importable_headers="$~/core.hxx" <=core.hxx; + #error poison + EOI +cat <=driver-imp.cxx; + import ; + int main () {return f ();} + EOI +cat <=driver-inc.cxx; + #define CORE_IN 1 + #include + int main () {return f ();} + EOI +# Remapping can only be tested with an out of source build. Note that we +# need a private out because of module sidebuilds. +# +out = ../../headers-remapped-out; +$* 'test:' ./@$out/remapped/ \ + config.cxx.importable_headers=$out/remapped/core.hxx <