xcopy brain damage
And now, a software development war story, if you’ll indulge me.
Once upon a time I worked on a project where one of the deliverables was a Windows executable. We had a
build.bat batch file with commands to copy executables and libraries from the build directories into a
bin directory so they can be run.
The initial version of this used the vanilla Windows
copy command. However this always copies every single file to the
bin directory, resulting in a small, but noticable, turnaround time between building the executable and running it.
I thought: surely it would be easy to only copy the files if they had actually changed? Most of the files were third-party DLLs and they never change.
I initially looked at using a makefile for this, more specifically the
nmake tool that comes with Visual C++. After wrangling this tool for a bit, and eventually realising that it implements maybe 10% of the functionality of a real make tool (eg GNU make), I gave up. Not only was the makefile a monster (the equivalent in GNU make would be about 2 lines), but also it didn’t quite do what I wanted. The existing build script ignores executables which haven’t been built yet (e.g. test harnesses for modules you’re not working on), and it was too hard to get
nmake to do this.
Why not just use GNU make? Well as a general principle I try not to introduce additional dependencies on the build system unless absolutely necessary. I had one other alternative that was available for free…
So the next step was to modify
build.bat to use
xcopy. This tool has a
\d option which (according to the help) “Copies files changed on or after the specified date. If no date is given, copies only those files whose source time is newer than the destination time.” Sounds just the ticket right?
Unfortunately this option is so broken that I wonder if anyone has ever managed to put it to any worthwhile use, ever.
Note that it says it compares the source time with the destination time. Unfortunately if you specify the destination as a directory it will use the timestamp of the directory as the comparison, even if the source is a file. Duh.
OK, so we just specify the destination as a full filename, such as
xcopy \d build\blah\foo.exe bin\foo.exe, right? Nope, Microsoft strikes again!
xcopy gets confused and prompts you as to whether the destination is a directory or a file (!) As Dave Barry says, I am not making this up:
Does c:\path\to\bin\foo.exe specify a file name or directory name on the target (F = file, D = directory)?
And of course there is no option to tell it which, beforehand.
After being struck with stupidity of such awesome magnitude, I simply gave up and went back to just blindly copying everything every time. And I can’t recall ever having used
xcopy since then.