How to change the structure of this makefile - makefile

I am new to handling makefiles and was provided with this one:
demo: demo.cpp vegas.o ranlxd.o
g++ -o demo demo.cpp vegas.o ranlxd.o -lgfortran
vegas.o: vegas.F
gfortran -c vegas.F
ranlxd.o: ranlxd.c
gcc -c ranlxd.c
clean:
rm -f vegas.o ranlxd.o
distclean: clean
rm -f demo
I use functions defined in the vegas and ranlxd files within the demo file. Now I want to change this so that all the codefiles are converted to object files first and then linked in the end so I tried the following:
demo: demo.o vegas.o ranlxd.o
demo.o vegas.o ranlxd.o -lgfortran
demo.o: demo.cpp
g++ -c demo.cpp
vegas.o: vegas.F
gfortran -c vegas.F
ranlxd.o: ranlxd.c
gcc -c ranlxd.c
clean:
rm -f vegas.o ranlxd.o
distclean: clean
rm -f demo
This resulted in the error
demo.o vegas.o ranlxd.o -lgfortran
make: demo.o: Command not found
make: *** [makefile:9: demo] Error 127
What am I doing wrong and what do I have to change in order to compile all the codefiles first? I highly appreciate any kind of help!

With your link command you forgot to actually call a program for the linker
demo: demo.o vegas.o ranlxd.o
demo.o vegas.o ranlxd.o -lgfortran
should be:
demo: demo.o vegas.o ranlxd.o
g++ -o demo demo.o vegas.o ranlxd.o -lgfortran

Samuel is right, you just forgot the link command (g++ -o demo). Make passed demo.o vegas.o ranlxd.o -lgfortran to the shell and the shell complained that demo.o is not a command it knows.
I am just adding this answer to let you know about GNU make Built-In Rules. If you use GNU make you could also rely on them and replace your compilation and link rules by a single demo: demo.o vegas.o ranlxd.o. Yes, just that. GNU make knows how to build the .o files form your source files and how to assemble them to create the executable. Modify the standard variables, if needed (e.g. FC := gfortran and CC := gcc). Your Makefile could be as simple as, for example:
FC := gfortran
CC := gcc
LDLIBS := -lgfortran
demo: demo.o vegas.o ranlxd.o
.PHONY: clean distclean
clean:
rm -f *.o
distclean: clean
rm -f demo
But of course, if your goal is to learn make, it is probably better to write all these rules yourself.

Related

How to link a shared library to a makefile

