creating makefile in unix - unix

I have been working on this problem for a while, I could use a little help:
The steps necessary to produce this program are:
Compile cpp2html.c to produce cpp2html.o. (Important: the source code in this project is C, not C++, and so must be compiled and linked with gcc, not g++.)
Run the command
flex cppscanner.l
to produce the file lex.yy.c from the language description in cppscanner.l.
Compile lex.yy.c to produce lex.yy.o. (This often produces a warning message about extra tokens. Ignore it.)
Link the the .o files to produce an executable program named cpp2html
Write a makefile that will carry out these steps. Your makefile should result in only the minimum required amount of steps when any input file to this process is changed.
these are the errors/warnings I get when compiled,
gcc: warning: cpp2html.o: linker input file unused because linking not done
gcc: warning; lex.yy.o: linker input file unused because linking not done
mv: cannot stat `a.out': No such file or directory
this is what I have in my makefile:
enter code here
#
CPPFLAGS=-g -DDEBUG
#
#
cpps2html: cpp2html.o lex.yy.o
gcc $(CPPFLAGS) -c cpp2thml.o lex.yy.o
mv a.out cpp2html
cpp2thml.o: cpp2html.c
gcc &(CPPFLAGS) -c cpp2html.c
lex.yy.c: cppscanner.l
flex cppscaner.l
lex.yy.o: lex.yy.c
gcc $(CPPFLAGS) -c lex.yy.c

This
gcc $(CPPFLAGS) -c cpp2thml.o lex.yy.o
mv a.out cpp2html
should be
gcc $(CPPFLAGS) -o cpp2html cpp2thml.o lex.yy.o
Certainly the -c option (which means "don't attempt linking") is bad here.
Side note: Using CPPFLAGS, which is conventionally reserved for options for the C preprocessor, is a bit odd in a linking command. It's not illegal, but the normal distribution is to use
CPPFLAGS for stuff that the preprocessor uses (such as -Dfoo or -Isomewhere)
CFLAGS for stuff the C compiler uses (such as -g)
LDFLAGS for linker flags (such as -Lsomewhere)
LDLIBS for libraries (-lfoo)
And then use them where pertinent (or use predefined rules, which use them appropriately). This usually means CPPFLAGS and CFLAGS when building .o targets and CFLAGS, LDFLAGS and LDLIBS when linking.

Related

gcc Compling and linking object file and source file at the same time

In a nutshell , the issue is I have some object file (say a.o , b.o ) and some source file (f.c and g.c)
I have to compile and link in a single step.
This is what I am doing but I don't think this is the write way atleast I should give something like -l or -L for linking
gcc -Wall -O0 -ggdb -fPIC a.o b.o f.c g.c -o executable
This is the correct way, -l is used to link to a library (for example, the ptheads library needs -lpthread) and -L is used to add directories to the directories in which the linker looks for library files.
There is nothing wrong with compiling the software this way.
Most build systems build files one at a time in order to avoid having to rebuild the object file in case the source file was not modified and the object file still exists. If you are fine with rebuilding code, then your approach is perfectly valid.

Why does gnumake remake the intermediate file?

I have a very simple makefile as below:
.PHONY: clean all
CC = /home/utils/gcc-5.2.0/bin/g++
CFLAGS = -Wall -Werror -fPIC
SRC = $(wildcard *.c)
OBJ = $(subst .c,.o,$(SRC))
.INTERMEDIATE: $(OBJ)
all: test.so
%.o: %.c
$(CC) $(CFLAGS) -o $# -c $<
test.so: $(OBJ)
$(CC) -shared $^ -o $#
clean:
#rm -f *.o *~ *.so
I have only two files in the same directory: a.c and b.c
When I execute "make all", I got the following which is perfect.
/home/utils/gcc-5.2.0/bin/g++ -Wall -Werror -fPIC -o a.o -c a.c
/home/utils/gcc-5.2.0/bin/g++ -Wall -Werror -fPIC -o b.o -c b.c
/home/utils/gcc-5.2.0/bin/g++ -shared a.o b.o -o test.so
rm a.o b.o
However, if I do:
touch a.c; make all
I got the same make execution sequence as above which is not what I expected. There is no dependency between a.c and b.c. What I expect is:
/home/utils/gcc-5.2.0/bin/g++ -Wall -Werror -fPIC -o a.o -c a.c
/home/utils/gcc-5.2.0/bin/g++ -shared a.o b.o -o test.so
rm a.o
I don't understand why b.c is compiled again. According to gnumake manual:
The first difference is what happens if the intermediate file does not exist. If an ordinary file b does not exist, and make considers a target that depends on b, it invariably creates b and then updates the target from b. But if b is an intermediate file, then make can leave well enough alone. It won’t bother updating b, or the ultimate target, unless some prerequisite of b is newer than that target or there is some other reason to update that target.
b.o is an intermediate file, it should not be compiled again since b.c has not changed.
What did I miss?
If b.o is not recompiled, then test.so cannot be created because it depends on b.o. You can't create the shared library from a.o and b.o if b.o was deleted.
If you were trying to create a static library then you could use make's special archive syntax to replace a.o without needing to recompile b.o, but that's not possible unless you use the archive special syntax, and it can't be done for shared libraries such as you're trying to build here.
There's a reason these .o files are not considered intermediate by default, and forcing them to be by adding the .INTERMEDIATE target doesn't mean you can avoid rebuilding them.
Your difficulty stems from the fact that what you mean by an intermediate file
is not what GNU Make means; but the .INTERMEDIATE special target allows you to insist
that a.o and b.o, which in your makefile are not intermediate files in GNU Make's
sense, shall be treated as if they are intermediate in GNU Make's sense, and
then you're taken aback by the consequences.
What you mean by F is an intermediate file is: F is a prerequisite of target T and
F itself has prerequisites. Thus a.o and b.o are intermediate with respect to
test.so because they are prerequisites of that target and themselves have the
respective prerequisites a.c and b.c`.
In your sense of intermediate, making the target test.so does not call for
(a.o|b.o) to be remade unless it is older than (a.c|b.c). So you are taken aback by the fact
that when a.o and b.o are made .INTERMEDIATE, GNU Make always deletes them
when it makes test.so:
b.o is an intermediate file, it should not be compiled again since b.c has not changed. What did I miss?
Chiefly you missed 10.4 Chains of Implicit Rules
Ordinarily, a file cannot be intermediate if it is mentioned in the makefile as a target or prerequisite.
However, you can explicitly mark a file as intermediate by listing it as a prerequisite of the special target .INTERMEDIATE.
This takes effect even if the file is mentioned explicitly in some other way.
So, a.o and b.o would ordinarily not be intermediate in GNU Make's sense,
because they are mentioned in your makefile as prequisites of test.so. But you can
make them be treated as intermediate, in GNU Make's sense, by listing them as prerequisites of .INTERMEDIATE - as you did.
What GNU Make means by intermediate is more technical than what you mean and
is explained in the same section of the manual:
Sometimes a file can be made by a sequence of implicit rules. For example, a file n.o
could be made from n.y by running first Yacc and then cc. Such a sequence is called a chain.
If the file n.c exists, or is mentioned in the makefile, no special searching is required:
make finds that the object file can be made by C compilation from n.c; later on, when
considering how to make n.c, the rule for running Yacc is used. Ultimately both n.c and n.o are updated.
However, even if n.c does not exist and is not mentioned, make knows how to envision it as the
missing link between n.o and n.y! In this case, n.c is called an intermediate file.
Once make has decided to use the intermediate file, it is entered in the data base as
if it had been mentioned in the makefile, along with the implicit rule that says how to create it.
(My emphasis). More briefly, if Make is required to make target output, and discovers a file input such
that:
It has no explicit rule for making output from input, but -
It knows a sequence of implicit (a.k.a builtin) rules by
which a file stage that is not a target or prerequisite in the makefile can
be made from input, and from which output can be made, then it will adopt this
sequence of rules to make output from input via stage, and stage will be
an intermediate file.
Crucially, since stage is not one of your targets, or a prerequisite of any of them, Make
knows that it is merely a disposable by-product of making output from input,
and therefore can be deleted when it has served that purpose.
Here is a simple example project involving files that are really intermediate in GNU Make's sense.
We have some yacc source yacc.y and lex source lex.l, in the project directory,
and we want to build a parser from them, parse, with the following makefile:
Makefile
YFLAGS := -d
OBJS := yacc.o lex.o
.PHONY: all clean
all: parse
parse: $(OBJS)
$(CC) $^ -o $#
clean:
$(RM) parse $(OBJS)
It runs like:
$ make
yacc -d yacc.y
mv -f y.tab.c yacc.c
cc -c -o yacc.o yacc.c
lex -t lex.l > lex.c
cc -c -o lex.o lex.c
cc yacc.o lex.o -o parse
rm lex.c yacc.c
Now you see that Make, using its catalogue of implicit rules, figured out
that yacc.o could be made by compiling the non-existent C source file
yacc.c, and that yacc.c could be produced from the existing source file
yacc.y by running yacc -d yacc.y; mv -f y.tab.c yacc.c. Likewise, it figured out that lex.o
could be made by compiling the nonexistent C source lex.c, and that lex.c
could be made from lex.l by running lex -t lex.l > lex.c. Then parse is
made from yacc.o and lex.o by the routine linkage that the makefile
specifies.
But your makefile says nothing whatever about yacc.c and lex.c. As far as
you have told Make, it does not matter to you whether or not such files ever exist.
They are intermediate files, merely stages in the .y -> .o and .l -> .o productions. So
when Make is done with them:
rm lex.c yacc.c
Then if you:
$ touch yacc.y
and again:
$ make
yacc -d yacc.y
mv -f y.tab.c yacc.c
cc -c -o yacc.o yacc.c
cc yacc.o lex.o -o parse
rm yacc.c
only yacc.o gets remade for the linkage of parse, and the one
intermediate file yacc.c that was generated this time is deleted.
Bottom line
Your object files are not intermediate in GNU Make's sense and you don't
want them to be treated as if they are. This is normal for object files.
So remove .INTERMEDIATE: $(OBJ).

