Monday, January 12, 2009

UNIX

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 –



Appendix C Complex Makefile Example
Here is the makefile for the GNU tar program. This is a moderately complex makefile.
Because it is the first target, the default goal is `all'. An interesting feature of this makefile is that testpad.h is a source file automatically created by the testpad program, itself compiled from testpad.c.
If you type `make' or `make all', then make creates the tar executable, the rmt daemon that provides remote tape access, and the tar.info Info file.
If you type `make install', then make not only creates tar, rmt, and tar.info, but also installs them.
If you type `make clean', then make removes the `.o' files, and the tar, rmt, testpad, testpad.h, and core files.
If you type `make distclean', then make not only removes the same files as does `make clean' but also the TAGS, Makefile, and config.status files. (Although it is not evident, this makefile (and config.status) is generated by the user with the configure program, which is provided in the tar distribution, but is not shown here.)
If you type `make realclean', then make removes the same files as does `make distclean' and also removes the Info files generated from tar.texinfo.
In addition, there are targets shar and dist that create distribution kits.
# Generated automatically from Makefile.in by configure.
# Un*x Makefile for GNU tar program.
# Copyright (C) 1991 Free Software Foundation, Inc.

# This program is free software; you can redistribute
# it and/or modify it under the terms of the GNU
# General Public License ...
...
...

SHELL = /bin/sh

#### Start of system configuration section. ####

srcdir = .

# If you use gcc, you should either run the
# fixincludes script that comes with it or else use
# gcc with the -traditional option. Otherwise ioctl
# calls will be compiled incorrectly on some systems.
CC = gcc -O
YACC = bison -y
INSTALL = /usr/local/bin/install -c
INSTALLDATA = /usr/local/bin/install -c -m 644

# Things you might add to DEFS:
# -DSTDC_HEADERS If you have ANSI C headers and
# libraries.
# -DPOSIX If you have POSIX.1 headers and
# libraries.
# -DBSD42 If you have sys/dir.h (unless
# you use -DPOSIX), sys/file.h,
# and st_blocks in `struct stat'.
# -DUSG If you have System V/ANSI C
# string and memory functions
# and headers, sys/sysmacros.h,
# fcntl.h, getcwd, no valloc,
# and ndir.h (unless
# you use -DDIRENT).
# -DNO_MEMORY_H If USG or STDC_HEADERS but do not
# include memory.h.
# -DDIRENT If USG and you have dirent.h
# instead of ndir.h.
# -DSIGTYPE=int If your signal handlers
# return int, not void.
# -DNO_MTIO If you lack sys/mtio.h
# (magtape ioctls).
# -DNO_REMOTE If you do not have a remote shell
# or rexec.
# -DUSE_REXEC To use rexec for remote tape
# operations instead of
# forking rsh or remsh.
# -DVPRINTF_MISSING If you lack vprintf function
# (but have _doprnt).
# -DDOPRNT_MISSING If you lack _doprnt function.
# Also need to define
# -DVPRINTF_MISSING.
# -DFTIME_MISSING If you lack ftime system call.
# -DSTRSTR_MISSING If you lack strstr function.
# -DVALLOC_MISSING If you lack valloc function.
# -DMKDIR_MISSING If you lack mkdir and
# rmdir system calls.
# -DRENAME_MISSING If you lack rename system call.
# -DFTRUNCATE_MISSING If you lack ftruncate
# system call.
# -DV7 On Version 7 Unix (not
# tested in a long time).
# -DEMUL_OPEN3 If you lack a 3-argument version
# of open, and want to emulate it
# with system calls you do have.
# -DNO_OPEN3 If you lack the 3-argument open
# and want to disable the tar -k
# option instead of emulating open.
# -DXENIX If you have sys/inode.h
# and need it 94 to be included.

DEFS = -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \
-DVPRINTF_MISSING -DBSD42
# Set this to rtapelib.o unless you defined NO_REMOTE,
# in which case make it empty.
RTAPELIB = rtapelib.o
LIBS =
DEF_AR_FILE = /dev/rmt8
DEFBLOCKING = 20

CDEBUG = -g
CFLAGS = $(CDEBUG) -I. -I$(srcdir) $(DEFS) \
-DDEF_AR_FILE=\"$(DEF_AR_FILE)\" \
-DDEFBLOCKING=$(DEFBLOCKING)
LDFLAGS = -g

