Reputation: 5652
In a classic MAKEfile, it was easy to list the main file and then all the dependent files (e.g. Include files) in a rule.
I thought that MSBuild had some attribute in the target for that, but it seems not! Given a list of input files and a transformation from input file to output file name, it runs the Target once for each input file, and skips it if the input file is not newer than the output file.
So how can you retain that behavior, and furthermore NOT SKIP if any of the dependent files are newer, too? The dependent files are noted from an earlier build, and I know how to read a text file into an Item array. But each input has a different list of dependent files, and I don't see how to tell the Target when it's OK or not OK to skip.
I see the logic for CL (the C and C++ compiler) is not handled in the MSBuild script at all! The "Task" for CL, which wraps the call to cl.exe, makes that determination and simply doesn't call cl.exe. But the Target never skips at all and feeds CL every input file.
I wonder if there's a useful way to do that directly in MSBuild without writing code in .NET to do the real work.
Upvotes: 4
Views: 875
Reputation: 11920
Let me address the question about CL target in MSBuild, since the way it is implement is quite special. Also, something tells me that you are doing something similar, perhaps with gcc or other C/C++ compiler, where you can get list of dependencies with command gcc -M
.
For C++ compilation, C++ linking, C++ resource compiler and few more things, MSBuild uses automated mechanism to establish all dependencies at build time. This is called File Tracker, and it is not described in detail online, but you can get lots of details in MSBuild book.
File Tracker watches what cl.exe, rc.exe and link.exe are doing with file system and creates list of files they read -- that will be the dependencies of currently compiled or linked file. Then it preserves this list in .tlog file in your obj folder. Next time you invoke build, the CL task (or Link task) read their .tlog files and compare timestamps of the files of all dependencies, checking if compiler (or linker) has to be executed again. These checking are all done inside CL/RC/LINK tasks. In other words, if you see CL task is being executed, if does not always mean cl.exe will be launched.
Now, to get you going, there are few alternative approaches:
Inputs
parameter of the target you can append list of dependencies to the primary file, and will get your incremental build going. Obvious drawback is that you have to maintain potentially lots of targets.Upvotes: 4