理清编译连接的那些事儿


   当你在linux下写C/C++代码的时候,是否是会遇到许多编译连接的问题? 时不时报个glibc、gcc,g++等相关的错误? 不少时候都无从下手,并且比较混乱。 这也是编译连接过程当中常常出现的问题。这篇文章不是去介绍如何编译连接,而是理清编译连接过程当中碰到的一些概念和出现的问题。尤为libc,glib,glibc,eglibc,libc++,libstdc++,gcc,g++。linux


一、libc和glibcc++

  从libc提及,libc是Linux下原来的(早期)标准C库,也就是当初写hello world时包含的头文件#include < stdio.h> 定义的地方。后来逐渐被glibc取代,也就是传说中的GNU C Library,在此以前除了有libc,还有klibc,uclibc。如今只要知道用的最多的是glibc就好了,主流的一些linux操做系统如 Debian, Ubuntu,Redhat等用的都是glibc(或者其变种,下面会说到).shell

  那glibc都作了些什么呢? glibc是Linux系统中最底层的API,几乎其它任何的运行库都要依赖glibc。 glibc最主要的功能就是对系统调用的封装,你想一想看,你怎么能在C代码中直接用fopen函数就能打开文件? 打开文件最终仍是要触发系统中的sys_open系统调用,而这中间的处理过程都是glibc来完成的。这篇文章详细介绍了glibc是如何与上层应用程序和系统调用交互的。除了封装系统调用,glibc自身也提供了一些上层应用函数必要的功能,如string,malloc,stdlib,linuxthreads,locale,signal等等。ubuntu


二、eglibc和glib
windows

  好了,那eglibc又是什么? 这里的e是Embedded(嵌入式)的意思,也就是前面说到的变种glibc。eglibc的主要特性是为了更好的支持嵌入式架构,能够支持不一样的shell(包括嵌入式),但它是二进制兼容glibc的,就是说若是你的代码以前依赖eglibc库,那么换成glibc后也不须要从新编译。ubuntu系统用的就是eglibc(而不是glibc),不信,你执行 ldd –version 或者 /lib/i386-linux-gnu/libc.so.6
(64位系统运行/lib/x86_64-linux-gnu)看看,便会显示你系统中eglibc/glibc的版本信息。  这里提到了libc.so.6,这个文件就是eglibc/glibc编译后的生成库文件。数据结构

  还有一个glib看起来也很类似,那它又是什么呢?glib也是个c程序库,不过比较轻量级,glib将C语言中的数据类型统一封装成本身的数据类型,提供了C语言经常使用的数据结构的定义以及处理函数,有趣的宏以及可移植的封装等(注:glib是可移植的,说明你能够在linux下,也能够在windows下使用它)。那它跟glibc有什么关系吗?其实并无,除非你的程序代码会用到glib库中的数据结构或者函数,glib库在ubuntu系统中并不会默认安装(能够经过apt-get install libglib2.0-dev手动安装),著名的GTK+和Gnome底层用的都是glib库。想更详细了解glib? 能够参考 这里架构


  看到这里,你应该知道这些库有多重要了吧? 你写的C代码在编译的过程当中有可能出现明明是这些库里面定义的变,却量还会出现’Undefined’, ‘Unreference’等错误,这时候你可能会怀疑是否是这些库出问题了? 是否是该动手换个gilbc/eglibc了? 这里强调一点,在你准备更换/升级这些库以前,你应该好好思考一下,你真的要更换/升级吗?你要知道你本身在作什么!你要时刻知道glibc/eglibc的影响有多大,无论你以前部署的什么程序,linux系统的ls,cd,mv,ps等等全都得依赖它,不少人在更换/升级都有过惨痛的教训,甚至让整个系统奔溃没法启动。因此,强烈不建议更换/升级这些库!ide


三、libc++和libstdc++函数

固然若是你写的是C++代码,还有两个库也要很是重视了,libc++/libstdc++,这两个库有关系吗?有。两个都是C++标准库。libc++是针对clang编译器特别重写的C++标准库,那libstdc++天然就是gcc的事儿了。libstdc++与gcc的关系就像clang与libc++. 其中的区别这里不做详细介绍了。spa

再说说libstdc++,glibc的关系。

  libstdc++与gcc是捆绑在一块儿的,也就是说安装gcc的时候会把libstdc++装上。 那为何glibc和gcc没有捆绑在一块儿呢?
相比glibc,libstdc++虽然提供了c++程序的标准库,但它并不与内核打交道。对于系统级别的事件,libstdc++首先是会与glibc交互,才能和内核通讯。相比glibc来讲,libstdc++就显得没那么基础了。



  说完了这些库,这些库最终都是拿来干吗的?固然是要将它们与你的程序连接在一块儿! 这时候就不得不说说gcc了(固然还有前文提到的clang以及llvm等编译器,本文就不细说它们的区别了)。

你写的C代码.c文件经过gcc首先转化为汇编.S文件,以后汇编器as将.S文件转化为机器代码.o文件,生成的.o文件再与其它.o文件,或者以前提到的libc.so.6库文件经过ld连接器连接在一块生成可执行文件。固然,在你编译代码使用gcc的时候,gcc命令已经帮你把这些细节所有作好了。

那g++是作什么的? 慢慢说来,不要觉得gcc只能编译C代码,g++只能编译c++代码。 后缀为.c的,gcc把它看成是C程序,而g++看成是c++程序;后缀为.cpp的,二者都会认为是c++程序,注意,虽然c++是c的超集,可是二者对语法的要求是有区别的。在编译阶段,g++会调用gcc,对于c++代码,二者是等价的,可是由于gcc命令不能自动和C++程序使用的库联接,须要这样,gcc -lstdc++, 因此若是你的Makefile文件并无手动加上libstdc++库,通常就会提示错误,要求你安装g++编译器了。

好了,就说到这,理清这些库与编译器之间的关系,相信会对你解决编译连接过程当中遇到的错误起到一点帮助。

相关文章
相关标签/搜索