【cmake实战十二:cmake问题集锦】LNK1104: 无法打开文件“xxxxxxxxx.lib”

news/2024/11/24 21:43:54/

【cmake实战十二:cmake问题集锦】LNK1104: 无法打开文件“xxxxxxxxx.lib”

  • 一、问题1:==编译时报错==,LNK1104: 无法打开文件“xxxxxxxxx.lib”
    • 1、问题分析
    • 2、解决方案
      • 2.1、方案一:link_directories
      • 2.2、方案二:target_link_libraries
    • 3、link_directories和target_link_libraries的区别
    • 4、其他方案
  • 二、问题2:关于 include_directories
    • 1、情况描述
    • 2、问题:porjectB引用的porjectC的头文件都是红色
    • 3、问题解决
    • 4、总结
  • 三、问题3:==cmake时报错==,get_target_property() called with non-existent target
    • 1、描述
    • 2、问题描述==cmake时报错==:get_target_property() called with non-existent target “xxxx”.
    • 3、问题原因
    • 4、解决方案
  • 四、问题4:==编译和安装时报错==setlocal
    • 1、原因1:对生成目录没有写入权限
    • 2、原因2:对生成的进程程序没有权限
    • 3、原因3:要install的文件不存在、or路径不正确
    • 4、原因4:要install文件被其他进程占用。
    • 5、总结:setlocal解决方案汇总如下:
  • 五、问题5:==编译时报错==无法解析的外部符号
    • 1、情况描述
    • 2、问题:无法解析的外部符号struck google:protobuf:
    • 3、原因分析
    • 4、解决方案
    • 后记:

一、问题1:编译时报错,LNK1104: 无法打开文件“xxxxxxxxx.lib”

  • 本周五新写了一个网络客户端的项目(cmake),编译时报错如下

LNK1104: 无法打开文件“libboost_data_time-vc141-mt-gd-x64-1_73.lib”

1、问题分析

由于公司产品框架依赖较多,应该是我引用的某个项目用到了boost库,编译链接时找不到对应的lib,所以报错“LNK1104: 无法打开文件“libboost_data_time-vc141-mt-gd-x64-1_73.lib”

2、解决方案

公司项目是不可以放出来的,用我自己之前写的一个小demo,具体说明下如何解决。

2.1、方案一:link_directories

  • 把boost库的lib路径,链接到当前项目。(也就是把上面报错的“xxxxxxxxx.lib”路径,链接到当前项目路径。
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)PROJECT(NEWHELLO)# link directories
link_directories("${BOOST_LIBRARY_PATH}") #BOOST_LIBRARY_PATH代表你设置的boost库lib的路径,否则会报错找不到lib# 将指定目录添加到编译器的头文件搜索路径之下
include_directories("${BOOST_INCLUDE_PATH}") #${BOOST_INCLUDE_PATH}代表要用到的boost库头文件的路径ADD_EXECUTABLE(hello main.cpp)

2.2、方案二:target_link_libraries

  • 链接报错的“xxxxxxxxx.lib”库
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)PROJECT(NEWHELLO)include_directories("${BOOST_INCLUDE_PATH}")ADD_EXECUTABLE(hello main.cpp)# link librarytarget_link_libraries(hello "${BOOST_LIBRARY_PATH}/xxxxxxxxx.lib")

3、link_directories和target_link_libraries的区别

  • link_directories:应该放到生成二进制文件前。

放到ADD_EXECUTABLE前,本代码生成的是可执行进程。

  • target_link_libraries:因为要放到生成二进制文件后。

放到ADD_EXECUTABLE后,如果是动态库类似

4、其他方案

  • 因为我们项目使用的CMakeLists.txt管理项目的,所以我这里讲解的是cmake的方式,当然link_directories和target_link_libraries也都可以在visual studio中配置,我就不在这里讲解了,大家可以自行查找下在visual studio中配置对应的解决方案。

二、问题2:关于 include_directories

在写代码的过程种,还遇到了一个和include_directories相关的问题。

