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

成都解放号网站建设怎么网络推广自己业务

成都解放号网站建设,怎么网络推广自己业务,企业组织网站建设方案,seo做的最好的十个网站文章目录 1. 目的2. 设计整体思路多层依赖的处理获取 DLL 所在目录探测剩余的 DLL 文件 3. 代码实现判断 stack 是否为空判断 stack 是否为空获取所有 target检测并拷贝 DLL 4. 使用 1. 目的 在基于 CMake 构建的 C/C 工程中,拷贝当前工程需要的每个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 it's 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 和 .dylib
  • windows 上的 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.khdw.cn/news/15780.html

相关文章:

  • 中国建设银行官网站住房公积金全网搜索关键词查询
  • 返利的网站怎么做站长工具是干嘛的
  • wordpress post下载信息流广告优化师
  • 嘉兴建站模板厦门人才网唯一官方网站
  • 网站建设多少钱个人网络广告营销策划方案
  • 有专门做ppt的网站吗免费推广广告链接
  • 常州专业网站建设公司深圳网络推广培训
  • 黄山网站推广公司seo黑帽技术
  • 网站建设的风险浏览器2345网址导航下载安装
  • 网站优化怎么学永久免费自助建站平台
  • 魏县做网站一键优化大师下载
  • 做跨境电商网站有哪些重庆关键词快速排名
  • 做外贸都有哪些好网站如何做网站营销推广
  • 网站设计项目书跨境电商怎么开店铺
  • 成都网站建设公司官网网络推广方案的基本思路
  • 委托别人做网站 域名所有权厦门百度seo
  • 如何对django网站做测试谷歌搜索引擎香港入口
  • 中文安卓app开发工具seo网站排名全选
  • 查看网站用什么软件做的风云榜小说排行榜
  • wordpress 企业网站制作商城网站建设
  • 网站建设哪家专业武汉疫情最新情况
  • 企业门户网站建设方案书网站建设公司大型
  • 黃色视频做爰网站安全做微商怎么找客源加人
  • 做论坛网站赚钱吗网络营销方式有哪些分类
  • 做四级题目的网站公司网页怎么做
  • 企业免费网站模板合肥网络推广外包
  • 东源县住房和城乡建设部网站性价比高seo排名优化的
  • 门窗网站模板家庭优化大师
  • 关键词优化seo优化排名浙江seo外包
  • w3c验证网站最新国际新闻事件今天