Lin操作基础系统 11_第1页
Lin操作基础系统 11_第2页
Lin操作基础系统 11_第3页
Lin操作基础系统 11_第4页
Lin操作基础系统 11_第5页
已阅读5页,还剩94页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第12章C/C++及其他编程环境《Linux操作系统(第5版)》学习目标

理解gcc/g++编译器的工作过程,掌握其基本用法

了解c/c++头文件与库文件的标准位置,掌握静态库与共享库的构造与使用

理解Makefile文件结构,掌握make自动化管理多文件工程的过程和编译方法

了解调试器gdb,掌握用gdb调试C/C++程序的基本流程和方法

了解Linux下其他编程环境的基本配置与使用方法章节概述本章聚焦Linux系统下的C/C++编程环境与工具链。首先介绍gcc/g++编译器的工作流程及常用选项。讲解头文件搜索路径和库文件的构造与管理,并通过示例演示静态库与共享库的使用。重点阐述make工具和Makefile文件的编写规则,实现多模块工程的自动化编译与管理。调试工具gdb的基本命令帮助排查程序错误。最后简要介绍Linux下的其他编程环境,包括KDevelop/Qt、Java、eclipse、Perl、Python、R等,为跨语言开发提供参考。目录0102编译器链接器与库文件030405060708头文件静态库共享库makeMakefile调试器(gdb)Linux其他编程工具简介编译器12.1Linux系统的C语言编译器为gcc,它是GNU推出的功能强大的编译工具,因为UNIX系统的C编译器为cc,所以在Linux系统中还保留一个链接cc,用于和UNIX的向后兼容。Linux的面向对象的C++编译器为g++或c++。可以把gcc和cc,g++和c++分别视为同一程序,且有相同的用法,它们不仅功能强大、结构灵活,且可以通过不同的可选模块来支持多种语言,如Java、Fortran、Ada和汇编等。12.1.1功能及用法Linux下C/C++编译工具gcc/g++能将C/C++源程序和目标程序编译并调用链接程序ld生成可执行文件,如果用户没有给出可执行文件的名字,gcc将默认生成一个名为a.out的可执行文件。在Linux系统下,用户可以使用vi、nano或gedit等文本编辑工具编写C/C++的源程序。gcc/g++需要通过文件扩展名来区别相关文件的类型,其所遵循的部分扩展名约定。12.1.1功能及用法1.继承的概念1.什么是异常Linux下C/C++编译工具12.1.1功能及用法1.继承的概念1.什么是异常扩展名文件类型扩展名文件类型.cC程序源代码.S,.sx未预处理的汇编程序.C,.cp,.cc,.c++,.cppC++程序源代码.h头文件.i预处理后的C源代码文件.o目标文件.ii预处理后的C++源代码文件.a静态库文件.mOC程序源代码.so共享库文件.M,.mmOC++程序源代码.s预处理后的汇编程序.mi预处理后的OC源代码文件.mii预处理后的OC++源代码文件gcc/g++文件扩展名约定文件扩展名gcc/g++有相同的用法,使用相同的参数或选项,其常用格式为:gcc/g++[-c][-S][-E][-s][-g][-static][-shared][-rdynamic] [-Idir…][-Ldir…][-lname][-fpic][-fPIC][-Olevel] [-Dmacro[=defn]…][-Umacro][-Wwarn...][-Wpedantic] [-ooutfile][@file]infile...12.1.1功能及用法常gcc/g++的部分参数。12.1.2参数及说明1.继承的概念1.什么是异常gcc/g++的部分参数12.1.2参数及说明1.继承的概念1.什么是异常12.1.3示例1.继承的概念1.什么是异常C程序设有一个HelloWorldC程序,其文件名为hello.c,内容如下。#include <stdio.h>intmain(){printf("HelloCWorld!\n");}可按以下方法进行编译,以生成相应的结果:$gcchello.c #生成可执行程序a.out$cc-ohellohello.c #生成可执行程序hello$gcc-chello.c #生成目标文件hello.o$gcc-Shello.c #生成汇编语言程序hello.s编译生成可执行文件之后,就可以运行了,方法为:$./hello或$./a.out输出为:HelloCWorld!12.1.3示例1.继承的概念1.什么是异常C++程序通常使用g++来完成C++程序的编译和连接,它会自动完成目标代码与C++库的链接并生成可执行程序。下面是一个C++版的HelloWorld程序,其文件名为hello.c++,内容为:#include <iostream>usingnamespacestd;intmain(){cout<<"Hello,C++World!"<<endl;}使用c++或g++来编译hello.c++:$g++hello.c++ #生成可执行程序a.out$c++-ohellohello.c++ #生成可执行程序hello$g++-s-oHellohello.c++ #生成删除符号表的可执行程序Hello也可以使用gcc来编译C++程序,但必须使用-l指定C++库stdc++,方法如下:$gcc-chello.c++ #生成目标文件hello.o$gcc-ohhello.c++-lstdc++ #指定标准C++库,生成可执行程序h12.1.3示例1.继承的概念设有一个开发项目,由3个C语言模块文件f1.c,f2.c和f3.c组成,它们的内容分别如下所示。f1.c源代码:多模块工程1234#include<stdio.h>intf1(intarg){printf("F1:youpassed:%d\n",arg);}f2.c源代码:1234#include<stdio.h>intf2(char*arg){printf("F2:youpassed:%s\n",arg);}12.1.3示例1.继承的概念f3.c源代码:123456789101112#include<stdio.h>#include<stdlib.h>intf1(int);intf2(char*);intmain(){inttmpi=16;fprintf(stderr,"Begine:\n");f1(tmpi);f2("HelloWorld!");fprintf(stderr,":End\n");exit(0);}可以采用各模块文件分别编译,然后再统一链接的办法进行编译。$gcc-cf1.cf2.c #生成f1.o和f2.o$gcc-off3.cf1.of2.o #生成f也可以将所有模块源代码一起编译$gcc-of123f3.cf1.cf2.c #生成f12312.1.4gcc/g++的工作过程1.继承的概念1.什么是异常使用gcc/g++由C/C++源代码文件生成可执行文件的过程有以下四个阶段:预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。在预处理阶段,调用cpp对源代码文件中的头文件、宏定义等进行处理,并进行语法、词法等分析,若无错误则生成中间文件。接着调用gcc进行编译,这个阶段根据中间文件生成以.s为后缀的汇编文件。第三阶段调用汇编语言as对中间文件进行汇编,生成以.o为后缀的目标文件。最后,当所有目标文件都生成之后,调用ld将这些目标文件和所需库文件链接起来,生成可执行程序。用户可以根据需要让gcc/g++在编译的任何阶段停下来,以便检查或使用编译器在相应阶段的输出,或者对最后生成的二进制文件进行控制。头文件12.212.2头文件1.继承的概念1.什么是异常在UNIX/Linux的C中规定,默认头文件位置为/usr/include及其子目录。依赖UNIX和Linux操作系统的头文件一般在/usr/include/sys和/usr/include/linux内。若不按默认规定存放头文件,则使用时必须用-Idir指定位置,否则编译器无法找到它们。在标准C中有两种形式的头文件使用方式: #include <headfile.h> #include "headfile.h"两者的区别是,#include<headfile.h>类型头文件搜索范围为默认位置/usr/include,而#include"headfile.h"类型头文件的搜索位置为当前目录,若当前目录内找不到,再到默认位置去搜索。链接器与库文件12.312.3链接器与库文件1.继承的概念1.什么是异常UNIX/Linux的链接器为ld,它的功能是将目标文件或库文件链接在一起,生成可执行文件,一般在编译过程的最后使用。ld有很多参数,这些参数可以直接通过ld命令在其命令行上使用,但在直接使用ld链接目标程序生成可执行程序时可能会遇到问题,更多的是通过编译器gcc或g++提供的参数来控制ld,部分参数说明参见表12-2。标准库文件一般存放在目录/lib或/usr/lib(64位系统下可能是/lib64或/usr/lib64)。默认情况下,编译、链接C程序时,ld使用标准C库;编译、链接C++程序时,使用标准C++库;若使用的不是标准库函数,必须通过-lname指定库名,或-Ldir指定库文件的存放位置,否则将无法找到它。12.3链接器与库文件1.继承的概念1.什么是异常库文件命名必须遵守一定命名规则,库文件名字必须永远以lib开头,后紧跟库名,文件名的后缀为.a:静态库.so:共享库或动态链接库例如,libc.a为标准C静态库,libstdc++.a为C++标准静态库,libm.a为数学运算静态库,libc.so、libstdc++.so和libm.so分别为C、C++库和数学运算标准共享库。libc.so、libstdc++.so和libm.so只是库的通用名称,它们往往是一个具体库链接,或通过某种办法指向一个具体的库文件,比如libc.so.6、libstdc++.so.6和libm.so.6。需要说明的是,静态库使的越来越少了。 静态库12.412.4.1静态库的管理1.继承的概念1.什么是异常静态库管理命令(ar)ar用于静态库文件的管理,其功能是库创建、修改和从库中取出模块等,其部分参数如表12-3所示。表12-3ar的部分参数12.4.1静态库的管理1.继承的概念1.什么是异常为静态库建立索引(ranlib)ranlib用于为刚建立的库文件建立索引表,通过索引表可以加快库文件搜索速度。ranlib的用法为:ranlib[options]libfileranliblibfile等同于ar-slibfile。12.4.1静态库的管理1.继承的概念1.什么是异常显示库文件中的符号表(nm)命令nm用于列出库文件或目标文件中的符号表,其用法为:nm[options][objfile...]若不提供objfile,默认为a.out。nm默认按符号类型进行排序输出,选项-r可让其逆序输出,-p让其不排序输出,-s用于显示索引。12.4.2静态库的构造1.继承的概念1.什么是异常这里,我们以12.1.3中多模块工程为例,使用ar构造自己的静态库。由于库文件中是不能包含main()函数的,故只使用f1.cf2.c来构造。设静态库名为libmyl.a,构造过程如下:$cc-cf1.cf2.cf3.c #生成目标文件f1.o、f2.o和f3.o$arcrvlibmyl.af1.of2.o #由f1.of2.o生成库libmyl.a$ranliblibmyl.a #为子函数建立索引表$nmlibmyl.a #查看索引表 12.4.3静态库的使用1.继承的概念1.什么是异常当用户创建自己的静态库之后,就可以按照使用系统库的方法来使用它。以下为使用静态库的实例:$cc-of123f3.clibmyl.a #使用库libmyl.a和f3.c生成可执行程序f123$cc-of123f3.olibmyl.a #使用库libmyl.a和f3.o生成可执行程序f123$cc-of123f3.c-L.-lmyl #-L.指定当前目录,-lmydl指定静态库文件libmyl.a若将libmyl.a放在系统的标准位置,比如/lib或/usr/lib,命令为#cplibmyl.a/usr/lib之后,就可像其他库一样使用。若已经存放到了标准位置,使用方法为:$cc-of123f3.c-lmyl #使用库libmyl.a和f3.c生成可执行程序f123$cc-of123f3.o-lmyl #使用库libmyl.a和f3.o生成可执行程序f123 共享库12.512.5共享库1.继承的概念1.什么是异常Linux系统的另一种库文件为共享库,用于生成动态链接的可执行程序,其标准位置与静态库相同。共享库文件名的格式为:libNAME.so #通用名称libNAME.so.N #具体版本的库NAME为库名,N为版本号。可用ldd和ldconfig命令管理共享库。共享库的搜索路径为环境变量LD_LIBRARY_PATH指定的位置或库文件的标准位置。 12.5.1共享库构造1.继承的概念1.什么是异常共享库构造非常简单,只需要在生成目标文件时使用-fpic选项,在构造库的时候使用-shared参数,当然还要使用-o指定一个库名。我们仍使用12.1.3节多模块工程中的f1.c和f2.c构造共享库,方法是:$gcc-fpic-cf1.cf2.c #生成目标文件。注意:使用了选项-fpic$gcc-shared-olibmydl.sof1.of2.o #由目标文件生成共享库libmydl.so或$gcc-shared-olibmydl.so-fPICf1.cf2.c #由源文件生成共享库libmydl.so12.5.2共享库的管理1.继承的概念1.什么是异常lddldd(LibraryDependencyDisplay)用来显示一个可执行程序或共享库所使用的共享库间的依赖关系。例如:$ldda.out$lddlibmydl.so$ldd`whichbash`12.5.2共享库的管理1.继承的概念1.什么是异常ldconfigldconfig的功能是在默认库目录(32位时为/lib和/usr/lib,64位时为/lib64和/usr/lib64)或动态库配置文件/etc/ld.so.conf内所列的目录或指定目录下搜索共享库,进而创建动态装入程序ld.so或ld-linux.so所需的链接和缓存文件。缓存文件默认为/etc/ld.so.cache,其中保存有已排好序的动态链接库列表。为了让系统或用户动态链接库能更好地被共享,需要运行ldconfig来对共享库进行配置。ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,需要手工运行这个命令,其用法为:ldconfig[options]选项-p用于显示当前缓存内的所有共享库;-v用于显示工作时正在扫描的目录及共享库,还有它所创建的链接名。显示搜索的目录和共享库,并更新缓存文件/etc/ld.so.cache,可以使用如下命令:ldconfig-v在默认情况下,ldconfig不输出任何东西,-v让其显示正在扫描的目录及搜索到的共享库。12.5.3共享库编程1.继承的概念1.什么是异常共享库打开(dlopen)dlopen()用于打开指定共享库,其原型为:void*dlopen(constchar*filename,intflag);dlopen()成功时返回文件描述符,失败时返回NULL。变量filename为共享库名。若文件名不带有路径,将按以下顺序搜索库文件:(1)环境变量LD_LIBRARY_PATH值所指的路径。(2)动态链接缓冲文件/etc/ld.so.cache。(3)库文件默认目录/lib和/usr/lib(64位时为/lib64和/usr/lib64)。变量flag用来表示在什么时候解决未定义的符号,其取值范围与意义如下:(1)RTLD_LAZY:指定在动态链接库的函数执行时解决。(2)RTLD_NOW:指定在dlopen返回前就解决所有未定义的符号问题。一旦有未解决好者,dlopen将返回NULL表示错误。RTLD_LAZY和RTLD_NOW可以与RTLD_GLOBAL配合使用,使得那些在以后才加载的库可以获得其中的符号。12.5.3共享库编程1.继承的概念1.什么是异常在共享库中查找函数等符号(dlsym)dlsym()用于从dlopen()打开的共享库中查找指定函数或符号,其原型为:void*dlsym(void*handle,char*symbol);handle为dlopen()返回的描述符,symbol为要查找的函数、变量等符号。若找到了,返回symbol对应的(函数)入口地址,相当于返回一个(函数)指针,失败时返回NULL。12.5.3共享库编程1.继承的概念1.什么是异常共享库关闭(dlclose)dlclose()用于关闭已经打开的指定共享库文件,此操作应在共享库相关操作完成之后进行,其原型为:intdlclose(void*handle); #handle为dlopen()返回的描述符12.5.3共享库编程1.继承的概念1.什么是异常共享库错误处理(dlerror)dlerror()用于返回共享库操作状态信息。当共享库操作函数执行失败时,dlerror可以返回出错信息,否则返回值NULL表示成功,其原型为:char*dlerror(void);12.5.4共享库使用示例1.继承的概念1.什么是异常为了使用刚创建的共享库,需要对12.1.3中多模块工程的文件f3.c进行修改。假定修改后的文件被命名为f3n.c,其代码如下所示。#include<stdio.h>#include<stdlib.h>#include<dlfcn.h>#defineSO_FILE"libmydl.so" //定义使用的共享库(未指定路径)intmain(){void*sfp; char*err; //定义文件描述符和错误指针int tmpi=16;int(*f1)(int),(*f2)(char*); //定义函数原型sfp=dlopen(SO_FILE,RTLD_LAZY); //打开共享库if(sfp==NULL){ //打开失败时fprintf(stderr,"%s",dlerror());exit(1);}示例12.5.4共享库使用示例1.继承的概念1.什么是异常f1=dlsym(sfp,"f1"); //获取函数f1入口地址(指针)err=dlerror(); //检查是否成功if(err){fprintf(stderr,"%s",err);exit(2);} //失败时f2=dlsym(sfp,"f2"); //获取函数f2入口地址(指针)err=dlerror(); //检查是否成功if(err){fprintf(stderr,"%s",err);exit(3);} //失败时fprintf(stderr,"begine\n");f2("TestString"); //调用函数f2f1(tmpi); //调用函数f1fprintf(stderr,"++++++++++++end+++++++++++++++\n");dlclose(sfp); //关闭共享库exit(0);}12.5.4共享库使用示例1.继承的概念1.什么是异常编译方法为:$cc-omydlpf3n.c-ldl选项-ldl则告诉链接程序ld使用dl函数库,由共享库libmydl.so生成可执行程序mydlp。编译时也可使用-rdynamic选项,告诉链接程序在链接时所有函数均使用共享库,方法为:$cc-rdynamic-omypf3n.c-ldl由于在f3n.c中共享库文件名没有带路径,故共享库libmydl.so必须放在标准位置(但放置后要执行ldconfig命令)或通过以下方法设置环境变量LD_LIBRARY_PATH的值:$exportLD_LIBRARY_PATH=MYPATH:$LD_LIBRARY_PATHMYPATH为共享库libmydl.so所在的非标准位置。若为当前目录,可写为:$exportLD_LIBRARY_PATH=.:$LD_LIBRARY_PATH #或$exportLD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH编译方法make与Makefile12.612.6make与Makefile在现代的编程环境中,各种集成开发环境已为编程者考虑得很周到,当一个软件或工程或项目中的一个文件或一部分被改变后,再重新编译或链接时,用户不需要特殊控制,开发系统就会根据当前状况自动完成。UNIX/Linux提供了make命令和Makefile文件来实现对开发项目的管理。本部分只介绍make和Makefile的入门知识或最基本的部分,更多的内容请参阅make的在线手册或info文档。12.6.1make的用法简介make命令会根据工程规划文件(称为Makefile)的内容对项目进行管理。make能自动确定哪一个模块被修改了,然后再进行统一、无遗漏、无重复的编译。UNIX/Linux系统中make使用的默认工程规划文件是makefile,若makefile不存在,则查找Makefile,也可通过-ffile指定工程规划文件文件名。make的用法为:make[-ffilename][options][targets]make用法12.6.1make的用法简介make命令的部分参数12.6.2Makefile文件Makefile文件的内容描述了项目或软件中模块之间的相互依赖关系以及目标文件、可执行程序产生时要执行的命令等。make在工作时,依据Makefile文件中的规定来生成目标或可执行文件,完成项目构建,并保证结果的正确性。什么是Makefile文件12.6.2Makefile文件Makefile文件的内容Makefile文件包含的内容有5类。

