MakeFile
执行顺序不是按代码顺序,而是依赖顺序
Makefile中的命令,必须要以[Tab]键开始
gcc包含编译器,链接器等等
加壳防止反汇编
make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。
多数UNIX平台都通过CC调用它们的C编译程序.除标准和CC以外,LINUX和FREEBSD还支持gcc
DEBUG版本比RELEASE版本多符号表,保存调试变量值函数名等等
make编译命令
1.-c 编译产生对象文件(*.obj)而不链接成可执行文件,当编译几个独立的模块,而待以后由链接程序把它们链接在一起时,就可以使用这个选项,如:
$cc -c hello.c ===> hello.o
$cc hello.o
2. -o 允许用户指定输出文件名,如
$cc hello.c -o hello.o
or
$cc hello.c -o hello
3. -g 指明编译程序在编译的输出中应产生调试信息.这个调试信息使源代码和变量名引用在调试程序中或者当程序异常退出后在分析core文件时可被使用.
$cc -c -g hello.c
4. -D 允许从编译程序命令行定义宏符号
一共有两种情况:一种是用-DMACRO,相当于在程序中使用#define MACRO,另一种是用-DMACRO=A,相当于程序中的#define MACRO A.如对下面这代码:
#ifdefine DEBUG
printf(“debug message\n”);
#endif
编译时可加上-DDEBUG参数,执行程序则打印出编译信息
5. -I 可指定查找include文件的其他位置.例如,如果有些include文件位于比较特殊的地方,比如/usr/local/include,就可以增加此选项如下:
$cc -c -I/usr/local/include -I/opt/include hello.c 此时目录搜索会按给出的次序进行.
6. -E 这个选项是相对标准的,它允许修改命令行以使编译程序把预先
处理的C文件发到标准输出,而不实际编译代码.在查看C预处理伪指令和C宏时,
这是很有用的.可能的编译输出可重新定向到一个文件,然后用编辑程序来分析:
$cc -c -E hello.c >cpp.out 此命令使include文件和程序被预先处理并重定向到文件cpp.out.以后可以用编辑程序或者分页命令分析这个文件,并确定最终的C语言代码看起来如何.
7. -o 优化选项, 这个选项不是标准的
-O和 -O1指定1级优化
-O2 指定2级优化
-O3 指定3级优化
-O0指定不优化
$cc -c O3 -O0 hello.c 当出现多个优化时,以最后一个为准!!
8. -Wall 以最高级别使用GNU编译程序,专门用于显示警告用!!
$gcc -Wall hello.c
9. -L指定连接库的搜索目录,-l(小写L)指定连接库的名字
$gcc main.o -L/usr/lib -lqt -o hello
上面的命令把目标文件main.o与库qt相连接,连接时会到/usr/lib查找这个库文件.也就是说-L与-l一般要成对出现.
显式规则
显式规则说明了如何生成一个或多个目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令
target:dependency
用dependcy生成target的cmd
Makefile中的变量
VARNAME在等式右端展开为定义它的字符串。变量一般都在Makefile的头部定义。按照惯例,所有的Makefile变量都应该是大写。
定义:
VARNAME=string
使用:
${VARNAME}
例子:
OBJS=prog.o code.o
CC=gcc
test:${ OBJS }
${ CC } –o test ${ OBJS }
prog.o:prog.c prog.h code.h
${ CC } –c prog.c –o prog.o
code.o:code.c code.h
${ CC } –c code.c –o code.o
clean:
rm –f *.o
对大小写敏感
可以从任何地方引用定义的变量
用一个变量来保存所有gcc命令的目标文件名,则可以方便地加入新的目标文件而且不易出错。
不同的Linux系统中存在着很多相似的编译器系统不同的Linux系统中存在着很多相似的编译器系统。使用一个变量来代替编译器名,那么只需要改变该变量的值。其他所有地方的命令名就都改变了
伪对象
.PHONY(声明以下对象皆为伪目标文件,make中使用):
clean:
rm rf ***
clean不是一个文件,它只不过是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
通配符
%任意一个
?匹配一个或多个
*所有
自动化变量
使用变量CC来定义编译器,并且传递变量CFLAGS(编译器参数)、CPPFLAGS(C语言预处理器参数)、TARGET_ARCH(目标机器的结构定义)给编译器,然后加上参数-c,后面跟变量
<
(
第
一
个
依
赖
文
件
名
)
,
然
后
是
参
数
−
o
加
变
量
<(第一个依赖文件名),然后是参数-o加变量
<(第一个依赖文件名),然后是参数−o加变量@(目标文件名)。
一个C编译的具体命令将会是:
$ {CC} $ {CFLAGS} $ {CPPFLAGS} $ {TARGET_ARCH} –c $< -o $@
隐式规则
由于make有自动推导的功能,所以隐式规则可以让我们比较粗糙地简略地书写Makefile,这是由make支持的
实践
-ltermcap库
https://ftp.gnu.org/gnu/termcap/
安装termcap
$ tar -xzvf ./*.tgz
$ cd ./*
$ ./configure
$ make
$ sudo make install
makefile 指定库的路径
现有libmad交叉编译后安装于:/home/andy/share/libmad_install目录
现在应用程序miniplayer位于:/home/andy/share/mini_player目录
mini_player中的makefile里,怎么指定libmad库和mad.h头文件的路径呢?
指定 头文件用
-I /home/andy/share/mini_player
指定 库文件: -L 后面是具体的目录。
-L /home/andy/share/libmad_install
makefile如下,先编译完,拷到arm板上运行时提示:
/flac_app: error while loading shared libraries: librt.so.1: cannot open shared object file: No such file or directory
这些lib我已经拷到板上的/lib里了,怎么会找不到
Makefile for the CAMERA Application.
#以下是指定编译器路径
CC = /opt/armv6/codesourcery/bin/arm-none-linux-gnueabi-gcc
#以下是指定编译需要的头文件
CFLAGS = -g -Wall -O0 -I/home/andy/share/alsalib/include -I/home/andy/share/libmad_install/include
#以下是源文件
SRCS = main.c miniplayer_decode.c miniplayer_play.c
#以下是指定需要的库文件
LIBS = -L/home/andy/share/libmad_install/lib -lmad -L/home/andy/share/alsalib/lib -lasound
#以下是指定目标文件 所有当.c文件变成.o文件
OBJS = $(SRCS:.c=.o)
#以下是生成可执行文件
EXECUTABLE = flac_app
#make all 执行生成可执行文件
#1编译器 2编译选项 3输出 4生成的可执行文件 5需要的源文件 6需要当库文件
all:
$(CC) $(CFLAGS) -o $(EXECUTABLE) $(SRCS) $(LIBS)
#make clean 删除所有的.o文件 和生成的可以执行文件
clean:
rm -f $(OBJS) flac_app
makefile中的指定头文件,源文件
可以使用VPATH变量也可以使用vpath后者可以分类指定头文件源文件的搜索路径
记住这样指定的路径仅仅是makefile本身查找头文件源文件的路径
在执行makefile时,还要指定gcc/g++搜索头文件库文件的搜索路径
-L //指定库文件搜索路径
-ltest//指定使用的动态库/静态库
-I //指定搜索头文件的路径
进阶
--static #静态编译,需要-l*.a文件
#函数
SRC = $(wildcard *.c)#提取当前目录所有.c文件
OBJ = $(patsubst %.c,%.o,$(SRC))#.c替换成.o
万能模板
TARGET=telnet
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c,%.o,$(SRC))
INCLUDE =
DEFS = -D_POSIX_SOURCE
CFLAGS = -g
CC =gcc
LIBS = -ltermcap
RELEASE=release
SYMBOL=debug
$(TARGET):$(OBJ)
$(CC) $(CFLAGS) $(DEFS) -o $@ $^ $(LIBS)
$(RELEASE):$(TARGET)
objcopy --strip-debug $(TARGET) $(TARGET).release
strip $(TARGET).release
$(SYMBOL):$(TARGET)
objcopy --only-keep-debug $(TARGET) $(TARGET).symbol
.PHONY:
clean:
rm -rf *.o $(TARGET) $(TARGET).release $(TARGET).symbol