随笔-57  评论-12  文章-0  trackbacks-0
                  Makefile Introduction (SunOS platform as example)

1. A simple Makefile

EXE = foo
SRC = foo.cc
OBJ = foo.o

CC = /SunOS/5.7/SUNWspro_6.0.OLD/WS6U1/bin/CC
FLAG = -g

$(EXE):$(OBJ)
$(CC) $(FLAG) $^ -o $@

$(OBJ):$(SRC)
$(CC) $(FLAG) -c $< -o $@

2. How to use the Makefile

/usr/ccs/bin/make [ -d ] [ -dd ] [ -D ] [ -DD ] [ -e ]
[ -i ] [ -k ] [ -n ] [ -p ] [ -P ] [ -q ] [ -r ] [ -s ]
[ -S ] [ -t ] [ -V ] [ -f makefile ] ...
[ -K statefile ] ... [ target ... ] [ macro = value ... ]

/usr/xpg4/bin/make [ -d ] [ -dd ] [ -D ] [ -DD ] [ -e ]
[ -i ] [ -k ] [ -n ] [ -p ] [ -P ] [ -q ] [ -r ] [ -s ]
[ -S ] [ -t ] [ -V ] [ -f makefile ] ... [ target... ]
[ macro = value ... ]

-e : Environment variables override assignments within makefiles.

-f makefile : Uses the description file makefile.

-i : Ignores error codes returned by commands.

-k : When a nonzero error status is returned by a rule,
or when make cannot find a rule, abandons work on
the current target, but continues with other
dependency branches that do not depend on it.

-n : No execution mode.

3. Special Characters in Makefle

# -- Start a comment
For example :
#This is a makefile

inlcude filename -- include a file
For example :
include make.sun57.inc

: -- Target list terminator
For example :
foo.o:foo.c foo.h

:: -- Target terminator for alternate dependencies
For example :
foo.o::foo.c foo.h

% -- Pattern matching wild card metacharacter
For example :
%.o:%.c

4. Macros

= -- Macro definition
For example :
CC=/SunOS/5.7/SUNWspro_6.0.OLD/WS6U1/bin/CC

+= appends a string to a macro definition
For example :
A=dir
B=bin
A+=$(B)

result : $(A) == dir bin

:= Conditional macro assignment
For example :
A=dir
B:=$(A)
A=bin

result : $(B) == dir

$ -- Macro reference
For example :
$(A),$(B)

( ),{ } -- Macro-reference name delimiters
For example :
$(A),${B}

$$ -- A reference to the dollar-sign macro
For example :
echo $$

result : $

\$ -- Escaped dollar-sign character

5. Rules

1) Special characters

+ -- always execute the commands
For example :
+echo hello

- -- ignores any nonzero error code returned by a command line
For example :
-echo hello

@ -- does not print the command line before executing it
For example :
@echo hello

? -- Escape command-dependency checking

! -- Force command-dependency checking

2) Dependency

foo.o:foo.c foo.h foo1.h
$(CC) $(FLAG) -c foo.c -o foo.o

3) Special macros

$@, $*, $(@D), $(@F) $^, $<, $?, $%
$(MAKE)...

$@ -- The name of the current target

$* -- The basename of the current target

$(@D) -- The directory part of the string `$@'
if there is no directory part, `.' is assigned

$(@F) -- The file name of '$@'

$^ -- All a dependency files

$< -- The name of the first dependency files

$? -- The list of dependencies that are newer than the target

$% -- The name of the library member being processed

$(MAKE) -- It has the value make by default, and temporarily
overrides the -n option for any line in which it is
referred to.

example :
../lib/liba.a:a.o b.o c.o d.o
@(AR) $@ $^

result :
$@ --> ../lib/liba.a
$* --> ../lib/liba
$(@D) --> ../lib
$($F) --> liba.a
$^ --> a.o b.o c.o d.o
$< --> a.o
$? --> b.o d.o (if b.o and d.o are newer than ../lib/liba.a)

example :
lib(member...):...

lib(a.o b.o c.o):a.o b.o c.o
$% --> a.o b.o c.o (lib(...))