1、情况描述

  • 我写的是项目A,porjectA
  • 项目A用到了项目B,projectB
  • 而项目B又用到了项目C,projectC

2、问题:porjectB引用的porjectC的头文件都是红色

  • 从porjectA进入porjectB时,发现porjectB引用的porjectC的头文件都是红色的,也就是说,porjectB没有把porjectC头文件包进来。
  • 我们查看项目B的CMakeLists.txt,发现porjectB已经把porjectC的头文件包进来了,porjectB使用了include_directories(“${projectC_INCLUDE_PATH}”)

3、问题解决

  • porjectA的CMakeLists.txt中也使用include_directories(“${projectC_INCLUDE_PATH}”),然后就好了。

4、总结

  • 在《1、情况描述》中说的这样的情况下,porjectA的CMakeLists.txt,需要包括porjectB的CMakeLists.txt中的include_directories。
  • 这样是否合理呢?个人认为不太合理,但是目前验证的就是这样一个情况,后续有新的理解,再更新

三、问题3:cmake时报错,get_target_property() called with non-existent target

1、描述

  • 我写的是项目A,porjectA
  • 项目A用到了项目B,projectB

2、问题描述cmake时报错:get_target_property() called with non-existent target “xxxx”.

get_target_property() called with non-existent target “xxxx”.Call Stack (most recent call first):

xxxx代表我们生成的某个项目,比如本项目projectB

3、问题原因

  • 在添加porjectA、projectB的CMakeLists.txt中,我们书写如下
add_subdirectory(projectB)
add_subdirectory(porjectA)

4、解决方案

因为porjectA依赖了projectB,所以应该先生成projectB

add_subdirectory(porjectA)
add_subdirectory(projectB)

四、问题4:编译和安装时报错setlocal

setLocal问题大致可以分为两类,一是没有权限,二是文件不存在。细分有以下四种情况。(具体原因可以从输出那查看)

1、原因1:对生成目录没有写入权限

  • 解决方案:给visual studio赋给写入目录的权限,比如项目建立在了c盘,就需要使用管理员启动visual studio

2、原因2:对生成的进程程序没有权限

  • 比如,我们要生成的进程A正在运行(或者被其他进程占用),这时我们是没有权限操作的,
  • 解决方案:把正在运行的程序A关闭。(也就是我们要生成的进程A)

3、原因3:要install的文件不存在、or路径不正确

  • 解决方案:把要install的文件放到我们CMakeLists.txt中写的路径下。

4、原因4:要install文件被其他进程占用。

我们知道同一个进程共享文件io和权限,但是不同进程就不行了。

  • 解决方案1:把占用安装文件的进程关闭
  • 解决方案2:重启电脑

5、总结:setlocal解决方案汇总如下:

  • 重启电脑(or关闭相关进程)
  • 检查install的文件是否存在
  • 检查install的路径是否错误

五、问题5:编译时报错无法解析的外部符号

  • 一般来说,这种的问题是由于没有链接的问题,或者链接的库找不到。但是此处并非是这样的。

1、情况描述

  • 我写的是项目A,porjectA
  • 项目A用到了项目B,projectB,(projectB中定义了很多导出的PB结构)

其中projectB的代码中如下

// projectB 代码
# ifdef PB_DLL_FLAG 
# define API __declspec(dllexport)
# else
# define API __declspec(dllimport)
# endif

其中projectB的CMakeLists.txt中如下

# projectB CMakeLists.txt
add_definitions(-DPB_DLL_FLAG )

其中projectA的CMakeLists.txt中如下

# projectA CMakeLists.txt
add_definitions(-DPB_DLL_FLAG )

2、问题:无法解析的外部符号struck google:protobuf:

编译是报错“无法解析的外部符号struck google:protobuf::EmptyDefaultTypeIernal google:protobuf::Empty_default_instance

