84669 person learning
152542 person learning
20005 person learning
5487 person learning
7821 person learning
359900 person learning
3350 person learning
180660 person learning
48569 person learning
18603 person learning
40936 person learning
1549 person learning
1183 person learning
32909 person learning
把一些函数封装成静态库使用和直接使用源代码的方式使用,关于使用者编译出来的体积是使用静态库的编译后体积要比直接使用源码编译的大吗?或者体积没变化呢
认证高级PHP讲师
基本上没有区别。如果非要说有区别的话,就是你要把另一个项目的代码扔到自己的项目中,没有经过./configure之类的步骤,一些开关(一般是config.h里的宏)没有开启,然后导致编译出来不同。又或者说在别的机器上编译完的静态库搬到自己的机器上,别人的编译器版本比较新优化得比较好,又或者说别人的编译器架构和平台根本不同然后不能用。也就这些很显然的区别了。
./configure
为什么说没有区别的呢?我们来看看一般多文件编译的过程:
.cpp
.o
即便是加入静态库仍然没有什么区别,因为:静态库本身就只不过是.o文件的一个打包(Archive)。以GCC的ar为例,我们看看静态库.a里面究竟是什么:
.a
$ ar -t libfltk.a Fl.o Fl_Adjuster.o Fl_Bitmap.o Fl_Browser.o Fl_Browser_.o Fl_Browser_load.o Fl_Box.o Fl_Button.o Fl_Chart.o Fl_Check_Browser.o Fl_Check_Button.o Fl_Choice.o Fl_Clock.o Fl_Color_Chooser.o Fl_Copy_Surface.o Fl_Counter.o Fl_Dial.o Fl_Device.o Fl_Double_Window.o Fl_File_Browser.o Fl_File_Chooser.o Fl_File_Chooser2.o Fl_File_Icon.o Fl_File_Input.o Fl_Group.o Fl_Help_View.o Fl_Image.o Fl_Image_Surface.o ...
真相就是,里面就是一大堆的.o。从源代码编译(第一步)也是生成一大堆.o,从静态库里解包也是生成一大堆相同的.o,其余的步骤完全是没有区别的。换句话说,比如你有一个libexample.a,它里面有src1.o和src2.o两个目标文件。你在链接的时候用ld -lexample开关链接一个静态库,和你先用ar -x libexample.a解包,然后用ld src1.o src2.o链接是完全一样的。
libexample.a
ld -lexample
ar -x libexample.a
ld src1.o src2.o
没有用到的符号将会被自动削除,所以跟直接从源码编译相比,也不会对体积有影响。
这里我全程在说GNU家族的东西,如果你是想了解微软家族的东西的话,对不起爱莫能助。
Shihira 已经说的很详细了,如果楼主想深入了解链接这块内容,推荐看看 《程序员的自我修养》
编译出来没区别。只是没法调试静态库里的代码而已
这个问题可以回答的再简单点:静态库是源代码编译而来(编译过的源代码),这也就意味编译你程序的时候如果使用静态库的话就直接链接使用,而如果是源代码的话就会经过编译之后才能链接使用。
补充点,如果是直接用源代码的话你可以根据你的要求进行配置之后再编译,而静态库的话就没办法了。
上面说的内容在linux、windows还是嵌入式c上都基本适用。
没有区别静态库就是一组obj的集合,而你的项目就是每个文件编译出来的obj链接而来的
lib有个问题是编译环境必须和你程序一致比如wchar是否内置,c++运行时是多线程动态还是多线程静态等,如果编译的选项不一致,最后会导致链接错误
源代码没有这种问题,因为可以修改编译选项
没有区别, 在不想提供源代码的时候可以提供头文件和静态库。
有一点要注意的是,如果你在写一个静态库的时候把,所有的一堆东西都放在了一个文件里,而你在某个项目中只使用其中的一两个函数或者类或者等等,那么会导致你binary变大
就编译来说两种方式都是可以的,前者叫做库依赖,后者叫做源码依赖
库依赖在由于库是之前已经编译好的,所以在第一编译的时候不用重新编译,所以第一编译会快一些,但是如果库也有可能依赖其他的库,这样当你的程序依赖的两个库依赖又同一个库的时候,就会有冲突。而源码依赖就不会有这样的问题,而相比较而言只是第一次编译的时候会比库依赖慢一些,而如果你所依赖的库非常多时,这个第一次编译的时间也可能会非常长,甚至是不能接受的。
目前google采用的就是源码依赖,他们有一个非常强大的编译集群,一个底层库源码的改变,可能会触发成千上万次编译。baidu现在好像也在推这个。
如果说静态库唯一的区别的话,就是平台问题,如果你拿着linux下的一份源代码和一个静态库放在windows下编译链接肯定是不行的,一个是elf一个是PE格式。但是你拿着一份儿完整的源代码就可以顺利的在windows下编译使用了。
基本上没有区别。如果非要说有区别的话,就是你要把另一个项目的代码扔到自己的项目中,没有经过
./configure
之类的步骤,一些开关(一般是config.h里的宏)没有开启,然后导致编译出来不同。又或者说在别的机器上编译完的静态库搬到自己的机器上,别人的编译器版本比较新优化得比较好,又或者说别人的编译器架构和平台根本不同然后不能用。也就这些很显然的区别了。为什么说没有区别的呢?我们来看看一般多文件编译的过程:
.cpp
都编译成一个目标文件.o
。目标文件里面有符号表,记录着函数和它所用到的符号、全局变量等等。.o
链接成系统可辨认的二进制文件,或者说“映像”。链接器将各个函数重新排列(Reallocation),然后将没有用到的函数舍弃。即便是加入静态库仍然没有什么区别,因为:静态库本身就只不过是
.o
文件的一个打包(Archive)。以GCC的ar为例,我们看看静态库.a
里面究竟是什么:真相就是,里面就是一大堆的
.o
。从源代码编译(第一步)也是生成一大堆.o
,从静态库里解包也是生成一大堆相同的.o
,其余的步骤完全是没有区别的。换句话说,比如你有一个libexample.a
,它里面有src1.o和src2.o两个目标文件。你在链接的时候用ld -lexample
开关链接一个静态库,和你先用ar -x libexample.a
解包,然后用ld src1.o src2.o
链接是完全一样的。没有用到的符号将会被自动削除,所以跟直接从源码编译相比,也不会对体积有影响。
这里我全程在说GNU家族的东西,如果你是想了解微软家族的东西的话,对不起爱莫能助。
Shihira 已经说的很详细了,如果楼主想深入了解链接这块内容,推荐看看 《程序员的自我修养》
编译出来没区别。只是没法调试静态库里的代码而已
这个问题可以回答的再简单点:静态库是源代码编译而来(编译过的源代码),这也就意味编译你程序的时候如果使用静态库的话就直接链接使用,而如果是源代码的话就会经过编译之后才能链接使用。
补充点,如果是直接用源代码的话你可以根据你的要求进行配置之后再编译,而静态库的话就没办法了。
上面说的内容在linux、windows还是嵌入式c上都基本适用。
没有区别
静态库就是一组obj的集合,而你的项目就是每个文件编译出来的obj链接而来的
lib有个问题是编译环境必须和你程序一致
比如wchar是否内置,c++运行时是多线程动态还是多线程静态等,如果编译的选项不一致,最后会导致链接错误
源代码没有这种问题,因为可以修改编译选项
没有区别, 在不想提供源代码的时候可以提供头文件和静态库。
有一点要注意的是,如果你在写一个静态库的时候把,所有的一堆东西都放在了一个文件里,而你在某个项目中只使用其中的一两个函数或者类或者等等,那么会导致你binary变大
就编译来说两种方式都是可以的,前者叫做库依赖,后者叫做源码依赖
库依赖在由于库是之前已经编译好的,所以在第一编译的时候不用重新编译,所以第一编译会快一些,但是如果库也有可能依赖其他的库,这样当你的程序依赖的两个库依赖又同一个库的时候,就会有冲突。而源码依赖就不会有这样的问题,而相比较而言只是第一次编译的时候会比库依赖慢一些,而如果你所依赖的库非常多时,这个第一次编译的时间也可能会非常长,甚至是不能接受的。
目前google采用的就是源码依赖,他们有一个非常强大的编译集群,一个底层库源码的改变,可能会触发成千上万次编译。baidu现在好像也在推这个。
如果说静态库唯一的区别的话,就是平台问题,如果你拿着linux下的一份源代码和一个静态库放在windows下编译链接肯定是不行的,一个是elf一个是PE格式。但是你拿着一份儿完整的源代码就可以顺利的在windows下编译使用了。