Make File and SDL with multiple files

My project is to make a simple little screen with some moving sprite using SDL in Linux, but I don't want to use an IDE. My goal is get a better understanding of makefiles and all that business; however, I've run into a wall that I can't seem to get past. I'm hoping that someone can explain why what I have is wrong and what I can do to avoid it!
So, my program has multiple dependencies that sort of cascade through each of the files--as such I have all the dependencies listed as need be in the makefile. Here is my code...
OUT=program
CC=g++
SDL=-lSDLmain -lSDL -lSDL_image -lSDL_ttf
all: constants globals functions sprite sprite_test
${CC} sprite_driver.o sprite.o functions.o globals.o constants.h -o ${OUT} ${SDL}
constants:
${CC} -c constants.h
globals: constants
${CC} -c globals.cpp globals.h constants.h ${SDL}
functions: constants globals
${CC} -c functions.cpp globals.h globals.o constants.h ${SDL}
sprite: constants globals functions
${CC} -c sprite.cpp functions.o globals.o constants.h ${SDL}
sprite_test: constants globals functions sprite
${CC} -c sprite_driver.cpp sprite.o functions.o globals.o constants.h ${SDL}
By the time the compiler reaches the functions, it says that the globals.o has not been properly linked. Inside this file are many external declarations that aren't recognized later in the compilation so it looks like there are multiple declarations of the same variables. Here's what the console spits out.
g++ -c constants.h
g++ -c globals.cpp globals.h constants.h -lSDLmain -lSDL -lSDL_image -lSDL_ttf
g++ -c functions.cpp globals.h globals.o constants.h -lSDLmain -lSDL -lSDL_image -lSDL_ttf
g++: warning: globals.o: linker input file unused because linking not done
g++ -c sprite.cpp functions.o globals.o constants.h -lSDLmain -lSDL -lSDL_image -lSDL_ttf
g++: warning: functions.o: linker input file unused because linking not done
g++: warning: globals.o: linker input file unused because linking not done
g++ -c sprite_driver.cpp sprite.o functions.o globals.o constants.h -lSDLmain -lSDL -lSDL_image -lSDL_ttf
g++: warning: sprite.o: linker input file unused because linking not done
g++: warning: functions.o: linker input file unused because linking not done
g++: warning: globals.o: linker input file unused because linking not done
g++ sprite_driver.o sprite.o functions.o globals.o constants.h -o program -lSDLmain -lSDL -lSDL_image -lSDL_ttf
sprite.o:(.bss+0x0): multiple definition of `screen'
sprite_driver.o:(.bss+0x0): first defined here
sprite.o:(.bss+0x4): multiple definition of `event'
sprite_driver.o:(.bss+0x4): first defined here
sprite.o:(.bss+0x18): multiple definition of `keystate'
sprite_driver.o:(.bss+0x18): first defined here
sprite.o:(.bss+0x1c): multiple definition of `font'
sprite_driver.o:(.bss+0x1c): first defined here
sprite.o:(.bss+0x20): multiple definition of `t_black'
sprite_driver.o:(.bss+0x20): first defined here
functions.o:(.bss+0x0): multiple definition of `screen'
sprite_driver.o:(.bss+0x0): first defined here
functions.o:(.bss+0x4): multiple definition of `event'
sprite_driver.o:(.bss+0x4): first defined here
functions.o:(.bss+0x18): multiple definition of `keystate'
sprite_driver.o:(.bss+0x18): first defined here
functions.o:(.bss+0x1c): multiple definition of `font'
sprite_driver.o:(.bss+0x1c): first defined here
functions.o:(.bss+0x20): multiple definition of `t_black'
sprite_driver.o:(.bss+0x20): first defined here
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
You've got so much wrong here that I think you might need to get some introductory materials and go through them. SO is not really the right place to learn these tools from scratch: there are lots of resources for that.
A few things:
You do not compile .h (header) files.
You do not list header files on the compile or link command line when you compile .c (source) files.
You do not list .o (object) files on the compile command line when you compile a source file into an object file. You only put object files on the link command line.
You do not list -l... (library) files on the compile command line when you compile a source file into an object file. You only put library files on the link command line.
Your makefile rules must use the actual file you're trying to create as the target, not just a word you choose.
By long-standing convention, the CC variable in makefiles stands for the C compiler. You're trying to compile C++ source, so you should use the CXX variable.
The make program has a lot of built-in rules on how to build various kinds of files, and one of them describes how to build an object file from a .cpp (C++ source) file. Taking advantage of that you can write your makefile very simply as:
OUT = program
CXX = g++
SDL = -lSDLmain -lSDL -lSDL_image -lSDL_ttf
OBJECTS = sprite_driver.o sprite.o functions.o globals.o
all: $(OUT)
$(OUT): $(OBJECTS)
$(CXX) -o $# $^ ${SDL}
$(OBJECTS): constants.h

