This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]