Modules ... "import" vs. "compilation" ... what is the real process here?

Mike Parker aldacron at gmail.com
Tue Sep 28 02:05:43 UTC 2021


On Monday, 27 September 2021 at 17:38:29 UTC, james.p.leblanc 
wrote:
> Dear D-ers,
>
> I have trouble understanding "module imports" vs. "module 
> compilations".

A module is implemented in a source file. Though we often use the 
term "module" to refer to both, it may help to think in terms of 
importing modules and compiling source files.

Given the source files `A.d` and `B.d`, which implement the 
modules A and B respectively, and given that module A uses 
symbols from module B, then we can say the following:

1. When the compiler is compiling `A.d`, it must be aware of 
which symbols from module B are accessible from module A. This is 
what imports are for and has no relation to the compilation 
status of `B.d`.
2. The compiler will produce a `A.o/obj` object file that it will 
then pass to the linker,  including references to the symbols in 
module B. At that point, the linker will also need an object file 
from a compiled `B.d` in order to fix up the symbol references 
and produce the final executable.

To achieve #1, the compiler needs to read either the source file 
`B.d` or a D interface file, `B.di`, in order to know which 
symbols are available to module A. There are a couple of ways 
this can happen:

```
dmd A.d B.d
```

Here, when the compiler encounters `import B` in `A.d`, it will 
recognize that `B.d` has been passed on the command line. If 
`B.d` has no module statement, then the file name `B` is used as 
the module name. If it has a module statement, it the file can be 
named anything when it's passed on the command line like this. It 
could be `foo.d`, but as long as it has a `module B` at the top, 
then `A.d` can `import B`.

```
dmd -c A.d
```

Here, when the compiler encounters `import B` in `A.d`, it will 
see that no `module B` declaration has been encountered in any 
other files on the command line, so it will search for `B.di` 
and, if it's not found, `B.d` on the import path (to which we can 
append directories with `-I`). I've included `-c` here, which 
will just compile `A.d` and not attempt to link it, because 
without it the linker will spew errors for every missing symbol 
from module B.

This is how D supports separate compilation. Assuming object 
files with the `.obj` extension on Windows, you could do this:

```
dmd -c B.d
dmd A.d B.obj
```

Now, the compiler uses the source of `B.d` to assess symbol 
accessibility as before, and it will pass both `A.obj` and 
`B.obj` to the linker to produce the executable.

Or you could compile `B.d` into `B.lib` and pass that on the 
command line as well.

>
> Finally, there have been discussions about allowing new ways of 
> "compiling a module" by including its name on the command line. 
>  For example this from 2017:
>
> https://forum.dlang.org/post/tcrdpvqvwxffnewzohuj@forum.dlang.org

This is what resulted in the `-i` compiler switch. Modifying the 
example above:

```
dmd -i A.d
```

Now, when the compiler encounters `import B` in `A.d`, if there 
is no `B.di` and it finds `B.d`, it will compile `B.d` alongside 
`A.d`, just as if the command line had been `dmd A.d B.d`.

Does that help?




More information about the Digitalmars-d-learn mailing list