2

We are looking for a way to speed up our local C++ builds. We have a simple idea in mind. We build our solution regularly on a build server. This build is incremental: when we push new changes, only necessary part of solution is rebuilt. Fast, convenient.

What if we copy all intermediate files produced by VS from the build server to our local machine? Ideally, VS should produce incremental build on top of these intermediate files. Fast, convenient.

The problem is, our build server and local machines use different paths for the solution. This does not play well with incremental builds.

What I tried for a test project: 1. Copy all intermediate files from build server to local machine 2. Update time stamps of all intermediate files to current time 3. Change all paths in all *.tlog files from server-specific to local-specific

And the first impression is good: VS reports that the project is up to date, nothing to build, yey! However, if I change a single file, VS tries to rebuild it reusing a precompiled header that it already has. And I have tons of errors like this:

1>e:\dev\prod3\shared\sdk\src\common\tblockalloc.h(18): error C2995: 'BlockManagerSPtr GetBlockManager(void)': function template has already been defined (compiling source file Requests.cpp)
1>d:\agent-home\xml-data\build-dir\ama-actd-job1\shared\sdk\src\common\tblockalloc.h(15): note: see declaration of 'GetBlockManager' (compiling source file Requests.cpp)

Seems like it is confused that the same symbol appears in headers with different paths.

Ok, I tried to simply replace paths in the PCH file the same way I did for .tlog files. But then even when I don't change any files, VS immediately thinks the project is out of date. Which is surprizing, because I thought it does not look into files themselves, but only observes their timestamps. Anyway, it then spitted off tons of errors like this:

1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'StdCall(/Gz)' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'CDecl(/Gd)' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'general PM representation(/vm[smv])' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'support for new floating-point model (/FP)' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'vtordisp(/vd[012])' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'DLL library (/MD)' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4652: compiler option 'Debug static MT library (/MTd)' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4653: compiler option 'Optimizations (one or more of /Oawstgp[y]) or debug checks (one or more of /GZ, /RTCcsu)' inconsistent with precompiled header; current command-line option ignored
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): warning C4653: compiler option 'For loop scope conformance (/Zc:forScope)' inconsistent with precompiled header; current command-line option ignored
1>e:\dev\prod3\shared\app.restserver\src\constants.cpp(1): error C2855: command-line option '/Zc:threadSafeInit' inconsistent with precompiled header

Seems like it does not like when I mess with PCH.

So at this point I am a little stuck. I expected to find some info about how to reuse build artifacts of Visual Studio to achieve easy incremental builds, but I actually found nothing.

Is it even possible? Had anyone tried it?

Mikhail
  • 20,685
  • 7
  • 70
  • 146
  • 1
    I don't want to flag this as duplicate after someone answered, but googling "ccache visual studio" led to https://stackoverflow.com/questions/1860331/is-there-a-ccache-for-visual-studio which led to https://stashed.io/home – Botje Feb 19 '19 at 15:55
  • Damn, that's not how I googled for it. Thanks a lot for the link! – Mikhail Feb 21 '19 at 09:16

1 Answers1

2

We have something similar. We have only relative paths for the VS solution, and then we also store the (empty/bogus) .tlog files with a proper timestamp. We only store the libraries, not the intermediate object files, so when someone change a file for a library, I think we rebuild the full library. But we don't have the slightest issue with precompiled headers, they are properly up to date and we have the same flags, so I think you have a different set up between your build server and your local builds. We don't have this issue because the VS flags come from our Makefiles, so everything is consistent.

The big drawback is that when we will move to CMake, we will have an uphill battle to reproduce the hierarchy like we do for our custom builds.

Then maybe you should use an off the shelf product like Incredibuild.

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
  • Great to hear someone has the same problem! Could you please clarify: if you "rebuild the full library" in the case anything changes, what is the point of having the PCH? Or do you mean you rebuild the whole library, _except_ PCH? – Mikhail Feb 19 '19 at 15:20
  • The PCH is there to speed up individual compilation units. It's not for the whole library, you get benefit for one file as well (as long as the dependencies in the pch are stable). But then I hate PCH because it makes people lazy and include everything by default insteda of making them think about efficiency ;) – Matthieu Brucher Feb 19 '19 at 15:22
  • "as long as the dependencies in the pch are stable" - interesting point! Will VS be able to properly trigger rebuild of the PCH in case a dependency changes? (Happens quite often in our case, sadly enough) – Mikhail Feb 19 '19 at 15:32
  • If your dependencies are not stable (headers keep on changing), maybe the precompiled headers is not the right way, as these are common to the full project. But if you set up the timestamps properly, then yes, VS should trigger the rebuild properly. But it's a grey area in the sense that it's not public API and may break with VS2019 for instance, or a new msbuild :/ – Matthieu Brucher Feb 19 '19 at 15:36
  • "But it's a grey area" - I agree... but it still so tempting. Thanks a lot for your comments! Maybe I get back to you a little later, if you don't mind :) – Mikhail Feb 19 '19 at 15:37
  • Yes, sure, no pb ;) – Matthieu Brucher Feb 19 '19 at 15:38