<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Tue, Jul 24, 2018 at 3:20 PM Stephen Kelly <<a href="mailto:steveire@gmail.com" target="_blank">steveire@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">David Blaikie wrote:<br>
<br>
> (just CC'ing you Richard in case you want to read my ramblings/spot any<br>
> inaccuracies, etc)<br>
> <br>
> Excuse the delay - coming back to this a bit now. Though the varying<br>
> opinions on what modules will take to integrate with build system still<br>
> weighs on me a bit<br>
<br>
Can you explain what you mean by 'weighs on you'? Does that mean you see it <br>
as tricky now?</blockquote></div><div dir="ltr"><div class="gmail_quote"><div><br>Yes, to some extent. If the build system is going to require the compiler-callsback-to-buildsystem that it sounds like (from discussions with Richard & Nathan, etc) is reasonable - yeah, I'd say that's a bigger change to the way C++ is compiled than I was expecting/thinking of going into this.<br><br>Some folks see this as not "tricky" but just "hey, C++ has been getting away with a vastly simplified build model until now - now that it's getting modular separation like other languages, it's going to have to have a build system like other languages" (ala Java/C#, Haskell/Go maybe, etc) - but I'm not especially familiar with any other languages enterprise-level build systems (done a bit of C# at Microsoft but wasn't looking closely at the build system - insulated from it by either Visual Studio or the OS release processes, etc - and the last time I did Java I was working on small enough things & without many cores, so throwing all the .java files in a package at the compiler in one go was totally reasonable)<br> </div></div></div><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I've kind of been assuming that people generally think it is not tricky, and <br>
I'm just wrong in thinking it is and I'll eventually see how it is all <br>
manageable.<br></blockquote></div></div><div dir="ltr"><div class="gmail_quote"><div><br>I think it's manageable - the thing that weighs on me, I suppose, is whether or not the community at large will "buy" it, as such. And part of that is on the work we're doing to figure out the integration with build systems, etc, so that there's at least the first few pieces of support that might help gain user adoption to justify/encourage/provide work on further support, etc... <br><br></div></div></div><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
> To that end, Stephen, I've made a fork of your example repository & a very<br>
> simple/direct change to use C++ modules as currently implemented in Clang.<br>
<br>
Interesting, thanks for doing that! Here's the link for anyone else <br>
interested:<br>
<br>
<a href="https://github.com/dwblaikie/ModulesExperiments" rel="noreferrer" target="_blank">https://github.com/dwblaikie/ModulesExperiments</a></blockquote><div><br></div></div></div><div dir="ltr"><div class="gmail_quote"><div>Oh, thanks - totally didn't realize I failed to link that!</div></div></div><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
> The build.sh script shows the commands required to build it (though I<br>
> haven't checked the exact fmodule-file dependencies to check that they're<br>
> all necessary, etc) - and with current Clang top-of-tree it does build and<br>
> run the example dinnerparty program.<br>
<br>
Ok. I tried with my several-weeks-old checkout and it failed on the first <br>
command with -modules-ts in it (for AbstractFruit.cppm - the simplest one).<br>
<br>
I'll update my build and try again, but that will take some time.<br></blockquote><div><br></div></div></div><div dir="ltr"><div class="gmail_quote"><div>Huh - I mean it's certainly a moving target - I had to file/workaround a few bugs to get it working as much as it is, so not /too/ surprising. Did you get it working in the end? If not, could you specify the exact revision your compiler's at and show the complete output?</div></div></div><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> If you happen to try experimenting with any ways the commands in the<br>
> build.sh file could be run from CMake it a sensible way - even if you<br>
> hypothesize what -MM support (or other compiler hooks like the dependency<br>
> server I alluded to above, etc) for modules might look like to do so, I'd<br>
> love to chat about it/throw ideas around/try mocking up/prototyping the<br>
> sort of compiler support (I don't think there's -MM support yet, but I<br>
> could see about adding it, for example) that seems like it might be most<br>
> useful.<br>
<br>
Yes, that would be useful I think.<br>
<br>
> One thing I'm vaguely concerned about is actually the dependency of<br>
> building modules within a single library (as in this project/example - at<br>
> least the way I've built it for now - I didn't try building it as separate<br>
> .so/.a files). At least across-library we can work at the library<br>
> granularity and provide on the command line (or via a file as GCC does)<br>
> the module files for all the modules from dependent libraries. But I'm not<br>
> sure how best to determine the order in which to build files within a<br>
> library<br>
<br>
Exactly, that's one of the reasons my repo has libraries of multiple files <br>
with dependencies between them, but building everything into one executable <br>
also exposes that issue.<br></blockquote></div></div><div dir="ltr"><div class="gmail_quote"><div><br>Ah, when I say "library" I mean static (.lib/.a) or dynamic (.so/.dll/etc) - same situation in either. But yeah - any situation where there are multiple modules within a single library, getting those dependencies will involve some discovery (either a pre-parsing check (same way a build system might check which headers are included in a file) or the compiler callback system, where the compiler asks the build system for the modules it needs) - and even in the one-module-per-library <br> </div></div></div><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I guess it would work in a similar way to determining the order to link <br>
libraries though, so probably not a major problem.<br></blockquote><div><br></div></div></div><div dir="ltr"><div class="gmail_quote"><div>The dependency between libraries is usually explicit in the build system, right? I don't think that would be the case for modules - there'd be a reasonable expectation that </div></div></div><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> - that's where the sort of -MM-esque stuff, etc, would be<br>
> necessary.<br>
<br>
Would it? I thought the -MM stuff would mostly be necessary for determining <br>
when to rebuild? Don't we need to determine the build order before the first <br>
build of anything? The -MM stuff doesn't help that.<br></blockquote><div><br>-MM produces output separate from the compilation (so far as I can tell - clang++ -MM x.cpp doesn't produce anything other than the makefile fragment on stdout) & finds all the headers, etc. So that's basically the same as what we'd need here - but -MM only has to preprocess, whereas this would have to do some C++ parsing to find imports, etc. But it would only have to look for direct dependencies (unlike -MM which walks through includes to find other includes) - and then the build system could re-invoke it for the next module and so on... <br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
>> It seems quite common to have one PCH file per shared library (that's<br>
>> what Qt does for example). What makes you so sure that won't be the case<br>
>> with modules?<br>
>><br>
> <br>
> Can't say I've worked with code using existing PCH - if that seems common<br>
> enough, it might be a good analogy/guidance people might follow with C++<br>
> modules.<br>
<br>
Perhaps. I wonder how the C++ code/build.sh code would change in that <br>
scenario? If there were only four modules - one for each of the libraries <br>
(as delimited in the CMakeLists). Would the C++ code change then too <br>
(something about building partial modules from each of the multiple cppm <br>
files?), or how would the build.sh code change?<br></blockquote><div><br>One module per library would be fairly clear, I think.<br><br>Looking at your example - if you have a library for all the fruits and libabstractfruit, libfruitsalad, libnotfruitsalad, and libbowls - then you'd have one module interface for each of those (AbstractFruit.cppm, FruitSalad.cppm, NotFruitSalad.cppm, Bowls.cppm) that would be imported (so replace "import Apple", "import Grape" with "import FruitSalad", etc... ) & the implementations could be in multiple files if desired (Apple.cpp, Grape.cpp, etc).<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>> Ok. That's not much better though. It still means editing/generating the<br>
>> buildsystem each time you add an import.<br>
> <br>
> <br>
> Isn't that true today with headers, though? <br>
<br>
No. Imagine you implemented FruitBowl.cpp in revision 1 such that it did not <br>
#include Grape.h and it did not add the Grape to the bowl.<br>
<br>
Then you edit FruitBowl.cpp to #include Grape.h and add the Grape to the <br>
bowl. Because Grape.h and Apple.h are in the same directory (which you <br>
already have a -Ipath/to/headers for in your buildsystem), in this (today) <br>
scenario, you don't have to edit the buildsystem.<br></blockquote><div><br>Well, you don't have to do it manually, but your build system ideally should reflect this new dependency so it knows to rebuild FruitBowl.cpp if Grape.h changes.<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">In your port, you would have to add an import of Grape (fine, equivalent), <br>
add the Grape to the bowl (the same as today), but additionally, you have to <br>
<br>
* add -fmodule-file=Grape.pcm to the compile line or run your buildsystem <br>
generator such as CMake to cause that compile line to be generated with the <br>
argument added.<br>
* Generate Grape.pcm (because the library has 1000 fruit classes in it and <br>
your buildsystem is smart enough to lazily generate pcm files as needed)<br>
<br>
Partly that is a result of the totally-granular approach you took to <br>
creating modules (one module per class). If you used the approach of one <br>
module per library, then you would not need to touch the buildsystem.</blockquote><div><br></div><div>Right - much like if you have coarse grained headers then picking up a new dependency doesn't involve adding a new #include nor modifying the build system.<br><br>Though in both header and module cases, there's some room for optimization from the coarse grained library dependencies you might have - if libA depends on libB, not every C++ source file in libA needs to be rebuilt if any header in libB is modified. That's why build systems use -MM-like behavior to create more fine-grained dependencies, both to ensure things are rebuilt when needed, but also to ensure they aren't rebuilt more often than needed too.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> I hope <br>
that's clear now, as I've mentioned it multiple times, but I wonder if that <br>
part of what I say is being understood.<br>
<br>
> But today the build system<br>
> does this under the covers with header scanning, -MM modes, etc?<br>
<br>
Perhaps. I notice that running CMake on my llvm/clang/clang-tools-extra <br>
checkout takes a non-zero amount of time, and for other buildsystems takes a <br>
significantly non-zero amount of time.<br>
<br>
Many buildsystem generators already avoid the time/complexity of <br>
automatically regenerating the buildsystem when needed. Users have to leave <br>
their IDE and run a script on the command line.<br></blockquote><div><br></div><div>That surprises me a bit - if I were using an IDE, I'd expect it to update the build system based on changes I made there - add a source file, #include, etc, and it should be reflected in the build system files. That's sort of meant to be one of the perks of using an IDE, I thought - that it kept all that in sync because it knows about what I'm doing when I say "create a new C++ source file" - rather than working on the command line where the build system isn't notified when I open vim and save a new .cpp file (unless the build system is using globs to consider anything with the .cpp file extension to be part of the project).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I wonder if people will use C++ modules if CMake/their generator has to be <br>
re-run (automatically or through explicit user action) every time they add <br>
'import foo;' to their C++ code... What do you think?<br></blockquote><div><br></div><div>If it's automatic & efficient (I hope it doesn't redo all the work of discovery for all files - just the ones that have changed) it seems plausible to me.</div><div> </div><div>Sorry for the rather long delay on this - hopefully it helps us converge a little.<br><br>I'll try to find some time to get back to my original prototype & your replies to do with that to see if I can flesh out the simpler "one module per library (with some of the inefficiency of just assuming strong dependencies between libraries, rather than the fine grained stuff we could do with -MM-esque support), no external modules" scenario (& maybe the retro/"header modules" style, rather than/in addition to the new C++ modules TS/atom style) - would be great to have a reasonable prototype of that as a place to work from, I think.<br></div><div><br></div><div>- Dave</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> What would be different about having a similar requirement for modules<br>
> (but a somewhat different discovery process)? <br>
<br>
I hope the above is clear. Please let me know if not. Maybe I'm missing <br>
something still.<br>
<br>
Thanks,<br>
<br>
Stephen.<br>
<br>
<br>
-- <br>
<br>
Powered by <a href="http://www.kitware.com" rel="noreferrer" target="_blank">www.kitware.com</a><br>
<br>
Please keep messages on-topic and check the CMake FAQ at: <a href="http://www.cmake.org/Wiki/CMake_FAQ" rel="noreferrer" target="_blank">http://www.cmake.org/Wiki/CMake_FAQ</a><br>
<br>
Kitware offers various services to support the CMake community. For more information on each offering, please visit:<br>
<br>
CMake Support: <a href="http://cmake.org/cmake/help/support.html" rel="noreferrer" target="_blank">http://cmake.org/cmake/help/support.html</a><br>
CMake Consulting: <a href="http://cmake.org/cmake/help/consulting.html" rel="noreferrer" target="_blank">http://cmake.org/cmake/help/consulting.html</a><br>
CMake Training Courses: <a href="http://cmake.org/cmake/help/training.html" rel="noreferrer" target="_blank">http://cmake.org/cmake/help/training.html</a><br>
<br>
Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" rel="noreferrer" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="https://cmake.org/mailman/listinfo/cmake-developers" rel="noreferrer" target="_blank">https://cmake.org/mailman/listinfo/cmake-developers</a><br>
</blockquote></div></div></div>