4) Predefined Macros and Implicit Rules (Partly)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Table of Predefined Macros
Use Macro Default Value
______________________________________________________________________
Library AR ar
Archives ARFLAGS rv
______________________________________________________________________
Assembler AS as
Commands ASFLAGS
COMPILE.s $(AS) $(ASFLAGS)
COMPILE.S $(CC) $(ASFLAGS) $(CPPFLAGS) -c
______________________________________________________________________
C CC cc
Compiler CFLAGS
Commands CPPFLAGS
COMPILE.c $(CC) $(CFLAGS) $(CPPFLAGS) -c
LINK.c $(CC) $(CFLAGS) $(CPPFLAGS)
$(LDFLAGS)
______________________________________________________________________
C++ CCC CC
Compiler CCFLAGS CFLAGS
Commands CPPFLAGS
COMPILE.cc $(CCC) $(CCFLAGS) $(CPPFLAGS) -c
LINK.cc $(CCC) $(CCFLAGS) $(CPPFLAGS)
$(LDFLAGS)
COMPILE.C $(CCC) $(CCFLAGS) $(CPPFLAGS) -c
LINK.C $(CCC) $(CCFLAGS) $(CPPFLAGS)
$(LDFLAGS)
______________________________________________________________________
FORTRAN 77 FC f77
Compiler FFLAGS
Commands COMPILE.f $(FC) $(FFLAGS) -c
LINK.f $(FC) $(FFLAGS) $(LDFLAGS)
COMPILE.F $(FC) $(FFLAGS) $(CPPFLAGS) -c
LINK.F $(FC) $(FFLAGS) $(CPPFLAGS)
$(LDFLAGS)
______________________________________________________________________
FORTRAN 90 FC f90
Compiler F90FLAGS
Commands COMPILE.f90 $(F90C) $(F90FLAGS) -c
LINK.f90 $(F90C) $(F90FLAGS) $(LDFLAGS)
COMPILE.ftn $(F90C) $(F90FLAGS) $(CPPFLAGS) -c
LINK.ftn $(F90C) $(F90FLAGS) $(CPPFLAGS)
$(LDFLAGS)
______________________________________________________________________
Link Editor LD ld
Command LDFLAGS
______________________________________________________________________
lex LEX lex
Command LFLAGS
LEX.l $(LEX) $(LFLAGS) -t
______________________________________________________________________
lint LINT lint
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



_______________________________________________________________
| Table of Standard |
| Implicit (Suffix) |
| Rules for C Files |
| Implicit Rule Name| Command Line |
|___________________|_________________________________________|
| .c | $(LINK.c) -o $@ $< $(LDLIBS) |
| | |
| .c.ln | $(LINT.c) $(OUTPUT_OPTION) -i $< |
| | |
| .c.o | $(COMPILE.c) $(OUTPUT_OPTION) $< |
| | |
| .c.a | $(COMPILE.c) -o $% $< |
| | $(AR) $(ARFLAGS) $@ $% |
| | $(RM) $% |
| .cc | $(LINK.cc) -o $@ $< $(LDLIBS) |
| | |
| .cc.o | $(COMPILE.cc) $(OUTPUT_OPTION) $< |
| | |
| .cc.a | $(COMPILE.cc) -o $% $< |
| | $(AR) $(ARFLAGS) $@ $% |
| | $(RM) $% |
| .f | $(LINK.f) -o $@ $< $(LDLIBS) |
| | |
| .f.o | $(COMPILE.f) $(OUTPUT_OPTION) $< |
| | |
| .f.a | $(COMPILE.f) -o $% $< |
| | $(AR) $(ARFLAGS) $@ $% |
| | $(RM) $% |
_______________________________________________________________


6. Reading Makefiles and the Environment

