C makefile with subfolders and several .c files (error. ld) - c

I'm trying to create a makefile for my project but it's not working at all.
I have the following directory structure
projectroot
|
|-----main.c
|
|-----makefile
|
|-----folder1
| |
| |-----Foobar1.c
| |-----Foo1.c
| |-----Bar1.c
| |-----Foobar1.h
|
|-----folder2
| |-----Foo2.c
| |-----Foo2.h
Foo1.c and Bar1.c are used in Foobar1.c and they are included in the Foobar.h and it workes if i run them (Foobar1.c) in the folder1 directory.
The main.c is useing functions from both Foobar1.c and Foo2.c
CC = gcc
CFLAGS = -c -Wall
LIBS = -lm
all: run
run: main.o Foobar1.o Foo2.o
$(CC) main.o Foobar1.o Foo2.o -o run $(LIBS)
main.o: main.c
$(CC) $(CFLAGS) main.c $(LIBS)
Foobar1.o: folder1/Foobar1.c folder1/Foo1.c folder1/Bar1.c
$(CC) $(CFLAGS) folder1/Foobar1.c folder1/Foo1.c folder1/Bar1.c $(LIBS)
Foo2.o: folder2/Foo2.c
$(CC) $(CFLAGS) folder2/Foo2.c $(LIBS)
clean:
rm -rf *o run
I tried to create a Makefile for whole project in the root directory and I got this error:
gcc -Wall main.c -lm
gcc -Wall folder1/Foobar1.c folder1/Foo1.c folder1/Bar1.c -lm
gcc -Wall folder2/Foo2.c -lm
gcc main.o Foobar1.o Foo2.o -o run -lm
Foobar.o: In function 'Foo1_func1':
Foobar.c: (.text+0x0): multiple definitions of 'Foo1_func1'
main.o:main.c:(.text+0x0): first defined here
Foobar.o: In function 'Bar1_func1':
Foobar.c: (.text+0x6a4): multiple definitions of 'Bar1_func1'
main.o:main.c:(.text+0x6a4): first defined here
Foobar.o: In function 'Bar1_func2':
Foobar.c: (.text+0xed8): multiple definitions of 'Bar1_func2'
main.o:main.c:(.text+0xed8): first defined here
collect2: error: ld returned 1 exit status
makefile:13: recipe for target "run" failed
make: *** [run] error 1
and I also tried to create a makefile for each sub-folder and one in the root directory it did work for the sub-makefile but I don't know how to write the root makefile I tried with this
in folder1
CC = gcc
CFLAGS = -c -Wall
LIBS = -lm
all: bar
bar: Foobar1.o
$(CC) Foobar1.o -o bar $(LIBS)
Foobar1.o: Foobar1.c Foo1.c Bar1.c
$(CC) $(CFLAGS) Foobar1.c $(LIBS)
clean:
rm -rf *o bar
in folder2
CC = gcc
CFLAGS = -c -Wall
LIBS = -lm
all: foo
foo: Foo2.o
$(CC) Foo2.o -o bar $(LIBS)
Foo2.o: Foo2.c
$(CC) $(CFLAGS) Foo2.c $(LIBS)
clean:
rm -rf *o foo
and in the root directory. is it the correct way to do this?
CC = gcc
CFLAGS = -c -Wall
LIBS = -lm
all:
+$(MAKE) -C folder1
+$(MAKE) -C folder2
run: main.o folder1/Foobar1.o folder2/Foo2.o
$(CC) main.o folder1/Foobar1.o folder2/Foo2.o -o run $(LIBS)
main.o: main.c
$(CC) $(CFLAGS) main.c $(LIBS)
clean:
rm -rf *o run
Please help, it is my first time to write a makefile.

You're running the executable (.o) without first compile the .c
run: main.o Foobar1.o Foo2.o
$(CC) main.o Foobar1.o Foo2.o -o run $(LIBS)
[...]
And here you should rm using *.o, its safer.
clean:
rm -rf *o run
The right order is:
1 - .h (library)
2 - .c (code)
3 - .o (executable)

Related

"clang: error: cannot specify -o when generating multiple output files" fix

