Let’s say I have two targets that I am working on Windows. Both of those targets include this CmakeLists.txt file as it is where the main executable is created for both of them. I use a visual studio generator for both of them.
One target has a dependency on some other external my_awesome.dll library that is linked to the executable and is its runtime dependency. The other target is just standalone main.cpp
So what happens is that target with the external library dependency will build successfully while the other will build but will error out at a post-build step. The reason is that TARGET_RUNTIME_DLLS will evaluate to an empty string and CMake will try to use that empty string as an argument for a CMake post-build copy command and will fail since the command will look malformed.
The copy command will look like below which will miss the actual DLL file that is needed to be copied.
Since there should be no DLL, I would expect that this post-build command should not even show up in the first place.
I think that cmake -E copy could have better syntax here. There is the cp -t <dest> flag which, if supported, would allow cmake -E copy -t $<TARGET_FILE_DIR:exe> $<TARGET_RUNTIME_DLLS:exe> which would work much better if the DLLS genex expands to nothing.
Note that the code example you have does not have any DLL dependencies, so it being empty is fine. I would first check that the imported targets you’re using actually know where their .dll file is (i.e., check the properties on the targets).
Sure, it could be improved (mainly be CMake providing better imported target utility bits myself). I’m just saying that there are times you’ll also actually have no dependencies and -E copy will fail.
Is there any plan to add this functionality? It seems easy and would really help simplify custom commands (even beyond this). I just bumped in to this exact issue today and wound up “fixing” it with an if (WIN32) check.
I think an issue would be the first step. But a solution would be accepted. I think best would be to add a -t <target dir> flag to cmake -E copy so that an otherwise-empty list of arguments still makes sense. That signature can then be used to do this.