www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How does import work?

reply Jens Mueller <jens.k.mueller gmx.de> writes:
Hi,

I have a simply example using imports that confuses me. Unfortunately I
cannot find explanation on the web site.
File a.d:
module a;

// some import here
//import std.conv;

File b.d:
module b;
import a;

void main() {
}

I do a
$ dmd -run b.d
and that works as expected.
If I commented in 'import std.conv;' in file a.d and do
$ dmd -run b.d
linking fails with
"b.o:(.data+0xc): undefined reference to `_D1a12__ModuleInfoZ'"

I figured out that I need to add a.d like this
$ dmd a.d -run b.d
Because the ModuleInfo for a.d needs to be generated.

So much for my limited understanding.
In my use case I want to do unit testing like this
$ dmd -unittest -run b.d

It seems that I always have to built a library to make sure that an
import works. Can somebody explain the rational behind that? What is
ModuleInfo? And why is it needed? How can I make the unit testing work
per module? How do you do it?
I think I missed something essential about imports.

Jens
Oct 19 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 19 Oct 2010 05:04:03 -0400, Jens Mueller <jens.k.mueller gmx.de>  
wrote:

 Hi,

 I have a simply example using imports that confuses me. Unfortunately I
 cannot find explanation on the web site.
 File a.d:
 module a;

 // some import here
 //import std.conv;

 File b.d:
 module b;
 import a;

 void main() {
 }

 I do a
 $ dmd -run b.d
 and that works as expected.
 If I commented in 'import std.conv;' in file a.d and do
 $ dmd -run b.d
 linking fails with
 "b.o:(.data+0xc): undefined reference to `_D1a12__ModuleInfoZ'"

 I figured out that I need to add a.d like this
 $ dmd a.d -run b.d
 Because the ModuleInfo for a.d needs to be generated.

 So much for my limited understanding.
 In my use case I want to do unit testing like this
 $ dmd -unittest -run b.d

 It seems that I always have to built a library to make sure that an
 import works. Can somebody explain the rational behind that? What is
 ModuleInfo? And why is it needed? How can I make the unit testing work
 per module? How do you do it?
 I think I missed something essential about imports.

ModuleInfo is the runtime representation of the module. Modules can have their own constructors and destructors to initialize global and thread-local data. You can also get the name of the module from the module info. They are stored by the compiler in an array that is accessible at runtime. A module's unit tests are also stored in the module info. To answer your other questions, just unit test everything at once. There is no need to run each individual file. In other words, just do: dmd -unittest -run b.d a.d And that will test all unittests in b and a. If you insist on only testing unittests in b, you still need a complete program. So a's module info must be included. Therefore you need to do a partial compilation: dmd -c a.d this creates a.o (or a.obj depending on your platform). If a has unittests they are *not* included in the object file. dmd -unittest -run b.d a.o Note that I'm passing the already-compiled version of a, this means it will not be recompiled to add a's unit tests. Why you'd want to do it this way, I have no idea. -Steve
Oct 19 2010
prev sibling next sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Steven Schveighoffer wrote:
 On Tue, 19 Oct 2010 05:04:03 -0400, Jens Mueller <jens.k.mueller gmx.de>  
 wrote:

 Hi,

 I have a simply example using imports that confuses me. Unfortunately I
 cannot find explanation on the web site.
 File a.d:
 module a;

 // some import here
 //import std.conv;

 File b.d:
 module b;
 import a;

 void main() {
 }

 I do a
 $ dmd -run b.d
 and that works as expected.
 If I commented in 'import std.conv;' in file a.d and do
 $ dmd -run b.d
 linking fails with
 "b.o:(.data+0xc): undefined reference to `_D1a12__ModuleInfoZ'"

 I figured out that I need to add a.d like this
 $ dmd a.d -run b.d
 Because the ModuleInfo for a.d needs to be generated.

 So much for my limited understanding.
 In my use case I want to do unit testing like this
 $ dmd -unittest -run b.d

 It seems that I always have to built a library to make sure that an
 import works. Can somebody explain the rational behind that? What is
 ModuleInfo? And why is it needed? How can I make the unit testing work
 per module? How do you do it?
 I think I missed something essential about imports.

ModuleInfo is the runtime representation of the module. Modules can have their own constructors and destructors to initialize global and thread-local data. You can also get the name of the module from the module info. They are stored by the compiler in an array that is accessible at runtime. A module's unit tests are also stored in the module info. To answer your other questions, just unit test everything at once. There is no need to run each individual file. In other words, just do: dmd -unittest -run b.d a.d And that will test all unittests in b and a. If you insist on only testing unittests in b, you still need a complete program. So a's module info must be included. Therefore you need to do a partial compilation: dmd -c a.d this creates a.o (or a.obj depending on your platform). If a has unittests they are *not* included in the object file. dmd -unittest -run b.d a.o Note that I'm passing the already-compiled version of a, this means it will not be recompiled to add a's unit tests. Why you'd want to do it this way, I have no idea.

Thanks very much for your explanation. It just seemed natural to me to test them separately. Often I do not know even which modules a module depends on. And assuming there are many tests that might take long, picking a specific one seemed the better option to me. In general if the test suite is large and something fails then after the problem is fixed or while fixing I want to run only the depended tests. But admittedly this does not come up in practice, does it? I mean phobos does not need it. Testing everything is fast. So then I'll just test all. Jens
Oct 19 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 19 Oct 2010 08:57:03 -0400, Jens Mueller <jens.k.mueller gmx.de>  
wrote:

 Thanks very much for your explanation. It just seemed natural to me to
 test them separately. Often I do not know even which modules a module
 depends on. And assuming there are many tests that might take long,
 picking a specific one seemed the better option to me. In general if the
 test suite is large and something fails then after the problem is fixed
 or while fixing I want to run only the depended tests.
 But admittedly this does not come up in practice, does it? I mean phobos
 does not need it. Testing everything is fast.
 So then I'll just test all.

Phobos unittests are run individually by a script. Why, I don't know. I think it has to do with a recent experiement in making the code continue on a failing unit test. To give you an idea of how long it takes to run unit tests, dcollections probably has about 156 unit tests, and each is tested with 11 different template instantiations. That's 156 * 11 = 1716 unit tests. It runs in less than a second (takes a long time to compile though). In general, unit tests are not going to slow you down unless you are doing some kind of i/o or timing tests. -Steve
Oct 19 2010