0

I am currently in the process of porting a Linux codebase on Windows. I finally got everything to compile and run, except for one thing: I do not know how to handle .dll files. So far I have been copying them manually because I was working on a single cmake configuration, but this is far from ideal.

So my question is: how can I make my executable work with CMake ? As far as I understand, DLL files HAVE to be in the same directory, so I probably need to copy them, but I do not understand the proper way to do it. I have been googling and results were not very satisfying (usually they had code snippets for specific libs and it seemed relatively 'quick and dirty').

I have multiple dependencies I need to get dlls from, most notably OpenCV, Qt, openssl, etc.

Is there a way to do it in a "generic" way, as in getting a property from an imported target and copying it ? I don't really want to explicitly list every single .dll...

In my CMakeLists I handle my dependencies using Find_Package and using target_link_libraries with the imported target.

I'm just wondering what is the best way to do this, or if I am doing something fundamentally wrong.

Edit: Consider the following CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)

project ("OpenCV_HelloWorld")

find_package(OpenCV 4.4.0 REQUIRED COMPONENTS core imgproc video)


# Add source to this project's executable.
add_executable (OpenCV_HelloWorld OpenCV_HelloWorld.cpp OpenCV_HelloWorld.h) # pretty much empty files, the main just declares a cv::Mat
target_link_libraries(OpenCV_HelloWorld ${OpenCV_LIBS} )

This compiles properly, however, when trying to run it I get a message saying I need opencv_core440.dll. What would be the best way to correct this ?

jacky la mouette
  • 523
  • 4
  • 17
  • dll don't have be in same directory. they may be in PATH. – Jarod42 Nov 10 '21 at 15:06
  • Providing sample CMakeList.txt might help. – Jarod42 Nov 10 '21 at 15:07
  • Does [this](https://stackoverflow.com/questions/10671916/how-to-copy-dll-files-into-the-same-folder-as-the-executable-using-cmake) answer your question? – badProgrammer0123456 Nov 10 '21 at 15:07
  • @Jarod42 I see. Is modifying PATH common practice on windows? I remember there being limitations, like relatively short length. As for my CMakeLists it's rather long so I'm not sure posting it would be relevant, I'm just asking about what the best practices are. I'm asking in general, how do people do it, not for my case specifically. So even for something as simple as just linking a simple target with OpenCV::OpenCV would have the same problem. Sorry if I'm not very clear. – jacky la mouette Nov 10 '21 at 15:28
  • Unclear for me if you rebuild your 3rd party, or expect them installed (and how). `FindXXX` provide several variables. – Jarod42 Nov 10 '21 at 15:32
  • Ah yes sorry. Well I expect the dependencies to be installed on the machine and that they provide either a find script or a config file. So I build them all independently beforehand. Is this a bad thing ? – jacky la mouette Nov 10 '21 at 15:38
  • So if there are installed, in the same way the .so files should be accessible, .dll files should be too. – Jarod42 Nov 10 '21 at 15:40
  • I'm not sure I understand. I'm supposed to copy them yes ? Because .so files can be linked from anywhere and CMake just handles it on its own when I link the targets. Maybe I should have specified that they are outside my project directory. The answer linked by @badProgrammer0123456 is the other way around as far as I understand it ? Sorry I am very confused maybe my posts don't make much sense – jacky la mouette Nov 10 '21 at 15:45
  • @Jarod42 I have added a snippet to my main question, if you want to check. Thank you. – jacky la mouette Nov 10 '21 at 16:06
  • Depending on the imported lib you can retrieve the `IMPORTED_LOCATION` or `IMPORTED_LOCATION_` target properties which provides you with the absolute path to the dll. Use `get_filename_component(DIRECTORY)` to get the directory containing the dll and concatenate all of those prefixing the whole thing to the path in the debugger environment. Theoretically you need to do this recursively, but usually there's only a single dir per installation providing all necessary dlls. `set_target_properties(OpenCV_HelloWorld PROPERTIES VS_DEBUGGER_EINVIRONMENT "PATH=${MY_PATH};$ENV{PATH}")` – fabian Nov 10 '21 at 18:53

1 Answers1

2

I have managed to partly solve this problem using CMake 3.21's $<TARGET_RUNTIME_DLLS:tgt> generator expression. However, this will only work if the libraries tgt links with are properly set as SHARED. In theory, this will handle all dependencies. In real life, a lot of package config files were written with UNKNOWN type instead of shared, so these will have to be handled individually.

jacky la mouette
  • 523
  • 4
  • 17