Add interface library but I want to copy my .dll in the same CMake

Hello everyone,
I’m currently doing a library that can be add in every project and just working directly without adding anything.
My project is quit easy, it’s just some header file, a .lib and a .dll, so nothing to compile.
Here is some code example :

cmake_minimum_required(VERSION 3.21.0)

project(Foo LANGUAGES CXX)

set(HEADER_FILES
	include/Foo-test.h
	include/Foo-test2.h
	include/Foo-test3.h
	include/Foo-test4.h
)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Header Files" FILES ${HEADER_FILES})

add_library(${PROJECT_NAME} INTERFACE ${HEADER_FILES})

target_link_libraries(Foo INTERFACE 
	${CMAKE_CURRENT_SOURCE_DIR}/lib/libfoo.lib
)

set_target_properties(Foo PROPERTIES LINKER_LANGUAGE CXX)

target_include_directories(Foo INTERFACE include)

set(FOO_DLL "${CMAKE_CURRENT_SOURCE_DIR}/bin/libfoo.dll" CACHE STRING "" FORCE)

#This function need to be add after the add_subdirectory of Foo
function(FooSetupDLLCopy ExecutableTarget)
	add_custom_command(
    	TARGET ${ExecutableTarget} POST_BUILD    
		COMMAND ${CMAKE_COMMAND} -E copy_if_different "${FOO_DLL}" "$<TARGET_FILE_DIR:${ExecutableTarget}>"
    	COMMAND_EXPAND_LISTS
  	)
endfunction()

But as you can see, because my library is an INTERFACE, I don’t have the PostBuild event, because there is no source code to compile, so I need to add a Function after the call of add_subdirectory of Foo with the ExecutableTarget that have the PostBuild Event.

Is there any clean way, to do the copy paste of the .dll directly in CMake of my project so I can just do add_subdirectory and everything is working directly?

Thanks a lot for your help,

Mathieu.

It looks like you’re trying to add a pre-compiled shared library. I suggest you use the IMPORTED keyword instead of INTERFACE. For example:

add_library(Foo SHARED IMPORTED)
set_target_properties(Foo PROPERTIES
    IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/bin/libfoo.dll"
    IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfoo.lib"/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2${CMAKE_STATIC_LIBRARY_SUFFIX}
    IMPORTED_LOCATION_DEBUG  "${CMAKE_CURRENT_SOURCE_DIR}/bin/libfoo.dll"
    IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfood.lib"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include"
)

The example above tells CMake to import a shared library, and gives it the location of all the files. You can then copy the DLL to the same directory as the executable by using the following:

# Copy DLL files on platforms where it's needed
if(CMAKE_IMPORT_LIBRARY_SUFFIX)
  add_custom_command(
    TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:${PROJECT_NAME}> $<TARGET_FILE_DIR:${PROJECT_NAME}>
    COMMAND_EXPAND_LISTS
  )
endif()

NOTE: It’s better to use ${CMAKE_STATIC_LIBRARY_PREFIX}, {CMAKE_STATIC_LIBRARY_SUFFIX}, and their shared library equivalents rather than hardcoding “lib” prefixes and “.dll” suffixes. I haven’t done it above to keep the example as simple as possible.

P.S., I cover how to link to pre-compiled libraries (and a lot more) in my CMake Tutorial book, which you can check out here: https://cmaketutorial.com/