prefix = /usr/local
# Prefix for each installed program,
# normally empty or `g'.
binprefix =

# The directory to install tar in.
bindir = $(prefix)/bin

# The directory to install the info files in.
infodir = $(prefix)/info

#### End of system configuration section. ####

SRC1 = tar.c create.c extract.c buffer.c \
getoldopt.c update.c gnu.c mangle.c
SRC2 = version.c list.c names.c diffarch.c \
port.c wildmat.c getopt.c
SRC3 = getopt1.c regex.c getdate.y
SRCS = $(SRC1) $(SRC2) $(SRC3)
OBJ1 = tar.o create.o extract.o buffer.o \
getoldopt.o update.o gnu.o mangle.o
OBJ2 = version.o list.o names.o diffarch.o \
port.o wildmat.o getopt.o
OBJ3 = getopt1.o regex.o getdate.o $(RTAPELIB)
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
AUX = README COPYING ChangeLog Makefile.in \
makefile.pc configure configure.in \
tar.texinfo tar.info* texinfo.tex \
tar.h port.h open3.h getopt.h regex.h \
rmt.h rmt.c rtapelib.c alloca.c \
msd_dir.h msd_dir.c tcexparg.c \
level-0 level-1 backup-specs testpad.c

.PHONY: all
all: tar rmt tar.info

.PHONY: tar
tar: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

rmt: rmt.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ rmt.c

tar.info: tar.texinfo
makeinfo tar.texinfo

.PHONY: install
install: all
$(INSTALL) tar $(bindir)/$(binprefix)tar
-test ! -f rmt || $(INSTALL) rmt /etc/rmt
$(INSTALLDATA) $(srcdir)/tar.info* $(infodir)

$(OBJS): tar.h port.h testpad.h
regex.o buffer.o tar.o: regex.h
# getdate.y has 8 shift/reduce conflicts.

testpad.h: testpad
./testpad

testpad: testpad.o
$(CC) -o $@ testpad.o

TAGS: $(SRCS)
etags $(SRCS)

.PHONY: clean
clean:
rm -f *.o tar rmt testpad testpad.h core

.PHONY: distclean
distclean: clean
rm -f TAGS Makefile config.status

.PHONY: realclean
realclean: distclean
rm -f tar.info*

.PHONY: shar
shar: $(SRCS) $(AUX)
shar $(SRCS) $(AUX) | compress \
> tar-`sed -e '/version_string/!d' \
-e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
-e q
version.c`.shar.Z

.PHONY: dist
dist: $(SRCS) $(AUX)
echo tar-`sed \
-e '/version_string/!d' \
-e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
-e q
version.c` > .fname
-rm -rf `cat .fname`
mkdir `cat .fname`
ln $(SRCS) $(AUX) `cat .fname`
tar chZf `cat .fname`.tar.Z `cat .fname`
-rm -rf `cat .fname` .fname

tar.zoo: $(SRCS) $(AUX)
-rm -rf tmp.dir
-mkdir tmp.dir
-rm tar.zoo
for X in $(SRCS) $(AUX) ; do \
echo $$X ; \
sed 's/$$/^M/' $$X \
> tmp.dir/$$X ; done
cd tmp.dir ; zoo aM ../tar.zoo *
-rm -rf tmp.dir




As I mentioned earlier, you must be root to edit the /etc/hosts file. It is possible to log on to the machine directly as root, but it is safer to log in as a normal user first, then execute the superuser command

su

in your shell and enter the root password.

If I wanted to add a new static IP to my /etc/hosts file, which looks like

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain centaur localhost
192.168.0.100 groucho
192.168.0.101 harpo

at present, I would go down below the last line and enter the new IP address, then press , then enter the new hostname and press . To leave the editor, type -X and answer Y if you want to save the changes, or N if you've accidentally erased a bunch of stuff and want to quit without saving. Once you're done editing, execute logout to leave the root session.



