-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a module interface unit #2240
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the PR! Looks good, just a few minor comments inline.
src/fmt.cc
Outdated
#endif | ||
#endif | ||
|
||
export module FMT_MODULE_NAME; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the module name should be configurable. Let's use fmt here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonderful, we can agree on a name.
src/fmt.cc
Outdated
#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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we should use this as a fix - foonathan/lexy#15
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be fixed with #2247, but I need help with this PR, some strange MSVC errors...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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}.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok with me.
src/fmt.cc
Outdated
#include "fmt/ostream.h" | ||
#include "fmt/ranges.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which then rules out printf.h
, too. Oh well...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.