Linux下编译与调试

发布时间 : 星期日 文章Linux下编译与调试更新完毕开始阅读

Linux总结 作者:王啸

1.1. make

工程管理器

可以试想一下,有一个上百个文件的代码构成的项目,如果其中只有一个活少数几个文件进行了修改,如果再从头到尾将每一个文件都重新编译是个比较繁琐的过程。为此,引入了Make工程管理器的概念,工程管理器指管理较多的文件,它是自动管理器能根据文件时间自动发现更新过的文件而减少编译的工作量,同时通过读入Makefile文件来执行大量的编译工作

makefile格式

target: dependency_files //目标项:依赖项

< TAB >command //必须以tab开头,command编译命令 注意点:在写command命令行的时候,必须要在前面按TAB键 例如,有makefile文件,内容如下: main.exe:main.o func.o g++ -o main.exe main.o func.o main.o:main.cpp g++ -c main.cpp func.o:func.cpp g++ -c func.cpp

使用make编译 对于该makefile文件,程序make处理过程如下:

? make程序首先读到第1行的目标文件main.exe和它的两个依赖文件main.o和func.o;然后

比较文件main.exe和main.o/func.o的产生时间,如果main.exe比main.o/func.o旧的话,则执行第2条命令,以产生目标文件main.exe。

? 在执行第2行的命令前,它首先会查看makefile中的其他定义,看有没有以第1行main.o

和func.o为目标文件的依赖文件,如果有的话,继续按照(1)、(2)的方式匹配下去。

? 根据(2)的匹配过程,make程序发现第3行有目标文件main.o依赖于main.cpp,则比较目

main.o与它的依赖文件main.cpp的文件新旧,如果main.o比main.cpp旧,则执行第4行的命令以产生目标文件main.o.在执行第4条命令时,main.cpp在文件makefile不再有依赖文件的定义,make程序不再继续往下匹配,而是执行第4条命令,产生目标文件main.o ? 目标文件func.o按照上面的同样方式判断产生.

? 执行(3)、(4)产生完main.o和func.o以后,则第2行的命令可以顺利地执行了,最终产生

了第1行的目标文件main.exe。 1.2. 特殊处理与伪目标

.PHONY是makefile文件的关键字,表示它后面列表中的目标均为伪目标 .PHONY:b b:

echo ?b? //通常用@echo “hello”

伪目标通常用在清理文件、强制重新编译等情况下。

Example1:main.c函数,func.c函数为前面计算+,-,*,/运算的程序 #vi Makefile //系统默认的文件名为Makefile

main.exe:main.o func.o //表示要想生成main.exe文件,要依赖于main.o和func.o文件 gcc -o main.exe main.o func.o//如果main.o,func.o已经存在了,就链接成main.exe main.o:main.c //表示main.o文件依赖于main.c文件

9

Linux总结 作者:王啸

gcc -c main.c //编译main.c,默认生成main.o。可写为:gcc –c main.c –o main.o func.o:func.c //表示func.o文件依赖于func.c文件

gcc -c func.c //如果func.c存在,则编译func.c ,生成func.o

.PHONY:rebuild clean //表示后面的是伪目标,通常用在清理文件、强制重新编译等情况下 rebuild:clean main.exe //先执行清理,在执行main.exe

clean:

rm –rf main.o func.o main.exe //最后删除.o和.exe的文件 按ESC键之后,:wq保存退出 再执行下面的命令: #make //直接make,即从默认文件名(Makefile)的第一行开始执行 #make clean //表示执行clean: 开始的命令段 #make func.o //表示执行func.o: 开始的命令段 #make rebuild //则先执行清除,再重新编译连接

如果不用系统默认的文件名Makefile,而是用户随便起的一个名字,如: #vi Makefile11

则make 后面必须要加上 -f Makefile11 ,如: #make –f Makefile11 clean //表示执行clean: 开始的命令段 #make –f Makefile11 main.exe //表示执行main.exe: 开始的命令段 1.3. 变量、函数与规则

随着软件项目的变大、变复杂,源文件也越来越多,如果采用前面的方式写makefile文件,将会使makefile也变得复杂而难于维护。通过make支持的变量定义、规则和内置函数,可以写出通用性较强的makefile文件,使得同一个makefile文件能够适应不能的项目。

变量:用来代替一个文本字符串

定义变量的2种方法: 变量名=变量值 递规变量展开(几个变量共享一个值) //不常用 变量名:=变量值 简单变量展开(类似于C++的赋值) //通常采用这种形式 使用变量的一般方法:$(变量名)=??? 赋值

???=$(变量名) 引用

例:将以前的那个可以写为:

OBJS:=main.o func.o//相当于main.o func.o EXE:=main.exe $(EXE):$(OBJS) g++ -o $(EXE) $(OBJS) main.o:main.cpp g++ -c main.cpp –o main.o func.o:func.cpp g++ -c func.cpp –o func.o clean: rm –rf $(EXE) $(OBJS) 10

Linux总结 作者:王啸

变量分为:用户自定义变量,预定义变量,自动变量,环境变量 自动变量:指在使用的时候,自动用特定的值替换。 常用的有: 变量 $@ $< $^ $? $(@D) $(@F) 说明 当前规则的目标文件 当前规则的第一个依赖文件 当前规则的所有依赖文件,以逗号分隔 规则中日期新于目标文件的所有相关文件列表,逗号分隔 目标文件的目录名部分 目标文件的文件名部分 Examp:用自动变量:

OBJS:= main.o func.o//$(OBJS)相当于main.o func.o (原样替换)

EXE:= main.exe

CFLAGS:= -Wall -O2 –fpic //显示所有警告信息,优化级别为2 LIBFUNCSO:= libfunc.so //动态库 LIBFUNCA:= libfunc.a //静态库

$(EXE):$(OBJS) $(LIBFUNCSO) $(LIBFUNCA) gcc -o $@ $< -L. -lfunc main.o: main.c

gcc -c $(CFLAGS) $< -o $@ func.o: func.c

gcc -c $(CFLAGS) $< -o $@ libfunc.a: func.o

ar rcsv $@ $< libfunc.so: func.o

gcc -shared -o $@ $< cp -f $@ /lib .PHNOY:rebuild clean rebuild:clean $(EXE) clean:

rm -rf $(EXE) $(OBJS) $(LIBFUNCSO) $(LIBFUNCA)

预定义变量:内部事先定义好的变量,但是它的值是固定的,并且有些的值是为空的。 AR:库文件打包程序默认为ar AS:汇编程序,默认为as CC:c编译器默认为cc

CPP:c预编译器,默认为$(CC) –E CXX:c++编译器,默认为g++ RM:删除,默认为rm –f ARFLAGS:库选项,无默认 ASFLAGS:汇编选项,无默认 CFLAGS:c编译器选项,无默认

CPPFLAGS:c预编译器选项,无默认 CXXFLAGS:c++编译器选项

11

Linux总结 作者:王啸

根据内部变量,可以将makefile改写为:

OBJS:=main.o func.o CC:=g++ main.exe:$(OBJS) $(CC) -o $@ $^ main.o:main.cpp $(CC) -o $@ -c $^ func.o:func.cpp $(CC) -o $@ -c $^

规则分为:普通规则,隐含规则,模式规则

隐含规则://*.o文件自动依赖*.c或*.cc文件,所以可以省略main.o:main.cpp等 OBJS := main.o fun.o CFLAGS := -Wall –O2 -g main.exe: $(OBJS) gcc $^ -o $@

模式规则:通过匹配模式找字符串, %匹配1或多个任意字符串

%.o: %.cpp任何目标文件的依赖文件是与目标文件同名的并且扩展名为.cpp的文件 OBJS := main.o fun.o CFLAGS := -Wall –O2 –g main.exe : $(OBJS) gcc $^ -o $@

%.o: %.cpp //模式通配

gcc -o $@ -c $^

函数:

1. wildcard搜索当前目录下的文件名,展开成一列所有符合由其参数描述的文件名,文件间以空格间隔。SOURCES = $(wildcard *.cpp)把当前目录下所有'.cpp'文件存入变量 SOURCES 里。

2. 字符串替换函数:$(patsubst,要查找的子串,替换后的目标子串,源字符串)。将源字符串(以空格分隔)中的所有要查找的子串替换成目标子串。如OBJS = $(patsubst %.cpp,%.o,$(SOURCES)) 把SOURCES中'.cpp' 替换为'.o' 。

3. $(addprefix 前缀,源字符串)函数把第二个参数列表的每一项前缀上第一个参数值 下面是一个较为通用的makefile: DIR := ./debug

EXE := $(DIR)/Main.exe CC := g++ LIBS :=

SRCS := $(wildcard *.cpp) $(wildcard *.c) $(wildcard *.cc) OCPP := $(patsubst %.cpp, $(DIR)/%.o, $(wildcard *.cpp)) OC := $(patsubst %.c, $(DIR)/%.co, $(wildcard *.c)) OCC := $(patsubst %.cc, $(DIR)/%.cco, $(wildcard *.cc))

12

联系合同范文客服:xxxxx#qq.com(#替换为@)