I have a directory structure like:
Current directory: within it there are two sub-directories (Directory1 and Directory2).
-Directory1: has a sub-directory with header files(.h) and .c files which are the implemnetations of the .h files in the sub-directory. (.c Files are not within sub-directory but Directory1)
-Directory2: has .c files and Makefile.
My Makefile is:
CC = gcc
OBJS = latency.o utils.o
out: $(OBJS)
HEADER = ../Directory1/include/
CFLAGS = -c -Wall -Iinclude
out: $(OBJS)
$(CC) -o out $(OBJS)
latency.o: latency.c include/utils.h $(HEADER)
$(CC) $(CFLAGS) $< -o $#
utils.o: utils.c include/utils.h $(HEADER)
$(CC) $(CFLAGS) $< -o $#
run:
./out
But i got :
gcc -c -Wall -Iinclude utils.c -o utils.o
gcc -o out latency.o utils.o
/usr/bin/ld: latency.o: in function `main':
latency.c:(.text+0x1b4): undefined reference to 'function_name'
/usr/bin/ld: latency.c:(.text+0x1bc): undefined reference to 'function_name'
/usr/bin/ld: utils.o: in function `get_timing':
utils.c:(.text+0x20c): undefined reference to `function_name'
What mistakes have i made ?
Related
I'm trying to make a simple Makefile with files in different subfolders. This is my Makefile
CFLAGS = -g -Wall
IFLAGS = -Iinclude
OPATH = obj/
CPATH = src/
vpath %.h include
vpath %.c src
vpath %.o obj
vpath main bin
main: main.o grille.o io.o jeu.o
gcc $(CFLAGS) -o main $(OPATH)main.o $(OPATH)grille.o $(OPATH)io.o $(OPATH)jeu.o
mv $# bin/
main.o: main.c grille.h io.h jeu.h
grille.o : grille.c grille.h
io.o: io.c io.h
jeu.o: jeu.c jeu.h
%.o :
gcc $(CFLAGS) -c $< $(IFLAGS)
mv $# $(OPATH)
clean:
rm obj/* bin/*
I have the files in subfolders called src, obj, and include.
I get this error
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find obj/main.o: No such file or directory
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find obj/grille.o: No such file or directory
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find obj/io.o: No such file or directory
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find obj/jeu.o: No such file or directory
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:15: main] Error 1
ERROR
Any Ideas how to fix this?
Writing output files to a different directory than the input files requires extra setup. You should look at your compile line that make runs. Does it put the object file in the right place? If not then that explains why you get those link errors: the object files don't exist where you told the linker they will be, so it fails.
This rule is not right:
%.o :
gcc $(CFLAGS) -c $< $(IFLAGS)
mv $# $(OPATH)
Also, you cannot use vpath to search for targets that are built by makefiles. That can't work. vpath can ONLY be used to search for source files (like .c or .h files). So these lines don't do anything and should be removed:
vpath %.o obj
vpath main bin
And these rules are not right: you need to put the object directory here:
grille.o : grille.c grille.h
io.o: io.c io.h
jeu.o: jeu.c jeu.h
You want something like this:
CC = gcc
CFLAGS = -g -Wall
IFLAGS = -Iinclude
OPATH = obj/
vpath %.h include
vpath %.c src
bin/main: obj/main.o obj/grille.o obj/io.o obj/jeu.o
$(CC) $(CFLAGS) -o $# $^
main.o: main.c grille.h io.h jeu.h
grille.o : grille.c grille.h
io.o: io.c io.h
jeu.o: jeu.c jeu.h
$(OPATH)%.o : %.c
$(CC) $(CFLAGS) $(IFLAGS) -c -o $# $<
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)
I am making my first Makefile for a simple shell system. I need to make library files but for some reason the library section is not working out. In the error message it says the library files do no exist (obviously).
Am I missing something obvious that could fix this? Also, is there any other way I can make this Makefile more efficient?
# Beginning of Makefile
OBJS = obj/shutil.o obj/parser.o obj/sshell.o obj/history.o obj/hash_table.o obj/variables.o
HEADER_FILES = include/shell.h include/parser.h include/history.h include/hash_table.h include/variables.h
EXECUTABLE = sshell
LIBS = lib/libshell.so lib/libparser.so lib/libhistory.so lib/libhash_table.so lib/libvariables.so
LIBCFLAGS = $(CFLAGS) -D_REENTRANT -fPIC
CFLAGS = -Wall
CC = gcc
# End of configuration options
#What needs to be built to make all files and dependencies
all: $(EXECUTABLE)
#Create the main executable
$(EXECUTABLE): $(OBJS) $(LIBS)
$(CC) -o $(EXECUTABLE) obj/sshell.o -Llib -lparser -lshell -lhistory -lhash_table -lvariables
#Create the library files
$(LIBS): $(OBJS)
$(CC) $(LIBCFLAGS) -shared -o $(LIBS) $(OBJS)
#Recursively build object files
obj/%.o: src/%.c
$(CC) $(CFLAGS) -I./include/ -c $< -o $#
#Define dependencies for objects based on header files
#We are overly conservative here, parser.o should depend on parser.h only
$(OBJS) : $(HEADER_FILES)
clean:
-rm -f $(EXECUTABLE) obj/*.o lib/*.so lib/*.a
-rm -f .sshell_history.txt
run: $(EXECUTABLE)
(export LD_LIBRARY_PATH=lib; ./$(EXECUTABLE))
# End of Makefile
Thanks!
-Lily Banks
Edit:
Before I tried to change it, here is what I had with regards to library files.
$(LIBS): $(OBJS)
$(CC) -shared -o lib/libparser.a obj/parser.o
$(CC) -shared -o lib/libshell.a obj/shutil.o
$(CC) -shared -o lib/libhistory.a obj/history.o
$(CC) -shared -o lib/libhash_table.a obj/hash_table.o
$(CC) -shared -o lib/libvariables.a obj/variables.o
The problem with this was that it compiled each file five times which is not efficient at all. So what I was trying to do was do it all in one go.
Edit2:
#Create the library files
lib/libparser.so: obj/parser.o
$(CC) $(LIBFLAGS) -shared lib/libparser.a -o $#
lib/libshell.so: obj/shutil.o
$(CC) $(LIBFLAGS) -shared lib/libshell.a -o $#
lib/libhistory.so: obj/history.o
$(CC) $(LIBFLAGS) -shared lib/libhistory.a -o $#
lib/libhash_table.so: obj/hash_table.o
$(CC) $(LIBFLAGS) -shared lib/libhash_table.a -o $#
lib/variables.so: obj/variables.o
$(CC) $(LIBFLAGS) -shared lib/libvariables.a -o $#
Unfortunately, here is the error I am getting:
make: *** No rule to make target `lib/libvariables.so', needed by `sshell'. Stop.
Thoughts?
Edit3:
#Create the library files
lib/libparser.so: obj/parser.o
$(CC) $(LIBFLAGS) -shared $^ -o lib/libparser.a
lib/libshell.so: obj/shutil.o
$(CC) $(LIBFLAGS) -shared $^ -o lib/libshell.a
lib/libhistory.so: obj/history.o
$(CC) $(LIBFLAGS) -shared $^ -o lib/libhistory.a
lib/libhash_table.so: obj/hash_table.o
$(CC) $(LIBFLAGS) -shared $^ -o lib/libhash_table.a
lib/libvariables.so: obj/variables.o
$(CC) $(LIBFLAGS) -shared $^ -o lib/libvariables.a
This works but is there anything else I need to change? Thanks
You need one set of object files for each library. And the -o flag only takes one argument which is the output file, you are trying to output all the library files which you cannot do with one invocation of gcc.
You need to do something like:
lib/libshell.so: obj/sshell.o
$(CC) $(LIBFLAGS) -shared obj/sshell.o -o lib/libshell.so
lib/libparser.so: obj/parser.o
$(CC) $(LIBFLAGS) -shared obj/parser.o -o lib/libparser.so
for each of the libraries.
This line is completely wrong:
$(LIBS): $(OBJS)
$(CC) $(LIBCFLAGS) -shared -o $(LIBS) $(OBJS)
If you expanded all the variables, this line would look like this (adding line breaks for clarity):
lib/libshell.so lib/libparser.so lib/libhistory.so lib/libhash_table.so lib/libvariables.so: \
obj/shutil.o obj/parser.o obj/sshell.o obj/history.o obj/hash_table.o obj/variables.o
gcc -Wall -D_REENTRANT -fPIC -shared -o lib/libshell.so lib/libparser.so lib/libhistory.so \
lib/libhash_table.so lib/libvariables.so obj/shutil.o obj/parser.o obj/sshell.o obj/history.o \
obj/hash_table.o obj/variables.o
Which, it should be clear, is very not right. It's so not right I can't even really tell what you're trying to accomplish. Do you really want to create one shared library for every .o file, where each shared library contains a single .o? If so why are you trying to link both the .o files AND the shared libraries into a single executable?
If you explain what you are really trying to do, at a higher level, we can help.
I have 3 functions separated in .c files and the main.c I would like to make the make file, I wrote in the file:
# Indicate that the compiler is the gcc compiler
CC=gc
# Indicate to the compiler to include header files in the local folder
CPPFLAGS = -I
main: method1.o
main: method2.o
main: method3.o
main: method4.o
main.o: main.h
Whereas method 1,2,3,4 is the functions of the main .c and I have the following problem when I type make in the shell:
make
gcc -I -c -o method1.o method1.c
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [method1.o] Error 1
if your project contains the following files: method1.c method2.c method3.c method4.c and main.c
you can use the following make file
CPPFLAGS=-I/path/to/header/files
CC=gcc
all: main
%.o: %.c
$(CC) $(CPPFLAGS) -c -o $# $^
main: method1.o method2.o method3.o method4.o main.o
$(CC) -o $# $^
The issue is in your CPPFLAGS definition:
# Indicate to the compiler to include header files in the local folder
CPPFLAGS = -I
According to the comment above it, it misses a .:
CPPFLAGS = -I.
Otherwise, gcc will treat the -c that comes after -I in your command line as the name of a directory where it can search for headers. Thus, as far as gcc is concerned there's no -c option, and it will attempt to link method1.c as a complete application, hence the error message complaining that there's no main function.
CC=gcc
CPPFLAGS=-I include
VPATH=src include
main: main.o method1.o method2.o method3.o method4.o -lm
$(CC) $^ -o $#
main.o: main.c main.h
$(CC) $(CPPFLAGS) -c $<
method1.o: method1.c
$(CC) $(CPPFLAGS) -c $<
method2.o: method2.c
$(CC) $(CPPFLAGS) -c $<
method3.o: method3.c
$(CC) $(CPPFLAGS) -c $<
method4.o: method4.c
$(CC) $(CPPFLAGS) -c $<
it worked like this
I'm trying to get a small project compiled but am getting this error, I've been searching around and people get this error mainly because of incorrect file extension, but I don't really think that's the cause here:
gcc -c -W -Wall -ggdb -I. router.c -o router.o
router.c:106: warning: unused parameter ‘hname’
router.c: In function ‘flood_neighbors’:
router.c:464: warning: unused variable ‘bytes_rcvd’
router.c: At top level:
router.c:536: warning: unused parameter ‘fd’
gcc -c -W -Wall -ggdb -I. link_info.h -o link_info.o
gcc -c -W -Wall -ggdb -I. route.h -o route.o
gcc -c -W -Wall -ggdb -I. sequence.h -o sequence.o
gcc -W -Wall -ggdb -I. router.o link_info.o route.o sequence.o -o router
link_info.o: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: *** [router] Error 1
and my make file looks like:
CC = gcc
INC = -I.
FLAGS = -W -Wall -ggdb
router: router.o link_info.o route.o sequence.o
$(CC) $(FLAGS) $(INC) $^ -o $#
router.o: router.c
$(CC) -c $(FLAGS) $(INC) $< -o $#
sequence.o: sequence.h sequence.h
$(CC) -c $(FLAGS) $(INC) $< -o $#
link_info.o: link_info.h link_info.c
$(CC) -c $(FLAGS) $(INC) $< -o $#
route.o: route.h route.c
$(CC) -c $(FLAGS) $(INC) $< -o $#
What I'm confused on is the rules for three object files are of the same format, but why only the link one yells? Thanks a lot!
I would like to suggest few edits in your makefile.
CC = gcc
INC = -I.
FLAGS = -W -Wall -ggdb
router: router.o link_info.o route.o sequence.o
$(CC) $(FLAGS) $(INC) $^ -o $#
router.o: router.c
$(CC) -c $(FLAGS) $(INC) $< -o $#
sequence.o: sequence.h sequence.h //Where is the c file ?
$(CC) -c $(FLAGS) $(INC) $< -o $#
link_info.o: link_info.h link_info.c //Change the order. Put c file first and then the header
$(CC) -c $(FLAGS) $(INC) $< -o $#
route.o: route.h route.c //Same as above
$(CC) -c $(FLAGS) $(INC) $< -o $#
With recent versions of make you can remove all the object rules because make uses a default rule to build an object from .c or .cpp files. Just leave the rule to build the final executable in place.
For example, change the file so it contains this line only:
router: router.o link_info.o route.o sequence.o
$(CC) $(FLAGS) $(INC) $^ -o $#
Move link_info.o to the end of the list in the router: dependencies and I suspect you'll blow up on route.o instead.
You seem to be compiling a headers as C files. I have no idea what GCC does in that case. In your makefile rules, the .c file must be the first dependency if you are going to use $< to generate the source file to compile.
The link_info: and route: rules have the .c and .h files reversed and the sequence: rule lists the .h file twice!