Why copy_if_different?

Hi all,

What is the reason for custom build rules in Visual Studion using
'cmake -E copy_if_different' instead of plain 'cmake -E copy'? If
target file is older than source but contents is the same the source
will not be copied and the timestamp of target will remain the same.
This means that VS will try to rebuild this file (and a dozen of
dependent projects) on every run (I observe this particular behavior
on my system).

I too observed this behaviour with MSVC 2008 but not with MSVC 2010.
That's one of the reason i switched from 2008 to 2010.

I really do not think that this behavior depends on particular version of VS.

I don't know. MSVC 2010 now use MSBUILD under the hood to build.
MSBUILD wasn't used with 2008 for C++ project. There could be side
effects to that. As I said I never observed even one case of
unnecessary recompilation with 2010, something I was seeing very often
with 2008. I really don't know why though.

BTW I think I have a real-world example of broken dependencies in Clang:

1) Firstly I build debug Clang.
include/clang/Basic/DiagnosticASTKinds.inc.tmp is generated using
debug tablegen and then copied to DiagnosticASTKinds.inc.

2) Now I switch to release and build it the DiagnosticASTKinds.inc.tmp
is regenerated (because it depends on release tablegen and it's newer
than debug tablegen that was used to generate it).

Note that now VS thinks that DiagnosticASTKinds.inc has to be rebuilt
(it's older than DiagnosticASTKinds.inc.tmp). But due to
copy_if_different DiagnosticASTKinds.inc.tmp is never copied to
DiagnosticASTKinds.inc. So VS will try to rebuild Clang forever.

Yuri Gribov <tetra2005@googlemail.com> writes:

What is the reason for custom build rules in Visual Studion using
'cmake -E copy_if_different' instead of plain 'cmake -E copy'?

We suppose that most of the time the tablegenned files do not
change. Using `copy' is like touching the tablegenned file and hence
forcing all dependencies to rebuild. This is a typical scenario:

* A change is made to Support or tblgen.

* tblgen is rebuilt.

* Everything is re-tablegenned.

* If the *.inc.tmp output files are the same as the definitive ones,
  using copy_if_different leaves the definitive files untouched, which
  saves a massive rebuild.

If target file is older than source but contents is the same the
source will not be copied and the timestamp of target will remain the
same. This means that VS will try to rebuild this file (and a dozen
of dependent projects) on every run (I observe this particular
behavior on my system).

Well, the idea is that this is less expensive than the occasional
massive rebuild mentioned above. This comes from the experience of some
users who contributed the patches for this behavior. You can try
changing the code in cmake/modules/TableGen.cmake and see if using
`copy' works significantly better for you. Then we could consider making
it optional.

Yuri Gribov <tetra2005@googlemail.com> writes:

BTW I think I have a real-world example of broken dependencies in Clang:

1) Firstly I build debug Clang.
include/clang/Basic/DiagnosticASTKinds.inc.tmp is generated using
debug tablegen and then copied to DiagnosticASTKinds.inc.

2) Now I switch to release and build it the DiagnosticASTKinds.inc.tmp
is regenerated (because it depends on release tablegen and it's newer
than debug tablegen that was used to generate it).

This is an unforntunate side effect of using the same root build
directory for more than one build configuration.

Note that now VS thinks that DiagnosticASTKinds.inc has to be rebuilt
(it's older than DiagnosticASTKinds.inc.tmp). But due to
copy_if_different DiagnosticASTKinds.inc.tmp is never copied to
DiagnosticASTKinds.inc. So VS will try to rebuild Clang forever.

The above wording sounds like VS entering an infinite loop, but I don't
think it is the case. More likely VS executes some commands whenever you
run the build, but it ends, doesn't it? Is seeing those commands
executed (and the associated wait time) instead of VS saying "everything
was up to date" what bothers you, right?