Thread overview
meson unittest
Jan 05
sfp
Jan 07
axricard
Jan 07
sfp
Jan 08
axricard
January 05

Anyone have a good way of yanking out all unittest { ... } blocks from a library compiled using Meson? It would be nice to approximate what dub does.

Meson has mentions this trick in its help docs (https://mesonbuild.com/D.html#using-embedded-unittests) but it isn't particularly useful. I have a library built from some source files, some of which contain unittest functions, and separate executables which link this library in. I might be using it the wrong way, but this trick did nothing useful for me...

January 07

On Sunday, 5 January 2025 at 23:52:24 UTC, sfp wrote:

>

Anyone have a good way of yanking out all unittest { ... } blocks from a library compiled using Meson? It would be nice to approximate what dub does.

Meson has mentions this trick in its help docs (https://mesonbuild.com/D.html#using-embedded-unittests) but it isn't particularly useful. I have a library built from some source files, some of which contain unittest functions, and separate executables which link this library in. I might be using it the wrong way, but this trick did nothing useful for me...

What do you mean by 'not particularly useful' ? Unittests are not being runned ?

I assume you have something like this in your lib/meson.build file :

mylib_test = executable('mylib_test', <mylib_srcs + fake_main>, d_unittest: true)
test('mylib', mylib_test)
January 07

On Tuesday, 7 January 2025 at 11:46:46 UTC, axricard wrote:

>

[...[

What do you mean by 'not particularly useful' ? Unittests are not being runned ?

[...]

I dug into this a bit more and figured out what the problem was.

File blah.d:

void f() {
  import std.stdio;
  writeln("hi");
}

unittest {
  writeln("bye");
}

File main.d:

import blah;

void main() {
  f();
}

File meson.build:

project('unittest', 'd')

mainlib = library('mainlib', ['blah.d'])

executable('maintest', ['main.d'], link_with: [mainlib], d_unittest: true)

Run:

$ meson setup builddir
$ cd builddir
$ meson compile
$ ./maintest

Outputs "hi" only.

Change meson.build to:

project('unittest', 'd')

mainlib = library('mainlib', ['blah.d'], d_unittest: true)

executable('maintest', ['main.d'], link_with: [mainlib])

Tests run, but maintest does not. You can add d_unittest: true to the executable invocation or not---doesn't make a difference.

Pretty unclear from the Meson docs what the expected behavior should be.

January 08

On Tuesday, 7 January 2025 at 17:55:50 UTC, sfp wrote:

>

File meson.build:

project('unittest', 'd')

mainlib = library('mainlib', ['blah.d'])

executable('maintest', ['main.d'], link_with: [mainlib], d_unittest: true)

Your first version is indeed wrong because the library is not compiled at all in unittest version. you can see this with -v option of meson compile :

# '-unittest' opt not present
╰─> meson compile -v
...
[2/5] ldc2 -I=libmainlib.so.p -I=. -I=.. -enable-color -wi -g -d-debug -relocation-model=pic -makedeps=libmainlib.so.p/blah.d.o.deps -of=libmainlib.so.p/blah.d.o -c ../blah.d
...

The second sample is pretty fine, unittests are actually activated for the library. The strange behavior comes from D runtime, not meson : the main is not being runned because by default if a unittest is present, the runtime won't run the main function.

see : https://dlang.org/phobos/core_runtime.html#.runModuleUnitTests

To have both unittests and main running, you'll have to set the --DRT-testmode option to "run-main". You can do it either when running the binary :

./testmain --DRT-testmode="run-main"

or in the source code :

╰─> cat main.d
extern(C) __gshared string[] rt_options = [ "testmode=run-main"];

import blah;

void main() {
  f();
}

You can even put it in your lib :

╰─> cat blah.d
extern(C) __gshared string[] rt_options = [ "testmode=run-main"];
...

Note: the default 'testmode' was "run-main" in previous runtime version (< 2.080 I believe), so you might get different behavior with old compilers

Note2: I'm not 100% sure what happens if rt_options is set in multiples files with a different value. Someone knows ?