I've worked on code that took that long to compile, and the cause of the problem was usually bad recursive makefiles doing work over and over again.
At the other extreme I've also worked at Google and have seen insanely complex C++ code bases compile in 30 seconds flat.
Multiple hour build times usually show that nobody smart enough had the interest and authority to solve the problem properly. It doesn't generally mean that your project is awesome. It certainly isn't something that I would brag about.
OK, that's great for google, but "complex" doesn't necessarily mean much. Do you think the linux kernel devs are slouches? The gcc devs? Both of those projects take hours to compile on reasonable hardware, and that's not for lack of trying.
Also, sometimes it's not about code, it's about digital assets, which is going to be IO bound. I've worked on projects that took a full working day to do a clean compile and others where it was necessary to do binary integrations instead of code because the overall build time would otherwise be measured in days or weeks.
They usually do incremental builds. And a lot of work goes into reproducible builds so that incremental builds can be trusted. But even clean builds are typically minutes of wall-clock time. Not hours.
Of course part of the trick is that work has been distributed across a cluster, so a lot longer was spent compiling than that...
I've seen tens of thousands of lines of code compile in 30 minutes.
I've seen a hundred thousand lines of code compile in 2 minutes.
It really depends on how the project is laid out. If you're using lots of header-only libraries and try to compile monolithically (like soooooo many C++ applications do these days), you're going to have a bad (compile) time.
CMake helps a good bit, ccache goes further, and ninja helps a bit too. But none of them can help templated header-only libraries with complex interdependencies. It gets particularly bad when the developer #includes a convenience header to bring in _everything_ in the library instead of just what they need.
Agreed. Good use of PImpl when you have large external header-only libraries is also generally recommended to keep the dependency graph nicer.
Also from what I've seen, large header-only codebases tend to be external and thus generally don't change that much, so if you can limit your own internal dependency tree ccache can still save you.