引子
使用VS编译C++程序经常会遇到这种情况:编译已经成功,没有报错;但是链接时报错,类似于:“error LNK2001!@#¥#¥@%#……@#¥%&*&¥%¥@#¥”。网上查到的相关文章和我实际遇到不太一样,在这里总结一下我所遇到的链接错误的解决方式。注:这里不明确指明error LNK的错误代码。
一、没有正确的配置XXX.lib
windows编译用到其他的dll库如XXX.dll,不但需要 .h的头文件,而且需要相应的 XXX.lib文件。之前查过说是这个XXX.lib文件是指明了函数的入口地址神马的,但为啥linux下就不需要呢?
回到问题本身,没有正确配置XXX.lib文件有以下几种可能:
a)没有在链接的附加依赖项中写入正确的XXX.lib(或者使用#param 在程序中设定);
b)搜索库文件的路径上XXX.lib不存在(库文件路径没有设置正确);
c)XXX.lib文件有多个版本,而库文件路径上那个版本与你头文件的版本不一致;
二、C++类的函数在头文件中声明了,但是在cpp文件中没有对应的定义。
这种错误比较容易发现。错误中会出现函数名。
三、VS的配置不正确
这个是刚发现,并且昨天折磨了我半个下午。
我们工程的一个solution中包含多个project,而且project之间有依赖关系——某些的project会用到一些基础project生成的lib。
之前的工程在VS2005上,项目依赖很简单,只要在项目点右键->项目依赖项中勾选被依赖的项目即可。
前几天新装电脑,把工程迁移到VS2013上。已有的旧project都没问题。但是新建项目(也是有项目依赖),总是会报error LNK2001或error LNK2019的链接错误。经过仔细对比新旧项目的差别,甚至对.vcxproj文件做diff排查,发现在VS2013中项目依赖要在通用属性->引用中设置。像VS2005那样只在项目依赖项中设置是不行的。具体的发现的过程如下:
- 首先排除了前面总结中第二种产生链接错误的可能,链接错误肯定是项目属性页中“连接器”项的某些项配置错了。于是将可以不报错的旧项目和新项目点开逐个页对比。在“命令行”选项卡中发现差别:
/DYNAMICBASE 项的参数中无链接错误的项目比有错误的多了几行,下图划红线的部分:
而画红线的部分正是项目所依赖project生成的lib。 - 对.vcxproj文件做diff
正常链接的项目多了以下的配置:<ProjectReference Include="..\ENOService\ENOService.vcxproj"> <Project>{050ad614-2864-4ca2-b878-e16d2b07ed33}</Project> <ReferenceOutputAssembly>false</ReferenceOutputAssembly> </ProjectReference> <ProjectReference Include="..\ENOUtils\ENOUtils.vcxproj"> <Project>{aa57406b-6277-443e-ba0b-8e782ee7ec07}</Project> <ReferenceOutputAssembly>false</ReferenceOutputAssembly> </ProjectReference>
而“ProjectReference Include”部分正是项目所依赖的project。
- 从上面的两点可以看出是项目依赖出了问题
但是项目依赖项已经配置了啊。问题在哪里呢?偶然间手贱,点开了正常链接项目的属性卡中第一项“通用属性”->“引用”:
而链接错误的项目中这一项是空白的。点击“添加新引用”对其进行设置,问题解决!
而且在这里引用了其他项目后,项目右键的“项目依赖项”中的选项是删不掉的。
- 总结
a)问题本质上来讲是没有正确配置lib——没有找到lib文件。
b)VS2005到VS2013有很多变化,但这个本来在2005中不要配置的项在2013中却要配置了算是被MS坑了?也可以说是我没跟上MS的步伐,out了~
c)IDE VS 纯文本。IDE在背后帮我们做了很多事。但是我们不了解(我自己水平差,理解不深)。而如果在linux下使用自己写Makefile可已很清楚知道工程所有编译的配置项。甚至当我使用文本编辑器打开了VS的.vcxproj文件,对其中的配置也是一目了然。现在我是越来越倾向于纯文本。IDE在随着版本的变化,哪里修改想要的配置?只能呵呵了。