# file : tests/cc/modules/modules.testscript # license : MIT; see accompanying LICENSE file # Test modules proper. # .include common.testscript +$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 export 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 export module bar.core; EOI +cat <<EOI >=ext-core.mxx export module foo.ext_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}@./: cxx.module_name = foo.core EOO : secondary-entire : : Secondary score: core.mxx vs ext-core.mxx (entire file name consumed). : ln -s ../ext-core.mxx ../../core.mxx ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{ext-core core}' : secondary-dir-separator : : Secondary score: sub/core.mxx vs ext-core.mxx (stronger separator). : mkdir sub; ln -s ../../../core.mxx ../../../core.cxx sub/; ln -s ../ext-core.mxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver} mxx{ext-core} sub/{mxx cxx}{core}' : secondary-real-separator : : Secondary score: sub-core.mxx vs extcore.mxx (real separator). : ln -s ../ext-core.mxx extcore.mxx; ln -s ../../core.mxx sub-core.mxx; ln -s ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{extcore sub-core}' : secondary-case-separator : : Secondary score: SubCore.mxx vs extcore.mxx (case separator). : ln -s ../ext-core.mxx extcore.mxx; ln -s ../../core.mxx SubCore.mxx; ln -s ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{extcore SubCore}' : secondary-unmatched : : Secondary score: gtk-core.mxx vs gtk-ext-core.mxx (unmatched-length). : ln -s ../ext-core.mxx gtk-ext-core.mxx; ln -s ../../core.mxx gtk-core.mxx; ln -s ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{gtk-ext-core gtk-core}' } : unresolved : ln -s ../driver.cxx ./; $* test &*.d <'exe{test}: cxx{driver}' 2>>EOE != 0 driver.cxx: error: unable to resolve module foo.core info: verify module interface is listed as a prerequisite, otherwise info: consider adjusting module interface file names or info: consider specifying module name with cxx.module_name 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 cxx.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 : module-marker : : Test global module fragment/leading module marker (module;). : if ($cxx.id != 'msvc') # Disabled for MSVC due to issue 845845. { cat <<EOI >=g.hxx; void g (); EOI cat <<EOI >=core.mxx; #if __cpp_modules >= 201810 module; #endif #include "g.hxx" EOI cat <<<../core.mxx >+core.mxx; ln -s ../core.cxx ../driver.cxx ./; $* test clean <<EOI exe{test}: cxx{driver} {mxx cxx}{core} EOI } : re-export : : Test module re-exporting (export import M;) : { +cat <<EOI >=base.mxx export module foo.base; export import foo.core; EOI +cat <<EOI >=extra.mxx #ifndef LIBFOO_EXPORT # define LIBFOO_EXPORT #endif export module foo.extra; export import foo.base; // Note: cannot be combined with the below. export { // 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 export module foo; export import foo.core; export import foo.base; export 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. : { +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; export 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} -> obje{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; export 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} # @@ VC: core-g EOI