Directories
The bin Directory
When the programs has been compiled,it is translated into what's called a Binary format.The bin directory is where all the executables binaries were kept in early Unix.Over time, as more and more executables were added to Unix, it became quite unmanageable to keep all the executables in one place and the bin directory split into multiple parts(/bin/sbin, /usr/bin)
The dev Directory
Among the most important portions of any computer are its device drivers.Without them, you would not have any information on your screen. You would not be able to enter information (the information is read and given to the system by the keyboard device driver).
The etc Directory
Unix adminstration can be quite a complex, invovling management of user accounts, the file system,security,device drivers and more.Unix designates the etc directory as the storage place for all the adminstrative files and information.
The lib Directory
If programs want to include certain features,they can reference just the shared copy of that utility in the Unix library rather than having a new unique copy.Many of the recent Unix systems also support what's called Dynamic Linking, here library of functions are included on- the-fly as you start up the program.


The mnt directory
The mnt directory is an empty directory reserved for mounting removable filesystems like hard disks,removable cartridge drives, and so on.
The tmp Directory
The tmp directory contains temporary files created by Unix system programs. The files are normally present when the corresponding program is running, but may also be left in the directory if the program is prematurely stopped. You can remove any temporary file that does not belong to a running program.
The usr Directory
The usr directory consists of several subdirectories that contain additional Unix commands and data files. It is also the default location of user home directories.
The /usr/bin directory contains more Unix commands. These commands are used less frequently or are considered nonessential to Unix system operation.
The /usr/include directory contains header files for compiling C programs.
The /usr/lib directory contains more libraries and data files used by various Unix commands.
The /usr/spool directory contains various directories for storing files to be printed, mailed, or passed through networks.
The /usr/tmp directory contains more temporary files.
The /usr/adm directory contains data files associated with system administration and accounting. In particular, the /usr/adm/messages and /usr/adm/syslog files contain a record of system error messages, including those sent to the system console. These files are especially useful for locating system problems, including hardware problems. For example, an unusual number of disk errors on a drive indicates a defective or misaligned drive. Because messages in the file can accumulate rapidly, these files must be deleted periodically. See ``Checking and clearing system log files'' for more information.




Hidden Files
A hidden file is any file with a dot as the first character of the filename.They are known as hidden files because they do not show up in a regular ls command and you do not get rid of them with a rm* command. It is common for Unix tools to create "dot" files for temporary files and to maintain control and history information.Users are also expected to create them as configuration files.
These are few files which are hidden :
.profile : this is a configuration file
.login : This is C shell termination file.
.cshrc : This is C shell configuration file.
.history : This is shell command history file.
.mailrc : This is mail configuration file
top of the page

The env Command
System remembers specifics about you using user enviornment.The user environment is a collection of specially named variables that have specific values.
To view your environment type
%env







Commands below are used for various tasks in computer networks.
ftp
file transfer program, anonymous and user-ID versions.ftp stands for File Transfer Protocol. File transfer provides a means for you to obtain computer files (text, image, sound, etc.) from other computers over the network. ftp can also be used to send (upload) files from your computer to another computer, providing you have write permission or a real account on the machine you are uploading. FTP runs on TCP/IP port 21 .
top of the page

telnet
establish a remote connection. Telnet is a utility that allows a computer user at one site to make a connection, login and then conduct work on a computer at another site. For example, you can use the telnet command to run a program in your directory on a supercomputer thousands of miles away. Telnet runs on TCP/IP port 23
top of the page.

ping
Ping command is used to test and time a route to other computer.This sends an echo request to a network host. It is useful for determining the status of the network and various foreign hosts. The ping command sends one datagram per second and prints one line of output for every response received. Round-trip times and packet loss statistics are calculated and displayed. Ping uses the ICMP protocol. This is an IP protocol, so it does not have a port number.
top of the page

traceroute x
Main purpose of traceroute is to test routes to x (address).This is a utility that records the route (the specific gateway computers at each hop) through the Internet between your computer and a specified destination computer. It also calculates and displays the amount of time each hop took. Traceroute also uses the ICMP protocol.



rlogin : remote login
irc : real-time text conversation with other irc users

who : display information on users logged in
ruser : display remote users (old)
dnslookup : display user information from DNS server

ypcat : display user or group information from NIS/YP server
id : display user's ID, name, group and group name
finger : enquire information (.plan) about a user or a node
rup: display information about network machines




nslookup x : look up or set address information



Directories are used to organize your files.Here is the list of directory commands :
mkdir || rmdir || pwd || ls ||cd ||


