Header-Only Library - pragma(root)
Petar
Petar
Tue Jun 16 07:06:16 UTC 2020
On Sunday, 14 June 2020 at 16:05:39 UTC, Andrei Alexandrescu
wrote:
> On 6/14/20 11:36 AM, Adam D. Ruppe wrote:
>> On Sunday, 14 June 2020 at 10:24:33 UTC, Walter Bright wrote:
>>> It would probably be better as the implementer, as a
>>> header-only library has to be designed for it.
>>
>> That's not true. -i just works with almost any D code. It is
>> enormously useful exactly the way it is.
>
> What code wouldn't it work with? Would be good to document
> those. "How to write a header-only D library". Blog post!
The '-i' flag is the symmetric opposite of '-I'. '-I' expects
either header-only libraries, or separate compilation, while '-i'
expects neither. What Walter is suggesting (marking modules with
'pragma (root);' to make them header-only mainly serves the '-I'
flag. The only advantage 'pragma (root);' may have to '-i' is a
compile-time guarantee that modules intended to be header-only
actually don't impose any link-time dependencies.
The main use case of the `-i` flag is to compile (not just
import) modules. However the killer feature of '-i' is that while
'-I' a is blunt tool that just adds all modules under a dir to
the import path, '-i' leverages D's import system and lazily
compiles only the modules that are imported starting from the
root set of modules.
For example, giving the following project structure:
project/
├── lib1
│ ├── mod1.d
│ ├── ...
│ └── modn.d
├── lib2
│ ├── mod1.d
│ ├── ...
│ └── modn.d
└── main.d
Previously, in order to compile it, you could do the following:
find lib1/ lib2/ -type f -name '*.d' | xargs dmd -betterC
main.d
However, this has the disadvantage of compiling stuff that main.d
doesn't need. Say main.d was this:
extern (C) int main(int argc, const char** argv)
{
import lib1.mod1 : fun1a;
return fun1a(argc, argc + 1);
}
The only function that ever needs to be compiled is fun1a.
However the command above will end up compiling the whole world
(every module under lib1/).
With the '-i' flag we can compile main.d like so:
dmd -betterC -i=lib1 -i=lib2 main.d
Now, set of modules that would be compiled equals precisely the
set of modules imported from main.d - in this case only
lib1/mod1.d.
The only deficiency currently is that it doesn't take advantage
of selective imports - each imported module is compiled as a
whole, even if you only need to compile the imported symbols.
This problem is not just an implementation deficiency though, as
whether something is compiled and whether it exists is somewhat
conflated and has impact on D's meta programming (DbI and all
that). I think the best way to address this issue is at the root
- we need to define precise semantics over what lazy compilation
means. I have been meaning to write a DIP that addresses this
issue for a while, based on the idea of an @export attribute
(orthogonal to public/protected/package/private access modifiers)
and @export inference. You can see a sketch of what I have in
mind in these posts:
https://forum.dlang.org/post/xbllqrpvflazfpowizwj@forum.dlang.org
https://forum.dlang.org/post/nvvgrdlucajshjngdjlj@forum.dlang.org
More information about the Digitalmars-d
mailing list