类型意义显式规则显式告诉make如何编译或构造一个目标隐式规则通过常规或隐式方法处理的规则。比如,由gcc编译*.c生成*.o,就可作为隐式规则变量定义在Makefile中可以像shell编程一样定义和使用变量命令完成某任务所使用的命令,一般为shell命令,也包括条件判断和分支结构注释#开始的部分,意义同shell编程Makefile文件的5类内容12.6.2Makefile文件规则规则由目标(targets)、依赖对象(prerequisites)以及根据依赖对象达成目标所应采取的方法或动作(recipes)组成。在Makefile中,一个规则定义必须从最左边开始,规则的第二及以后的行必须以<tab>键开始(或者说缩进一个制表符)目标的格式如下:targets:prerequisites<tab>recipes或targets:prerequisites;recipes<tab>recipes12.6.2Makefile文件其中,targets为目标;prerequisites为目标所依赖的对象;recipes为达成或生成目标所需采取的动作或应该执行的命令(可以参照shell编程的方法处理。)。若一个命令以@开始,则在make的执行过程中不会被显示,否则执行前将首先显示该命令。比如,由f1.c生成f1.o的规则可以简单地描述为:f1.o:f1.c<tab>gcc-cf1.c这里的f1.o为目标,它依赖于f1.c,依赖方法为执行命令“gcc-cf1.c”。这是直截了当地显式规则,有时为了完成整个工程、体现工程的局部,或考虑安装、卸载更广泛的用途,还可人为制造出一些具有特殊意义的规则,比如all(整个工程)、install(安装)、uninstall(卸载)、clean(清理)等目标,这些通常被称为伪目标(PhonyTarget)。

