0

I have a folder structure with the following

mainfolder/
          folderA/a.dll
          folderB/subFolderB/subsubFolderB/b.dll
          folderC/c.dll

I want to get all DLLs which are in mainfolder, including sub folders.

I don't get any result by doing a GLOB_RECURSE on the mainfolder. The DLLs are definitely there before the code reaches the GLOB_RECURSE call. Here is what I am doing:

set(THIRDPARTY_INSTALLFOLDER ${CMAKE_BINARY_DIR}/3rdparty/${CMAKE_BUILD_TYPE})
file(GLOB_RECURSE THEDLLS ${THIRDPARTY_INSTALLFOLDER} "*.dll")
message(STATUS ${THEDLLS})

so the ${THIRDPARTY_INSTALLFOLDER} is the mainfolder I mentioned above. The output of the message with ${THEDLLS} is just nothing.

NOTE: After clean/rebuild/run cmake again it finds the DLLs which are in folderA but nothing more(nothing in folderB or folderC). And again, the DLLs are definitely created before the GLOB_RECURSE call but NOT before the CMakeLists.txt is called.

EDIT: Here is a working example. Be aware that it downloads the rather large library OpenCV. I used this because my main concern is that the DLLs are created in different folder structures depending on which system you built it, which is why copying the DLLs seems so difficult to me. To run this example, just create a CMakeLists.txt and a main.cpp with the following content:

CMakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(DownloadAndLinkOpenCV)
###First I define where to output .exe and DLLs if there were any
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/${CMAKE_BUILD_TYPE}/bin)
###This defines the INSTALL dir of OpenCV(Where to put DLLs etc.)
set(THIRDPARTY_INSTALLFOLDER ${CMAKE_BINARY_DIR}/3rdparty/${CMAKE_BUILD_TYPE})

####function to download and build external project from https://stackoverflow.com/questions/17446981/cmake-externalproject-add-and-findpackage
function (build_external_project target git_repo git_tag cmake_custom_args)
    message(STATUS "building ${target} this might take a while...")
    set(trigger_build_dir ${CMAKE_BINARY_DIR}/3rdparty_${target})
    file(MAKE_DIRECTORY ${trigger_build_dir} ${trigger_build_dir}/build)

    set(CMAKE_LIST_CONTENT "
    cmake_minimum_required(VERSION 3.13)
    include(ExternalProject)
    ExternalProject_Add(${target}
        GIT_REPOSITORY ${git_repo}
        GIT_TAG        ${git_tag}
        PREFIX ${target}
        CMAKE_ARGS ${cmake_custom_args}
    )
ExternalProject_Add_StepTargets(${target} build install)
add_custom_target(trigger_${target})
add_dependencies(trigger_${target} ${target})
")

file(WRITE ${trigger_build_dir}/CMakeLists.txt "${CMAKE_LIST_CONTENT}")

execute_process(COMMAND ${CMAKE_COMMAND} .. -G${CMAKE_GENERATOR}
    WORKING_DIRECTORY ${trigger_build_dir}/build
    )
execute_process(COMMAND ${CMAKE_COMMAND} --build .
    WORKING_DIRECTORY ${trigger_build_dir}/build
    )
message(STATUS "finished building ${target}!")
endfunction()

####build OpenCV
set(OPENCV_GIT_REPO https://github.com/opencv/opencv.git)
set(OPENCV_TAG 3.4.6)
set(OPENCV_CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${THIRDPARTY_INSTALLFOLDER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
build_external_project(opencv ${OPENCV_GIT_REPO} ${OPENCV_TAG} ${OPENCV_CMAKE_ARGS})
####finished building OpenCV now that it is built we can use find_package
set(OpenCV_DIR ${THIRDPARTY_INSTALLFOLDER})
find_package(OpenCV REQUIRED)

####finished 3rdparty building
add_executable(TestApplication main.cpp)
target_link_libraries(TestApplication ${OpenCV_LIBS})

####Now I want to copy the DLLs which were built but GLOB_RECURSE will not give me the name of all DLLs
####I specifically used OpenCV since the main problem is that it creates a more complex folder structure
####in the INSTALL dir. In my case it creates /x64/vc15/...the dlls (x64 is architecture and vc15 the compiler)
####I don't want to hard code the x64/vc15 string because anyone should be able to built it with any compiler
file(GLOB_RECURSE THEDLLS ${THIRDPARTY_INSTALLFOLDER} "*.dll")
message(STATUS ${THEDLLS})

main.cpp

#include <iostream>
#include <opencv2/core.hpp>
int main()
{
    cv::Mat Mat;
    std::cout<<"Hello World"<<std::endl;
}

Note that I use Qt Creator as IDE and the Visual Studio 2017 compiler

Captain GouLash
  • 1,257
  • 3
  • 20
  • 33
  • How are these DLLs created? Via a CMake command such as `add_custom_command()` or similar? – Kevin Jun 17 '19 at 14:10
  • Above the mentioned lines I create a new CMakeLists.txt (with file(WRITE....) which has ExternalProject_Add(...) inside and then I call cmake again on this file to build 3rdparty dependencies. – Captain GouLash Jun 17 '19 at 14:14
  • Basically I use this approach to create 3rdparty DLLs https://stackoverflow.com/questions/17446981/cmake-externalproject-add-and-findpackage – Captain GouLash Jun 17 '19 at 14:16
  • "And again, the DLLs are definitely created before the GLOB_RECURSE call but NOT before the CMakeLists.txt is called." - This is only possible with `execute_process` or other `file()` command. `ExternalProject_Add` is built during **build** process, not during *configuration* one. – Tsyvarev Jun 17 '19 at 15:11
  • @Tsyvarev yes you are right I do an execute_process which calls a different CMakeLists.txt which contains ExternalProject_Add – Captain GouLash Jun 17 '19 at 15:17
  • Usage of GLOB is not recommended. See https://stackoverflow.com/questions/46618281/automatically-detect-newly-added-source-file/46636669#46636669 – Th. Thielemann Jun 17 '19 at 15:20
  • so what would be a recommendation to use instead? The third party lib I use appends the version number to the resulting .dll file and also a "d" if it is debug or not "thirdparty346d.dll" for example. And there are more than 10 and in different folders. Should I hard code the "copy command" for each dll? – Captain GouLash Jun 17 '19 at 17:50
  • Please, prepare [mcve] which shows, among other things, `execute_process` calls which create the files. It is difficult to guess what can be wrong without reproducing the problem. – Tsyvarev Jun 17 '19 at 22:12
  • First of all, thank you for investing time on a complete stranger to solve his problem. I appreciate it very much. I edited the post with an example which you should be able to build – Captain GouLash Jun 18 '19 at 07:51

1 Answers1

0

After some additional thoughts I found the very simple solution to it. I did a wrong call to GLOB_RECURSE. Here is the snippet which is working and does what I want: Copying all DLLs inside a folder to a specific directory

####get all dlls in a folder including sub folders
####The wrong call was this one: 
####file(GLOB_RECURSE THEDLLS ${THIRDPARTY_INSTALLFOLDER} "*.dll")
file(GLOB_RECURSE THEDLLS "${THIRDPARTY_INSTALLFOLDER}/*.dll")
#####This will copy the DLLs to a folder
foreach(currentDLL ${THEDLLS})
    add_custom_command(TARGET TestApplication POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy
                    ${currentDLL}
                    ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endforeach(currentDLL)

The thing is GLOB_RECURSE does a complete path pattern matching.

Captain GouLash
  • 1,257
  • 3
  • 20
  • 33