Provide a module interface unit - #2240
Conversation
vitaut
left a comment
There was a problem hiding this comment.
Thanks a lot for the PR! Looks good, just a few minor comments inline.
| #endif | ||
| #endif | ||
|
|
||
| export module FMT_MODULE_NAME; |
There was a problem hiding this comment.
I don't think the module name should be configurable. Let's use fmt here.
There was a problem hiding this comment.
Wonderful, we can agree on a name.
| #define FMT_MODULE_EXPORT_BEGIN export { | ||
| #define FMT_MODULE_EXPORT_END } | ||
|
|
||
| #define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1 |
There was a problem hiding this comment.
C++20 modules unsurprisingly require C++20 which includes NTTPs. compile.h enables the use of NTTPs in a non-standard way that excludes compilers like msvc that support this feature. My current code to support FMT_STRING and FMT_COMPILE relies on this feature. So I enable it by overriding the macro until compile.h gets updated to the reality.
There was a problem hiding this comment.
Looks like we should use this as a fix - foonathan/lexy#15
There was a problem hiding this comment.
It should be fixed with #2247, but I need help with this PR, some strange MSVC errors...
There was a problem hiding this comment.
This FMT_STRING thing is bothering me in a different context, too. At present fmt::to_wstring() cannot be invoked from client code because identifiers from the expansion of FMT_STRING cannot be looked-up from the body of instantiations of to_wstring. But that should be adressed in a different PR.
There was a problem hiding this comment.
C++20 modules unsurprisingly require C++20 which includes NTTPs.
While this is true, modules and NTTP are independent features so presence of one doesn't imply presence of the other. I suggest removing this define from the current PR. It can be set when building {fmt}.
| #include "fmt/ostream.h" | ||
| #include "fmt/ranges.h" |
There was a problem hiding this comment.
These two should be moved to separate modules because in many cases they should be disabled / explicitly opted in.
There was a problem hiding this comment.
ostream.h is included through printf.h anyway.
ranges.h can be implemented in a different module if it neither requires any macro from other parts of {fmt} nor any non-exported identifier. Not to mention that teensy tiny modules are not recommended afaik.
What do you think about conditionally including these parts of {fmt} by macro definitions from the command line like it is already proposed for os.h? So users of the module can decide on their own if they want this or not.
There was a problem hiding this comment.
The currently existing dependency levels are as such:
1
core.h
2
args.h -> core.h
format.h -> core.h
3
compile.h -> format.h
ostream.h -> format.h
ranges.h -> format.h
color.h -> format.h
locale.h -> format.h
os.h -> format.h
format-inl.h -> format.h
4
printf.h -> ostream.h
chrono.h -> format.h locale.h
There was a problem hiding this comment.
Not that I have a say in this, but why split it up and/or have conditional inclusion (this also applies to OS)? In principle, it shouldn't matter how much stuff is included in the module and it's not like fmt has no/few standard library dependencies without them.
There was a problem hiding this comment.
I'm not sure if I get your point here. You are right about your comment on the amount of stuff included in a module, but why do you mention the standard library? Do you propose not to carve out anything from inclusion into the module interface? If so we are on the same page. So far I've excluded os.h for the simple fact that it doesn't matter: nothing is exported from there because there doesn't seem to exist a documented interface that hints on which declarations to export. Additional exports can be added in a subsequent PR by tagging them accordingly. IIUC, Victor's concerns are about template specializations they bring into the TUs that import {fmt}. I have hardly any clue about ranges.h in this regard but I cannot really see a problem with ostream.h.
There was a problem hiding this comment.
It must be split because ostream and ranges provide formatter specialization that should not be available by default.
There was a problem hiding this comment.
Which then rules out printf.h, too. Oh well...
There was a problem hiding this comment.
printf.h dependency on ostream.h is accidental and will be removed by b9ab5c8.
|
So I will proceed this way:
Additional changes like already mentioned need to be subject of PRs against regular {fmt}. |
I think it's OK to keep |
|
Looks like a plan to me. Hold tight... |
9d29eff to
ab54a18
Compare
ab54a18 to
99bb864
Compare
|
Merged, thank you! |
|
I am getting the following error when building the module with gcc: Any ideas? |
|
I think the problem is that the declaration is exported twice. |
|
Ok, if so, the problem should be easy to resolve by exporting it only from the location where the name is intoduced first. That's most likely in core.h. MSVC didn't complain and I don't have any other compiler available to test with. |
|
Strange. The declaration in core.h is in namespace detail, the one in format.h is in namespace fmt. I hope neither file is changed too much, my clone isn't up-to-date. |
To compile {fmt} as named module, there must be at least the source provided with the (primary) module interface.
I chose the most elegant and probably the most desirable implementation strategy: a single-file module with a private module partition. This has these benefits:
The macro-based interfaces FMT_STRING and FMT_COMPILE are not yet implemented. Macros cannot get exported from modules.
The inclusion of the 'os' part is optional an can be configured from the command line at build time.
The module name can be configured from the command line at build time. By default it is 'fmt'.
The module may be configured and provided as a static or dynamic-load lib as before.
This requires a sufficiently complete and bug-free implementation of C++20 modules to compile!
At present, msvc 16.10-pre2 requires a workaround for successful compilation (which is not included). 16.10-pre3 is reportedly fine according the the compiler devs.
I have no experience how gcc and clang fare. Let's give them a serious drill!
@vitaut : this is how I do it n my own repo. Let's discuss this.