This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, PR d/89255][1/3] Add -fbuilding-libphobos-tests
- From: Iain Buclaw <ibuclaw at gdcproject dot org>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 29 Mar 2019 18:46:16 +0100
- Subject: [PATCH, PR d/89255][1/3] Add -fbuilding-libphobos-tests
Hi,
Currently, the druntime and phobos unittests are compiled as a
separate check program, then ran by the
libphobos.unittest/unittest.exp script. As PR 89255 notes, this
process lacks proper multilib handling.
What I want to do instead is compile and run each module that contains
unittests as a standalone program using dg-runtest. Doing this
however requires linking to libphobos, where a second copy of the
module and all its symbols exist. This does not fair well at all with
shared libraries where the D runtime module registry will error and
abort because of two modules in different DSOs have the same name.
To handle this conflict, I've added a new internal option that
instructs the compiler to put the reference to all unittest functions
in another symbol.
Its use being along the lines of:
# make: Compile module to then add to libphobos.a and libphobos.so
gdc-c $PIC $MULTILIB $GDCFLAGS core/foo.d
# make check: Compile module as standalone program linking
# against libphobos, trusting that any symbol that appears in the
# library is overridden without a linking error.
gdc $MULTILIB -fmain -funittest -fbuilding-libphobos-tests core/foo.d
I checked this on x86_64-linux-gnu, and all links, runs, and passes
without problems.
Would there be any problems in doing this with other linkers/platforms?
--
Iain
---
gcc/d/ChangeLog:
2019-03-29 Iain Buclaw <ibuclaw@gdcproject.org>
* lang.opt (-fbuiding-libphobos-tests): Add option.
* modules.cc (build_module_tree): Generate second moduleinfo symbol to
hold reference to unittests if flag_building_libphobos_tests.
---
diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt
index 523f73c90de..f65be444d45 100644
--- a/gcc/d/lang.opt
+++ b/gcc/d/lang.opt
@@ -197,6 +197,10 @@ Enum(bounds_check) String(safeonly) Value(1)
EnumValue
Enum(bounds_check) String(on) Value(2)
+; Generates a secondary ModuleInfo symbol for linking in unittests
+fbuilding-libphobos-tests
+D Undocumented Var(flag_building_libphobos_tests)
+
fbuiltin
D Var(flag_no_builtin, 0)
; Documented in C
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index a1fc534c3b6..a863f525a27 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -718,6 +718,33 @@ build_module_tree (Module *decl)
}
}
+ /* For libphobos-internal use only. Generate a separate module info symbol
+ that references all compiled in unittests, this allows compiling library
+ modules and linking to libphobos without having run-time conflicts because
+ of two ModuleInfo records with the same name being present in two DSOs. */
+ if (flag_building_libphobos_tests && mi.unitTests)
+ {
+ /* Associate the module info symbol with a mock module. */
+ const char *name = concat (GDC_PREFIX ("modtest__"),
+ decl->ident->toChars (), NULL);
+ Module *tm = Module::create (decl->arg, Identifier::idPool (name), 0, 0);
+ Dsymbols members;
+
+ /* Setting parent puts module in the same package as the current, to
+ avoid any symbol conflicts. */
+ tm->parent = decl->parent;
+ tm->members = &members;
+ /* Register the current module as being imported by the mock module.
+ This informs run-time that there is a dependency between the two. */
+ tm->aimports.push (decl);
+
+ tm->stest = build_funcs_gates_fn (get_identifier ("*__modtest"),
+ mi.unitTests, NULL);
+ mi.unitTests = NULL;
+
+ layout_moduleinfo (tm);
+ }
+
/* Default behavior is to always generate module info because of templates.
Can be switched off for not compiling against runtime library. */
if (!global.params.betterC