Additinal Dependencies和#pragma comment(lib,"*.lib")的分析

网上、一些书上也写道,这两种方式作用一样。其实仔细分析,它们两者还是有非常大的差异的。

Additinal Dependencies和#pragma comment(lib,"*.lib")都是针对.lib文件的。

而.lib文件其实有两种。

一种是与DLL相关的,描述DLL中的函数入口地址等的,在这里两种方法作用一样。

一种是静态链接库,就是将静态库工程当前所有目标文件编译成一个二进制文件(通常是以.lib为扩展名)。Additinal Dependencies和#pragma comment(lib,"*.lib")在这静态库这里会体现出重大的不同。

假如我们有4个工程,静态库工程A,B,C和EXE工程D,B依赖A,C依赖B,D依赖C,D依赖于C。

#pragma comment(lib,"*.lib")

其作用是放置1个库的链接搜索记录到目标文件中,这个搜索记录排在默认搜索记录之后。可以在一个目标文件中放置多个搜索记录,其顺序依据于源码中添加的顺序。因为这行代码的作用只是指明链接时去相应的lib文件中查找相应函数的实现代码,只是一个记录指明的作用,并没有链接的作用。

lib工程并没有链接过程,只有编译过程。只有在生成DLL/EXE时,才会有链接过程的产生,将会将所有目标链接在一起。

因为没有链接过程,所以在编译B,C, D工程时并不需要指明其依赖的静态库(lib),只需要#include相应的头文件即可以编译生成lib文件。

那么在链接生成DLL/EXE时,则需要指明链接搜索记录。

可以在工程D中指明所有需要链接搜索的lib文件。

#pragma comment(lib,"A.lib")

#pragma comment(lib,"B.lib")

#pragma comment(lib,"C.lib")

这个时候才会真正完成链接过程,会检查函数是否定义了,是否重复定义等链接错误。

因为D表面看只依赖C,所以指明B.lib, C.lib感觉不太直观,更直观的可能是用到哪个lib添加哪个:

工程B中添加#pragma comment(lib,"A.lib")

工程C中添加#pragma comment(lib,"B.lib")

工程D中添加#pragma comment(lib,"C.lib")

Project Property->Additinal Dependencies->*.lib

这种方式附加lib文件,看起来效果与上面的方式一样,其实工作原理是不一样的,认识不清,容易产生一些问题。

AdditinalDependencies->*.lib分两种情况:

1、静态库工程中,Configuration Properties->Librarian->General->Additinal Dependencies

其作用是附加指定的lib文件至当前工程,并编译生成至当前的lib文件中。这种行为有点类似链接,但不是链接,只是将将指定lib文件合并到新的lib文件中来。

如果单独编译A, B, C, 它们均生成50K大小的lib文件。

工程B中Additinal Dependencies->A.lib

工程C中Additinal Dependencies->B.lib

那么B.lib将会是100K,C.lib将会是150K。可以看到是直接合并进来的。

但如果是如下设置:

工程B中Additinal Dependencies->A.lib

工程C中Additinal Dependencies->A.lib;B.lib

那么B.lib将会是100K,C.lib将会是200K。可以看到C.lib直接将A.lib,B.lib直接合并进来了,相当于合并了两份A.lib。这样会导致重复合并,VS编译器会提出warning LNK4006,already defined in *.obj;second definition ignored。虽然报出来的是一个链接警告,但其实并不是链接过程的。因为这样的情况很多,所以会出现非常多这类警告。MSDN对这类警告的有个相差描述:You can get this warning if you try to merge twoimport libs into one.就是指我们上面合并两个lib文件。

解决方法也分两种:

A、不合并多个lib文件成1个lib文件,则我们不需要在静态库工程中设置Additinal Dependencie。可以在DLL/EXE中通过

#pragma comment(lib,"*.lib")一次全部指明lib搜索记录,也可以在DLL/EXE工程中通过Additinal Dependencie一次附加所有涉及到的lib。如果想更直观点,用到哪个lib指明哪个,即分别在相应的lib工程里用#pragma comment(lib,"*.lib")指明相应的lib文件即可。

B、合并多个lib文件,工程B Additinal Dependencies->A.lib, 工程C Additinal Dependencies->B.lib即可。

2、DLL/EXE工程中,Configuration Properties->Linker->Input->AdditinalDependencies

可以看出,这里是在链接器下面的一个设置,也说明这里的附加是为链接完成的,即指明链接lib搜索记录,作用与#pragma comment(lib,"*.lib")一样,只不过在DLL/EXE中会产生链接过程。静态库中出现的重复重复定义、定义未实现均不会报错,但是链接过程中会检查这类错误,所以很多静态库中的错误会在DLL/EXE工程的链接结果中报出来。

