add_custom_command with generator config commands

I am trying to copy a pdb file on windows as part of a add_custom_commad

Since it only is generated in RelWithDebInfo and Debug my command looks like the following

COMMAND $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE_DIR:bif>/$<TARGET_FILE_BASE_NAME:bif>.pdb $<TARGET_FILE_DIR:MyApp>

Unfortunately the batch file command created for VS 2019 generates a call like this

""$"<1:C:\Program Files\CMake\bin\cmake.exe" 

Any ideas on the right way to format this?

I think you’re missing a trailing > at the end.

Looks like there was a cut and paste issue sorry.

    COMMAND $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE_DIR:bif>/$<TARGET_FILE_BASE_NAME:bif>.pdb" "$<TARGET_FILE_DIR:App>/imageformats" >

Note that variable splitting happens before genex parsing, so you have these arguments here:

  • $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:${CMAKE_COMMAND}
  • -E
  • copy_if_different
  • "$<TARGET_FILE_DIR:bif>/$<TARGET_FILE_BASE_NAME:bif>.pdb"
  • "$<TARGET_FILE_DIR:App>/imageformats"
  • >

You can use ; to separate it or do something like this:

set(pdb_copy_command
  ${CMAKE_COMMAND} -E copy_if_different
    "$<TARGET_FILE_DIR:bif>/$<TARGET_FILE_BASE_NAME:bif>.pdb"
    "$<TARGET_FILE_DIR:App>/imageformats")
add_custom_command(…
    COMMAND $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:${pdb_copy_command}>)

Additionally $<CONFIG:Debug,RelWithDebInfo> would be simpler.

Thanks Ill give it a try and let you know

And yes… the Debug,RelWithDebInfo is definitely easier, I couldnt find that on out there as a valid syntax. Very nice!

Unfortunately that didnt help. this is the current as variable and custom command

SET( _PDB_COPY_CMD 
	${CMAKE_COMMAND} -E
	copy_if_different 
	"$<TARGET_FILE_DIR:bif>/$<TARGET_FILE_BASE_NAME:bif>.pdb"
	"$<TARGET_FILE_DIR:App>/imageformats"
	)
add_custom_command( TARGET App POST_BUILD 
    COMMAND $<$<CONFIG:Debug,RelWithDebInfo>:${_PDB_COPY_CMD} >
    DEPENDS bif
    COMMENT "ADDING BIF Image Format Shared Library PDB file Library"
    )

and this is the generated output from the vcxproj

App/MediaManager.vcxproj:""$"&lt;1:C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/SABUtils/bif/Debug/bif.pdb" "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/App/Debug/imageformats" &gt;
App/MediaManager.vcxproj:""$"&lt;0:C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/SABUtils/bif/Release/bif.pdb" "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/App/Release/imageformats" &gt;
App/MediaManager.vcxproj:""$"&lt;0:C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/SABUtils/bif/MinSizeRel/bif.pdb" "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/App/MinSizeRel/imageformats" &gt;
App/MediaManager.vcxproj:""$"&lt;1:C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/SABUtils/bif/RelWithDebInfo/bif.pdb" "D:/Visual Studio/sb/github/scottaronbloom/MediaManager/build/App/RelWithDebInfo/imageformats" &gt;

Remove the space before the >. The genex needs to be a single argument for it to be parsed properly. The whole thing may need quoted, but my gut says it shouldn’t need to be.

Getting closer :slight_smile: removing the space and wrapping the command in quotes is a bit better

SET( _PDB_COPY_CMD 
	${CMAKE_COMMAND} -E
	copy_if_different 
	"$<TARGET_FILE_DIR:bif>/$<TARGET_FILE_BASE_NAME:bif>.pdb"
	"$<TARGET_FILE_DIR:App>/imageformats"
	)
add_custom_command( TARGET App POST_BUILD 
    COMMAND "$<$<CONFIG:Debug,RelWithDebInfo>:${_PDB_COPY_CMD}>"
    DEPENDS bif
    COMMENT "ADDING BIF Image Format Shared Library PDB file Library"
    )

But the final step (this one was easier to debug)… You need to add the COMMAND_EXPAND_LISTS to the add_custom_command

add_custom_command( TARGET MediaManager POST_BUILD 
    COMMAND "$<$<CONFIG:Debug,RelWithDebInfo>:${_PDB_COPY_CMD}>"
    DEPENDS bif
    COMMENT "ADDING BIF Image Format Shared Library PDB file Library"
	COMMAND_EXPAND_LISTS
    )

Thanks for all the help. How would a normal person debug this?

Other than knowing CMake variable expansion, parsing, and argument passing behaviors through hard-earned experience? Not sure (as that’s how I knew what to look for). Using cmake --trace-expand to see what is happening helps to see what arguments are actually being passed around. Knowing that literal spaces in genexes in source code basically invalidate them is the other piece of knowledge there.

Thanks. Ill try the --trace-expand next time.

I would be really great, if the add_custom_command had a CONFIGURATIONS option like install does

Now that we have configuration-dependent outputs for add_custom_command in all generators, this seems like a reasonable request to me at least.

1 Like

Do you know of any way to have a post build command that is a CMake functon?

for exmaple

FUNCTION( foo in1 in2 )
# do something in cmake that modifies something using config generators
endfnction

add_custom_command( TARGET xxx POST_BUILD
COMMAND foo $<$CONFIG:Debug:xxxx.pdb>> $<TARGET_FILE_DIR:MediaManager>
)

You can put the code you want to run into a script and use ${CMAKE_COMMAND} -P path/to/script.cmake (with -D flags as needed to pass information).

That is exactly what Im doing :frowning: I was hoping for a better way

In case you are interested. You can take a look at how I wound up using it.

You can take a look at two Files, InstallFile.cmake and FindInstallFile.cmake for the end result of whats going on.

Basically the InstallFile function is a wrapper around configure_file with COPYONLY that also reports on the file being updated or not.

InstallFile.cmake allows for it to be used directly with a -P