http://www.gnu.org/software/make/manual/make.html#toc_Error-Messages
EXAMPLE
targets col 1
commands tabbed
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
can be compressed into the fllowing equal makefile
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
-rm edit $(objects)
Here is a straightforward makefile that describes the way an executable file called edit depends on eight object files which, in turn, depend on eight C source and three header files.
In this example, all the C files include defs.h, but only those defining editing commands include command.h, and only low level files that change the editor buffer include buffer.h.
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
We split each long line into two lines using backslash-newline; this is like using one long line, but is easier to read. To use this makefile to create the executable file called edit, type:
make
To use this makefile to delete the executable file and all the object files from the directory, type:
make clean
In the example makefile, the targets include the executable file `edit', and the object files `main.o' and `kbd.o'. The prerequisites are files such as `main.c' and `defs.h'. In fact, each `.o' file is both a target and a prerequisite. Commands include `cc -c main.c' and `cc -c kbd.c'.
When a target is a file, it needs to be recompiled or relinked if any of its prerequisites change. In addition, any prerequisites that are themselves automatically generated should be updated first. In this example, edit depends on each of the eight object files; the object file main.o depends on the source file main.c and on the header file defs.h.
A shell command follows each line that contains a target and prerequisites. These shell commands say how to update the target file. A tab character must come at the beginning of every command line to distinguish command lines from other lines in the makefile. (Bear in mind that make does not know anything about how the commands work. It is up to you to supply commands that will update the target file properly. All make does is execute the commands in the rule you have specified when the target file needs to be updated.) The target `clean' is not a file, but merely the name of an action. Since you normally do not want to carry out the actions in this rule, `clean' is not a prerequisite of any other rule. Consequently, make never does anything with it unless you tell it specifically. Note that this rule not only is not a prerequisite, it also does not have any prerequisites, so the only purpose of the rule is to run the specified commands. Targets that do not refer to files but are just actions are called phony targets. See Phony Targets, for information about this kind of target. See Errors in Commands, to see how to cause make to ignore errors from rm or any other command.
VMake is the CSD group's unified build system. It differs from other build system in that it is built purposely for traditional developers on HPC systems. It is hence designed to be lightweight (it only requires GNU make and basic shell utilities), simple to use (it only requires running 2 commands: "./configure.sh" and "make"), flexible (defaults can be overriden at compile-time), and feasible to maintain (its written in simple shell script, not an archaic macro language or over-complicated scripting language).
For example, SCons doesn't make you list dependencies but instead automatically parses the files being compiled and looks for includes. You simply specify which files should be compiled and which files go into which executables. Switching build systems will be easier for the fact that your developers aren't really Make experts.
Another alternative if you stick with Make is to use the gcc -M option to automatically detect dependencies. The answer to the Automatically discovering C dependencies question has an example of how to have your makefiles automatically discover dependencies so that you don't need to specify them by hand.
We set up a continuous integation build machine that does a make clean in about 45 minutes compared to about 2 hours on a dev machine.The integration server polls the SVN repository every 2 hours for new check-ins and starts a make clean.
That way, we can monitor exactly when the build was broken and fix it right away. We use Hudson as our continuous integration server, its free and open source, its a work of art and very easy to set up. Plus the User Interface is very intuitive, all the other developers love it.
The canonical way of solving this is to let the compiler automatically generate dependency info for you. Something like this (assuming gcc, you'll want to check your compiler for similar options)
SOURCES=foo.c bar.c%.d: %.c$(CC) $(CFLAGS) -MM $< >$@ include $(SOURCES:.c=.d)
The GNU Make manual has a chapter on automatically generating prerequisites.
EDIT: I usually recommend people to start using CMake when they have this kind of issue.
I'm required to write documentation for my current project that lists all .c files and for each one lists every .h file which is directly or indirectly included by that file.
This is a large project, and although we have Makefiles which theoretically have this information, those Makefiles are sometimes incorrect (we inherited this project from another company). We've often had to do a make clean ; make for our changes to actually be reflected in the recompilation, so I don't want to rely on these Makefiles.
So is there a tool which lets us give it the name of a .c file and an include path and have it tell us all of the .h files which are directly or indirectly included by the .c file? We don't have anything weird like
#define my_include "some_file.h"#include my_include
so the tool doesn't need to be perfect. Anything that searched .c and .h files in an include path for regular includes would be good enough.
What I do in my Makefile is
SRCS=$(wildcard *.c)depend: $(SRCS)gcc -M $(CFLAGS) $(SRCS) >dependinclude depend
This means that if any of the source files are updated, the depend rule will run, and use gcc -M to update the file called depend. This is then included in the makefile to provide the dependency rules for all the source files.
Make will check that a file is up to date before including it, so this depend rule will run if necessary whenever you run make without you needing to do a "make depend".
This will run any time any file has changed. I've never found this a problem, but if you had a huge number of files in the directory you might find it took too long, in which case you could try having one dependency file per source file, like this:
SRCS=$(wildcard *.c)DEPS=$(SRCS:.c=.dep)%.dep : %.cgcc -M $(CFLAGS) $< >$@include $(DEPS)
Note that you can use -MM instead of -M to not include system headers.
In MSVC (2005 and 2008 at least, possibly other versions as well but not VC6) you can get the compiler to tell you all the files that were included during compilation. The output is quite verbose, but complete and fairly easy to parse with human eyes.
In Project Settings, go to the C/C++>Advanced tab, and toggle "Show Includes," then rebuild your project from the ground up.
Example Make of a kernal:
AS = nasmCC = gccLD = ldTARGET = coreBUILD = buildSOURCES = sourceINCLUDE = includeASM = assemblyVPATH = $(SOURCES)CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \-nostdinc -fno-builtin -I $(INCLUDE)ASFLAGS = -f elf#CFILES = core.c consoleio.c system.cCFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))SFILES = assembly/start.asmSOBJS = $(SFILES:.asm=.o)COBJS = $(CFILES:.c=.o)OBJS = $(SOBJS) $(COBJS)build : $(TARGET).img$(TARGET).img : $(TARGET).elfc:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img$(TARGET).elf : $(OBJS)$(LD) -T link.ld -o $@ $^$(SOBJS) : $(SFILES)$(AS) $(ASFLAGS) $< -o $@%.o: %.c@echo Compiling $<...$(CC) $(CFLAGS) -c -o $@ $<#Clean Script - Should clear out all .o files everywhere and all that.clean:-del *.img-del *.o-del assembly\*.o-del core.elf
Now regarding this make file
My main issue with this makefile is that when I modify a header file that one or more C files include, the C files aren't rebuilt. I can fix this quite easily by having all of my header files be dependencies for all of my C files, but that would effectively cause a complete rebuild of the project any time I changed/added a header file, which would not be very graceful.
What I want is for only the C files that include the header file I change to be rebuilt, and for the entire project to be linked again. I can do the linking by causing all header files to be dependencies of the target, but I cannot figure out how to make the C files be invalidated when their included header files are newer.
I've heard that GCC has some commands to make this possible (so the makefile can somehow figure out which files need to be rebuilt) but I can't for the life of me find an actual implementation example to look at. Can someone post a solution that will enable this behavior in a makefile?
EDIT: I should clarify, I'm familiar with the concept of putting the individual targets in and having each target.o require the header files. That requires me to be editing the makefile every time I include a header file somewhere, which is a bit of a pain. I'm looking for a solution that can derive the header file dependencies on its own, which I'm fairly certain I've seen in other projects.
GO HERE to see followup:
http://stackoverflow.com/questions/297514/how-can-i-have-a-makefile-automatically-rebuild-source-files-that-include-a-modif
Solution?
$(OBJDIR)/%.d: %.c$(CC) -MM -MG $(CPPFLAGS) $<>$@ifneq ($(MAKECMDGOALS),clean)include $(SRCS:%.c=$(OBJDIR)/%.d)endif
Absolutely. g++ -MM will generate a GMake compatible list of dependencies. I use something like this:
# Add .d to Make's recognized suffixes.SUFFIXES += .d#We don't need to clean up when we're making these targetsNODEPS:=clean tags svn#Find all the C++ files in the src/ directorySOURCES:=$(shell find src/ -name "*.cpp")#These are the dependency files, which make will clean up after it creates themDEPFILES:=$(patsubst %.cpp,%.d,$(SOURCES))#Don't create dependencies when we're cleaning, for instanceifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))#Chances are, these files don't exist. GMake will create them and#clean up automatically afterwards-include $(DEPFILES)endif#This is the rule for creating the dependency filessrc/%.d: src/%.cpp$(CXX) $(CXXFLAGS) -MM -MT '$(patsubst src/%,obj/%,$(patsubst %.cpp,%.o,$<))' $< > $@#This rule does the compilationobj/%.o: src/%.cpp src/%.d src/%.h@$(MKDIR) $(dir $@)$(CXX) $(CXXFLAGS) -o $@ -c $<
What this will do is automatically generate the dependencies for each file that has changed, and compile them according to whatever rules you have in place. This allows me to just dump new files into the src/ directory, and have them compiled in automatically dependencies and all.
Or Makedepend
The GNU C preprocessor cpp has an option, -MM, which produces a make-suitable set of dependencies based on inclusion patterns.
The Digital Mars C/C++ compiler comes with a makedep tool.
MakeDepend is deprecated in favor of the dependency generation built into the compilers themselves, since there is/can be differences in the file depending upon how they process the preprocessor macros. (ie #ifdef G++ #include "gpp.h" #endif –
Important adjuncts are lint (source code checking for obvious errors) ctags (locate functions, etc. in source code) and mkdepend. These are nice, and good programmers use them.
Makefile Naming
make is going to look for a file called Makefile, if not found then a file called makefile. Use the first (so the name stands out in listings).
You can get away without any Makefile (but shouldn't)! Make has default rules it knows about.
Makefile Components
Comments
Comments are any text beginning with the pound (#) sign. A comment can start anywhere on a line and continue until the end of the line. 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
PSROFF= groff -Tps
DITROFF= groff -Tdvi
CFLAGS= -O -systype bsd43
There are lots of default macros -- you should honor the existing naming conventions. To find out what rules/macros make is using type:
% 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)
$(DITROFF) $(MACROS) $(SRCS) >paper.dvi
NOTE: The the line beginning with $(DITROFF) begins with TAB not spaces.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 default macros (type "make -p" to print out the defaults). Most are pretty obvious 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
$(CC) $(CFLAGS) $? $(LDFLAGS) -o $@
alternatively:
printenv: printenv.c
$(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@
There are two more special macros used in implicit rules. They are:
$< 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 ....]
[ command ...]
Items in brackets are optional, ellipsis means one or more. Note the tab to preface each command is required.
The semantics is pretty simple. When you say "make target" make finds the target rule that applies and, if any of the dependents are newer than the target, make executes the com- mands one at a time (after macro substitution). If any dependents have to be made, that happens first (so you have a recursion).
A make will terminate if any command returns a failure sta- tus. That's why you see rules like:
clean:
-rm *.o *~ core paper
Make ignores the returned status on command lines that begin with a dash. eg. who cares if there is no core file?
Make will echo the commands, after macro substition to show you what's happening as it happens. Sometimes you might want to turn that off. For example:
install:
@echo You must be root to install
Example Target Rules
For example, to manage sources stored within RCS (sometimes you'll need to "check out" a source file):
SRCS=x.c y.c z.c
$(SRCS):
co $@
To manage sources stored within SCCS (sometimes you'll need to "get" a source file):
$(SRCS):
sccs get $@
Alternativley, to manage sources stored within SCCS or RCS let's generalize with a macro that we can set as required.
For example, a macro defined using
search-path = ../foo/ /usr/bar/ /usr/baz/
may be invoked with "${search-path}" or "$(search-path)", and so
random-target: ${search-path}
make-core-depends.pl -search-path ${search-path} . . .
is understood as
random-target: ../foo/ /usr/bar/ /usr/baz/
make-core-depends.pl -search-path ../foo/ /usr/bar/ /usr/baz/ . . .
Macros that are not defined expand to the null string when invoked, without causing an error.
the following standard definition causes make-mrf-depends.pl to use the sing-envs.pl script for computing singleton environments.
MRF-SING-ENVS = sing-envs.pl
This is because make-mrf-depends.pl generates singleton environment targets that look something like this:
mrf-se-f10vv-2ss-1aba.dat: ../cores/1aba.core ../vv-data/1aba_bb.singl \
../cores/1aba.seq ‘the colon sets PATH
${MRF-SING-ENVS} -sing-env-file mrf-se-f10vv-2ss-1aba.dat -core-file \
../cores/1aba.core -sequence-file ../cores/1aba.seq \
-exposure-file ../vv-data/1aba_bb.singl
Other traditional targets are "clean", which deletes the files that are made, presumably in order to remake them again, and "install", which, for a sofware package such as needle tools, causes the newly built programs to be moved to the correct place in the system so that they may be used by users other than the person who constructed the system. The clean target is usually implemented with "rm -f ${files}", where "${files}" is a macro (or series of macros) that names all of the files to be deleted.
Another example
#
# Laboratory for Scientific Computing
# http://www.lam-mpi.org/tutorials/
# University of Notre Dame
#
# MPI Tutorial
# Sample Makefile
#
# "mpicc" adds the directories for the include and lib files. Hence,
# -I and -L for MPI stuff is not necessary
#
CC = mpicc
#
# Modify TOPDIR if you use your own include files and library files
#
TOPDIR = .
LIBDIR = $(TOPDIR)/libs
INCDIR = $(TOPDIR)/include
LIBS = # add any -l's that you need here
# don't need any for the sample program
CFLAGS = -I$(INCDIR)
LDFLAGS = -L$(LIBDIR) $(LIBS)
PROGRAM = hello # name of the binary
SRCS = MPI_C_SAMPLE.c # source file
OBJS = $(SRCS:.c=.o) # object file
#
# Rules
#
.SUFFIXES: .c .o
.c.o:
$(CC) -c $(CFLAGS) $<
#
# Targets
#
default: all
all: $(PROGRAM)
$(PROGRAM): $(OBJS)
$(CC) $(OBJS) -o $(PROGRAM) $(LDFLAGS)
clean:
/bin/rm -f $(OBJS) $(PROGRAM)
:
BSD make, which is derived from Adam de Boor's work on a version of make capable of building targets in parallel, and survives with varying degrees of modification in FreeBSD, NetBSD and OpenBSD.
Below is a very simple makefile that would compile a source called "helloworld.c" using cc, a C compiler. The PHONY tag is a technicality that tells make that a particular target name does not produce an actual file. The $@ and $< href="http://www.blogger.com/wiki/Automatic_variable">automatic variables and stand for the target name and so-called "implicit" source, respectively. There are a number of other automatic variables.[1][2]
helloworld: helloworld.o
cc -o $@ $<
helloworld.o: helloworld.c
cc -c -o $@ $<
.PHONY: clean
clean:
rm -f helloworld helloworld.o
It is possible to create make files that generate some of these dependencies, but a more common solution is to use one of the available generators to make, e.g. the Automake toolchain provided by the GNU Project.
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
rm edit $(objects)
Variable definitions are parsed as follows:
immediate = deferred
immediate ?= deferred
immediate := immediate
immediate += deferred or immediate
define immediate
deferred
endef
For the append operator, `+=', the right-hand side is considered immediate if the variable was previously set as a simple variable (`:='), and deferred otherwise.
Implicit rules
x: y.o z.o
when x.c, y.c and z.c all exist will execute:
cc -c x.c -o x.o
cc -c y.c -o y.o
cc -c z.c -o z.o
cc x.o y.o z.o -o x
rm -f x.o
rm -f y.o
rm -f z.o
For example, if you have three .mk files, a.mk, b.mk, and c.mk, and $(bar) expands to bish bash, then the following expression
include foo *.mk $(bar)
is equivalent to
include foo a.mk b.mk c.mk bish bash
If a makefile named Makefile has this content:
name1 := $(lastword $(MAKEFILE_LIST))
include inc.mk
name2 := $(lastword $(MAKEFILE_LIST))
all:
@echo name1 = $(name1)
@echo name2 = $(name2)
then you would expect to see this output:
name1 = Makefile
name2 = inc.mk
Overriding/overloading make
foo:
frobnicate > foo
%: force
@$(MAKE) -f Makefile $@
force: ;
If you say `make foo', make will find GNUmakefile, read it, and see that to make foo, it needs to run the command `frobnicate > foo'. If you say `make bar', make will find no way to make bar in GNUmakefile, so it will use the commands from the pattern rule: `make -f Makefile bar'. If Makefile provides a rule for updating bar, make will apply the rule. And likewise for any other target that GNUmakefile does not say how to make.
Secondary Expansion of Explicit Rules
During the secondary expansion of explicit rules, $$@ and $$% evaluate, respectively, to the file name of the target and, when the target is an archive member, the target member name. The $$< variable evaluates to the first prerequisite in the first rule for this target. $$^ and $$+ evaluate to the list of all prerequisites of rules that have already appeared for the same target ($$+ with repetitions and $$^ without). The following example will help illustrate these behaviors:
.SECONDEXPANSION:
foo: foo.1 bar.1 $$< $$^ $$+ # line #1
foo: foo.2 bar.2 $$< $$^ $$+ # line #2
foo: foo.3 bar.3 $$< $$^ $$+ # line #3
In the first prerequisite list, all three variables ($$<, $$^, and $$+) expand to the empty string. In the second, they will have values foo.1, foo.1 bar.1, and foo.1 bar.1 respectively. In the third they will have values foo.1, foo.1 bar.1 foo.2 bar.2, and foo.1 bar.1 foo.2 bar.2 respectively.
This is done with the automatic variables such as `$^' (see Automatic Variables). For instance, the value of `$^' is a list of all the prerequisites of the rule, including the names of the directories in which they were found, and the value of `$@' is the target. Thus:
foo.o : foo.c
cc -c $(CFLAGS) $^ -o $@
Suppose you are writing a pattern rule to compile a `.c' file into a `.o' file: how do you write the `cc' command so that it operates on the right source file name? You cannot write the name in the command, because the name is different each time the implicit rule is applied.
What you do is use a special feature of make, the automatic variables. These variables have values computed afresh for each rule that is executed, based on the target and prerequisites of the rule. In this example, you would use `$@' for the object file name and `$<' for the source file name.
Here is a table of automatic variables:
$@
The file name of the target of the rule. If the target is an archive member, then `$@' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), `$@' is the name of whichever target caused the rule's commands to be run.
$%
The target member name, when the target is an archive member. See Archives. For example, if the target is foo.a(bar.o) then `$%' is bar.o and `$@' is foo.a. `$%' is empty when the target is not an archive member.
$<
The name of the first prerequisite. If the target got its commands from an implicit rule, this will be the first prerequisite added by the implicit rule (see Implicit Rules).
$?
The names of all the prerequisites that are newer than the target, with spaces between them. For prerequisites which are archive members, only the member named is used (see Archives).
$^
The names of all the prerequisites, with spaces between them. For prerequisites which are archive members, only the member named is used (see Archives). A target has only one prerequisite on each other file it depends on, no matter how many times each file is listed as a prerequisite. So if you list a prerequisite more than once for a target, the value of $^ contains just one copy of the name. This list does not contain any of the order-only prerequisites; for those see the `$' variable, below.
$+
This is like `$^', but prerequisites listed more than once are duplicated in the order they were listed in the makefile. This is primarily useful for use in linking commands where it is meaningful to repeat library file names in a particular order.
$
The names of all the order-only prerequisites, with spaces between them.
$*
The stem with which an implicit rule matches (see How Patterns Match). If the target is dir/a.foo.b and the target pattern is a.%.b then the stem is dir/foo. The stem is useful for constructing names of related files. In a static pattern rule, the stem is part of the file name that matched the `%' in the target pattern.
In an explicit rule, there is no stem; so `$*' cannot be determined in that way. Instead, if the target name ends with a recognized suffix (see Old-Fashioned Suffix Rules), `$*' is set to the target name minus the suffix. For example, if the target name is `foo.c', then `$*' is set to `foo', since `.c' is a suffix. GNU make does this bizarre thing only for compatibility with other implementations of make. You should generally avoid using `$*' except in implicit rules or static pattern rules.
Note that we use a special stylistic convention when we talk about these automatic variables; we write “the value of `$<'”, rather than “the variable <” as we would write for ordinary variables such as objects and CFLAGS. We think this convention looks more natural in this special case. Please do not assume it has a deep significance; `$<' refers to the variable named < just as `$(CFLAGS)' refers to the variable named CFLAGS. You could just as well use `$(<)' in place of `$<'.
libs_for_gcc = -lgnu
normal_libs =
foo: $(objects)
ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
The ifeq directive begins the conditional, and specifies the condition. It contains two arguments, separated by a comma and surrounded by parentheses. Variable substitution is performed on both arguments and then they are compared. The lines of the makefile following the ifeq are obeyed if the two arguments match; otherwise they are ignored.
The else directive causes the following lines to be obeyed if the previous conditional failed. In the example above, this means that the second alternative linking command is used whenever the first alternative is not used. It is optional to have an else in a conditional.
The endif directive ends the conditional. Every conditional must end with an endif. Unconditional makefile text follows.
When the variable CC has the value `gcc', the above example has this effect:
foo: $(objects)
$(CC) -o foo $(objects) $(libs_for_gcc)
When the variable CC has any other value, the effect is this:
foo: $(objects)
$(CC) -o foo $(objects) $(normal_libs)
Equivalent results can be obtained in another way by conditionalizing a variable assignment and then using the variable unconditionally:
libs_for_gcc = -lgnu
normal_libs =
ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
foo: $(objects)
$(CC) -o foo $(objects) $(libs)
EXAMPLE
CFLAGS = -g -Wall
CC = gcc
LIBS = -lm
INCLUDES =
OBJS = a.o b.o c.o
SRCS = a.c b.c c.c prog1.c prog2.c
HDRS = abc.h
all: prog1 prog2
# The variable $@ has the value of the target. In this case $@ = psort
prog1: prog1.o ${OBJS}
${CC} ${CFLAGS} ${INCLUDES} -o $@ prog1.o ${OBJS} ${LIBS}
prog2: prog2.o ${OBJS}
${CC} ${CFLAGS} -o $@ prog2.o ${OBJS} ${LIBS}
.c.o:
${CC} ${CFLAGS} ${INCLUDES} -c $<
depend:
makedepend ${SRCS}
clean:
rm *.o core *~
tar:
tar cf code.tar Makefile *.c *.h testfile1
print:
more Makefile $(HDRS) $(SRCS) enscript -2r -p listing.ps
# DO NOT DELETE
Subscribe to:
Post Comments (Atom)

No comments:
Post a Comment