从Windows Visual Studio开发迁移到Linux GCC开发的人们,经常会遇到一些奇怪的问题,因为在Linux上面的一些行为和Windows不同,当人们习惯了Windows的行为以后,往往不会想到这些不同的地方。
在这里,我把Linux下gcc编译和Windows下VC编译不同的地方列出来,方便大家避开坑。
编译程序
Windows 下VC编译C++ 程序使用 cl.exe
,链接程序使用 link.exe
Linux 下GCC编译C++ 程序使用 g++
,并会链接程序,无需单独再调用链接程序。
另外GCC还有一个程序名叫gcc
, g++
相当于 gcc -xc++ -lstdc++ -shared-libgcc
依赖库名字
link 时,Windows下面要指定完整的lib的名称,而linux默认静态库的名字为libXXX.a,动态库为libXXX.so,因此在链接时,只需加选项 -lXXX
即可。
如果Linux下面的动态库不符合这一命名规则,如test.so,则需要选项 -Wl,test.so
库依赖顺序
在Linux下,gcc命令行的链接外部库选项,如-lXXX
的位置会影响链接结果。链接器按照指定的顺序搜索和处理库和对象文件。因此,如果命令行如foo.o -lz bar.o
,连接器将在文件foo.o
之后、bar.o
之前搜索库z
。如果bar.o
引用z
中的函数,则可能不会加载这些函数。编译错误显示为未定义的符号。
生成动态库
在Linux下gcc编译动态库时,需要使用-fPIC
选项支持生成位置独立代码(PIC),才可以被可执行文件在运行时加载到适当的位置,否则可能因为无法加载而失败。
运行时动态库路径
通常,在Windows下,只要把exe文件用到的dll文件放在同一个目录,即可正常运行。无需放到PATH环境变量指定的目录下。因为Windows首先在exe文件所在目录查找dll,具体规则可以参考这个链接,更详细的规则参考这个链接。
Linux 引入了一个 rpath 的概念,即run-time search path。它规定了可执行文件在寻找.so文件时的优先路径。可以参考这个链接。
在gcc编译时,可以通过选项-Wl,-rpath=.
指定到和可执行文件相同目录,或者-Wl,-rpath=./lib
指定到其他目录如可执行文件所在目录下的lib目录。
rpath也可以在编译后用chrpath
工具修改,详情见这个链接。
在Windows下,可以通过 Dependencies.exe
程序查看一个可执行文件依赖的库。对应于Linux,可以使用 ldd
命令。
===============
其他细节想到以后,再补充。也欢迎大家留言补充。谢谢!