I'm not sure whether this is a git question or a make question, or maybe both, but here goes...
Imagine you have a file foo.cpp which is generated by a generator program, gen.py. If the generator program is modified, it must be run again to generate a fresh version of foo.cpp.
A makefile rule that encodes this behavior could be as follows1:
foo.cpp: gen.py
gen.py
For active development on gen.py, this is ideal I think.
However, consider the case where you make your project available remotely via git, say on github or some similar site. Users will download and make your project.
The traditional way of handing generated files is not to check them in all: don't include foo.cpp in git all (add it to your `.gitignore), and when the user builds your project, the file will be generated.
However, an alternately approach is to include the the generated file foo.cpp in git. This raises the possibility that gen.py and foo.cpp might be "out of sync"2 if one is changed without updating the other but has a few other advantages:
- Users who just want to build the project but never update
gen.pydon't need to have the prerequisites to rungen.py(e.g., Python). - The unmodified build is faster because the generation step doesn't run.
- You get direct feedback during staging/commit about what changes to
foo.cppare implied bygen.py, since the file will part of the diff.
I'm not interested in litigating the merits of checking in generated files versus always generating them locally. You may assume that for some project the decision has been taking to check in generated files, and this decision is not up for debate.
In that context then, my question is:
For a user who freshly clones a project, or who syncs a commit involving both files, how can I ensure that make doesn't try to generate foo.cpp? By default git will use current time when it syncs files, so the foo.cpp and gen.py will have the same timestamps, and foo.cpp will be rebuilt.
I can't ask users to change their git configuration.
1 Perhaps there would be additional dependencies for foo.cpp which would also appear as a prerequisite, but this is the "base case".
2 A reasonable approach is to enforce that they are in sync via a git hook.