12.6.2Makefile文件Makefile文件中的自动变量一个Makefile文件中可能会有多个规则,这些规则肯定是不同的,但从结构上应该有相同或相似的地方,如果加以抽象就可以得到一些有共性的描述信息,这就是所谓的自动变量。Makefile的部分自动变量如表12-6所示。12.6.2Makefile文件自动变量的内容会随规则的改变而改变。其实,关于自动变量我们已经在awk部分见到过,那里的$0、$1、$2等的内容,会随记录的改变而改变。符号意义$@目标名$*隐式规则中的词干(stem);静态规则中的%;显式规则中的删除了后缀的目标名(若无后缀,则为空)$%当目标是库文件时,目标内的成员名。例如,目标x.a(y.o)的目标名为x.a,成员名为y.o$^由空格分隔的所有依赖对象(去除重复者)$+由空格分隔的所有依赖对象(包含重复者)$?依赖对象中被更新者$<当前规则中的第一个依赖对象表12-6Makefile的自动变量12.6.2Makefile文件变量与通配符Makefile文件中可以像shell一样使用变量,且比shell中有更大的灵活性,比如定义变量时,等号的两边可有空格等。定义变量的等号有“=”或“:=”两种形式,主要作用是定义新变量或修改已经定义的变量或在已定义变量的基础上定义新变量,例如已知:var1=a.cb.cc.c则var2=$(var1:.c=.o)定义var2=a.ob.oc.o而var1+=d.c重定义var1,其值为var1=a.cb.cc.cd.c需要说明的是,“:=”与“=”是有区别的,当使用“=”时,变量将做递归或扩展,而使用“:=”只进行简单替换。Makefile文件中还可以使用通配符“%”,目的是定义或重定义模式规则。例如:%.o:%.c<tab>gcc-c$<定义一个规则:所有目标文件*.o依赖C语言源程序*.c,且生成方法为gcc-c$<。12.6.3Makefile示例多模块项目编译Makefile示例在12.1.3中的多模块工程中有三个模块,分别是f1.c,f2.c和f3.c,它们之间的关系如图所示。按照gcc的工作过程,对模块的编译和链接过程如下所述。(1)编译各源文件生成目标代码:gcc-cf1.cgcc-cf2.cgcc-cf3.c(2)生成可执行程序:gcc-of123f1.of2.of3.o模块间关系示意图12.6.3Makefile示例(3)Makefile文件上述生成f123的过程,按照Makefile文件的规定可表示为:f123:f1.of2.of3.o #f123依赖于目标文件f1.o,f2.o和f3.o,其生成过程为: gcc-of123f1.of2.of3.of1.o:f1.c #f1.o依赖于f1.c,生成过程为:(此行及以下为隐式规则,可以省略或删除) gcc-cf1.cf2.o:f2.c #f2.o依赖于f2.c,生成过程为: gcc-cf2.cf3.o:f3.c #f3.o依赖于f3.c,生成过程为: gcc-cf3.c12.6.3Makefile示例这里有个提示,因为make工作时,当不指定目标时,默认为第一个,因此,在这个Makefile中,将总目标f123写在了最前面。有了Makefile文件,可以使用make命令对此项目进行编译,编译方法为:$make #(默认第1个)编译f1.c、f2.c和f3.c生成f123或$makef123若要编译单个项目,例如f1.o,可以使用以下方法:$makef1.o #编译f1.c生成f1.o还可为此Makefile文件增加all、clean、install和uninstall目标,若此时Makefile文件记为makefile_1,其内容如下所示。12.6.3Makefile示例all:f123 #makealltobuildf123f123:f1.of2.of3.o gcc-of123f1.of2.of3.of1.o:f1.c #此及以下3个规则为隐式规则,可以删除 gcc-cf1.cf2.o:f2.c gcc-cf2.cf3.o:f3.c gcc-cf3.cclean: #cleanallmyobjectfilef?.o&f123 rm-ff?.of123&>/dev/nullinstall:all #makeallandinstallf123to/usr/binwithpermission755 install-m755f123/usr/binuninstall: rm-f/usr/bin/f123 12.6.3Makefile示例可以使用通配符对makefile_1进行简化,若简化后的文件记为makefile_2,其内容如下所示。all:f123 #makealltobuildf123f123:f1.of2.of3.o gcc-of123f1.of2.of3.o%.o:%.c #此为隐式规则,可以删除 gcc-c$<clean: #cleanallmyobjectfilef?.o&f123 rm-ff?.of123&>/dev/nullinstall:all #makeallandinstallf123to/usr/local/binwithpermission755