Hello everyone I have the following makefile:
LHAPDFldflag = -L "/home/user/local/lib -lLHAPDF"
LHAPDFincdir = -I "/home/user/local/include/"
demo: demo.o vegas.o ranlxd.o
g++ -o demo demo.o vegas.o ranlxd.o -lgfortran ${LHAPDFldflag}
demo.o: demo.cpp
g++ ${LHAPDFincdir} -c demo.cpp
vegas.o: vegas.F
gfortran -c vegas.F
ranlxd.o: ranlxd.c
gcc -c ranlxd.c
clean:
rm -f vegas.o ranlxd.o
distclean: clean
rm -f demo
In my demo.cpp I call a function from the library. After trying 'make' I receive the following error:
g++ -o demo demo.o vegas.o ranlxd.o -lgfortran -L "/home/user/local/lib -lLHAPDF"
/usr/bin/ld: demo.o: in function `main':
demo.cpp:(.text+0x13ca): undefined reference to `LHAPDF::initPDFSet(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
collect2: error: ld returned 1 exit status
make: *** [makefile:6: demo] Error 1
As far as I know an undefined reference error originates from a problem in the linker stage which is also indicated by the last line of the error. But I am wondering that in the fourth line of the error code it seems to know the function that I want to call. Is the problem here really in the linking? I don´t see whats wrong with the line 6 of my makefile which is refered to in the error code. Could there be another explanation? I highly appreciate any kind of help!

makefile with two rules for the same target

I have a makefile to create a library, and I need it to create a 80% library or a complete library, which means a library with 80% of the functions or a library with all of the functions.
When I call make, the "all" rule should create the 80% library (so far so good), and when I call "make complete" the "complete" rule should create the 100% library (still easy), and it should not relink in any case, here I have a problem.
WHAT GOES WELL:
here is what I have :
all: $(NAME)
$(NAME): $(OBJS)
ar -rc $# $^
complete: $(NAME) $(MORE_OBJS)
ar -rc $^
%.o : %.c
gcc -I. -c -o $# $<
.PHONY: complete
so if I run make it goes:
>make
gcc -I. -c -o function01.o function01.c
gcc -I. -c -o function02.o function02.c
gcc -I. -c -o function03.o function03.c
gcc -I. -c -o function04.o function04.c
ar -rc libtest.a function01.o function02.o function03.o function04.o
and make again:
>make
make: Nothing to be done for 'all'.
perfect. then with make complete:
>make complete
gcc -I. -c -o function_05.o function05.c
gcc -I. -c -o function_06.o function06.c
ar -rc libtest.a function05.o function06.o
or of course:
>make fclean
rm *.o
rm libtest.a
>make complete
gcc -I. -c -o function01.o function01.c
gcc -I. -c -o function02.o function02.c
gcc -I. -c -o function03.o function03.c
gcc -I. -c -o function04.o function04.c
ar -rc libtest.a function01.o function02.o function03.o function04.o
gcc -I. -c -o function_05.o function05.c
gcc -I. -c -o function_06.o function06.c
ar -rc libtest.a function05.o function06.o
WHAT GOES WRONG:
but if I prompt make complete again:
>make complete
ar -rc libtest.a function05.o function06.o
I don't recompile but I relink the library.
I've tried a lot of approach, with the target-specific assignment, re-ordering the targets and the rules in many different combination, but I didn't find any way of doing it. am I missing something or is it indeed hard?
also, I can't put the additional functions in another file with its own makefile and use "make -C" to make it and then add it to the library, everything has to be in this makefile and the sources at the root
make complete will always run, because the target name is complete and no file named complete is ever created. So as far as make knows that file is not up to date and needs to be rebuilt.
There is no straightforward way to do this because make doesn't support multiple different recipes creating the same target.
You can fake it out by using a sentinel file to inform make whether the target exists or not. To do this, you need to create the file complete so make can use it to track whether or not it needs to be rebuilt. Try:
complete: $(NAME) $(MORE_OBJS)
ar -rc $^
#touch $#

Make did not work after I changed my file

These are my files:
add.c add.h main.c makefile
This is makefile:
main:main.o add.o
gcc -o main main.o add.o
main.o:$(#:%.o=%.c)
gcc -o main.o -c main.c
add.o:$(#:%.o=%.c) $(#:%.o=%.h)
gcc -o add.o -c add.c
.PHONY:clean
clean:
rm *.o -rf
rm main -rf
Then after I change the main.c and make.
But make told me this:
make: `main' is up to date.
If I change my makefile:
main:main.o add.o
gcc -o main main.o add.o
main.o:main.c
gcc -o main.o -c main.c
add.o:$(#:%.o=%.c) $(#:%.o=%.h)
gcc -o add.o -c add.c
.PHONY:clean
clean:
rm *.o -rf
rm main -rf
Then after I change the main.c and make.
It can work.
I donot know the reason.
The dependencies in
main.o:$(#:%.o=%.c)
add.o:$(#:%.o=%.c) $(#:%.o=%.h)
are not valid make syntax.
Replace these two rules with one pattern (generic) rule:
%.o : %.c
gcc -c -o $# ${CPPFLAGS} ${CFLAGS} $<
The above rule is actually very similar to the built-in rule for compiling .o files from .c:
Compiling C programs
n.o is made automatically from n.c with a recipe of the form $(CC) $(CPPFLAGS) $(CFLAGS) -c.
In other words, you can remove your original rules for main.o and add.o and it should build correctly.

make recompiles everything every time, why?

Here's my makefile:
all: lex yacc compile
lex: sql.l
lex -i sql.l
yacc: sql.y
yacc -d -v sql.y
compile: y.tab.c lex.yy.c
$(CC) -o sql_parser y.tab.c lex.yy.c -ly -ll
test: all
#./parsesql.sh selecttest.sql
#./parsesql.sh insertintotest.sql
#./parsesql.sh deletefromtest.sql
#./parsesql.sh createtest.sql
cleanup:
rm test.tab.cacc
rm y.output
Running make will always trigger a full recompile, even if nothing has changed:
parsesql> make
lex -i sql.l
yacc -d -v sql.y
cc -o sql_parser y.tab.c lex.yy.c -ly -ll
parsesql> make
lex -i sql.l
yacc -d -v sql.y
cc -o sql_parser y.tab.c lex.yy.c -ly -ll
parsesql> make
lex -i sql.l
yacc -d -v sql.y
cc -o sql_parser y.tab.c lex.yy.c -ly -ll
None of the files have changed, so why is it doing this? The lex and yacc commands should only trigger if sql.l or sql.y respectively have changed, no?
Your targets are all not real files. Make them the names of the actual files you're generating so that make can find them and check timestamps.
Example:
all: sql_parser
lex.yy.c: sql.l
lex -i sql.l
y.tab.c: sql.y
yacc -d -v sql.y
sql_parser: y.tab.c lex.yy.c
$(CC) -o sql_parser y.tab.c lex.yy.c -ly -ll
test: all
#./parsesql.sh selecttest.sql
#./parsesql.sh insertintotest.sql
#./parsesql.sh deletefromtest.sql
#./parsesql.sh createtest.sql
cleanup:
rm test.tab.cacc
rm y.output
You can add .PHONY: all test cleanup to indicate to make that those targets are not intended to be real files.

make file : yacc command not found and [y.tab.c] error 127 after installing bison

There is a given r-tree code by Toni Guttman(it's been modified for my homework), however, if I change an parameter(the dimension of the node), then "make" will cause such errors:
yacc y.spec
make: yacc:command not found
make: *** [y.tab.c] error 127
I've installed bison and flex, and "which yacc" shows that
alias yacc='bison'
/usr/bin/bison
What should I do to solve the problem?
Here is the "Makefile":
# %W% %G%
# use flag -O for optimized code, slower compile
FLAGS=
SRC= main.c index.c newtid.c node.c rectangle.c \
printstats.c clock.c y.spec allocate.c error.c\
split.l.c \
split.q.c \
split.e.c
HEADERS= options.h macros.h index.h assert.h
ALL= $(SRC) $(HEADERS) split.l.h split.q.h split.e.h
OBJ= main.o index.o newtid.o node.o rectangle.o \
printstats.o clock.o y.tab.o allocate.o error.o
OBJLIN= split.l.o
OBJQ= split.q.o
OBJEXP= split.e.o
$(OBJ): $(HEADERS)
$(OBJLIN): $(HEADERS) split.l.h
$(OBJQ): $(HEADERS) split.q.h
$(OBJEXP): $(HEADERS) split.e.h
# assembler chokes if graphics.c is compiled with -g option, do it without.
# graphics.o: graphics.c $(HEADERS)
# cc -c graphics.c
# assembler chokes if y.tab.c is compiled with -g option, do it without.
# y.tab.o: y.tab.c $(HEADERS)
# cc -c y.tab.c
.c.o: $(HEADERS)
cc -c $(FLAGS) $*.c
linear: $(OBJ) $(OBJLIN)
cc $(FLAGS) $(OBJ) $(OBJLIN) -lm -o linear
quad: $(OBJ) $(OBJQ)
cc $(FLAGS) $(OBJ) $(OBJQ) -lm -o quad
exp: $(OBJ) $(OBJEXP)
cc $(FLAGS) $(OBJ) $(OBJEXP) -lm -o exp
y.tab.c: y.spec $(HEADERS)
yacc y.spec
edit:
sccs edit $(SRC) $(HEADERS) split.l.h split.q.h split.o.h
unedit:
sccs unedit $(ALL)
rm -f tags
delta:
sccs delta $(ALL)
rm -f tags
get:
sccs get $(ALL)
clean:
rm -f *.o core y.tab.c tags
tags: $(SRC)
ctags *.c
lint:
rm -f lint.out
lint *.c > lint.out
You don't have yacc installed, as you've seen. Changing an alias in your shell won't help, because it's make that is trying to run the yacc command, not the shell. You have to edit your makefile, and add a line like:
YACC = bison -y
(the -y flag makes bison behave like yacc)
Since you didn't show your actual makefile we can't be sure that this will do it, but it's likely.
EDIT:
I your makefile above, change the reference to yacc to say bison -y instead.
Your makefile is not following many best practices but that's for another day.
manually add this script /usr/bin/yacc is simply a script containing:
#! /bin/sh
exec '/usr/bin/bison' -y "$#"

Resources