资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第 3 章 Linux系统C语言开发工具,2,本章重点,Linux,环境中将,C,程序转换成可执行文件所经历的过程和命令,gcc,、,make,、,gdb,工具的使用,2,3,3.,1,第一个,Linux,C,程序,例3-,1,:设计一个程序,,在屏幕打印,5,行“,HELLO,LINUX WORLD”,。,步骤,1:,设计编辑源程序代码,编辑程序只需要用文本编辑器,vim,,编辑程序在终端中输出,:,rootlocalhost root#vim,3-,1.c,/*,3-,1.c,程序:在屏幕上输出“这是第一个,Linux c,程序,!”*/,#include /*,文件预处理,包含标准输入输出库*,/,int main()/*C,程序的主函数,开始入口*,/,int i,j;,for(i=0,j=5;i j;i+),printf(HELLO,LINUX WORLDn);,exit(0),return 0;,输入完成后存盘:按,ESC,键输入“,:wq”,回车,3,4,3.,1,第一个,Linux c,程序,步骤,2:,编译程序,编译程序前,最好请确认,c,源程序文件的存在,打开,Linux,终端输入“,ls”,命令,查看当前目录下是否有3-,1.c,文件,;,输入命令,:rootlocalhost root#,gcc,3-,1.c,;,若编译时没有出现错误信息,说明程序编译成功。,步骤,3:,运行程序,编译好3-,1.c,程序后,默认生成的可执行文件是,a.out,;,输入命令:,rootlocalhost root#,./a.out,此时系统会出现运行结果,。,4,3.2.1 gcc,编译器,gcc,是(,GNU Cmpiler Collection,的简称),它是,GNU,项目中符合,ANSI C,标准的编译系统,能够编译用,C,、,C+,和,Object C,等语言编写的程序。,cc,命令可以启动,C,编译系统,当执行,gcc,时,它将完成预处理、编译、汇编和连接,4,个步骤并最终生成可执行代码。产生的可执行程序,默认被保存为,a.out,文件,。,gcc,命令可以接受多种文件类型并依据用户指定的命令行参数对它们做出相应处理。,如果,gcc,无法根据一个文件的扩展名决定它的类型,它将假定这个文件是一个目标文件或库文件。,5,6,3.2.1 gcc,编译器,gcc,编译流程,6,7,3.2.1 gcc,编译器,gcc,支持编译的一些源文件的后缀及其解释,7,8,3.2.1 gcc,编译器,gcc命令语法:,gcc,参数,要编译的文件,参数,目标文件,目标文件可省略,,gcc,默认生成可执行的文件为,a.out,,如果想要生成自己命名的可执行文件,通常使用“,-o”,参数。,rootlocalhost root#,gcc,3-,1.c o,3-,1,8,3.2.1 gcc,编译器,例3-,2,:,设计一个程序,要求把输入的百分制的成绩转换成五级制输出。即输入成绩大于等于,90,分,显示“优秀”;若成绩介于,8090,分,显示“良好”;若成绩介于,7080,分,显示“中等”;若成绩介于,6070,分,显示“及格”;若成绩小于,60,分,显示“不及格”。,9,10,3.2.1 gcc,编译器,步骤,1:,编辑源程序代码,rootlocalhost root#,vim,3-,2.c,10,11,3.2.1 gcc,编译器,步骤 2:,用gcc编译程序,rootlocalhost root#,gcc,3-,2.c o,3-,2,步骤 3:运行程序,rootlocalhost root#./,3-,2,思考题:设计一个程序,要求输入一个数,如果此数大于,0,,显示“输入的为正数”,否则显示“输入的为负数”。,11,3.2.2,函数库,标准系统库文件一般存放在,linux,文件系统,/lib,和,/usr/lib,目录中。,C,语言编译器需要知道要搜索哪些库文件,默认情况下,它只搜索标准,C,语言库。,库文件必须遵循特定的命名规范并且需要在命令行中明确指定。,库文件的名字总是以,lib,开头,随后的部分指明这是什么库(例如,,c,代表,C,语言库,,m,代表数学库)。文件名的最后部分以,.,开始,然后给出库文件的类型:,.a,代表传统的静态函数库,.so,代表共享函数库,例如,:libm.a,为静态数学函数库。,12,3.2.2,函数库,1,静态库,静态库,也称作归档库(,archive,),按惯例它们的文件名都以,.a,结尾。比如,标准,C,语言函数库,/usr/lib/libc.a,和,X11,函数库,/usr/X11/lib/libX11.a,。,创建和维护自己的静态库,:,只要使用,ar,(代表,archive,,即建立归档文件)程序和,gcc,-c,命令对函数分别进行编译。,应该尽可能把函数分别保存到不同的源文件中。如果函数需要访问公共数据,则把它们放在同一个源文件中并使用在该文件中声明的静态变量。,13,3.2.2,函数库,例,3.5,:创建一个小型函数库,它包含两个函数,pro1,和,pro2,,然后在一个示例程序中调用其中一个函数。,步骤,1,为两个函数分别创建各自的源文件(将它们分别命名为,pro1.c,和,pro2.c,)。,rootlocalhost root#cat pro1.c,#include,void pro1(int arg),printf(“hello,:,%dn”,arg);,rootlocalhost root#cat pro2.c,#include,void pro2(char*arg),printf(“,您好:,%sn”,arg);,14,3.2.2,函数库,步骤,2,分别编译这两个函数,产生要包含在库文件中的目标文件。,通过调用带有,-c,选项的,gcc,编译器来实现,,,-c,选项的作用是阻止编译器创建一个完整的程序,gcc,将把源程序编译成目标程序,文件名为以,.o,结尾。如果此时试图创建一个完整的程序将不会成功,因为还未定义,main,函数。,rootlocalhost root#gcc-c pro1.c pro2.c,rootlocalhost root#ls*.o,pro1.o pro2.o,步骤,3,编写一个调用,pro2,函数的程序。首先,为库文件创建一个头文件,lib.h,。这个头文件将声明库文件中的函数,它应该被所有希望使用库文件的应用程序所包含。,rootlocalhost root#cat lib.h,/*lib.h,:,pro1.c,,,pro2.c*/,void pro1(int);,void pro2(char*);,15,3.2.2,函数库,步骤,4,主程序(,program.c,),它包含库的头文件并且调用库中的一个函数。,rootlocalhost root#cat program.c,#include“lib.h”,int main(),pro2(“Linux world”);,exit(0);,步骤,5,编译并测试程序。暂时为编译器显式指定目标文件,然后要求编译器编译的文件并将其与预先编译好的目标模块,pro2.o,链接。,rootlocalhost root#gcc-c program.c,rootlocalhost root#gcc-o program program.o pro2.o,rootlocalhost root#./program,您好:,Linux world,16,3.2.2,函数库,步骤,6,创建并使用一个库文件。用,ar,程序创建一个归档文件并将目标文件添加进去。这个程序之所以称为,ar,,是因为它将若干单独的文件归并到一个大的文件中以创建归档文件。注意,也可以用,ar,程序来创建任何类型文件的归档文件。,rootlocalhost root#ar crv libfoo.a pro1.o pro2.o,函数库就可使用了。,17,3.2.2,函数库,可以在编译器命令行的文件列表中添加该库文件以创建程序:,rootlocalhost root#gcc-o program program.o libfoo.a,rootlocalhost root#./program,您好:,Linux world,也可以用,-l,选项来访问函数库,但是因为其未保存在标准位置,所以必须用,-L,选项来指示,gcc,在何处可以找到它:,rootlocalhost root#gcc-o program program.o-L.-lfoo,-L.,选项指示编译器在当前目录”,.”,中查找函数库。,-lfoo,选项指示编译器使用名为,libfoo.a,的函数库(或者名为,libfoo.so,的共享库,如果它存在的话)。,18,3.2.2,函数库,2,共享库,静态库的一个缺点,当同时运行许多应用程序并且它们都使用来自同一个函数库的函数时,就会在内存中有同一函数的多份拷贝,在程序文件自身中也有多份同样的拷贝。这将消耗大量宝贵的内存和磁盘空间。可以用共享库来实现函数的动态链接。,Linux,支持共享库,(,动态链接库,),。共享库的保存位置与静态库是一样的,但共享库有不同的文件名后缀。在典型的,Linux,系统中,标准数学库的共享库是,/usr/lib/libm.so,。,程序使用共享库时,它的链接方式是这样的:它本身不再包含函数代码,而是运行时可访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解析并产生对共享库的调用,如果有必要共享库才被加载到内存中。,19,3.3 make,工具,Linux,有个很强大的工具,make,,它可以管理多个模块。,make,工具提供灵活的机制来建立大型的软件项目。,make,工具依赖于一个特殊的、,名字为,makefile,或,Makefile,的文件,,这个文件描述了系统中各个模块之间的依赖关系。,系统中部分文件改变时,,make,根据这些关系决定一个需要重新编译的文件的最小集合。如果软件包括几十个源文件和多个可执行文件,这时,make,工具特别有用。,20,3.3.1 make,命令,命令语法:,make,选项,目标,宏定义,常用选项:,-d,显示调试信息,-f,文件告诉,make,使用指定文件作为依赖关系文件。,-n,不执行,makefile,中的命令,只显示输出这些命令,-s,执行但不显示任何信息。,21,3.3.2 make,规则,makefile,的默认文件名为,GNUmakefile,、,makefile,或,Makefile,,当然也可以在,make,的命令行中指定别的文件名。,多数,Linux,程序员使用第三种文件名,Makefile,。,Makefile,中包含一些规则来告诉,make,处理哪些文件以及如何处理这些文件。这些规则主要是描述哪些文件(称为,target,目标文件,不要和编译时产生的目标文件相混淆)是从哪些别的文件(称为,dependency,依赖文件)中产生的,以及用什么命令(,command,)来执行这个过程。,依靠这些信息,,make,会对磁盘上的文件进行检查,如果目标文件的生成或被改动时的时间(称为该文件时间戳)至少比它的一个依赖文件还旧的话,,make,就执行相应的命令,以更新目标文件。目标文件不一定是最后的可执行文件,可以是任何一个中间文件并可以作为其他目标文件的依赖文件。,22,3.3.2 make,规则,一个,Makefile,文件主要含有一系列的,make,规则,每条,make,规则包含以下内容:,目标文件列表,:,依赖文件列表,命令列表,目标文件列表:即,make,最终需要创建的文件,中间用空格隔开,如可执行文件和目标文件;也可以是要执行的动作。,依赖文件列表:是编译目标文件所需要的其他文件。,命令,(comman
展开阅读全文