I wonder what 'ls -l $@ $^' generates (just before the copy)?
make (and I doubt gmake is very different) ends up checking the timestamps on everything twice, once at the start and again just before running each command.
There might also be something odd about the way that definition file doesn't get updated when nothing changes - since I suspect it is rewritten. Getting that wrong could cause make to rebuild the following items.
As I said earlier, you should be able to override the in-makefile assignment to $(CP) by putting it on the command line "make CP='cp -fp' xxxx", or maybe in the environment "CP='cp -fp' make xxx".
Or look at $PATH and add the script file "cp" containing:
#!/bin/sh
/bin/cp -p "$@"
in one of the first directories searched.