aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-06-07 09:43:21 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-06-07 09:43:21 +0200
commite6bb0d21f1865a389b82296823cf2ea555580a92 (patch)
tree15db9398743d83fb4f7e5dd1fa772c5c8a647334
parentdaa35c9e4b592f055b42e482fe1398527cfdf90b (diff)
Complete and normalize paths in cxx.importable_headers
Also add more header unit include/import tests.
-rw-r--r--build2/cc/module.cxx59
-rw-r--r--tests/cc/modules/common.testscript8
-rw-r--r--tests/cc/modules/headers.testscript139
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 <<EOI >=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 <<EOI >=driver.cxx;
++cat <<EOI >=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 <<EOI
- exe{test}: cxx{driver}
+
++cat <<EOI >=core.hxx.in
+ #ifdef CORE_IN
+ # error macro isolation
+ #endif
+ inline int f () {return 0;}
EOI
-: include-translation
+: basics
:
ln -s ../core.hxx ./;
-cat <<EOI >=driver.cxx;
+cat <<EOI >=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 <<EOI >=driver-inc.cxx;
#define CORE_IN 1
#include "core.hxx"
#ifndef CORE_OUT
@@ -46,8 +71,100 @@ cat <<EOI >=driver.cxx;
int main () {return f () - CORE_OUT;}
EOI
$* test clean config.cxx.importable_headers="$~/core.hxx" <<EOI
- exe{test}: cxx{driver}
+ ./: exe{test-imp}: cxx{driver-imp} hxx{core}
+ ./: exe{test-inc}: cxx{driver-inc} hxx{core}
+ EOI
+
+: module
+:
+{
+ +cat <<EOI >=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 - <<EOI >=driver.cxx;
+ int main () {return g ();}
+ EOI
+ $* test clean <<EOI
+ exe{test}: cxx{driver} hxx{core} mxx{base}
+ EOI
+
+ #\
+ #@@ MODGCC
+ : include
+ :
+ ln -s ../../core.hxx ../../base.mxx ./;
+ cat ../driver.cxx - <<EOI >=driver.cxx;
+ int main () {return g ();}
+ EOI
+ $* test clean config.cxx.poptions=-DBASE_INCLUDE \
+ config.cxx.importable_headers="$~/core.hxx" <<EOI
+ exe{test}: cxx{driver} hxx{core} mxx{base}
+ EOI
+ #\
+
+ : re-export
+ :
+ ln -s ../../core.hxx ../../base.mxx ./;
+ cat ../driver.cxx - <<EOI >=driver.cxx;
+ int main () {return g () + (f () - 1);}
+ EOI
+ $* test clean config.cxx.poptions=-DBASE_RE_EXPORT <<EOI
+ exe{test}: cxx{driver} hxx{core} mxx{base}
+ EOI
+}
+
+: generated
+:
+ln -s ../core.hxx.in ./;
+cat <<EOI >=driver-imp.cxx;
+ import <generated/core.hxx>;
+ int main () {return f ();}
+ EOI
+cat <<EOI >=driver-inc.cxx;
+ #define CORE_IN 1
+ #include <generated/core.hxx>
+ int main () {return f ();}
+ EOI
+$* test clean config.cxx.importable_headers="$~/core.hxx" <<EOI
+ ./: exe{test-imp}: cxx{driver-imp} hxx{core}
+ ./: exe{test-inc}: cxx{driver-inc} hxx{core}
+ hxx{core}: in{core}
+ EOI
+
+: remapped
+:
+ln -s ../core.hxx.in ./;
+cat <<EOI >=core.hxx;
+ #error poison
+ EOI
+cat <<EOI >=driver-imp.cxx;
+ import <remapped/core.hxx>;
+ int main () {return f ();}
+ EOI
+cat <<EOI >=driver-inc.cxx;
+ #define CORE_IN 1
+ #include <remapped/core.hxx>
+ 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 <<EOI;
+ ./: exe{test-imp}: cxx{driver-imp} hxx{core}
+ ./: exe{test-inc}: cxx{driver-inc} hxx{core}
+ hxx{core}: in{core}
EOI
+rm -r -f $out
# Clean module sidebuilds.
#