3、原因分析

  • projectB的CMakeLists.txt中,添加add_definitions(-DPB_DLL_FLAG ),这样在编译时,代码中就可以使用PB_DLL_FLAG 了
  • 而根据代码中的逻辑,如果定义了PB_DLL_FLAG ,API 就是导出的接口__declspec(dllexport)
// projectB 代码
# ifdef PB_DLL_FLAG 
# define API __declspec(dllexport)
# else
# define API __declspec(dllimport)
# endif
  • 而我们在projectA的CMakeLists.txt中如下,就也把API也当作导出了,
# projectA CMakeLists.txt
add_definitions(-DPB_DLL_FLAG )
  • 其实我前面也说了,其实我的projectA是要使用projectB导出的PB类型,这就出问题了。所以projectA不应该定义add_definitions(-DPB_DLL_FLAG ),这样API 就是导入了,也就是__declspec(dllimport)

4、解决方案

把而我们在projectA的CMakeLists.txt中的“add_definitions(-DPB_DLL_FLAG )”删除,这样就是导入了。

后记:

前面讲解过__declspec(dllexport)、__declspec(dllimport)、add_definitions,但是并没有综合的使用过,且对__declspec(dllexport)、__declspec(dllimport)理解的都不深入,所以才会犯这样的错误。所以后面还会找一篇文章,深入细致的讲解下操作系统的dllexport、dllimport。


http://www.ppmy.cn/news/75177.html

相关文章

[CTF/网络安全] 攻防世界 view_source 解题详析

[CTF/网络安全] 攻防世界 view_source 解题详析 查看页面源代码方式归类总结 题目描述:X老师让小宁同学查看一个网页的源代码,但小宁同学发现鼠标右键好像不管用了。 查看页面源代码方式归类 单击鼠标右键,点击查看页面源代码: …

Start JDKFlightRecorder--人工翻译

可以同时运行多个JFR记录,并且每个JFR记录都可以使用不同的配置,你可以使用不同的JFR记录去捕获不同的事件集。但是,为了使JFR内部逻辑更加精简,生成的记录始终包含当时活动的所有记录的所有事件的并集。这意味着,运行…

Java中 动态代理的应用场景

Java中 动态代理的应用场景 动态代理的应用场景 动态代理的应用场景 \使用JDK动态代理的技术使用CGLIB动态代理的技术1Spring Cloud FeignHibernate 延迟加载2Spring Cloud OpenFeignMyBatis 缓存3Spring Cloud SecuritySpring 事务控制4Spring Cloud ContractSpring Cloud Zu…

UI自动化测试用例管理平台搭建

用到的工具:python3 django2 mysql RabbitMQ celery selenium python3和selenium这个网上很多教程,我不在这一一说明; 平台功能介绍: 项目管理:用于管理项目。每个项目可以设置多个环境,例如开发环境…

物联网网络通讯知识

RTU是什么 RTU英文全称Remote Terminal Units,中文全称为远程终端单元。远程终端设备(RTU)是安装在远程现场的电子设备,用来监视和测量安装在远程现场的传感器和设备。通俗理解就是能够编程的还可以将数据传输到服务器的工具。RTU内部是包含通讯模块的&…

libvirt job机制浅析

libvirt 中,job 机制用于处理和跟踪针对虚拟机域(domain)的长时间操作,如迁移、快照、保存,热插拔等。job 机制的主要目的是确保在同一时间只有一个长时间操作可以执行,从而避免竞争条件和不一致性问题。 …

JS中字符串一些常用的方法

以下是一些常用的 JavaScript 字符串操作方法,按照字母顺序进行分类: 字符串操作方法 charAt(position): 返回指定位置的字符。concat(string1, string2, …, stringN): 将两个或多个字符串连接起来。includes(searchString, position):判断…

【数据结构与算法篇】栈与队列(详解)附加Leetcode经典笔试题

​👻内容专栏:《数据结构与算法专栏》 🐨本文概括: 讲述数据结构栈与队列基本知识。 🐼本文作者:花 碟 🐸发布时间:2023.5.23 文章目录 一、栈1.栈的概念及结构2.栈的实现 二、有效的…