Linux平台gcc和动态共享库的基础知识
- 格式:doc
- 大小:86.00 KB
- 文档页数:6
gcc的使用方法GCC(GNU Compiler Collection)是一款由GNU开发的编程语言编译器集合,支持多种编程语言,如C、C++、Fortran等。
它被广泛用于各种操作系统和硬件平台上的软件开发,提供了强大的功能和灵活的配置选项。
本文将介绍GCC的基本使用方法,帮助读者快速上手。
一、安装GCC要使用GCC,首先需要在您的计算机上安装它。
GCC可以在多个操作系统上运行,包括Linux、Windows和Mac OS。
具体的安装方法因操作系统而异,下面将分别介绍。
1. 在Linux上安装GCC:在大多数Linux发行版中,GCC已经默认安装。
如果您的系统中没有安装GCC,您可以通过包管理器来安装它。
例如,在Debian或Ubuntu系统上,可以使用以下命令安装GCC:```sudo apt-get install gcc```其他Linux发行版的安装方法请参考相应的文档。
2. 在Windows上安装GCC:在Windows上,可以通过MinGW或MSYS2来安装GCC。
这两个工具集提供了一种在Windows环境中使用GCC的方式。
您可以从官方网站上下载并按照安装向导进行安装。
3. 在Mac OS上安装GCC:在Mac OS上,可以使用Homebrew或MacPorts来安装GCC。
这两个软件包管理系统可以让您以与Linux相似的方式在Mac OS上安装软件。
例如,使用Homebrew安装GCC的命令如下:```brew install gcc```其他安装方法请参考相应文档。
二、编写源代码安装好GCC后,我们就可以开始编写源代码了。
GCC支持多种编程语言,但本文以C语言为例进行介绍。
打开任何文本编辑器,创建一个后缀名为.c的文件,并编写您的C 源代码。
例如,创建一个名为`hello.c`的文件,其中包含以下代码:```c#include <stdio.h>int main() {printf("Hello, world!\n");return 0;}```三、编译和运行代码一旦您编写好了源代码,接下来就可以使用GCC将其编译成可执行文件。
gcc的使⽤简介与命令⾏参数说明(⼀) gcc的基本⽤法(⼆) 警告提⽰功能选项(三) 库操作选项(四) 调试选项(五) 交叉编译选项(⼀) gcc的基本⽤法使⽤gcc编译器时,必须给出⼀系列必要的调⽤参数和⽂件名称。
不同参数的先后顺序对执⾏结果没有影响,只有在使⽤同类参数时的先后顺序才需要考虑。
如果使⽤了多个 -L 的参数来定义库⽬录,gcc会根据多个 -L 参数的先后顺序来执⾏相应的库⽬录。
因为很多gcc参数都由多个字母组成,所以gcc参数不⽀持单字母的组合,Linux中常被叫短参数(short options),如 -dr 与 -d -r 的含义不⼀样。
gcc编译器的调⽤参数⼤约有100多个,其中多数参数我们可能根本就⽤不到,这⾥只介绍其中最基本、最常⽤的参数。
gcc最基本的⽤法是:gcc [options] [filenames]其中,options就是编译器所需要的参数,filenames给出相关的⽂件名称,最常⽤的有以下参数:-c只编译,不链接成为可执⾏⽂件。
编译器只是由输⼊的 .c 等源代码⽂件⽣成 .o 为后缀的⽬标⽂件,通常⽤于编译不包含主程序的⼦程序⽂件。
-o output_filename确定输出⽂件的名称为output_filename。
同时这个名称不能和源⽂件同名。
如果不给出这个选项,gcc就给出默认的可执⾏⽂件 a.out 。
-g产⽣符号调试⼯具(GNU的 gdb)所必要的符号信息。
想要对源代码进⾏调试,就必须加⼊这个选项。
-O对程序进⾏优化编译、链接。
采⽤这个选项,整个源代码会在编译、链接过程中进⾏优化处理,这样产⽣的可执⾏⽂件的执⾏效率可以提⾼,但是编译、链接的速度就相应地要慢⼀些,⽽且对执⾏⽂件的调试会产⽣⼀定的影响,造成⼀些执⾏效果与对应源⽂件代码不⼀致等⼀些令⼈“困惑”的情况。
因此,⼀般在编译输出软件发⾏版时使⽤此选项。
-O2⽐ -O 更好的优化编译、链接。
linux的gcc使用方法Linux是一种开源的操作系统,广泛应用于服务器和嵌入式系统中。
而GCC(GNU Compiler Collection)是Linux下最常用的编译器套件之一,用于将源代码编译成可执行文件。
本文将介绍GCC的使用方法,帮助读者快速上手。
一、安装GCC在Linux系统中,默认情况下已经安装了GCC。
可以通过运行以下命令来验证是否已经安装了GCC:```gcc --version```如果GCC已经安装,则会显示GCC的版本信息;如果没有安装,则可以通过运行以下命令来安装GCC:```sudo apt-get install gcc```二、编写源代码在使用GCC之前,我们需要先编写源代码。
可以使用任何文本编辑器创建一个以.c为后缀的源文件,例如hello.c。
下面是一个示例的源代码:```c#include <stdio.h>int main() {printf("Hello, world!\n");return 0;}```三、编译源代码编写完源代码后,我们可以使用GCC来将其编译成可执行文件。
在终端中运行以下命令:```gcc -o hello hello.c```其中,-o参数用于指定编译后生成的可执行文件的名称,hello为示例的可执行文件名,hello.c为源代码文件名。
如果编译成功,GCC将会生成一个名为hello的可执行文件。
四、运行可执行文件在编译成功后,我们可以通过以下命令来运行可执行文件:```./hello```如果一切顺利,终端将会输出"Hello, world!"的字符串。
五、GCC的其他常用选项除了上述基本的使用方法外,GCC还提供了许多其他的选项,用于控制编译过程的行为。
以下是一些常用的选项:- -Wall:开启所有警告信息的显示。
- -g:生成供调试器使用的调试信息。
- -O2:进行优化处理,提高程序执行效率。
gcc命令行详解1、gcc包含的c/c++编译器gcc、cc、c++、g++gcc和cc是一样的,c++和g++是一样的,一般c程序就用gcc编译,c++程序就用g++编译2、gcc的基本用法gcc test.c这样将编译出一个名为a.out的程序gcc test.c -o test这样将编译出一个名为test的程序-o参数用来指定生成程序的名字3、为什么会出现undefined reference to 'xxxxx'错误?首先这是链接错误,不是编译错误,也就是说如果只有这个错误,说明你的程序源码本身没有问题,是你用编译器编译时参数用得不对,你没有指定链接程序要用到得库,比如你的程序里用到了一些数学函数,那么你就要在编译参数里指定程序要链接数学库,方法是在编译命令行里加入-lm4、-l参数和-L参数-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?-lname,在连接时,装载名字为“libname.a”的函数库:-lm表示连接名为“libm.a”的数学函数库。
就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了好了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。
linux动态库和静态库调用方法
在Linux操作系统中,动态库和静态库的调用方法如下:
1. 动态库(Shared Library):动态库在程序运行时被载入内存,可以被多个程序同时使用,节省内存空间。
在Linux中,动态库一般存放在/usr/lib或/lib目录下。
调用方法:在程序中使用extern "C"来声明函数接口,然后通过dlopen(), dlsym()等函数来动态调用动态库中的函数。
2. 静态库(Static Library):静态库在程序编译时被包含进可执行程序中,每个程序都有一份自己的库副本。
静态库一般存放在/usr/lib或/lib目录下。
调用方法:在程序中直接使用静态库中的函数,不需要额外的调用方法。
只需要在编译时使用"-l"选项指定要链接的库名,例如"gcc -o test test.c -lmylib"。
需要注意的是,对于动态库和静态库的使用,一般建议优先使用动态库,因为这样可以节省内存空间,并且可以在不停止程序运行的情况下更新库文件。
第1页/ 共1页。
Linux学习基础1、什么是Linux?准确的说,是指Linux的kernel(系统的核心程序),其内核版权属于Linus Torvalds,在GPL(GNU General Public License)版权协议下发行, 任何人都可以自由的复制(copy), 修改(change), 套装分发(distribute),销售,但是不可以在分发时加入任何限制, 而且所有原码必须是公开的,所以任何人都可以无偿取得所有执行文件和原代码。
对于Linux用户和系统管理员来说,Linux是指包含Linux kernel、utilities (系统工具程序)以及application (应用软件)的一个完整的操作系统。
Linux的应用软件是由自由软件基金会(FSF)开发的,全世界许多热心的程序员为Linux开发或移植了很多应用程序,包括X-Windows、Emacs、TCP/IP网络(包括SLIP/PPP/ISDN)等等,现在Linux(包括内核和大量的应用程序)光是执行程序就已经达到200M,完全安装后的规模将更大(大约500M左右)。
从本质上讲,Linux是Unix的”克隆”或Unix风格的操作系统,在原代码级上兼容绝大部分的Unix标准(如IEEE POSIX,System V,BSD),它遵从 POSIX规范,例如对于System V来说,把其上程序源代码拿到 Linux下重新编译后就可以运行,而对于BSD Unix来说,它的可执行文件可以直接在Linux环境下运行。
Linux的标志是可爱的企鹅,至于为什么选用企鹅,Linus是这样说的:别的都被他人用了,企鹅,不是也非常可爱吗?!由Linux作者发布的仅仅是一个内核而己,有一些公司或组织把内核、原代码及相关的应用程序组织在一起发行, 于是就产生了不同的Linux发行(distributor)版本, 比较著名的发行版本有RedHat、SlackWare 、S.u.S.e、Debian 等。
一、编译过程概览gcc编译器对程序的编译过程有四个阶段:预处理(preprocessing)、编译(com- pilation proper)、汇编(assembly)和链接(linking)。
预处理:对源文件(source file)进行预处理,进行宏定义的替换等。
编译:将进行完预处理的源文件编译成汇编文件(assembly file)。
将C源代码编译成汇编语言。
汇编:将汇编文件汇编成目标文件(object file)。
链接:将一个或多个目标文件链接成一个可执行的二进制文件(execute file)。
链接的目标文件中有且只有一个main函数,作为可执行文件的开始。
-E在预处理阶段之后停止,不进行编译。
输出是预处理之后的源码,默认发送到标准输出(standard output)。
输入文件格式为.c等,默认输出为标准输出。
-S在编译阶段之后停止,不进行汇编。
输出为每一个指定的未编译的输入文件的汇编代码文件。
输入文件格式为.c、.i等,输出文件格式为.s。
-c编译或者汇编源文件,不进行链接。
输出为每一个源文件的目标文件。
输入文件格式为.c、.i、.s,输出文件格式为.o。
-o filename-o指定输出文件的文件名,如果没有指定-o,则默认输出的可执行文件名是a.out,默认输出的source.suffix的汇编文件名为source.s、目标文件名位source.o。
默认的预处理后的源文件输出到标准输出。
main.cgcc –E main.c –o main.itali main.igcc –S main.i –o main.stail main.sps:gcc –S main.c –o main.s也是可以的。
gcc –c main.s –o main.ogcc main.o –o test./testps:gcc –c main.i(main.c) –o main.ogcc main.c(main.i main.s) –o test都是可以的二、预处理预处理阶段可以用到的一些选项。
GCC(GNU Compiler Collection)是一套开源的编译器集合,广泛用于开发和编译C、C++、Objective-C、Fortran 等程序。
针对Linux 系统使用GCC,以下是一些基本的系统要求:
1. 操作系统版本:GCC 可以在多个版本的Linux 系统上运行。
具体的要求取决于你使用的GCC 版本和你的Linux 发行版。
在大多数常见的Linux 发行版上,都可以安装和使用GCC。
2. 系统架构:GCC 可以针对多种架构进行交叉编译,包括x86、x86_64、ARM、PowerPC 等。
你需要选择与目标架构相匹配的GCC 版本,并在相应的Linux 系统上进行安装和使用。
3. 系统资源:GCC 是一个相对较大的软件包,需要一定的系统资源来安装和使用。
具体的资源要求取决于你要编译的项目的大小和复杂性,以及你的编译选项和优化级别等。
4. 工具链:GCC 通常需要一些附加的工具和库来支持编译过程,如binutils(包括as、ld 等)、libc(如glibc)、头文件等。
确保你的Linux 系统上已经安装了相应的工具链组件。
具体的系统要求和安装步骤可能会因为Linux 发行版和GCC 版本而有所不同。
建议在安装GCC 之前,查阅你所使用的Linux 发行版和GCC 官方文档,了解相关的系统要求和安装指南,并根据实际情况进行安装和配置。
对大多数不从事Linux平台C语言开发的人来说,GNU gcc的一套工具和Linux平台的共享库的使用还是十分陌生的,其实我也不太熟悉,姑且写点基础知识,权当做备忘吧。
一、GNU gcc的编译工具用法我们先来写一个简单的C程序:hello.cC代码#include <stdio.h>void print_hello() {printf("Hello World\n");}int main(int argc, char argv[]) {print_hello();return 0;}定义了一个print_hello函数,调用main函数打印Hello World。
如何编译它呢?C代码gcc -o hello -O2 hello.c-o参数指定生成的可执行程序的文件名, -O2是优化级别。
该命令会编译生成hello可执行程序,看看这个文件:ls -l helloC代码-rwxr-xr-x 1 robbin users 11939 2008-11-02 13:48 hello有11KB大小。
看看他链接了哪些系统动态链接库,用ldd命令:C代码ldd hello输出信息为:C代码libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9566d000)/lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)libc是C语言标准函数库,ld是动态链接器。
接着我们看看hello这个程序里面有哪些符号,用nm命令:C代码nm hello输出:C代码1.00000000005008f8 A __bss_start2.000000000040043c t call_gmon_start3.......4.00000000004004f0 T main5.0000000000500658 d p.06.00000000004004e0 T print_hello7. U puts@@GLIBC_2.2.58.0000000000400410 T _start中间省略了一些,不过我们还是可以在符号表里面找到函数定义。
hello有11KB,体积偏大,去处符号表可以给它瘦身,我们用strip命令:C代码strip hello然后再ls -l hello,输出为:C代码-rwxr-xr-x 1 webuser users 4464 2008-11-02 13:56 hello只有4.4KB了,瘦身效果明显!不过这次符号表再也看不到了,nm hello,输出为:nm: hello: no symbols。
最后如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令:C代码strings hello输出信息为:C代码/lib64/ld-linux-x86-64.so.2SuSElibc.so.6puts__libc_start_main__gmon_start__GLIBC_2.2.5t fffHello World友情提醒一下,如果你用Java写一个HelloWorld.java,编译以后你也可以用strings窥探一番。
二、动态共享库怎么使用这次我们把hello.c拆开成为两个文件:hello.c和main.c。
hello.c的代码是:C代码1.#include <stdio.h>2.3.void print_hello() {4. printf("Hello World\n");5.}而main.c的代码是:C代码#include <stdio.h>void print_hello() {printf("Hello World\n");}hello.c是我们的动态共享库,在hello.c里面我们声明和实现了各种公用的函数,最后main.c可以去调用这些公用函数。
首先我们要把hello.c编译成为动态共享库:C代码gcc -o libhello.so -O2 -fPIC -shared hello.c-fPIC参数声明链接库的代码段是可以共享的,-shared参数声明编译为共享库。
请注意这次我们编译的共享库的名字叫做libhello.so,这也是Linux共享库的一个命名的惯例了:后缀使用so,而名称使用libxxxx格式。
然后编译main.c的时候,我们需要更多的参数让gcc知道如何寻找共享库:C代码gcc -o main -O2 -L. -lhello main.c-L参数指定到哪个附加路径下面去寻找共享库,现在我们指定在当前目录下面寻找;-l参数指定链接到哪个共享库上面,我们传的参数hello,那么gcc就会自动链接到libhello.so这个共享库上面(注意我们上面说的libXXXX.so命名规则);-I参数指定到哪个附加路径下面去寻找h文件,这个我们没有使用。
最后我们成功编译好了main,执行一下,报错:引用./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory找不到libhello.so这个共享库,怎么回事?这是因为libhello.so并不在操作系统默认的共享库的路径下面,我们可以临时指定一下链接路径:C代码export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH这样就成功了。
我们用ldd main看一下:C代码1.libhello.so => ./libhello.so (0x0000002a9566d000)2.libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9576e000)3./lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)这次main程序链接到了libhello.so这个共享库上面。
三、关于Linux的动态共享库的设置可执行程序找不到要链接的动态共享库,这是Linux上面编译和运行程序很容易碰到的问题,通过上面的小例子,我们已经大致了解共享库的一点基本原理,接下来我们要探讨一下怎么设置程序寻找动态共享库的行为。
Linux操作系统上面的动态共享库大致分为三类:1、操作系统级别的共享库和基础的系统工具库比方说libc.so, libz.so, libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr/lib64目录。
如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6/lib64目录。
此外还可能有其他特定Linux版本的系统库目录。
这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。
2、应用程序级别的系统共享库并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib 和/usr/local/lib64这两个目录下面。
很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local/lib下面去寻找共享库。
以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。
这是为什么呢?因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。
Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。
这个文件的内容格式大致如下:C代码1./usr/X11R6/lib642./usr/X11R6/lib3./usr/local/lib4./lib645./lib6./usr/lib647./usr/lib8./usr/local/lib649./usr/local/ImageMagick/lib假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用ImageMagick的动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig 命令即可。
ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。
为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:C代码strings /etc/ld.so.cache | grep ImageMagick输出结果为:C代码1./usr/local/ImageMagick/lib/libWand.so.102./usr/local/ImageMagick/lib/libWand.so3./usr/local/ImageMagick/lib/libMagick.so.104./usr/local/ImageMagick/lib/libMagick.so5./usr/local/ImageMagick/lib/libMagick++.so.106./usr/local/ImageMagick/lib/libMagick++.so已经成功了!3、应用程序独享的动态共享库有很多共享库只被特定的应用程序使用,那么就没有必要加入系统库路径,以免应用程序的共享库之间发生版本冲突。
因此Linux还可以通过设置环境变量LD_LIBRARY_PATH来临时指定应用程序的共享库搜索路径,就像我们上面举的那个例子一样,我们可以在应用程序的启动脚本里面预先设置LD_LIBRARY_PATH,指定本应用程序附加的共享库搜索路径,从而让应用程序找到它。