How to write a Makefile
来源:互联网 发布:广电网络公司员工出路 编辑:程序博客网 时间:2024/05/22 03:37
How to write a Makefile
Introduction
Make is one of the original Unix tools for Software Engineering. ByS.I. Feldman of AT&T Bell Labs circa 1975. But there are publicdomain versions (eg. GNU) and versions for other systems(eg. Vax/VMS).
Related tools are the language compilers (cc, f77, lex, yacc, etc.)and shell programming tools (eg. awk, sed, cp, rm, etc.). You need toknow how to use these.
Important adjuncts are lint (source code checking for obvious errors)ctags (locate functions, etc. in source code) and mkdepend. These arenice, and good programmers use them.
Important, and related tools, are the software revision systems SCCS(Source Code Control System) and RCS (Revision Control System -- therecommended choice)
The idea is to automate and optimize the construction ofprograms/files -- ie. to leave enough foot prints so that others canfollow.
Makefile Naming
make is going to look for a file called Makefile, if not found then afile called makefile. Use the first (so the name stands out inlistings).
You can get away without any Makefile (but shouldn't)! Make hasdefault rules it knows about.
Makefile Components
- Comments
Comments are any text beginning with the pound (#) sign. Acomment can start anywhere on a line and continue until the end of theline. For example:
# $Id: slides,v 1.2 1992/02/14 21:00:58 reggers Exp $
- Macros
Make has a simple macro definition and substitution mechanism. Macros are defined in a Makefile as = pairs. For example:
MACROS= -me
There are lots of default macros -- you should honor the existingnaming conventions. To find out what rules/macros make is using type:
PSROFF= groff -Tps
DITROFF= groff -Tdvi
CFLAGS= -O -systype bsd43% make -p
NOTE: That your environment variables are exported into the make as macros. They will override the defaults.You can set macros on the make command line:
% make "CFLAGS= -O" "LDFLAGS=-s" printenv
cc -O printenv.c -s -o printenv - Targets
You make a particular target (eg. make all), in none specified then the first target found:
paper.dvi: $(SRCS)
NOTE: The the line beginning with $(DITROFF) begins with TAB not spaces.
$(DITROFF) $(MACROS) $(SRCS) >paper.dvi
The target is made if any of the dependent files have changed. The dependent files in this case are represented by the $(SRCS) statement. - Continuation of Lines
Use a back slash (/). This is important for long macros and/or rules.
- Conventional Macros
There are lots of defaultmacros (type "make -p" to print out the defaults). Most are prettyobvious from the rules in which they are used:
AR = ar
GFLAGS =
GET = get
ASFLAGS =
MAS = mas
AS = as
FC = f77
CFLAGS =
CC = cc
LDFLAGS =
LD = ld
LFLAGS =
LEX = lex
YFLAGS =
YACC = yacc
LOADLIBS =
MAKE = make
MAKEARGS = 'SHELL=/bin/sh'
SHELL = /bin/sh
MAKEFLAGS = b - Special Macros
Before issuing any command in a target rule set there are certain special macros predefined.
- $@ is the name of the file to be made.
- $? is the names of the changed dependents.
So, for example, we could use a rule
printenv: printenv.c
alternatively:
$(CC) $(CFLAGS) $? $(LDFLAGS) -o $@printenv: printenv.c
There are two more special macros used in implicit rules. They are:
$(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@- $< the name of the related file that caused the action.
- $* the prefix shared by target and dependent files.
- Makefile Target Rules
The general syntax of a Makefile Target Rule is
target [target...] : [dependent ....]
Items in brackets are optional, ellipsis means one or more.Note the tab to preface each command is required.
[ command ...]The semantics is pretty simple. When you say "make target"make finds the target rule that applies and, if any of thedependents are newer than the target, make executes the com-mands one at a time (after macro substitution). If anydependents have to be made, that happens first (so you havea recursion).
A make will terminate if any command returns a failure sta-tus. That's why you see rules like:
clean:
Make ignores the returned status on command lines that beginwith a dash. eg. who cares if there is no core file?
-rm *.o *~ core paperMake will echo the commands, after macro substition to showyou what's happening as it happens. Sometimes you might wantto turn that off. For example:
install:
@echo You must be root to install - Example Target Rules
For example, to manage sources stored within RCS (sometimesyou'll need to "check out" a source file):
SRCS=x.c y.c z.c
To manage sources stored within SCCS (sometimes you'll needto "get" a source file):
$(SRCS):
co $@$(SRCS):
Alternativley, to manage sources stored within SCCS or RCSlet's generalize with a macro that we can set as required.
sccs get $@SRCS=x.c y.c z.c
For example, to construct a library of object files
# GET= sccs get
GET= co
$(SRCS):
$(GET) $@lib.a: x.o y.o z.o
Alternatively, to be a bit more fancy you could use:
ar rvu lib.a x.o y.o z.o
ranlib lib.aOBJ=x.o y.o z.o
Since AR is a default macro already assigned to "ar" you canget away without defining it (but shouldn't).
AR=ar
lib.a: $(OBJ)
$(AR) rvu $@ $(OBJ)
ranlib $@If you get used to using macros you'll be able to make a fewrules that you can use over and over again.
For example, to construct a library in some other directoryINC=../misc
Beware:, the following will not work (but you'd think itshould)
OTHERS=../misc/lib.a
$(OTHERS):
cd $(INC); make lib.aINC=../misc
Each command in the target rule is executed in a separateshell. This makes for some interesting constructs and longcontinuation lines.
OTHERS=../misc/lib.a
$(OTHERS):
cd $(INC)
make lib.aTo generate a tags file
SRCS=x.c y.c z.c
On large projects a tags file, that lists all functions andtheir invocations is a handy tool.
CTAGS=ctags -x >tags
tags: $(SRCS)
${CTAGS} $(SRCS)
To generate a listing of likely bugs in your problemslint:
Lint is a really good tool for finding those obviousbugs that slip into programs -- eg. type classes, bad argu-ment list, etc.
lint $(CFLAGS) $(SRCS) - Some Basic Make Rule
People have come to expect certain targets in Makefiles. Youshould always browse first, but it's reasonable to expectthat the targets all (or just make), install, and clean willbe found.
- make all -- should compile everything so that you can do local testing before installing things.
- make install -- should install things in the right places. But watch out that things are installed in the right place for your system.
- make clean -- should clean things up. Get rid of the executables, any temporary files, object files, etc.
You may encounter other common targets, some have beenalready mentioned (tags and lint).
- An Example Makefile for printenv
# make the printenv command
#
OWNER=bin
GROUP=bin
CTAGS= ctags -x >tags
CFLAGS= -O
LDFLAGS= -s
CC=cc
GET=co
SRCS=printenv.c
OBJS=printenv.o
SHAR=shar
MANDIR=/usr/man/manl/printenv.l
BINDIR=/usr/local/bin
DEPEND= makedepend $(CFLAGS)
all: printenv
# To get things out of the revision control system
$(SRCS):
$(GET) $@
# To make an object from source
$(CC) $(CFLAGS) -c $*.c
# To make an executable
printenv: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS)
# To install things in the right place
install: printenv printenv.man
$(INSTALL) -c -o $(OWNER) -g $(GROUP) -m 755 printenv $(BINDIR)
$(INSTALL) -c -o $(OWNER) -g $(GROUP) -m 644 printenv.man $(MANDIR)
# where are functions/procedures?
tags: $(SRCS)
$(CTAGS) $(SRCS)
# what have I done wrong?
lint: $(SRCS)
lint $(CFLAGS) $(SRCS)
# what are the source dependencies
depend: $(SRCS)
$(DEPEND) $(SRCS)
# to make a shar distribution
shar: clean
$(SHAR) README Makefile printenv.man $(SRCS) >shar
# clean out the dross
clean:
-rm printenv *~ *.o *.bak core tags shar
# DO NOT DELETE THIS LINE -- make depend depends on it.
printenv.o: /usr/include/stdio.h - Makefile Implicit Rules
Consider the rule we used for printenv
printenv: printenv.c
We generalized a bit to get
$(CC) $(CFLAGS) printenv.c $(LDFLAGS) -o printenvprintenv: printenv.c
The command is one that ought to work in all cases where webuild an executable x out of the source code x.c This can bestated as an implicit rule:
$(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@.c:
This Implicit rule says how to make x out of x.c -- run ccon x.c and call the output x. The rule is implicit becauseno particular target is mentioned. It can be used in allcases.
$(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@Another common implicit rule is for the construction of .o(object) files out of .c (source files).
.o.c:
alternatively
$(CC) $(CFLAGS) -c $<.o.c:
$(CC) $(CFLAGS) -c $*.c - Make Dependencies
It's pretty common to have source code that uses includefiles. For example:
% cat program.c
The implicit rule only covers part of the source code depen-dency (it only knows that program.o depends on program.c).The usual method for handling this is to list the dependen-cies separately;
#include
#include "defs.h"
#include "glob.h"
etc....
main(argc,argv)
etc...etc...
Usually an implicit rule and a separate list of dependenciesis all you need. And it ought to be easy enough to figureout what the dependencies are.
$(CC) $(CFLAGS) -c $*.c
etc...
program.o: program.c defs.h glob.hHowever, there are a number of nice tools around that willautomatically generate dependency lists for you. For example(trivial):
DEPEND= makedepend $(CFLAGS)
These tools (mkdepend, mkmkf, etc.) are very common thesedays and aren't too difficult to use or understand. They'rejust shell scripts that run cpp (or cc -M, or etc.) to findout what all the include dependencies are. They then justtack the dependency list onto the end of the Makefile.
etc...
# what are the source dependencies
depend: $(SRCS)
$(DEPEND) $(SRCS)
etc....
# DO NOT DELETE THIS LINE -- ....
printenv.o: /usr/include/stdio.h
Based on Make and Makefiles by
Reg Quinton Computing and Communications ServicesThe University of Western OntarioLondon, Ontario N6A 5B7Canada
Press here to return to the General Unix Software Menu.
- How to write a Makefile
- How to write a Makefile
- how to write a makefile
- How to write a Makefile
- How to write a Makefile
- how to write a makefile
- How to write a simple Makefile
- how to write makefile
- How to write makefile
- how to write Makefile
- How to write a Makefile for ARM board
- How to Write a Summary?
- How to write a paper
- how to write a plugin
- How to write Makefile for kernel modules
- how to write a a paper
- How to write a A+ paper?
- how to create a Makefile
- oracle优化学习笔记
- asp.net 自定义分页
- 14.Adding Validation to Struts 2 Login Application
- Instancof详解
- 我翻译的Struts2教程.
- How to write a Makefile
- 新兴XML处理方法VTD-XML介绍
- [Java] Appfuse 源代码分析
- 一个简单的滑动门效果代码
- 测试点击“测试”后,不让这部分链接到别的地方
- 第一天正式学习jQuery
- 猴子分桃---小有意思
- 40 个轻量级 JavaScript 库
- c#中多线程---线程同步基础