当前位置: 首页 > news >正文

淮安市城市建设档案馆网站大连网站制作的

淮安市城市建设档案馆网站,大连网站制作的,湖南人文科技学院继续教育学院,电商平台运营公司文章目录 1. 目的2. 设计整体思路多层依赖的处理获取 DLL 所在目录探测剩余的 DLL 文件 3. 代码实现判断 stack 是否为空判断 stack 是否为空获取所有 target检测并拷贝 DLL 4. 使用 1. 目的 在基于 CMake 构建的 C/C 工程中#xff0c;拷贝当前工程需要的每个DLL文件到 Visu… 文章目录 1. 目的2. 设计整体思路多层依赖的处理获取 DLL 所在目录探测剩余的 DLL 文件 3. 代码实现判断 stack 是否为空判断 stack 是否为空获取所有 target检测并拷贝 DLL 4. 使用 1. 目的 在基于 CMake 构建的 C/C 工程中拷贝当前工程需要的每个DLL文件到 Visual Studio 工程的启动路径下 让可执行目标在运行阶段正常运行解决“DLL找不到”导致的程序终止、异常退出等问题解决“每次都要手动拷贝有时候忘记拷贝”的问题。 举例 OpenCV 官方预编译版本包含的 opencv_world.dll, 以及读取某些视频时需要的 opencv_ffmpeg dll 文件windows-pthreads 的 DLL 文件其他依赖库当中提供的 DLL 文件 实际上不仅限于 Windows 平台的 DLL 在 Linux / MacOSX 上也同样有这样的问题此时只需要增加 .so 和 .dylib 文件后缀的动态库支持即可。 本文给出基于 CMake 语言的解决方案。 2. 设计 整体思路 枚举所有 target 筛选出 SHARED_LIBRARRY 类型的 target 获取它们的动态库的路径 shared_library_path, 然后拷贝到用户指定的目录 dstDir. 此外有些 dll 文件并没有被 xxx-config.cmake 等配置文件所配置 需要额外扫描和拷贝例如 opencv 预编译库中的 ffmpeg 的 dll 文件。 多层依赖的处理 有时候工程比较复杂 target 至少包括三层 最后一层是可执行文件 第二层可能没有DLL但第二层依赖的第一层则可能存在DLL文件这就导致枚举 target 时不能只枚举一层。换言之枚举 target 的过程是一个递归过程 需要使用深度优先搜索 DFS 算法。 获取 DLL 所在目录 这个问题比较简单 用 cmake 的 get_target_property 函数获取。 探测剩余的 DLL 文件 包括两种情况 target 本身是动态库类型 那么它的 DLL 文件所在的目录应该被扫描扫描出的新的 DLL 文件也应该被拷贝target 本身是静态库类型 但它所在目录的上一级目录中 有一个 bin 目录 bin 目录里存放有 DLL 文件 3. 代码实现 代码实现过程中遇到一些“难点”主要是对 cmake 不够足够熟悉 简单列举 判断 stack 是否为空 DFS 算法的实现过程中 怎样判断 stack 为空获取 stack 首部元素依赖于对 list 的操作 包括将“列表是否为空”封装为函数 # # Determine if a list is empty # # Example: # cvpkg_is_list_empty(testbed_requires testbed_requires_empty) # message(STATUS testbed_requires_empty: ${testbed_requires_empty}) #---------------------------------------------------------------------- function(cvpkg_is_list_empty the_list ret)list(LENGTH ${the_list} the_list_length)if(${the_list_length} EQUAL 0)set(${ret} TRUE PARENT_SCOPE)else()set(${ret} FALSE PARENT_SCOPE)endif() endfunction()判断 stack 是否为空 通过判断元素是否在列表中来实现。封装为了函数 # # Determine if item is in the list # # Example: # cvpkg_is_item_in_list(testbed_requires protobuf protobuf_in_the_lst) # message(STATUS protobuf_in_the_lst: ${protobuf_in_the_lst}) # # cvpkg_is_item_in_list(testbed_requires opencv opencv_in_the_lst) # message(STATUS opencv_in_the_lst: ${opencv_in_the_lst}) #---------------------------------------------------------------------- function(cvpkg_is_item_in_list the_list the_item ret)list(FIND ${the_list} ${the_item} index)if(index EQUAL -1)set(${ret} FALSE PARENT_SCOPE)else()set(${ret} TRUE PARENT_SCOPE)endif() endfunction()获取所有 target 原本的依赖关系是 hierarchical 的 怎样拍平得到一维的依赖列表并且不能有重复元素答案是用 DFS。 # # 4. Recursively get required packages for a package. No duplicated. # # Example: # cvpkg_get_flatten_requires(testbed flatten_pkgs) # message(STATUS flatten_pkgs: ${flatten_pkgs}) #---------------------------------------------------------------------- function(cvpkg_get_flatten_requires input_pkg the_result)list(LENGTH input_pkg input_pkg_length)if(NOT (${input_pkg_length} EQUAL 1))cvpkg_error(input_pkg should be single element list)endif()set(visited_pkgs )set(pkg_stack ${input_pkg})while(TRUE)cvpkg_is_list_empty(pkg_stack pkg_stack_empty)if(${pkg_stack_empty})break()endif()cvpkg_debug(pkg_stack: ${pkg_stack})# pop the last elementlist(POP_BACK pkg_stack pkg)cvpkg_debug(pkg: ${pkg})# mark the element as visitedcvpkg_is_item_in_list(visited_pkgs ${pkg} pkg_visited)if(NOT ${pkg_visited})cvpkg_debug( visiting ${pkg})list(APPEND visited_pkgs ${pkg})# traverse its required dependencies and put into pkg_stackget_target_property(subpkgs ${pkg} LINK_LIBRARIES)cvpkg_debug(LINK_LIBRARIES: ${subpkgs})if(subpkgs)foreach(subpkg ${subpkgs})if(TARGET ${subpkg}) # if called target_link_libraries() more than once, subpkgs contains stuffs like ::(000001FAFA8C75C0)cvpkg_debug( subpkg: ${subpkg})list(APPEND pkg_stack ${subpkg})endif()endforeach()endif()get_target_property(subpkgs ${pkg} INTERFACE_LINK_LIBRARIES)cvpkg_debug(INTERFACE_LINK_LIBRARIES: ${subpkgs})if(subpkgs)foreach(subpkg ${subpkgs})if(TARGET ${subpkg}) # if called target_link_libraries() more than once, subpkgs contains stuffs like ::(000001FAFA8C75C0)cvpkg_debug( subpkg: ${subpkg})list(APPEND pkg_stack ${subpkg})endif()endforeach()endif()endif()endwhile()list(POP_FRONT visited_pkgs visited_pkgs)set(${the_result} ${visited_pkgs} PARENT_SCOPE) endfunction()检测并拷贝 DLL 这是代码最多的函数 不过思路上前面已经提到过 并不复杂。 代码多的几个原因 支持 .dll 的同时 要支持 .so 和 .dylibwindows 上的 target 可能 debug 和 release 库的文件不是同一个都需要拷贝因此需要枚举5个属性 set(prop_lst IMPORTED_LOCATION;IMPORTED_LOCATION_DEBUG;IMPORTED_LOCATION_RELEASE)去重 拷贝过的文件要忽略 重复的目录要合并 Talk is cheap, show me the code: # # Copy imported lib for all build types # Should only be used for shared libs, e.g. .dll, .so, .dylib # # Example: # cvpkg_copy_imported_lib(testbed ${CMAKE_BINARY_DIR}/${testbed_output_dir}) #---------------------------------------------------------------------- function(cvpkg_copy_imported_lib targetName dstDir)set(prop_lst IMPORTED_LOCATION;IMPORTED_LOCATION_DEBUG;IMPORTED_LOCATION_RELEASE)if(NOT (TARGET ${targetName}))return()endif()if(CMAKE_SYSTEM_NAME MATCHES Windows)set(shared_library_filename_ext .dll)elseif(CMAKE_SYSTEM_NAME MATCHES Linux)set(shared_library_filename_ext .so)elseif(CMAKE_SYSTEM_NAME MATCHES Darwin)set(shared_library_filename_ext .dylib)endif()get_target_property(pkg_type ${targetName} TYPE)if(NOT (${pkg_type} STREQUAL SHARED_LIBRARY))if(${pkg_type} STREQUAL STATIC_LIBRARY)if(CMAKE_SYSTEM_NAME MATCHES Windows)set(static_library_filename_ext .lib)elseif(CMAKE_SYSTEM_NAME MATCHES Linux)set(static_library_filename_ext .a)elseif(CMAKE_SYSTEM_NAME MATCHES Darwin)set(static_library_filename_ext .a)endif()### for static library targets, there might be bin directory, parallel to lib directory.# 先获取静态库文件路径foreach(prop ${prop_lst})get_target_property(static_library_path ${pkg} ${prop})if(static_library_path)# 获取静态库所在目录get_filename_component(static_library_live_directory ${static_library_path} DIRECTORY)# 获取静态库目录的上层目录get_filename_component(static_library_parent_directory ${static_library_live_directory} DIRECTORY)set(candidate_bin_dir ${static_library_parent_directory}/bin)# 判断上层目录是否存在 bin 目录, 如果存在 bin 目录 执行扫描和拷贝if(EXISTS ${candidate_bin_dir})set(glob_pattern ${candidate_bin_dir}/*${shared_library_filename_ext})file(GLOB shared_library_path_lst ${glob_pattern})foreach(shared_library_path ${shared_library_path_lst})list(APPEND copied_shared_library_path_lst ${shared_library_path})cvpkg_info(Copy ${shared_library_filename_ext} file (for static library, we detect and copy them!))cvpkg_info( - shared library file: ${prop}${static_library_path})cvpkg_info( - dstDir: ${dstDir})execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${shared_library_path} ${dstDir})endforeach()endif()endif()endforeach()endif()return()endif()### copy as the package description file (xxx-config.cmake or xxx.cmake) decribedset(pkg ${targetName})set(copied_shared_library_path_lst )foreach(prop ${prop_lst})cvpkg_debug(!! prop: ${prop})get_target_property(shared_library_path ${pkg} ${prop})if(shared_library_path)list(APPEND copied_shared_library_path_lst ${shared_library_path})cvpkg_info(Copy ${shared_library_filename_ext} file)cvpkg_info( - package(target): ${pkg})cvpkg_info( - prop: ${prop}${shared_library_path})cvpkg_info( - dstDir: ${dstDir})execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${shared_library_path} ${dstDir})endif()endforeach()### copy un-tracked shared library files that under same directory of each tracked shared library filescvpkg_is_list_empty(copied_shared_library_path_lst copied_shared_library_path_lst_empty)if(${copied_shared_library_path_lst_empty})return()endif()# get directories of each copied shared library filesset(shared_library_live_directory_lst )foreach(copied_shared_library_path ${copied_shared_library_path_lst})get_filename_component(shared_library_live_directory ${copied_shared_library_path} DIRECTORY)list(APPEND shared_library_live_directory_lst ${shared_library_live_directory})endforeach()# remove duplicated directorieslist(REMOVE_DUPLICATES ${shared_library_live_directory_lst})# for each candidate directory, scan shared library filesforeach(shared_library_live_directory ${shared_library_live_directory_lst})set(glob_pattern ${shared_library_live_directory}/*${shared_library_filename_ext})file(GLOB shared_library_path_lst ${glob_pattern})foreach(shared_library_path ${shared_library_path_lst})# if the scanned shared library file is not copied, do a copycvpkg_is_item_in_list(copied_shared_library_path_lst ${shared_library_path} shared_library_already_copied)if(NOT shared_library_already_copied)list(APPEND copied_shared_library_path_lst ${shared_library_path})cvpkg_info(Copy ${shared_library_filename_ext} file (xxx-config.cmake forget this file, but we copy them!))cvpkg_info( - package(target): ${pkg})cvpkg_info( - prop: ${prop}${shared_library_path})cvpkg_info( - dstDir: ${dstDir})execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${shared_library_path} ${dstDir})endif()endforeach()endforeach()endfunction()4. 使用 从使用的角度非常简单:调用 cvpkg_copy_required_dlls() 函数即可它的实现代码为 # # Recursively copy required DLL files into destination directory # # Example: # cvpkg_copy_required_dlls(testbed ${CMAKE_BINARY_DIR}) # cvpkg_copy_required_dlls(testbed ${CMAKE_BINARY_DIR}/${testbed_output_dir}) #---------------------------------------------------------------------- function(cvpkg_copy_required_dlls targetName dstDir)cvpkg_get_flatten_requires(testbed flatten_pkgs)#cvpkg_debug(flatten_pkgs: ${flatten_pkgs})message(STATUS flatten_pkgs: ${flatten_pkgs})foreach(pkg ${flatten_pkgs})cvpkg_copy_imported_lib(${pkg} ${dstDir})endforeach() endfunction()调用代码为: cvpkg_copy_required_dlls(testbed ${CMAKE_BINARY_DIR})
http://www.hkea.cn/news/14575411/