Problem with my short Unix Makefile

What can I do to fix this problem? I'm new to emacs, Unix, and makefiles. Please explain what I'm doing wrong and how I can fix it. I'm sure it's a simple problem
progA: yesno.h yesno.cpp
g++ -DDEBUG -c yesno.cpp yesno.h
progB: guess.cpp
g++ -DDEBUG -c guess.cpp
progC: yesno.o guess.o
g++ -DDEBUG -o guess guess.o yesno.o
My error is:
Your makefile does too much work when only guess.cpp has been changed:
g++ -c yesno.cpp yesno.h
g++ -c guess.cpp
g++ -o guess guess.o yesno.o
Your makefile would recompile everything each time.
You don't need the first four lines; make knows how to create object files from source. Or, alternatively, you need to revise those 4 lines into 2, and put them at the end, and change the target names:
guess: yesno.o guess.o
g++ -o guess yesno.o guess.o
guess.o: yesno.h
yesno.o: yesno.h
The first target is the one that is built by default, so that ensures that guess (the program) is built. The command line omits the -DDEBUG since that only affects source code compilation and there is no source in that link line (though, if using macros as one would in an advanced makefile, I'd be fine with the options such as -DDEBUG appearing in the link line).
The third line says that guess.o depends on yesno.h; this is a guess (on my part). The make program already knows how to convert guess.cpp to guess.o; it just needs the extra information that it also uses the yesno.h header. (If it doesn't, how does it know about the functions defined in yesno.cpp?)
The last line says that yesno.o depends on yesno.h; again, make knows how to compile yesno.cpp to yesno.o but needs the extra information about the header.
This should only recompile guess.o when only guess.cpp changes; it should only recompile yesno.o when yesno.cpp changes; it should recompile both object files when yesno.h changes. If any of the source files changes, the program will be relinked; if no source files change, then the make command should do nothing (or simply report that there is nothing to do).

rules for makefile

let's assume I have some Makefile for Unix
prog:a.o b.o c.o
gcc a.o b.o c.o -o prog
a.o:a.c a.h b.h
gcc -c a.c
b.o:b.c b.h
gcc -c b.c
c.o:c.c c.h b.h
gcc -c c.c
I read that if I change *.c file I must recompile only this file, but if I change *.h file I must recompile all files which are depending on my *.h file, after both cases anyway I must link all files from the beginning
1)let's assume that I change only b.h, so what do I need to do?
my variant is make a.o b.o c.o am I right?
2)let's assume that I change only c.c, so what do I need to do?
my variant is make c.o am I right?
and finally if I write make c.o for example my makefile ONLY recompile c.o but what about linker? I have only gcc -c c.c and not -o
thanks in advance for any help
What exactly do you mean 'what do I need to do?'. In every case, just run make prog, and let make figure it out, that's the whole point.
EDIT: If you're curious what make will do in each case, assuming you're running make prog every time, read on:
In case 1) b.h has changed, so anything depending on it (a.o, b.o and c.o) will be rebuilt, and prog will be relinked.
In case 2) c.o is only a direct dependency of c.c, so only c.o is built and prog relinked.
BTW, gcc can give you it's take on your dependencies by just running gcc -MM *.c in your project directory.
In all cases, you just do
make prog
or just
make
The idea of having the Makefile is that make can examine the dependencies, find out what's out of date, and do just the required recompilation (and no more).
If you change a .c file, obviously it's going to recompile that .c file, and because this updates a .o file on which prog depends, it will also relink prog.
If you change a .h file, this will trigger the recompilation of one or more .c files, which again will also cause prog to be relinked.

Resources