# file : tests/cc/modules/testscript # copyright : Copyright (c) 2014-2017 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file crosstest = false test.arguments = config.cxx="$recall($cxx.path)" .include ../../common.test +cat <<EOI >+build/bootstrap.build using test EOI +cat <<EOI >=build/root.build cxx.std = experimental cxx.features.symexport = true # Force modules. # cxx.features.modules = true using cxx # We forced modules but for VC we need at least 15u3 (19.11). So "unforce" # them in this case. # if ($cxx.id == 'msvc' && $cxx.version.major == 19 && $cxx.version.minor < 11) cxx.features.modules = false hxx{*}: extension = hxx mxx{*}: extension = mxx cxx{*}: extension = cxx if ($cxx.target.class == 'windows') bmis{*}: cxx.poptions += '-DLIBFOO_EXPORT=__declspec(dllexport)' exe{*}: test = true EOI # Determine if we have module support. # +$* noop <<EOI | set modules print $cxx.features.modules EOI +$modules || exit # Common source files that are symlinked in the test directories if used. # +cat <<EOI >=core.mxx #ifndef LIBFOO_EXPORT # define LIBFOO_EXPORT #endif #if __cpp_modules >= 201704 export #endif module foo.core; export LIBFOO_EXPORT int f (int); EOI +cat <<EOI >=core.cxx module foo.core; int f (int i) {return i - 1;} EOI +cat <<EOI >=driver.cxx import foo.core; int main (int argc, char*[]) {return f (argc);} EOI : bmi-combined : : Test combined interface/implementation unit specified as bmi{}. : cp ../core.mxx ./ && cat >+core.mxx <<EOI; int f (int i) {return i - 1;} EOI ln -s ../driver.cxx ./; $* test clean <<EOI exe{test}: cxx{driver} bmi{core} bmi{core}: mxx{core} EOI : mxx-combined : : Test combined interface/implementation unit specified as mxx{}. : cp ../core.mxx ./ && cat >+core.mxx <<EOI; int f (int i) {return i - 1;} EOI ln -s ../driver.cxx ./; $* test clean <<EOI exe{test}: cxx{driver} mxx{core} EOI : bmi-separate : : Test separate interface/implementation unit specified as bmi{}. : ln -s ../core.mxx ../core.cxx ../driver.cxx ./; $* test clean <<EOI exe{test}: cxx{driver} {bmi cxx}{core} bmi{core}: mxx{core} EOI : mxx-separate : : Test separate interface/implementation unit specified as mxx{}. : ln -s ../core.mxx ../core.cxx ../driver.cxx ./; $* test clean <<EOI exe{test}: cxx{driver} {mxx cxx}{core} EOI : name-match : : Test fuzzy/explicit match between module name and file name. : { # "Bad" match which we should better. # +cat <<EOI >=core.mxx #if __cpp_modules >= 201704 export #endif module bar.core; EOI : separator : : Test separator equivalence. : ln -s ../../core.mxx foo-core.mxx; ln -s ../core.mxx ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{core foo-core}' : case : : Test case-insensitivity and case-change as a separator. : ln -s ../../core.mxx FooCore.mxx; ln -s ../core.mxx ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{core FooCore}' : dir : : Test subdirectory. : mkdir foo; ln -s ../../core.mxx foo/core.mxx; ln -s ../core.mxx ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{core} foo/mxx{core}' : explicit : : Explicit module name. : ln -s ../../core.mxx baz.mxx; ln -s ../core.mxx ../../core.cxx ../../driver.cxx ./; $* test clean <<EOO exe{test}: cxx{driver core} mxx{core baz} mxx{baz}@./: cc.module_name = foo.core EOO } : unresolved : ln -s ../driver.cxx ./; $* test &*.d <'exe{test}: cxx{driver}' 2>>EOE != 0 driver.cxx: error: unable to resolve module foo.core EOE : misguessed : ln -s ../core.mxx ./; cat <'import bar.core;' >=driver.cxx; $* test &*.d &*.ii <'exe{test}: cxx{driver} mxx{core}' 2>>EOE != 0 driver.cxx: error: failed to correctly guess module name from mxx{core} info: guessed: bar.core info: actual: foo.core info: consider adjusting module interface file names or info: consider specifying module name with cc.module_name EOE : library : : Test importing a module from a library. : ln -s ../core.mxx ../core.cxx ../driver.cxx ./; $* test clean <<EOI ./: lib{foo} exe{test} # Full build. exe{test}: cxx{driver} lib{foo} lib{foo}: {mxx cxx}{core} EOI : re-export : : Test module re-exporting (export import M;) : if ($cxx.id.type != "clang") { +cat <<EOI >=base.mxx #if __cpp_modules >= 201704 export #endif module foo.base; export import foo.core; EOI +cat <<EOI >=extra.mxx #ifndef LIBFOO_EXPORT # define LIBFOO_EXPORT #endif #if __cpp_modules >= 201704 export #endif module foo.extra; export { import foo.base; // VC appears to require dll-export of inline functions. // LIBFOO_EXPORT inline int g (int i) {return i != 0 ? i : -1;} } EOI +cat <<EOI >=foo.mxx #if __cpp_modules >= 201704 export #endif module foo; export { import foo.core; import foo.base; import foo.extra; } EOI : basic : ln -s ../base.mxx ../../core.mxx ../../core.cxx ./; cat <<EOI >=driver.cxx; import foo.base; int main (int argc, char*[]) {return f (argc);} EOI $* test clean <'exe{test}: cxx{driver core} mxx{core base}' : recursive : ln -s ../base.mxx ../extra.mxx ../../core.mxx ../../core.cxx ./; cat <<EOI >=driver.cxx; import foo.extra; int main (int argc, char*[]) {return f (g (argc));} EOI $* test clean <'exe{test}: cxx{driver core} mxx{core base extra}' : duplicate : ln -s ../base.mxx ../extra.mxx ../foo.mxx ../../core.mxx ../../core.cxx ./; cat <<EOI >=driver.cxx; import foo; int main (int argc, char*[]) {return f (g (argc));} EOI $* test clean <'exe{test}: cxx{driver core} mxx{core base extra foo}' : library : ln -s ../base.mxx ../extra.mxx ../foo.mxx ../../core.mxx ../../core.cxx ./; cat <<EOI >=driver.cxx; import foo; int main (int argc, char*[]) {return f (g (argc));} EOI $* test clean <<EOI exe{test}: cxx{driver} mxx{foo} lib{foo} lib{foo}: mxx{core base extra} cxx{core} EOI } : import : : Test module import. Currently, all the implementation require access to the : entire, recursively-explored list of BMIs. : { # Note: using VC export module fixup support. +cat <<EOI >=base.mxx export module foo.base; import foo.core; export int g (int i) {return f (i);} EOI +cat <<EOI >=extra.mxx export module foo.extra; import foo.base; export int h (int i) {return g (i);} EOI : basic : ln -s ../base.mxx ../../core.mxx ../../core.cxx ./; cat <<EOI >=driver.cxx; import foo.base; int main (int argc, char*[]) {return g (argc);} EOI $* test clean <'exe{test}: cxx{driver core} mxx{core base}' : recursive : ln -s ../base.mxx ../extra.mxx ../../core.mxx ../../core.cxx ./; cat <<EOI >=driver.cxx; import foo.extra; int main (int argc, char*[]) {return h (argc);} EOI $* test clean <'exe{test}: cxx{driver core} mxx{core base extra}' } : resolve-change : : Test detection of module name to BMI resolution change. : ln -s ../core.mxx ../core.cxx ../driver.cxx ./; cat <<EOI >=foo-core.mxx; #if __cpp_modules >= 201704 export #endif module foo.core; export inline int f (int i) {return i - 2;} EOI $* update <<EOI; ./: exe{test} bmie{foo-core} exe{test}: cxx{driver} {mxx cxx}{core} bmie{foo-core}: mxx{foo-core} EOI $* test --verbose 1 <<EOI 2>>EOE; exe{test}: cxx{driver} {mxx}{foo-core} exe{test}: test.arguments = two EOI c++ cxx{driver} ld exe{test} test exe{test} EOE $* test clean <<EOI ./: exe{test} bmie{foo-core} exe{test}: cxx{driver} {mxx cxx}{core} bmie{foo-core}: mxx{foo-core} EOI : symexport : : Test the __symexport feature. : cat <<EOI >=core.mxx; #if __cpp_modules >= 201704 export #endif module foo.core; export __symexport int f (int); __symexport int g_impl (int i) {return i - 1;} export __symexport inline int g (int i) {return g_impl (i);} EOI ln -s ../core.cxx core-f.cxx; cat <<EOI >=core-g.cxx; module foo.core; int g_impl (int i) {return i - 1;} EOI cat <<EOI >=driver.cxx; import foo.core; int main (int argc, char*[]) {return f (argc) + g (argc);} EOI $* test clean <<EOI ./: lib{foo} exe{test} # Full build. exe{test}: cxx{driver} lib{foo} lib{foo}: mxx{core} cxx{core-f} # core-g @@ VC EOI : export-fixup : : Test removing the export keyword for VC compatibility. : ln -s ../core.cxx ../driver.cxx ./; cat <<EOI >=core.mxx; export module foo.core; export int f (int); EOI $* test <'exe{test}: cxx{driver core} mxx{core}'; touch core.mxx; # Test use of cached .ii's. $* test clean <'exe{test}: cxx{driver core} mxx{core}'