Ls with options

type % ls -a ls is an example of a command which can take options: -a is an example of an option. The options change the behaviour of the command.
Command flags for ls are as following :
Flag Meaning
-1 Force single-column output on listings.
-a List all files, including any dot files.
-C Force multiple-column output on listings.
-l Generate a long listing of files and directories.
-r Reverse the order of any file sorting.
-R Recursively show directories and their contents.
-s Show size of files, in blocks
-t Sort output in most-recently-modified order.
-x Sort output in row-first order.





Commands to find out where you are
pwd
Prints current directory.Use to check directory in which you are working.
whoami
For people who use multiple IDs, tells you which ID you are using.
ls : Commands to get information about contents of current directory
Use options -l, -a, -t, -g in any combination or order as shown in examples.
ls : Lists files and directories in current directory.
ls -l : Lists files and directories and details about them.
ls -a : Lists files and directories and hidden files.
ls -t : Lists files and directories in order by last modified date.
ls -g : Lists files and directories and which group owns them.
ls -la : Lists files and directories, including hidden files, and gives information about them.
ls -latg :Lists files and directories showing all options.
ls p* :Lists any files in the current directory that begin with the letter p. The asterisk (*) is used as a wild card. It replaces one or more characters in a file name. For example, *p* looks for any file with the letter p anywhere in the name.

Commands to add or delete directories or files
mkdir directory1 : Makes a directory and names it directory1.
rmdir directory1 : Removes the directory named directory1. (Note: You cannot remove a directory unless it is empty.)


mv file1 file2 : Moves file1 into file2. If file2 has not been created, it creates file2 and moves the contents of file1 into it. If file2 exists, its contents are replaced by the contents of file1. In all cases, file1 no longer exists. mv file1 directory_name Moves the file named file1 into the directory named.
cp file1 file2 : Copies the contents of file1 into file2. Leaves file1 as is.




Permissions and Ownerships

There are three primary types of permission for files: read,write and execute.If no letter is present then it is substituted by a dash -. The dash means that this type of permission is not granted whether it be in the r, w or x position.The first column is broken down into four sub columns. The first sub column is one character long the second, third and fourth are all three characters long for a total of ten characters.The table below is a reflection of the four columns.
File/Directory User Group Other
d rwx r-x r--

The most common file permissions are
Permission Meaning
--- No access is allowed
r-- Read only access
r-x Read and execute access, for programs and shell scripts
rw- Read and write access, for files
rwx All access allowed, for programs

If the permission of the directory is write then you can add new items and remove items in the directory.
chmod command enables you to specify permissions in two different ways.
type %chmod [permission level] name_of _file.
Check option buttons
Common permissions and their numeric equivalents
Permission Numeric Used with
---|---|--- 000 All types
r--|---|--- 400 Files
r--|r--|r-- 444 Files
rw-|---|--- 600 Files
rw-|r--|r-- 644 Files
rw-|rw-|r-- 664 Files
rw-|rw-|rw- 666 Files
rwx|---|--- 700 Programs and Directories
rwx|r-x|--- 750 Programs and Directories
rwx|r-x|r-x 755 Programs and Directories







%grep 'jon' /etc/passwd
to search the /etc/passwd file for any lines containing the string "jon".
Type the command
% grep '^jon' /etc/passwd
to see the lines in /etc/passwd that begin with the character string "jon".



Ls -l | grep ‘jon’







Compiling C Programs:
Compiling single source C Programs
The easiest case of compilation is when you have all your source code set in a single file.Let us illustrate with an example test.c program:
#include
int main(int argc, char* argv[]) {
printf ("hello world\n");
return 0; }
There is a file named 'test.c' that we want to compile. We will do so using a command line similar to this:
%gcc test.c
We are using a GNU compiler, you'll write 'gcc' instead. If you program complies well you should get a file 'a.out' as a result.
Suppose that you want the resulting program to be called "test_output". In that case, you could use the following line to compile it:
%gcc test.c -o test_output
Here -o flag indicates name of the resulting executable file(test_output).


Running the resulting program
Once we created the program, we wish to run it. This is usually done by simply typing its name, as in: test_output.



