1

I have a project that I am building using CMake for Visual Studio.
The .exe file requires 2 dll files (That I am copying to the Debug forlder for now).

Is there a way to add the dlls/ dlls directory through CMakeLists.txt / FindLibrary.cmake
(the same way it's done with find_library to find *.lib or in some other way that I ignore) so that I don't copy them MANUALLY inside the Debug folder each time I generate the project in another folder/pc (since the dll's folder is known)?

UPDATE :

CMakeLists.txt

..
..
set (ENVLIB $ENV{MYLIB})
FUNCTION (CONFIGURE_DEBUGGER TARGET_NAME)
  CONFIGURE_FILE(common/build/template/Main.vcxproj.user
    ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.vcxproj.user
    @ONLY
    )
ENDFUNCTION (CONFIGURE_DEBUGGER)
..
..
ADD_EXECUTABLE(Main Main.cxx)
CONFIGURE_DEBUGGER(Main)

Main.vcxproj.user

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerEnvironment>PATH=@ENVLIB@bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>

  <!-- Additional PropertyGroups for the rest of Configuration/Platform combos -->

</Project>

Output of vcxproj.user after generation
<LocalDebuggerEnvironment>PATH=C:\Program Files\MyLib\bin;$(Path)

The variable ENVLIB has been changed to the correct PATH when the file has been copied but
Visual studio is still asking for those DLLs. It's like it is ignoring the file .vcxproj.user

SOLVED :

Solved changed the property : <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> to
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

Mohamed Benmahdjoub
  • 1,270
  • 4
  • 19
  • 38
  • 1
    Question, why don't you put them in a folder that you then add to the PATH environment variable instead? Not a long term solution maybe and leaving your question still relevant, but as a short term solution? Aside from that, does https://stackoverflow.com/questions/17225121/how-to-use-external-dlls-in-cmake-project answer your question? – Aziuth Jan 04 '19 at 13:21
  • For the simple reason that I want it to be less work for others. Only if there's a way to add to the PATH environment variable from `CMakeLists.txt` / `FindLibrary.cmake` that would be good for me – Mohamed Benmahdjoub Jan 04 '19 at 13:39
  • 2
    Option 1: Make a custom target that runs a CMake script that copies the necessary files. Option 2: Generate (using `CONFIGURE_FILE`) a `.vcxproj.user` file that sets up `LocalDebuggerEnvironment` such that the directory with the DLLs is added to the `PATH`. (This is my preference, since I can also set up working directory and command line arguments to pass to the debugged application) – Dan Mašek Jan 04 '19 at 14:16
  • 2
    You can use `find_file()` and `add_custom_command()` to copy the `.dll` to the folder `${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}`. – fdk1342 Jan 04 '19 at 17:58
  • Gonna check both solutions (Dan & @Fred) as soon as possible ! Thanks ! – Mohamed Benmahdjoub Jan 04 '19 at 18:04

1 Answers1

1

First option would be to create a custom target, that will run a CMake script to copy the files.

The second option (which I prefer) is to use CONFIGURE_FILE to generate a .vcxproj.user file, which set up LocalDebuggerEnvironment such that the directory with the DLLs is added to the PATH.

For example, my build system defines a function CONFIGURE_DEBUGGER:

FUNCTION(CONFIGURE_DEBUGGER TARGET_NAME)
  CONFIGURE_FILE(${ROOT}/common/build/template/executable_vs14.vcxproj.user
    ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.vcxproj.user
    @ONLY
    )
ENDFUNCTION(CONFIGURE_DEBUGGER)

I call this function right after I define an executable target, e.g.

ADD_EXECUTABLE(example
  ${EXAMPLE__SRC}
  ${EXAMPLE__HDR}
)
CONFIGURE_DEBUGGER(example)

The template executable_vs14.vcxproj.user looks as follows:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>

  <!-- Additional PropertyGroups for the rest of Configuration/Platform combos -->

</Project>

Note: In the above example, I also set some default command arguments to run the app with when debugging as well as the working directory where it runs -- adjust things as you need.

Note 2: Now that I'm looking at it, perhaps we can change the Condition on the PropertyGroup to make it apply to every configuration/platform. Gotta look into that.

Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
  • I am going to test it in some time, Thanks for the effort! – Mohamed Benmahdjoub Jan 04 '19 at 18:01
  • 1
    @Calips Yeah, if you need them there at the time of generating the solution, rather than after the compilation, then this won't help. – Dan Mašek Jan 07 '19 at 12:03
  • Now that I think about it, in my case it isn't possible to use that, the reason is simple : I am using a `FindLibrary.cmake` file which for now uses an environment variable as `HINTS`(in `find_path()` and `find_library()`) to find the library directory (which contains the DLLs/bin folder). And since the `CONFIGURE_DEBUGGER` needs to be placed after `ADD_EXECUTABLE`, it's already late. – Mohamed Benmahdjoub Jan 07 '19 at 12:04
  • Supposing I can just use the DLLs later and keep The environment variable which points to the root of the library that has : `include`, `lib` and `bin` folders, can it be used to replace `SolutionDir` in : `PATH=$(SolutionDir)..\deps\bin;$(Path)` something like `PATH=@ENV ${VARIABLE_NAME}@\bin;$(Path)` ? – Mohamed Benmahdjoub Jan 07 '19 at 12:11
  • 1
    @Calips I think so, using the substitution capabilities of `CONFIGURE_FILE`. Not sure if you can use environment variable directly, but that shouldn't be a bit issue to overcome (just load it into regular CMake var). – Dan Mašek Jan 07 '19 at 12:14
  • Please Check the update section and tell me if there is anything I am missing ! Thanks in advance. – Mohamed Benmahdjoub Jan 07 '19 at 12:50
  • 1
    Solved changed the property : `` to `` – Mohamed Benmahdjoub Jan 07 '19 at 13:18
  • 1
    Thanks for the support @Dan – Mohamed Benmahdjoub Jan 07 '19 at 13:19