On 4/9/24 17:33, Boris Kolpackov wrote:
Andrey Semashev via Boost
writes: It doesn't make sense to have to build the whole Boost into a module only to pull a small part from it. I would much rather include the headers I want instead.
I actually don't think having a single/only `boost` module would be the right way to modularize Boost. I would suggest having a module per library (at least; maybe even more granular, say for Spirit, which is actually three libraries in one). And a single `boost` module that re-exports them all. Users who want all of Boost, can import `boost`, those like you who want to carefully manage their dependencies can import more granular modules. And, at least in build2, we only build BMIs that are actually used (imported).
(This brings an interesting question: if I import `boost`, but only use a small subset of libraries, how do I know which ones I should be linking. Trial and error until there are no more unresolved symbols feels a bit stone age.)
You link every library from Boost. Preferably, with -Wl,--as-needed. But I agree that having a module for the entire Boost doesn't make sense.
One other thing that isn't clear is how modules interact with compiled libraries. I don't suppose modules will replace static/shared libraries, so I presume a module will be added on top of the library?
Yes, from the library perspective, module interfaces are pretty similar to headers: when building the library, the object files produced when compiling module interfaces are linked into the library along with other TU object files. The interfaces are shipped/installed with the library and then compiled by the library consumers.
How should it "export" the symbols that are already exported from the compiled library then?
Modules actually make authoring portable shared libraries almost sane. Specifically, with modules, you only need the dllexport part of the dllexport/dllimport dance (and yes, this works for variables, not only functions). That is, you need to compile the BMI for a shared library with dllexport and then, when this BMI is used in import, dllimport happens auto-magically.
Which means that this can all be taken care of by the build system without you having to provide the export header (or equivalent) that arranges for the dllexport/dllimport dance. For example, in build2 we have implemented the __symexport keyword-like macro (defined automatically by the build system) which you use like so:
export namespace n { __symexport void f ();
class __symexport C { ... }; }
Thanks for the example. So, if I understood correctly, this is the same as what we do now: define a macro for symbol markup that expands to either dllexport or dllimport, depending on whether the library is being compiled or consumed. I'm assuming this is ok to have `f()` and members of `C` not defined in the module? The "attachment" thing that was mentioned before made it sound like it may be problematic. Also, will this work if the compiled library itself is built without modules?