install--mode=755f123/usr/local/binuninstall: rm-f/usr/local/bin/f12312.6.3Makefile示例此时,编译整个工程的做法是:$make-fmakefile_2 #或$makef123-fmakefile_2若要编译单个项目,例如f1.o,可以使用以下方法:$makef1.o-fmakefile_2编译并安装的命令是$makeinstall-fmakefile_2卸载的命令是$makeuninstall-fmakefile_2这里再说一下隐式规则。由于由*.c生成*.o的方法常识性的,或是标准办法,因此关于.c生成.o的规则作为隐式规则,可以不出现在Makefile中。基于此,在Makefile、Makefile_1和Makefile_2中,可以不出现这样的规则,读者不妨删除或注释掉这些规则。12.6.3Makefile示例多模块项目共享库构造与使用Makefile示例1)共享库创建根据12.5.1共享库构造过程和Makefile文件的要求,可为共享库的构造过程编制Makefile。设文件名为makefile.somk,其内容如下所示。libmydl.so:f1.of2.o #定义共享库生成规则 gcc-shared-o$@f1.of2.o-ldl #共享库生成命令(注意:使用了-shared)%.o:%.c #定义目标文件生成规则(此非隐式规则) gcc-fpic-c$< #目标文件生成命令(注意:使用了-fpic)据此,构造共享库libmydl可以使用以下命令来完成:makelibmydl.so-fmakefile.somk为了应用的方便,我们对makefile.somk进行改造,为其添加更加灵活的变量定义和完成特定功能伪目标。设改造后的makefile名为makefile.somk1,其内容如下。12.6.3Makefile示例mydl=libmydl.so #定义目标名dst=/usr/lib/$(mydl) #定义安装位置SRC=f1.cf2.c #定义源文件OBJ=$(SRC:.c=.o) #定义目标文件all:$(mydl) #定义all目标(只编译,不安装)%.o:%.c #定义目标文件生成规则(非隐式规则) cc-fpic-c$< #目标文件生成命令(注意:使用了-fpic)$(mydl):$(OBJ) #定义共享库生成规则 cc-shared-o$@$(OBJ)-ldl#共享库生成命令(注意:使用了-shared)install: cp$(mydl)$(dst) #仅复制libmydl.so到标准位置uninstall: rm-f$(dst) #仅删除/usr/lib/libmydl.somake_install:allinstall #构造并安装clean: #定义清理目标 rm-f$(OBJ) #仅清理目标措施clean_all:clean #删除目标文件和libmydl.so rm$(mydl)clean_uninstall:clean_alluninstall#删除目标文件、libmydl.so和/usr/lib/libmydl.solist: #列出所有内容:源文件、目标文件、libmydl.so和/usr/lib/libmydl.so ls-l$(SRC)$(OBJ)$(mydl)$(dst)12.6.3Makefile示例在makefile.somk1中有all、$(mydl)、install、uninstall、make_install、clean、clean_all、clean_uninstall和list等目标。all与$(mydl)是相同的,功能是构造libmydl.so;install和uninstall分别只用于对共享库的安装与删除;make_install用于共享库的构造与安装;clean仅仅用于对目标文件的删除;clean_all用于对目标文件和当前目录内共享库文件的删除;clean_uninstall则是彻底的清理,删除除源代码和makefile以外的所有文件;list用于对源代码文件、目标文件、共享库文件和已经安装共享库文件的显示。用户可根据需要,继续添加其他功能目标。12.6.3Makefile示例2)共享库使用对于12.5.4中的共享库使用示例,也可以为其编写一个简单的makefile文件。设makefile为makefile.souse,其内容如下。SRC=f3n.c #定义源文件OBJ=$(SRC:.c=.o) #定义目标文件TGT=mydlp #定义成果程序all:$(TGT) #定义all目标#%.o:%.c #定义目标文件生成规则