If we define a function (or a variable) in one file, and try to access them from a second file, we need to declare them as external symbols in that second file. This is done using the C "extern" keyword. The order of presenting the source files on the command line may be altered. The compiler (actually, the linker) will know how to take the relevant code from each file into the final program, even if the first source file tries to use a function defined in the second or third source file.






%gcc -c a.c
%gcc main.o a.o b.o -o hello_world
In our small example, it's hard to notice the speed-up, but in a case of having few tens of files each containing a few hundred lines of source-code, the time saving is significant; not to mention even larger projects
Getting a Deeper Understanding - Compilation steps
Now that we've learned that compilation is not just a simple process, lets try to see what is the complete list of steps taken by the compiler in order to compile a C program.
Driver -
what we invoked as "cc". This is actually the "engine", that drives the whole set of tools the compiler is made of. We invoke it, and it begins to invoke the other tools one by one, passing the output of each tool as an input to the next tool.
C Pre-Processor -
normally called "cpp". It takes a C source file, and handles all the pre-processor definitions (#include files, #define macros, conditional source code inclusion with #ifdef, etc.) You can invoke it separately on your program, usually with a command like:
%gcc -E single_source.c
The C Compiler -
normally called "cc1". This is the actual compiler, that translates the input file into assembly language. As you saw, we used the "-c" flag to invoke it, along with the C Pre-Processor, (and possibly the optimizer too, read on), and the assembler.
Optimizer -
sometimes comes as a separate module and sometimes as the found inside the compiler module. This one handles the optimization on a representation of the code that is language-neutral. This way, you can use the same optimizer for compilers of different programming languages.
Assembler -
sometimes called "as". This takes the assembly code generated by the compiler, and translates it into machine language code kept in object files. With gcc, you could tell the driver to generated only the assembly code, by a command like: cc -S single_source.c
Linker-Loader -



This is the tool that takes all the object files (and C libraries), and links them together, to form one executable file, in a format the operating system supports. A Common format these days is known as "ELF". On SunOs systems, and other older systems, a format named "a.out" was used. This format defines the internal structure of the executable file - location of data segment, location of source code segment, location of debug information and so on. As you see, the compilation is split in to many different phases. Not all compiler employs exactly the same phases, and sometimes (e.g. for C++ compilers) the situation is even more complex. But the basic idea is quite similar - split the compiler into many different parts, to give the programmer more flexibility, and to allow the compiler developers to re-use as many modules as possible in different compilers for different languages (by replacing the preprocessor and compiler modules), or for different architectures (by replacing the assembly and linker-loader parts).
Compiling Single-Source C++ Program
All we need to do is use a C++ compiler, in place of the C compiler . So, if our program source is in a file named 'test.cpp' .
#include
int main(int argc, char* argv[]) {
cout << "hello world" << endl;
return 0; }
We will use a command such as the following
% g++ test.cpp -o test_output














SHELL


Whenever you login to a Unix system you are placed in a program called the shell. You can see its prompt at the bottom left of your screen.(i.e Paris).To get your work done, you enter commands at this prompt. The shell acts as a command interpreter; it takes each command and passes it to the operating system kernel to be acted upon. It then displays the results of this operation on your screen.
Following are few of the features of the shell :
Create an enviornment
Working environment is defined whenever you login or start another shell. This environment is set using the values that the shell finds in initialisation files which it always reads as it starts up. You can change your working environment by editing these files and setting new values for variables. Each shell handles its initialisation files in a different way.
Frequently used Environment Variables
Name Description
EDITOR Sets the editor that will be used by other programs such as the mail program.
PATH Specifies the directories that the shell is to look through to find a command. These directories are searched in the order in which they appear.
HOME The HOME variable contains the name of your home directory. When you issue the cd command with no directory argument, you will be placed in the directory defined in the HOME environment variable. The HOME variable is also where the shell will look for the user login scripts
PRINTER Sets the printer to which all output is sent by the lpr command
SHELL Sets your default shell.
MAIL The MAIL variable contains the name of the directory where your incoming mail is stored. When you start a mail program, the program will look in the directory stored in the MAIL environment variable for your incoming mail messages.
TERM Sets your terminal type for programs such as the editor and pager.
USER The USER variable contains your username. Any time you access a file or directory, the access permissions are checked against the value of USER
TZ Sets the time zone you are in.


Finding out which shell you are using
Information about which shell you are using is held in the SHELL environment variable.The command
echo $SHELL
displays the value of this variable. You can identify which shell you are presently using from the last part of the pathname.
Pathname Shell
/.../sh Bourne shell
/.../csh C shell
/.../tcsh TC shell
/.../ksh Korn shell
/.../bash Bourne Again shell

To view all the environment variables,use the command printenv

Changing your environment :Bourne shell
At login the Bourne shell reads the initialisation files /etc/profile and $HOME/.profile. You cannot change the content of /etc/profile, but you have permission to edit the contents of .profile, which is in your home directory and is owned by you.
Useful tip : Make a copy of your shell start up file before editing it to change environment or shell variables. You can always return to using this copy if you find that the modified file is not working and you are unable to fix the problem.
For example:
cd
cp .profile old_profile
pico .profile
The first command changes you to your home directory, where a copy of the file .profile is made in old_profile. You can then edit the .profile.
To revert to using the original .profile you simply copy it back. For example:
cp old_profile .profile
Displaying current variables
You can use the echo command to display the value of an environment variable. For example:
echo $PATH
This displays the value of the environment variable PATH. The name of an environment variable is given in UPPER CASE. The $ sign is a shell metacharacter that uses the value of the variable instead of its name. The method for displaying the value of every variable varies according to which shell you are using.
For the Bourne shell use the command set to display the value of environment variables.
For the C and TC shell use the command printenv or env to display the value of environment variables and the command set to display the value of local shell variables.
If the list of variables is so long that it scrolls off the screen and you want to display the information one screenful at a time, pipe the output through a pager. For example:
set | more

Setting environment and shell variables
csh
To set an environment variable in csh, use the setenv command. The command has the syntax: setenv VARIABLE value. To set the EDITOR variable to the value emacs in csh, use the command: setenv EDITOR emacs.
sh, or ksh
To set an environment variable in sh or ksh, use the syntax VAR=value;export VAR, where VAR is the name of the environment variable and value is the value you wish to assign. Do not put spaces on either side of the equals sign. The export command instructs the shell to propagate the value of the variable to all programs that are run by the shell. If an environment variable is reset, but not exported, the change will only apply to the shell itself. To set the EDITOR variable to the value emacs in ksh or sh, use the command:
EDITOR=emacs;export EDITOR
It is also possible to unset environment variables, with the unset command. Unsetting an environment variable removes the definition of the variable.













Command to enter vi edit mode
vi filename (press Enter/Return key) : Opens the named file if it exists, or creates new file and opens it.

Commands to move the cursor
k j l h (lowercase)
These keys move the cursor one line above, one line below, one space right, or one space left respectively.





Commands to put you in text insert mode
Note: After inserting text, press Esc (escape) key to return to command mode.
a (lowercase)
Use to insert (append) text to the right of cursor.
A (uppercase)
Use to insert (append) text at the end of the current line.
i (letter i (eye) lowercase)
Use to insert text to the left of cursor.
I (letter I (eye) uppercase)
Use to insert text at the beginning of the current line.
o (letter o lowercase)
Use to open a new line for inserting text below cursor line.
O (letter O uppercase)
Use to open a new line for inserting text above cursor line.




Commands to delete text
x (lowercase)
Removes the character under the cursor.
dd (lowercase)
Deletes the cursor line.

Command to join two lines
J (uppercase)
Joins next line to the end of the cursor line.


n (lowercase)
Searches in direction of original /keyword, ?keyword, /string, or ?string command. Locates next instance of keyword or string.
N (uppercase)
Searches in opposite direction of original /keyword, ?keyword, /string, or ?string command. Locates next instance of keyword or string.



Y (uppercase)
Yanks (copies) line the cursor is on.
p (lowercase)
Puts last word or line yanked or deleted after cursor.
P (uppercase)
Puts last word or line yanked or deleted before cursor.

Command to recover from last change
u (lowercase)
Undoes last change.


Commands to save changes or leave vi editing session
:w (colon and lowercase w)
Saves changes, but does not leave vi editing session.
:wq (colon and lowercase wq)
Saves changes, and leaves vi editing session.
ZZ (uppercase)
Saves changes, and leaves vi editing session.
:q! (colon, lowercase q, and exclamation)
Does not save changes made. Just leaves vi editing session.

Make notes

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