When make first starts, it reads the MAKEFLAGS environment
variable to obtain any of the following options specified
present in its value: -d, -D, -e, -i, -k, -n, -p, -q, -r,
-s, -S, or -t. Due to the implementation of POSIX.2 (see
POSIX.2(5), the MAKEFLAGS values will contain a leading `-'
character. The make utility then reads the command line
for additional options, which also take effect.

Next, make reads in a default makefile that typically con-
tains predefined macro definitions, target entries for
implicit rules, and additional rules, such as the rule for
retrieving SCCS files. If present, make uses the file
make.rules in the current directory; otherwise it reads the
file /usr/share/lib/make/make.rules, which contains the
standard definitions and rules. Use the directive:

include /usr/share/lib/make/make.rules
in your local make.rules file to include them.

Next, make imports variables from the environment (unless
the -e option is in effect), and treats them as defined mac-
ros. Because make uses the most recent definition it
encounters, a macro definition in the makefile normally
overrides an environment variable of the same name. When -e
is in effect, however, environment variables are read in
after all makefiles have been read. In that case, the
environment variables take precedence over definitions in
the makefile.

Next, make reads any makefiles you specify with -f, or one
of makefile or Makefile as described above and then the
state file, in the local directory if it exists. If the
makefile contains a .KEEP_STATE_FILE target, then it reads
the state file that follows the target. Refer to special
target .KEEP_STATE_FILE for details.

Next (after reading the environment if -e is in effect),
make reads in any macro definitions supplied as command
line arguments. These override macro definitions in the
makefile and the environment both, but only for the make
command itself.

make exports environment variables, using the most recently
defined value. Macro definitions supplied on the command
line are not normally exported, unless the macro is also an
environment variable.

make does not export macros defined in the makefile. If an
environment variable is set, and a macro with the same name
is defined on the command line, make exports its value as
defined on the command line. Unless -e is in effect, macro
definitions within the makefile take precedence over those
imported from the environment.

Simply :
make --> Reads MAKEFLAGS environment variable to obtain the
following options :
-d, -D, -e, -i, -k, -n, -p, -q, -r, -s, -S, or -t

--> Reads in a default makefile, contains :
Predefined macros
Target entries for implicit rules
Additional rules
Default makefile :
make.rules in current directory
if no,/usr/share/lib/make/make.rules
in make.rules in current directory will include
/usr/share/lib/make/make.rules

--> Imports environment variables as defined macros.
if no -e,macros defined in makefile will override
the environment variables(same names)
if -e, exchange

--> Reads makefile specified by -f,
or Makefile(makefile) in current directory.

--> Reads in macro definitions supplied as command line.
Overrides both Environment variables and macros
defined in makefile,even if -e is supplied.

--> Exports environment variables,using the most recently
value.

Note :
Macros override sequence :
The later override the previous.

7. Advanced Macro Definitions

1) CSRC=$(wildcard *.c)

2) $(name:str1=str2)
For example :
CSRC=a.c b.c c.c
OBJS=$(CSRC:.c=.o)

result: $(OBJS)==a.o b.o c.o

3) OBJS=$(patsubst %.c,%.o,$(CSRC))
For example :
CSRC=a.c b.c c.c

result: $(OBJS)==a.o b.o c.o

CC=$(patsubst $(CC),$(CC_DBG),$(CC))
replace the value of CC with the value of CC_DBG

(patsubst or subst)

4) OBJS=$(addprefix ../obj/,$(CSRC:.c=.o))
For example :
CSRC=a.c b.c c.c

result: $(OBJS)==../obj/a.o ../obj/b.o ../obj/c.o

4) $(name: op%os= np%ns)
(op--old prefix,os--old suffix,
np--new prefix,ns--new suffix)
For example :
name=MMandGG
name1=$(name:MM%GG=GG%MM)

result: $(name1) == GGandMM

name=and
name1=$(name:%=MM%GG)

result: $(name1) == MMandGG

8. Phony Targets
1)
.PHONY:all

all:exe1 exe2

Note:want to build two binaries:exe1 exe2,
and exe1 and exe2 is separate.
all does not exist,make will try to update this rule,
so,make try to check exe1 and exe2 if they want to be updated.

2)
.PHONY:release debug
release:
...

debug:
...

release and debug have no dependency,so it will not execute until
use "make release" or "make debug"

but,make's default is the first phony target:
if release is the first,"make" means "make release"

The dependency does not exist,

9. Control Structure

1) Jump

release:
@$(MAKE) A=dir \
B=bin compile

compile:
...
...

2) if
if [ ! -d $(@D) ]; then $(MK_DIR) $(@D); fi

3) for
compile:
@for dir in $(SUBDIRS); do \
if [ -d $$dir ]; then \
(cd $$dir; echo build in $$dir;$(MAKE) compile;) \
else echo not build in $$dir; fi \
done

4) Command Macro definition

define MKDIR
if [ ! -d $(@D) ]; then $(MK_DIR) $(@D); fi
endef

usage: $(MKDIR)

10. A Makefile Example

#
# --> ***Makefile** <-- #
#

BIN = bin
OBJ = obj
RLS = rls
DBG = dbg

OBJS = $(addprefix $(OBJ)/$(RLS)/,$(CCSRCS:.cc=.o))

BINDIR = $(BIN)/$(RLS)
OBJDIR = $(OBJ)/$(RLS)

RM = rm -rf
CP = cp -p
MV = mv
MK_DIR = mkdir -p
AR = /usr/local/bin/ar cq

CC_RE = /SunOS/5.7/SUNWspro_6.0.OLD/WS6U1/bin/CC
CCFLAGS_RE = -fast -xarch=v9 -DNDEBUG

CC_DBG = $(CC_RE)
CCFLAGS_DBG = -g

#############define mkdir macro#############
define MKDIR
if [ ! -d $(@D) ]; then $(MK_DIR) $(@D); fi
endef

define MKOBJDIR
if [ ! -d $(OBJ)/$(RLS) ]; then $(MK_DIR) $(OBJ)/$(RLS); fi
endef

define MKLIBDIR
if [ ! -d $(LIBDIR)/$(RLS) ]; then $(MK_DIR) $(LIBDIR)/$(RLS); fi
endef

define MKBINDIR
if [ ! -d $(BIN)/$(RLS) ]; then $(MK_DIR) $(BIN)/$(RLS); fi
endef

################make release################
release:
@$(MAKE) CC='$(subst $(CC),$(CC_RE),$(CC))' \
CC_OPT='$(subst $(CC_OPT),$(CCFLAGS_RE),$(CC_OPT))' compile

################make debug##################
debug:
@$(MAKE) CC='$(subst $(CC),$(CC_DBG),$(CC))'\
CC_OPT='$(subst $(CC_OPT),$(CCFLAGS_DBG),$(CC_OPT))'\
RLS='$(subst $(RLS),$(DBG),$(RLS))' compile

##################compile###################
compile:
ifdef SUBDIRS
@for dir in $(SUBDIRS); do \
if [ -d $$dir ]; then \
(cd $$dir; echo build in $$dir;$(MAKE) compile;) \
else echo not build in $$dir; fi \
done
else
@$(MKDIR)
@$(MKOBJDIR)
ifdef EXECUTE
@$(MKDIR)
@$(MKBINDIR)
@$(MAKE) build_bin
else
@$(MKDIR)
@$(MKLIBDIR)
@$(MAKE) build_dir
endif
endif

build_bin:$(BINDIR)/$(EXECUTE)
@echo finished building $(BINDIR)/$(EXECUTE)

build_dir:$(LIBDIR)/$(RLS)/$(LIB)
@echo finished building $(LIBDIR)/$(LIB)

$(LIBDIR)/$(RLS)/$(LIB):$(OBJDIR)/$(LIB)
$(RM) $(LIBDIR)/$(RLS)/$(LIB)
$(CP) $(OBJDIR)/$(LIB) $(LIBDIR)/$(RLS)

$(OBJDIR)/$(LIB):$(OBJS)
# $(CC) -xar -o $(OBJDIR)/$(LIB) $(OBJS)
$(AR) $(OBJDIR)/$(LIB) $(OBJS)

#$(OBJDIR)/%.o:%.cc
$(OBJS):$(CCSRCS)
$(CC) $(CC_OPT) $(INCDIR) -c $< -o $@

$(BINDIR)/$(EXECUTE):$(OBJS)
$(CC) $(CC_OPT) $^ $(LINKLIB) -o $@

##################make clean###################
define CLEAN
if [ -d $(OBJ) ]; then (echo $(RM) $(OBJ); $(RM) $(OBJ);)fi
if [ -d $(BIN) ]; then (echo $(RM) $(BIN); $(RM) $(BIN);)fi
endef

clean:
ifdef SUBDIRS
@for dir in $(SUBDIRS); do \
if [ -d $$dir ]; then \
(cd $$dir; echo make clean in $$dir; $(MAKE) clean;) \
else echo not make clean in $$dir; fi \
done
else
@$(CLEAN)
endif

# --> **end of Makefile** <-- #
posted on 2006-04-13 17:46 Martin 阅读(697) 评论(0)  编辑 收藏 引用 所属分类: Project Management
只有注册用户登录后才能发表评论。