www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Allow `-version=unittest` flag

reply Ilya <ilya.yanok gmail.com> writes:
Currently D compilers don't allow passing `-version=unittest` 
flag explicitly, requiring to pass `-unittest` instead. But 
`-unittest` has a additional meaning: it will compile UTs as well!

So, if I have two modules `A.d` and `B.d`, both define some UTs, 
`B` imports `A` **and** `A` has some `version(unittest)` blocks 
in non-templated code, there is no way to build **just** UTs from 
`B`.

I can build `B` using `dmd -c -unittest B.d`, but there is no way 
to build `A` correctly:
- if I build it without `-unittest`, conditional compilation for 
`version(unittest)` blocks won't trigger;
- and if I build it with `-unittest`, I get also UTs from `A`.

It's a simplified example, instead of two modules in reality it's 
a dependency chain of groups of modules, where each group is 
compiled in one step, but we still want to get separate UTs for 
every group, instead of getting everything in the root group.

I get it, in D world people are usually compiling everything in 
one shot, so that's not a problem. But unfortunately this 
approach doesn't scale very well.

How bad it will be to stop failing on `-version=unittest`? Seems 
like compiling UTs dependencies is a valid use case for it.
Apr 08
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Tuesday, 8 April 2025 at 13:26:42 UTC, Ilya wrote:
 How bad it will be to stop failing on `-version=unittest`? 
 Seems like compiling UTs dependencies is a valid use case for 
 it.
What you want is to be able to select the code to include using a version statement, and also select it when you compile with unittests: ```d version(testing) void utThing() { ... } version(unittest) version = testing; // also enable for unittests ``` Now, you can build with unittests or with `-version=testing`, and the function is included. -Steve
Apr 10
parent reply Ilya <ilya.yanok gmail.com> writes:
On Thursday, 10 April 2025 at 19:13:18 UTC, Steven Schveighoffer 
wrote:
 On Tuesday, 8 April 2025 at 13:26:42 UTC, Ilya wrote:
 How bad it will be to stop failing on `-version=unittest`? 
 Seems like compiling UTs dependencies is a valid use case for 
 it.
What you want is to be able to select the code to include using a version statement, and also select it when you compile with unittests: ```d version(testing) void utThing() { ... } version(unittest) version = testing; // also enable for unittests ``` Now, you can build with unittests or with `-version=testing`, and the function is included.
Thanks, what works indeed, I think we even use this pattern in some of our code. But it also feels like a workaround. So, I think my question still stands, why `version(unittest)` has to be special? Why can't we simply allow users set it without `-unittest`?
Apr 12
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Saturday, 12 April 2025 at 10:46:37 UTC, Ilya wrote:
 Thanks, what works indeed, I think we even use this pattern in 
 some of our code. But it also feels like a workaround. So, I 
 think my question still stands, why `version(unittest)` has to 
 be special? Why can't we simply allow users set it without 
 `-unittest`?
The `version(unittest)` means "the compiler was invoked with the `-unittest` flag". It shouldn't mean anything else. If you want to include more code in a related feature (such as custom-defined test functions), use a different version, and apply a version statement like I mentioned. Allowing specifying predefined versions on the command line loses the authority of the version statement. Should I be able to switch to `BigEndian` mode whenever I want? -Steve
Apr 13
parent reply Ilya <ilya.yanok gmail.com> writes:
On Monday, 14 April 2025 at 03:31:15 UTC, Steven Schveighoffer 
wrote:
 The `version(unittest)` means "the compiler was invoked with 
 the `-unittest` flag". It shouldn't mean anything else.
Ok, that's a fair point. If someone _actually_ needs to know if the compiler was invoked with `-unittest`, than yes, we definitely shouldn't allow setting it explicitly. But how useful is that? I was assuming `version(unittest)` means "I'm building unit tests" and then it's seems natural to extend it to "I'm building unit tests or UTs' dependencies".
 If you want to include more code in a related feature (such as 
 custom-defined test functions), use a different version, and 
 apply a version statement like I mentioned.
Yes, the trick with another version works. And in the long run we should get rid of `version(unittest)` altogether, I think.
 Allowing specifying predefined versions on the command line 
 loses the authority of the version statement. Should I be able 
 to switch to `BigEndian` mode whenever I want?
Ok, I see your point, even though I don't think it's a fair analogy. I can try to re-state my point. I think the `-unittest` flag should actually be ternary, not binary: apart from no-UT and UT options, there should also be a dep-UT option, that allows building dependencies of UTs with `version(unittest)`, but without building the UTs of dependencies. Otherwise people have to use the "custom-UT version" trick to build UTs with separate compilation. So I suggested to allow explicit `-d-version=unittest` as an easy way to enable that third option. But anyway, if people have strong opinions here, I'm not going to insist.
Apr 14
parent kinke <noone nowhere.com> writes:
On Monday, 14 April 2025 at 09:03:20 UTC, Ilya wrote:
 I can try to re-state my point. I think the `-unittest` flag 
 should actually be ternary, not binary: apart from no-UT and UT 
 options, there should also be a dep-UT option, that allows 
 building dependencies of UTs with `version(unittest)`, but 
 without building the UTs of dependencies. Otherwise people have 
 to use the "custom-UT version" trick to build UTs with separate 
 compilation.
You haven't really stated what the problem with compiling those 'UT deps' with `-unittest` (instead of just your proposed `-version=unittest`) is: - Just that those unittests are run by default too? The test runner can be customized, to only run the unittests of a subset of the linked modules. The druntime/Phobos unittest runners do just that, optionally allowing to specify the modules to be tested as cmdline options: https://github.com/dlang/dmd/blob/master/druntime/src/test_runner.d - The compilation overhead for those unittest functions? I'd say it's better to recompile a dirty module *once* in `-unittest` mode and using it for its own unittest runner, as well as those other unittest runners which require the module to be compiled with `-version=unittest` - instead of having to compile twice, once with `-unittest` and once with `-version=unittest` alone.
 I get it, in D world people are usually compiling everything in 
 one shot, so that's not a problem.
No, dub defaults to compiling each (non-source) (sub-)package in one shot. So if you replace your term 'group of modules' by 'dub packages/libraries', then that's exactly what most D users are building. The dub package dependencies can be tightly coupled as well (e.g., subpackages depending on one another), so this need to compile deps with `-version=unittest` for a parent project's unittest runner doesn't seem very popular. Out of interest, what's behind those `version (unittest)` blocks? Extra checks, or test helpers that dependents need?
Apr 14