相关文章:

  • 百度手机网站建设wordpress首页悬浮框
  • 建设网站用什么语言好h5长页面怎么制作
  • 学院网站建设功能如何建立网站空间
  • 流行网站设计免费国外医疗静态网站模板下载
  • 中国建设银行开放式网站长沙网站制作有哪些公司
  • 中国风网站建设如何快速制作一个网站
  • 专业的企业智能建站比较好wordpress关键词标签
  • 怎样在微信上做网站网站建设必学课程
  • 移动4G网站建设ppt做的比较好的网站有哪些
  • 怎么建设网站上传音乐小企业网站建设平台
  • 宝塔软件做网站在哪个网站做问卷好
  • 网站seo优化是什么无锡网站策划
  • 投票网站制作求个网站谢谢啦
  • 网站的域名可以修改吗个人网站自助建站
  • 制作付费下载网站免费流量网站推广
  • 顺德网站建设公司价位网站建设选择本地
  • 网站建设收费标准精英淘宝网页是如何设计那么多的
  • 天津网站建设服务公司专业企业网站建设价格
  • 为什么python不适合开发网站前端做网站需要
  • 自己做的网站慢是什么原因廉江网站开发公司
  • 湘潭做网站出色磐石网络变量命名网站
  • 张家界做旅游网站邢台网站建设设计制作
  • 网站制作案例图片外贸网页设计公司
  • 装修公司做网站好做吗扶贫网站建设
  • 保定专门做网站重庆必玩景点排名
  • 营销型外贸网站广州wordpress重新配置ftp
  • 笔记本做网站服务器报价单模板表格
  • 如何建设传奇网站西安市网站
  • 南县做网站网站备案号怎么看
  • 创世网站建设公司英文网站建设之后怎么推