I'm trying to compile my C project using clang (I'm on MacOS Monterry) and a Makefile, but I keep getting the same error from clang in the command line:
> make
gcc -c src/ji.c src/main.c -o src/ji.o
clang: error: cannot specify -o when generating multiple output files
make: *** [src/ji.o] Error 1
These are the only files I have in the project so far:
src/main.c
src/ji.c
include/ji.h
The Makefile looks like this:
cc = gcc
src = $(wildcard src/*.c)
obj = $(src:.c=.o)
exec = ji
$(exec): $(obj)
$(cc) -Iinclude $< -o build/$#
%.o: %.c
$(cc) -c $(src) -o $#
clean:
-rm src/*.o
-rm ji
From YouTube videos I've seen, this should be the ideal Makefile for the project but no matter what I change I get the error.
There are a few issues:
-Iinclude needs to be on the %.o: %.c rule command
In %.o: %.c, we don't want $(src) but rather $<
We want patsubst to get the .o list obj
The $(exec) target doesn't match the -o option
The clean doesn't match the placement of the executable
Here's a refactored version (e.g. one way to do this--there are others):
cc = gcc
src = $(wildcard src/*.c)
obj = $(patsubst %.c,%.o,$(src))
exec = build/ji
$(exec): $(obj)
mkdir -p build
$(cc) $^ -o $#
%.o: %.c
$(cc) -c $< -o $# -Iinclude
clean:
rm -f src/*.o
rm -fr build
Here's the output of make:
gcc -c src/ji.c -o src/ji.o -Iinclude
gcc -c src/main.c -o src/main.o -Iinclude
mkdir -p build
gcc src/ji.o src/main.o -o build/ji
Here's the output of make clean:
rm -f src/*.o
rm -fr build

makefile not updating .o file with respectively with .h file

I have following make file :-
VER = Debug
CC = gcc
objectfiles = Getstr.o ui.o ustreqsol.o main.o
pkg = `pkg-config --cflags --libs gtk+-3.0`
obj = $(addprefix objs/,$(objectfiles))
../$(VER)/Calculator: $(obj)
$(CC) -o $# $(obj) $(pkg)
./objs/ui.o:ui.c
$(CC) -c -o $# $< $(pkg)
./objs/main.o:main.c
$(CC) -c -o $# $< $(pkg)
./objs/%.o: %.c %.h
$(CC) -c -o $# $<
clean:
-rm ../$(VER)/Calculator
-rm /objs/*
and follwing files in my src dir:-
$ ls
Getstr.c main.c Makefile objs ui.c ui.h ustreqsol.c ustreqsol.h
objs is directory. Whenver I change ustreqsol.h file it compiles ustreqsol.c file but not in case for ui.h file
$ touch ustreqsol.h
$ make
gcc -c -o objs/ustreqsol.o ustreqsol.c
gcc -o ../Debug/Calculator objs/Getstr.o objs/ui.o objs/ustreqsol.o objs/main.o `pkg-config --cflags --libs gtk+-3.0`
$ make
make: '../Debug/Calculator' is up to date.
$ touch ui.h
$ make
make: '../Debug/Calculator' is up to date.
As a noob in makefiles i have no idea why is this happening
The reason ui.c is not being rebuilt is because you explictly said ui.h is not a dependency:
./objs/ui.o:ui.c
$(CC) -c -o $# $< $(pkg)
For the general dependency you have set up:
./objs/%.o: %.c %.h
$(CC) -c -o $# $<
The dependency list only takes effect for files that you didn't explicitly set them for, such as ustreqsol.c.
You need to add targets for each object file specifying the dependencies for each one. The targets can be blank, as the %.o target will fill in what to do.
For example:
./objs/ustreqsol.o: ustreqsol.c ustreqsol.h ui.h
./objs/ui.o: ui.c ui.h
./objs/main.o: main.c ui.h ustreqsol.h
./objs/Getstr.o: Getstr.c
./objs/%.o: %.c %.h
$(CC) -c -o $# $<

How to create make file for only object and header file?

I'm performing blackbox testing using a set.h interface where I have no access to set.c, I've been provided with the object file set.o and I'm required to write a bunch of tests in a main.c file for the set. How do I create a makefile that would include set.o, set.h and main.c?
**I already have the set.o file so I don't have to regenerate it using set.c
I'm confused because I only know how to do this using the complete files.
Here's my template
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o $(OBJDIR)/set.o
# compiling rules
$(PROG): $(OBJS) $(OBJDIR)
$(CC) $(CFLAGS) $(OBJS) -o $(PROG)
$(OBJDIR)/set.o: set.h $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c set.h -o $(OBJDIR)/set.o
$(OBJDIR)/main.o: main.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(PROG) $(OBJS)
If you already have the set.o file there is no need to create a rule for it, just use it. Also note I got rid of the mkdir because if you already have a set.o, it should already be in objects/ right?
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o
# compiling rules
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(OBJDIR)/set.o -o $(PROG)
$(OBJDIR)/main.o: main.c $(HDRS)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
clean:
rm -f $(PROG) $(OBJS)

GNU make undefined reference to functions defined in shared library

I am trying to link to a shared library. But I kept getting the undefined reference error. The following is makefile:
LIBDIR :=./lib
LIB :=-lminus
OBJDIR :=objdir
SOURCES=$(wildcard ./src/*.c)
OBJS :=$(patsubst ./src/%.c, $(OBJDIR)/%.o, $(SOURCES))
INCPATH = -Ilib -Isrc
vpath %.h ./src ./lib
vpath %.c ./src ./lib
optest : $(OBJS)
cc -o optest $(OBJS)
$(OBJDIR)/main.o : main.c add.h mul.h did.h minus.h
cc $(INCPATH) -o $# -c $< -L$(LIBDIR) $(LIB)
$(OBJDIR)/%.o: %.c %.h | $(OBJDIR)
cc -o $# -c $<
$(OBJDIR):
mkdir $#
clean :
rm -rf $(OBJDIR)
rm -f optest
rm -f ./src/*.o
The shared library is called libminus, which is put in the ./lib directory. The main function in main.c uses the function minus defined in this library. I searched online, people met this problem before. Most of their problems were solved after the shared libraries were put after the object files in the rule command. I also tried this, but it didn't work for me. The error I got is as follows:
mkdir objdir
cc -o objdir/mul.o -c ./src/mul.c
cc -o objdir/did.o -c ./src/did.c
cc -Ilib -Isrc -o objdir/main.o -c ./src/main.c -L./lib -lminus
cc -o objdir/add.o -c ./src/add.c
cc -o optest objdir/mul.o objdir/did.o objdir/main.o objdir/add.o
objdir/main.o: In function `main':
main.c:(.text+0xa5): undefined reference to `minus'
collect2: error: ld returned 1 exit status
makefile:11: recipe for target 'optest' failed
make: *** [optest] Error 1
Can any one give some suggestion? Thank you.
You're putting the lib stuff into the wrong rule:
$(OBJDIR)/main.o : main.c add.h mul.h did.h minus.h
cc $(INCPATH) -o $# -c $< -L$(LIBDIR) $(LIB)
This just compiles main.c to main.o. The -L and $(LIB) don't belong here. They have to be in the build recipe of this rule, which links the executable:
optest : $(OBJS)
cc -o optest $(OBJS)

makefile exit with no reason when compile .pc and .c at the same time. very strange

I am using pro*c in AIX,I want make my .pc file compile to a .so libary. And link it. This is my directory:
ls
connect.pc func.c get_log.pc main.c makefile sql_err.pc
This is my makefile:
#Makefile
CC = cc -g -brtl
CFLAGS = -g -c
ESQL = proc
RM = rm -f
MYHOME = /home/xxx
OBJ = main.o func.o
LIBOBJ = get_log.o connect.o sql_err.o
DBINC = -I$(ORACLE_HOME)/precomp/public
DBLIB = -L$(ORACLE_HOME)/lib -lclntsh
INCLUDE = -I$(MYHOME)/include
.SUFFIXES: .pc .c .o
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
clean:
rm -f *.o *.lis
when I make I get this:
.......
cc -g -brtl -o sql_err.o -g -c sql_err.c -I/home/xxx/include -I/oracle/product/10.2.0/precomp/public -L/oracle/product/10.2.0/lib -lclntsh
rm -f sql_err.c
rm -f sql_err.lis
cc -g -brtl -qmkshrobj -o libmydb.so get_log.o connect.o sql_err.o -L/oracle/product/10.2.0/lib -lclntsh
mv libmydb.so /home/xxxlib
when it done mv libmydb.so ,it exit!!!without wrong message.why?? I also need my .c to compile to .o and finally to an executable file query link libmydb.so.
when I change the squeuce like this put .c.o before .pc.o:
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
it give this message,although I have libmydb.so last step:
prepaid(wmfe)/home/xxx/src>make
cc -g -brtl -c -g -c main.c -I/home/xxx/include
cc -g -brtl -c -g -c func.c -I/home/xxx/include
cc -o query main.o func.o -L/home/xxx/lib -lmydb
ld: 0706-006 Cannot find or open library file: -l mydb
ld:open(): A file or directory in the path name does not exist.
make: 1254-004 The error code from the last command is 255.
Stop.
I can't handle this ,very strange,Help!!
By default make will make the first rule in your makefile, but it must not start with a dot. So the default rule in your makefile is libmydb.so and that is being built.
That rule is only dependent on the LIBOBJ and OBJ is not a dependency so it doesn't care about those. It doesn't exit with no reason, it exits because it has done the job you defined for it. There is no error to report.
If you change the order then the default rule is changed and it tries to compile query. This has no dependencies to the library, so it doesn't try to compile that.
If you want to compile everything you should have, for example, a rule all that lists the dependencies. In this case probably libmydb.so and query at least, in correct order. If this is the first rule it will be the default and your compilation will succeed.

Resources