【问题标题】:CMake GLOB_RECURSE not working as expectedCMake GLOB_RECURSE 未按预期工作
【发布时间】:2019-10-31 03:24:09
【问题描述】:

我的文件夹结构如下

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

我想获取主文件夹中的所有 DLL,包括子文件夹。

在主文件夹上执行 GLOB_RECURSE 没有得到任何结果。在代码到达 GLOB_RECURSE 调用之前,DLL 肯定就在那里。 这是我正在做的事情:

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

所以${THIRDPARTY_INSTALLFOLDER} 是我上面提到的主文件夹。带有${THEDLLS} 的消息的输出什么都没有。

注意: 再次清理/重建/运行 cmake 后,它会找到文件夹 A 中的 DLL,但仅此而已(文件夹 B 或文件夹 C 中没有)。同样,DLL 肯定是在调用 GLOB_RECURSE 之前创建的,而不是在调用 CMakeLists.txt 之前创建的。

编辑:这是一个工作示例。 请注意,它会下载相当大的 OpenCV 库。我使用它是因为我主要担心的是 DLL 是在不同的文件夹结构中创建的,具体取决于您构建它的系统,这就是为什么复制 DLL 对我来说如此困难的原因。要运行此示例,只需创建一个 CMakeLists.txt 和一个包含以下内容的 main.cpp:

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;
}

请注意,我使用 Qt Creator 作为 IDE 和 Visual Studio 2017 编译器

【问题讨论】:

  • 这些 DLL 是如何创建的?通过 add_custom_command() 或类似的 CMake 命令?
  • 在上面提到的行之上,我创建了一个新的 CMakeLists.txt (其中包含有 ExternalProject_Add(...) 的文件(WRITE....),然后我在这个文件上再次调用 cmake 来构建 3rdparty依赖关系。
  • 基本上我使用这种方法来创建 3rdparty DLL stackoverflow.com/questions/17446981/…
  • “同样,DLL 肯定是在调用 GLOB_RECURSE 之前创建的,而不是在调用 CMakeLists.txt 之前创建的。” - 这仅适用于execute_process 或其他file() 命令。 ExternalProject_Add 是在 build 过程中构建的,而不是在 configuration 过程中构建的。
  • @Tsyvarev 是的,你是对的,我做了一个 execute_process,它调用了一个不同的 CMakeLists.txt,其中包含 ExternalProject_Add

标签: c++ cmake glob


【解决方案1】:

经过一些额外的思考,我找到了非常简单的解决方案。我打错了 GLOB_RECURSE。这是正在工作并执行我想要的操作的 sn-p:将文件夹中的所有 DLL 复制到特定目录

####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)

问题是 GLOB_RECURSE 做了一个完整的路径模式匹配。

【讨论】:

    猜你喜欢
    • 2021-06-04
    • 2022-01-24
    • 2015-05-11
    • 2020-05-15
    • 2014-10-31
    • 2018-02-12
    • 2014-01-20
    • 2015-01-13
    • 2013-08-01
    相关资源
    最近更新 更多