Generator expressions cmake: copying works in debu

2019-04-02 12:41发布

问题:

I am trying to figure out how to copy some libs depending on the config in cmake.

I tried this:

add_custom_command(TARGET Myapp
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
  $<$<CONFIG:Debug>:${_LIBS_DEBUG}> 
  $<$<CONFIG:Release>:${_LIBS_RELEASE}> 
  $<TARGET_FILE_DIR:MyApp>)

It copies libs in Debug but not in release:

  1. Is this supposed to be legal and should work?
  2. If it is not legal (I do not get error), how can I achieve the same effect?

回答1:

Turning my comments into an answer

What I normally do to debug those case is to add another COMMAND before the actual line in question that just echos the command line. In your case:

COMMAND ${CMAKE_COMMAND} -E echo 
    $<$<CONFIG:Debug>:${_LIBS_DEBUG}>
    $<$<CONFIG:Release>:${_LIBS_RELEASE}> 

I've run this a few tests and you will see that the $<1:...> and $<0:...> expressions are not evaluated.

So seeing this I was searching CMake's bug tracker database and this is a known issue and yet (as for CMake 3.5.2) unresolved: 0009974: CMake should support custom commands that can vary by configuration.

There are several ways proposed in this ticket that do work with existing versions of CMake.


In your case - until this issue is resolved and if you want to have it shell independent - I would do it the "old way" and call a CMake script:

CopyLibsByConfig.cmake.in

if (_CONFIG STREQUAL "Debug")
    file(COPY @_LIBS_DEBUG@ DESTINATION "${_DEST_PATH}")
else()
    file(COPY @_LIBS_RELEASE@ DESTINATION "${_DEST_PATH}")
endif()

CMakeLists.txt

...
configure_file(CopyLibsByConfig.cmake.in CopyLibsByConfig.cmake @ONLY)
add_custom_command(TARGET MyApp
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} 
    -D _CONFIG=$<CONFIG> 
    -D _DEST_PATH="$<TARGET_FILE_DIR:MyApp>"
    -P "${CMAKE_CURRENT_BINARY_DIR}/CopyLibsByConfig.cmake"
)

But the solution can very much depend on the files you want to copy to your binary output folder. And there are a lot of way doing it, like using install():

install(FILES ${_LIBS_DEBUG} CONFIGURATIONS Debug DESTINATION $<TARGET_FILE_DIR:MyApp>)
install(FILES ${_LIBS_RELEASE} CONFIGURATIONS Release DESTINATION $<TARGET_FILE_DIR:MyApp>)

set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)

Obviously that's not the way install() is meant to be used, so consider using the INSTALL or PACKAGE targets properly to distribute your application and all its dependencies.

And if we are talking about Visual Studio runtime DLLs you most likely want to take a look at the InstallRequiredSystemLibraries CMake module.



标签: c++ cmake