(隐式规则)# gcc-c$< #目标文件生成命令$(TGT):$(OBJ) #定义成果文件生成规则 gcc-o$@$(OBJ)-ldl #成果文件生成命令(注意:使用了-ldl选项)clean: #定义清理目标 rm-f$(OBJ)clean_all:clean #删除目标文件和成果文件 rm$(TGT)12.6.3Makefile示例需要时,还可为其增加install、uninstall等功能,用于结果程序的安装和卸载。使用共享库编译生成可执行程序mydyl,可使用命令:$make-fmakefile.souse #或$makeall-fmakefile.souse生成目标文件可使用:$make-fmakefile.sousef3n.o必要时可先做清理准备:$makeclean-fmakefile.souse #或$makeclean_all-fmakefile.souse

调试器(gdb)12.712.7调试器(gdb)程序调试是程序开发中的一个重要环节,通过调试可以找到程序中的问题。在UNIX/Linux系统里,调试工具为gdb。gdb是一个用来调试C和C++程序的功能强大的调试器,它使用户能在程序运行时观察程序的内部结构、变量的值和内存的使用情况等。gdb提供的功能有:监视或修改程序中变量的值;设置断点以使程序在指定的代码行上暂停执行和单步执行或程序跟踪等。使用前需要安装gdb,甚至还可能需要与debuginfo相关的软件。什么是gdb12.7.1gdb基本命令gdb有很多内容命令用于程序的调试等操作。gdb部分常用命令12.7.1gdb基本命令gdb的命令在不引起歧义的情况下是可以缩写的,比如list可缩写为l、kill可缩写为k、step缩写为s等。同样在不引起歧义的情况下,可以使用tab键命令进行自动补全或查找某一类字符开始的命令,比如在w后输入tab键,可得到以下输出:watchwherewhile-steppingwhatiswhilews表示这些是w开头的命令。12.7.2程序调试方法下面以12.1.3中多模块工程为例,介绍Linux系统C程序调试的最基本方法。1)编译时使用调试参数-g编译时需要使用-g选项,在生成的可执行文件中加入调试信息,方法是:$gcc-g-omypf1.cf2.cf3.c2)启动gdb$gdbmyp示例12.7.2程序调试方法3)查看源文件(gdb)list #首次使用list,每次10行(可以设置)1 #include <stdio.h>2 #include <stdlib.h>3 intf1(int);4 intf2(char*);5 intmain(){6 inttmpi=16;7 fprintf(stderr,"Begine:\n");8 f1(tmpi);9 f2("HelloWorld!");10 fprintf(stderr,":End\n");(gdb)l #再次使用list,显示剩余部分11 exit(0);12 }12.7.2程序调试方法4)设置断点(gdb)break8Breakpoint1at0x4006da:filef3.c,line8.12.7.2程序调试方法5)开始执行(gdb)runStartingprogram:/root/myp##说明:因为在/etc/gdbinit中没有启用debuginfo,则会出现以下信息:#ThisGDBsupportsauto-downloadingdebuginfofromthefollowingURLs:#</> #Enabledebuginfodforthissession?(yor[n])y #回答y立即下载并启用debuginfod功能#Debuginfodhasbeenenabled.#Tomakethissettingpermanent,add'setdebuginfodenabledon'to.gdbinit.#Downloadingseparatedebuginfoforsystem-suppliedDSOat0x7ffff7fc7000#Downloadingseparatedebuginfofor/lib64/libc.so.6#[Threaddebuggingusinglibthread_dbenabled]#Usinghostlibthread_dblibrary"/lib64/libthread_db.so.1".##避免以上输出的办法是,按照以上说明将setdebuginfodenabledon作为一行添加到/etc/gdbinitBegine: #第7行的输出Breakpoint1,main()atf3.c:88 f1(tmpi);12.7.2程序调试方法6)打印变量的值(gdb)printtmpi$1=16注:也可通过set命令设置变量tmpi的值,比如settmpi=1007)单步执行,跟踪进入函数f1(也可使用next命令执行f1,而不进入函数f1)(gdb)stepf1(arg=16)atf1.c:33 printf("F1:youpassed:%d\n",arg);8)显示f1()变量arg的值(gdb)printarg$2=169)可在任何位置使用where命令,显示程序的调用栈,得到自己的位置。方法是:(gdb)where#0f1(arg=16)atf1.c:3#10x00000000004006e4inmain()atf3.c:812.7.2程序调试方法10)列出当前文件的内容(gdb)list1 #include <stdio.h>2 intf1(intarg){3 printf("F1:youpassed:%d\n",arg);4 }11)程序继续执行直到结束(gdb)continueF1:youpassed:16F2:youpassed:HelloWorld!:End[Inferior1(process11906)exitednormally]12)退出gdb(gdb)quitLinux其他编程工具简介12.812.8.1KDevelop/Qt开发KDevelop是一个基于GPL的集成开发环境(IDE),它最初是用于提供与KDE无缝式互操作的IDE及KDE基于Qt框架,因此提供了可以产生Qt图形界面的资源编辑程序。它提供编辑、编译、链接、排错、版本管理及计划管理等基本功能。KDevelop的Qt提供图形界面的widget库,用于对象通信的signal-slot机制,使用事件循环和虚拟方法事件控制机制,其他辅助功能。Linux自带KDevelop开发集成环境,安装kdevelop后,用户可通过“活动菜单”→KDevelop,或从CLI直接运行kdevelop命令打开操作界面,用户还可以通过设置来改变集成开发环境的界面外观。KDevelop简介12.8.2JavaJava是由美国SUN计算机公司研究而成的一种语言,自从1995年发表以来,以其简单、跨平台和面向对象等优点,深受广大程序员的青睐,经过数年的迅速发展,已经成为和C++等主流开发语言并列的语言。Java以其安全性、结构独立性、可移植性、高效能、多线程和动态性享誉编程界。近年来在移动开发、云计算、大数据、Web开发与应用方面发挥了巨大作用。在Linux系统中,有多种方法进行Java开发,常用的有Eclipse集成开发平台和JavaJDK开发环境。什么是java12.8.2Java1.安装Java运行和开发环境Java运行和开发需要Java运行和开发环境的支持。现在的Linux都提供Java开发和运行所需的软件包,需要时,可先安装它们,也可在安装系统时安装它们。在不同系统下的安装方法有所区别,在红帽系列系统和ubuntu系统的安装方法如下:#dnfinstalljava-21-openjdk-devel-y #红帽#aptinstalldefault-jdk-y #ubuntujava的安装及示例12.8.2Java2.Java示例安装之后,用户就可使用它编译和运行Java程序了。设有一个Java版的helloworld程序hello.java,代码如下:publicclasshello{ publicstaticvoidmain(String[]argc){ System.out.println("HelloJAVAWorld!"); }}编译和运行hello.java方法如下:$javachello.java #编译$javahello #运行12.8.3eclipseeclipse是一开源的、基于Java的可扩展平台,用于搭建开发平台,目前可以支持的语言有Java、C/C++、COBOL、PHP和Eiffel等。用户可以使用eclipse的集成环境进行Java开发,使用前需要先安装之。若使用test用户安装,eclipse安装方法及过程大致如下。1.下载安装包从/downloads/packages/下载所需要的eclipse软件包,至于是什么包取决于用户爱好和所用系统。笔者用的是64位系统,下载的为当前版本的eclipse-inst-jre-linux64.tar.gz安装包。2.解压进入eclipse-inst-jre-linux64.tar.gz所在目录,然后执行命令$tarxvfzeclipse-inst-jre-linux64.tar.gz或双击之,会产生目录eclipse-installer。进入eclipse-installer,可看到其中有安装程序eclipse-inst。eclipse的安装12.8.3eclipse3.执行命令eclipse-inst在执行eclipse-inst(双击之或输入后./eclipse-inst回车)。eclipse安装界面EcpliseIDEJavaDevelopers安装界面12.8.3eclipse用户可以此界面中,选择软件包进行安装,比如选择“EclipseIDEforJavaDevelopers”,之后会出现安装位置设置界面。一切选择默认,比如安装位置为/home/test/eclipse/java-2025-03/,然后单击“INSTALL”开始安装。安装的快慢取决于网速。安装完成后,出现“>LAUNCH”按钮,可以点击“LAUNCH”启动eclipse;也可以进入到安装目录,比如,/home/test/eclipse/java-2025-03/eclipse/,执行命令eclipse启动eclipse;当然,也可以直接执行命令/home/test/eclipse/java-2025-03/eclipse/eclipse启动eclipse-Java开发环境。为了应用方便,在/usr/bin/下为/home/test/eclipse//java-2025-03/eclipse/eclipse创建一个符号链接,方法为:#ln-s/home/test/eclipse/java-2025-03/eclipse/eclipse/usr/bin/eclipse这样,再启动eclipse就只需执行eclipse而不需要指定路径了。需要说明的是,这里的“/home/test/eclipse/java-2025-03”是安装时选择的路径,其中的2025-03为版本号,会随版本的变化而变化。关于安装位置,安装者可根据具体情况或个人偏好来指定。12.8.3eclipse创建桌面启动项若勾选了“CreateDesktopShortcut”,安装成功后,在安装者自己的“活动”启动菜单产生了一个名为“EclipseIDEforJavaDevelopers-2025-03”启动项,点击它可启动eclipse。此启动项只能安装者用户自己能看到,它的配置文件为~/.local/share/applications/epp.package.java.desktop,内容为:[DesktopEntry]Type=ApplicationTerminal=falseEncoding=UTF-8Version=1.1Name=EclipseIDEforJavaDevelopers-2025-03StartupWMClass=EclipseExec=/home/test/eclipse/java-2025-03/eclipse/eclipseCategories=Development;IDE;EclipseIcon=/opt/eclipse/java-2025-03/eclipse/icon.xpm若安装时未创建这个启动项,可创建~/.local/share/applications/epp.package.java.desktop文件,并使其内容如上所示。12.8.4PerlPerl(PracticalExtractionandReportLanguage)是实用摘录和报表语言,这是Perl设计的初衷,但随着进一步的发展,它的功能大大增加,被广泛应用于各个领域,从航天工程到分子生物学,从数学到语言学,从图形处理到文档处理,从数据库操作到网络管理等。Perl最初是作为一种UNIX的黏合语言设计的,但很快就被移植到了大多数其他操作系统上,所以Perl几乎可以在任何“地方”运行,甚至同一Perl脚本可以不加修改地在不同操作系统上工作。Perl简介12.8.4PerlPerl是开源的,是一种易学易用语言,但也是一种特性非常丰富的语言,且具有高级语言的强大功能和灵活性。Perl被设计成可以通过模块进行扩展,用户可以使用Perl快速设计、编写、调试Perl应用程序,还可以在需要时扩展自己的应用程序。用户可以在其他语言中嵌入Perl程序,也可以在Perl程序中嵌入其他语言,还可以通过模块导入机制,把外部的扩展当成Perl的内置特性,而且那些面向对象的语言模块在Perl内仍保持其面向对象特性。Perl是一种脚本语言,它的解释器是Perl。但Perl脚本的执行过程不完全与shell脚本相同,首先将脚本程序“编译”成内部格式代码,还可以进行优化,并将所遇到的错误反馈给用户,一经编译通过,这些中间代码就会被立即执行。12.8.4PerlPerl脚本的执行需要perl软件包的支持,用户可在系统安装时安装它们,也可在系统扩充时安装它们。事实上,perl已经作为操作系统的基础部分被安装。以下是一个简单的Perl脚本:#!/usr/bin/perlprint"HelloPerlWorld!\n";print"NamePlease:";$name=<stdin>;chop($name);print"yournameis\"$name\",Yourarewelcome!\n";perl脚本程序的扩展名为.perl或.pl。假设此脚本文件的文件名为hello.pl,如果第一行#!/usr/bin/perl设置正确,可在先为其增加执行权后,再按shell命令方式运行它,方法是:$chmod+xhello.pl;$./hello.pl如果第一行设置不正确,就只能使用perl命令直接解释并执行之,方法为:$perlhello.pl12.8.5数据库在Linux系统中可以使用数据库的选择较多,其中MySQL、PostgreSQL和SQLite是最流行的、开源的和基于SQL的数据库,并且MySQL和PostgreSQL的许可证也是免费的。Linux还支持传统UNIX的dbm数据库。除此之外,用户还可使用商业数据库,比如Oracle、Sybase等。关于MySQL数据库服务管理与mysql客户端的简单应用已经见于3.3.11,更多内容不再介绍。12.8.6PHPPHP(PersonalHomePage)是一种跨平台的在服务器端执行的脚本语言,可以在Windows、UNIX/Linux系统上运行,尤其是与全球网站服务器普及和使用率最高的Apache整合后,速度大大提高,也可以为CGI使用。PHP是免费的,用户可从网站中得到所需的版本,作为Linux的用户,建议从Linux系统发行版本软件包源安装所需要的内容。PHP可支持相当多的数据库,比如dBase、Empress、Informix、InterBase、MySQL、Oracle、PostgreSQL、Sybase和UNIXdbm等。由于免费和自由软件的原因,现在较流行的网站开发模式是Apache+MySQL+PHP,因此需要Apache服务器和MySQL服务的支持。如果是在Linux环境下使用Apache+MySQL+PHP开发模式,那就是Linux+Apache+MySQL+PHP,即所谓的LAMP,这是Linux环境网站建设与运行的普遍模式。在15章中,可以看到Linux+Apache+MySQL+PHP的LAMP架构及示例。12.8.7Objective-CObjective-C通常简记为ObjC、Obj-C或OC,是扩充C的面向对象编程语言。它主要用于MacOSX和GNUstep这两个使用OpenStep标准的系统。Linux支持Objective-C开发,但需要安装相关的软件。1.安装gnustep*及相关软件#yuminstallgnustep*gcc-objcgcc-objc++redhat-rpm-config-y #红帽(CentOS需要epel支持)#aptinstallgnustep*-y 12.8.7Objective-C2.helloworld设有OC版的helloworld程序,文件名为hello.m,清单如下所示。#import<Foundation/Foundation.h>intmain(intargc,constchar*argv[]){ NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init]; NSLog(@"HelloOCworld!\n"); [pooldrain]; return0;}12.8.7Objective-C3.编译hello.m编译和链接需要很多与OC相关的环境和库选择与设定,常见方法如下:$gcchello.m$(gnustep-config--objc-flags)-lobjc-lgnustep-base-ohello$gcchello.m`gnustep-config--objc-flags`-lobjc-lgnustep-base-ohello$gcchello.m-ohello-lgnustep-base-lobjc`gnustep-config--objc-flags`必要时,可调整参数或选项的先后次序,或将源程序文件写在其他参数的前面。12.8.8PythonPython是由荷兰人GuidovanRossum发明的,第一个公开发行版发行于1991年。Python是从ABC语言发展起来的,主要受到Modula-3的影响,并且结合了UNIXshell和C的习惯。Python是完全自由的,一切遵循GPL。Python的设计哲学是“优雅”、“明确”、“简单”。在设计上坚持清晰划一的风格,这使得Python成为一门易读、易维护,并且被大量用户所欢迎、用途广泛的语言。它的应用涉及操作系统运维、游戏、图像、图表、科学计算、人工智能、XML、大数据、云计算、机器人、网络编程与Web开发等。由于Python语言的简洁性、易读性以及可扩展性,在国外用Python做科学计算的研究机构日益增多,一些知名大学已经采用Python作为程序设计课程。Python的起源12.8.8PythonPython有以下特点:脚本语言,也是解释语言,强大的动态数据类型支持;兼容性好、跨平台、可移植;自动内存回收;面向对象特性;强大的类库支持,编程容易;易于扩展,便于拼接(嵌入);开源、免费。还有,单行语句和单行命令行输入(每行只书写一条语句),缩进成为语法的一部分。Python使用缩进表示语句块的开始和结束,而不是像其他语言那样使用花括号或者其他定界符。这与其他语言有明显的不同,需要初学者注意,一不小心就会造成编译或语法错误,尤其要注意Tab与空格有区别。Python的特点12.8.8PythonPython在执行时,首先将源代码编译成Python的字节码,然后再由Python虚拟机来执行。除此之外,Python还可以交互模式运行,比如,可在命令模式下直接运行Python交互环境,可在交互环境输入操作指令或Python语句,让Python立即执行。idle为Python的集成工作环境。python发展很快,有多个版本,现在使用的是版本3,命令为python3,一个通用的名字是python,是python3的一个链接。在ubuntu下可以为python3创建一个python链接,或安装python-is-python3包解决此问题。12.8.8Python当用户输入python命令并回车后,将进入交互界面,以下为一个交互过程的记录。>>> #>>>为Python的提示符>>>print("H

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论