时间: 2024-10-25 02:44:35

Additinal Dependencies和#pragma comment(lib,"*.lib")的分析的相关文章

[C/C++]pragma comment的使用

该宏放置一个注释到对象文件或者可执行文件. #pragma comment( comment-type [,"commentstring"] ) comment-type是一个预定义的标识符,指定注释的类型,应该是compiler,exestr,lib,linker之一.commentstring是一个提供为comment-type提供附加信息的字符串,Remarks:1.compiler:放置编译器的版本或者名字到一个对象文件,该选项是被linker忽略的.2.exestr:在以后的

pragma comment的使用(转

蜗牛の狂奔笔记 对于蜗牛来说,狂奔虽不代表极速,但展现的却是一种拼尽全力的姿态........ #pragma 的使用 尽管 C 和 C++ 都已经有标准,但是几乎每个编译器 (广义,包含连接器等) 扩展一些 C/C++ 关键字. 合理地应用这些关键字,有时候能使我们的工作非常方便.下面随便说说 Visual C++ 中 #pragma 指示符的使用. 一.用#pragma导出DLL函数     传统的到出 DLL 函数的方法是使用模块定义文件 (.def),Visual C++ 提供了更简洁方

pragma comment的使用 pragma预处理指令详解

pragma comment的使用 pragma预处理指令详解 #pragma comment( comment-type [,"commentstring"] ) 该宏放置一个注释到对象文件或者可执行文件.comment-type是一个预定义的标识符,指定注释的类型,应该是compiler,exestr,lib,linker之一.commentstring是一个提供为comment-type提供附加信息的字符串,Remarks:1.compiler:放置编译器的版本或者名字到一个对象

pragma comment的使用

#pragma 的使用 我们经常用到的是#pragma comment(lib,"*.lib")这类的. pragma comment(lib,"Ws2_32.lib")表示链接Ws2_32.lib这个库. 和在工程设置里写上链入Ws2_32.lib的效果一样,不过这种方法写的 程序别人在使用你的代码的时候就不用再设置工程settings了 转自 https://www.cnblogs.com/guoxiaoqian/p/3984972.html 原文地址:http

#pragma comment(转)

此文转自微软MSDN.注意这是在Windows上才有的,Linux上可没有. #pragma comment( comment-type [,"commentstring"] ) 备注 comment-type 是一个预定义的标识符(如下所述),它指定了注释记录的类型. 可选 commentstring 是一个字符串,它提供了某些注释类型的附加信息. 由于commentstring 是一个字符串,因此它遵循有关转义字符.嵌入的引号 (") 和串联的字符串的所有规则.  1.

pragma comment

pragma指令简介 在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作. 下面介绍了一下该指令的一些常用参数,希望对大家有所帮助! 一. message 参数. message 它能够在编译信息输出窗 口中输出相应的信息,这对于源代码信息的控制是非常重要的.其使用方法为: #pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来. 当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可

关于#pragma comment

#pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib")表示连接Ws2_32.lib这个库.和在工程设置里写上链入Ws2_32.lib的效果一样,不过这种方法写的程序,别人在使用你的代码时就不用再设置工程settings了.告诉连接器连接的时候要找ws2_32.lib,这样你就不用再linker的lib设置里指定这个lib了. 比如: #include "Mwic_32.h&qu

#include 和 #pragma comment 的相对路径起点

#include 是以当前文件所在路径为当前目录 #pragma comment 是以当前工程所在路径为当前目录 #include "../../../../ThirdParty/Include/REG/DH/dhnetsdk.h" #pragma comment(lib, "../../ThirdParty/Lib/REG/DH/dhnetsdk.lib") 如上,大华车牌识别仪的头文件和链接文件都在项目解决方案目录下的ThirdParty目录,而相对引用时当前目

quick-cocos2d-x教程8:程序框架内lib文件夹分析

lib文件夹是如今全部文件夹中最复杂的,包括了整个运行所需的库文件.我们简单看下,在开发初期,不须要深入到这个库里去研究 cocos2d-x 文件夹就是c++版的原始文件 framework_precompiled文件夹,就是放预编译好的framework_precompiled.zip文件,运行时,放在res文件夹中 luabinding文件夹,是放的这个接口的原始文件.打开build.bat文件,就能够看到用tolua++.exe 来调用生成 proj.android.proj.ios.pr