使用make可以编译Linux内核,make是C/C++项目开发中重要的工具。GNU make仿照make的标准功能(通过clean-room工程)重新改写,并加入作者觉得值得加入的新功能,常和GNU编译系统一起被使用,是大多数GNU Linux安装的一部分。
如何创建makefile 格式如下
#用“#”号表明注释。
target(要生成的文件): dependencies(被依赖的文件)
#命令前面用的是“tab”而非空格。误用空格是初学者容易犯的错误!
命令1
命令2
命令3
.
.
.
命令n
#可以使用“\”表示续行。注意,“\”之后不能有空格!
make的规则、变量、函数和脚本
Make命令
在make命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些参数指定了需要编译的目标文件。其标准形式为:
target1 [target2 …]:[:][dependent1 …][;commands][#…]
[(tab) commands][#…]
Makefile文件
Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。makefile 文件是许多编译器--包括 Windows NT 下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改 makefile 文件而已。
Makefile文件作为一种描述文档一般需要包含以下内容:
◆ 宏定义
◆ 源文件之间的相互依赖关系
◆ 可执行的命令
下面是helloworld的makefile:
hello:hello.c
gcc hello.c -o hello
要编译此程序,只需输入:$ make
如果要使用其他文件作为 makefile,则可利用类似下面的 make 命令选项指定 makefile 文件: $ make -f Makefile.debug
Linux下make的部分标志位:
-c dir 在读取 makefile 之前改变到指定的目录dir。
-I dir 当包含其他 makefile文件时,利用该选项指定搜索目录。
-h help文挡,显示所有的make选项。
-w 在处理 makefile 之前和之后,都显示工作目录。
系统中默认的常用文件扩展名及其含义为:
.o 目标文件
.c C源文件
.f FORTRAN源文件
.s 汇编源文件
.y Yacc-C源语法
.l Lex源语法
下面是GNU bison的Makefile:
CINC = -Iinclude
CONF = config
SRC = src
BIN = bin
UTILSRC = $(SRC)/list.c $(SRC)/error.c $(SRC)/ast.c
CC = gcc -g $(CINC)
LEX = flex -i -I
YACC = bison -d -y
all: expr expr1 asgn asgn1 asgn_err asgn2ast
# Generates a compiler for a simple expression language,
# the grammar is ambiguous, and uses precedence declarations
expr: $(CONF)/expr.y $(CONF)/expr.lex
$(YACC) -b expr -o $(SRC)/expr.tab.c $(CONF)/expr.y
$(LEX) -o$(SRC)/expr.lex.c $(CONF)/expr.lex
$(CC) -o $(BIN)/expr $(SRC)/expr.lex.c $(SRC)/expr.tab.c -ll -lm
# Generates a compiler for a simple expression language,
# the grammar is disambiguous.
expr1: $(CONF)/expr1.y $(CONF)/expr.lex
$(YACC) -b expr1 -o $(SRC)/expr1.tab.c $(CONF)/expr1.y
mv $(SRC)/expr1.tab.h $(SRC)/expr.tab.h
$(LEX) -o$(SRC)/expr.lex.c $(CONF)/expr.lex
$(CC) -o $(BIN)/expr1 $(SRC)/expr.lex.c $(SRC)/expr1.tab.c -ll -lm
# Generates a compiler for an assignment statement sequence language,
# which evaluates each assignment statement in an input program.
asgn: $(CONF)/asgn.y $(CONF)/asgn.lex
$(YACC) -b asgn -o $(SRC)/asgn.tab.c $(CONF)/asgn.y
$(LEX) -o$(SRC)/asgn.lex.c $(CONF)/asgn.lex
$(CC) -o $(BIN)/asgn $(SRC)/asgn.lex.c $(SRC)/symtab.c $(SRC)/asgn.tab.c -ll -lm
# Similar to asgn,
# but nonterminal 'op' is introduced to represent all infix operators.
asgn1: $(CONF)/asgn1.y $(CONF)/asgn.lex
$(YACC) -b asgn -o $(SRC)/asgn1.tab.c $(CONF)/asgn1.y
mv $(SRC)/asgn1.tab.h $(SRC)/asgn.tab.h
$(LEX) -o$(SRC)/asgn.lex.c $(CONF)/asgn.lex
$(CC) -o $(BIN)/asgn1 $(SRC)/asgn.lex.c $(SRC)/symtab.c $(SRC)/asgn1.tab.c -ll -lm
# Generates a compiler for an assignment statement sequence language.
# The compiler provides error recovery.
asgn_err: $(CONF)/asgn_err.y $(CONF)/asgn.lex
$(YACC) -b asgn_err -o $(SRC)/asgn_err.tab.c $(CONF)/asgn_err.y
$(LEX) -o$(SRC)/asgn_err.lex.c $(CONF)/asgn_err.lex
$(CC) -o $(BIN)/asgn_err $(SRC)/asgn_err.lex.c $(SRC)/symtab.c $(SRC)/asgn_err.tab.c $(UTILSRC) -ll -lm
# Generates a compiler for an assignment statement sequence language,
# which constructs an abstract syntax tree for an input program.
asgn2ast: $(CONF)/asgn2ast.y $(CONF)/asgn.lex
$(YACC) -b asgn2ast -o $(SRC)/asgn2ast.tab.c $(CONF)/asgn2ast.y
$(LEX) -o$(SRC)/asgn.lex.c $(CONF)/asgn.lex
$(CC) -DDEBUG -o $(BIN)/asgn2ast $(SRC)/asgn.lex.c $(SRC)/symtab.c $(SRC)/asgn2ast.tab.c $(UTILSRC) -ll -lm
clean:
rm -f *.BAK *.o core *~* *.a
rm -f $(SRC)/*.tab.h $(SRC)/*.tab.c
rm -f $(SRC)/*.lex.c *.out