I need some assistance with Makefile in my project - c

I'm trying to make a Makefile but I'm having some problems
first I have
2 source files: ~/main.c ~/lib/library.c
1 header file: ~/include/library.h
main.c and library.c both share the same header file library.h
# Compiler options
CC = gcc
INC = -I../include
CFLAGS = -Wall -g -c $(INC)
LIB = -L../lib
LFLAGS = -Wall -g $(LIB)
# Dependencies
LIBS = -libmylib
OBJS = main.o
SRCS = $(OBJS:.o=.c)
EXEC = a.out
# Other rules
RM = rm -rf
TAGS = tags
BAK = Makefile.bak
all: $(EXEC)
#echo ------------------------ Compile Complete ----------------------------
.PHONY: clean depend
$(EXEC): $(OBJS)
$(CC) $(LFLAGS) -o $# $^ $(LIBS)
.c.o:
$(CC) $(INC) -M $^
$(CC) $(CFLAGS) -o $# $<
clean:
$(RM) *.o *~ $(EXEC) $(TAGS) $(BAK)
depend: $(SRCS)
makedepend $(INC) $^
it keeps saying that I it can't make a rule out of library.o
plus I have another question
I acknowledge the fact that when Makefile comes in to action after calling 'make',
and subsequently go to the line .c.o or %c: %o(in GNU enhanced version) and make
.o files. but why doesn't it also call clean and depend automatically?
I've edited some things from the previous version of Makefile
this time, (well pretty similar to the previous problem) even though I
clarified the library path(-I../lib),
the Makefile cannot find the archive file (which I created as libmylib.a in ../lib dir)
now it's driving me crazy

but why doesn't it also call clean and depend automatically?
Because make only builds the target you tell it. If you don't specify one, the first target is built, which in many cases, such as yours, is the 'all' target.

Related

How can I improve this Makefile to optimize the usage of the SRC and BIN folders?

This is my first attempt at making a Makefile after having gone through several tutorials and the gnu make manual. The Makefile works and creates the .o, .a and .exe files in the BIN folder. However, I have have added src\ and bin\ prefixes to all files. I know there must be a better way of addressing folder issues while using Makefiles. Only problem is, I am unable to figure it out after hours of editing and trying out different things, based on the tutorials. I find GNU make manual too overwhelming at this stage of my learning curve.
I am using MinGW GCC toolchain on Windows 7. I have copied mingw32-make.exe to make.exe for the purpose of trying out the tutorials and exampples I have been going through.
I would really appreciate any help on the subject. Thank you.
My Makefile is as follows:
CC = gcc
CFLAGS = -O3 -Wall -c
BIN = bin/
LDFLAGS = -L$(BIN) -lmyLib
all: test.exe
test.exe: test.o libmyLib.a
gcc bin\test.o -o bin\test.exe $(LDFLAGS)
test.o: src\test.c src\myLib.h
$(CC) $(CFLAGS) -o bin\test.o src\test.c
libmyLib.a: myLib.o
ar rcs bin\libmyLib.a bin\myLib.o
myLib.o: src\test.c src\myLib.h
$(CC) $(CFLAGS) -o bin\myLib.o src\myLib.c
clean:
del bin\*.* /Q
First, there are some issues with your Makefile, even if it apparently works. When you write:
myLib.o: src\test.c src\myLib.h
$(CC) $(CFLAGS) -o bin\myLib.o src\myLib.c
you are lying to make:
You tell it that the result of the rule is myLib.o while it is bin\myLib.o, that is, a different file.
You tell make that myLib.o depends on src\test.c while it in fact depends on src\myLib.c.
Same with your other rules as in:
libmyLib.a: myLib.o
ar rcs bin\libmyLib.a bin\myLib.o
You tell make that the rule shall be executed if myLib.o is newer than libmyLib.a while the real prerequisite is bin\myLib.o and the real target is bin\libmyLib.a.
By doing so you totally prevent make from doing what it is supposed to do: decide if a recipe must be executed or not, depending on the last modification times of target files and prerequisite files. Give it a try: run make twice and you'll see that it uselessly redoes what it did already. Never, never lie to make.
Second, you can improve your Makefile by using several advanced features like automatic ($#, $<, $^), standard (LDLIBS, AR, ARFLAGS) and regular (BIN, SRC) make variables. Here is an example of what you could try, after fixing the above mentioned issues and better using variables (plus adding the missing -I gcc option, and declaring all and clean as phony because these targets are not real files and we do not want to lie to make):
BIN = bin
SRC = src
CC = gcc
CFLAGS = -O3 -Wall -c -I$(SRC)
LDFLAGS = -L$(BIN)
LDLIBS = -lmyLib
AR = ar
ARFLAGS = rcs
.PHONY: all clean
all: $(BIN)/test.exe
$(BIN)/test.exe: $(BIN)/test.o $(BIN)/libmyLib.a
$(CC) $< -o $# $(LDFLAGS) $(LDLIBS)
$(BIN)/test.o: $(SRC)/test.c $(SRC)/myLib.h
$(CC) $(CFLAGS) -o $# $<
$(BIN)/libmyLib.a: $(BIN)/myLib.o
$(AR) $(ARFLAGS) $# $^
$(BIN)/myLib.o: $(SRC)/myLib.c $(SRC)/myLib.h
$(CC) $(CFLAGS) -o $# $<
clean:
del $(BIN)\*.* /Q
Now, all non-phony targets and prerequisites are regular files, the ones that are really involved in the rules. Again, give it a try and you'll see that make rebuilds only what is out of date and thus needs to be rebuilt.
If you want to get rid of the $(SRC)/ prefix you can use the vpath directive that tells make where to look for source files (I insist on source, many people try to use it for target files, this is not what it is intended for):
vpath %.h $(SRC)
vpath %.c $(SRC)
And then:
$(BIN)/test.o: test.c myLib.h
$(CC) $(CFLAGS) -o $# $<
$(BIN)/myLib.o: myLib.c myLib.h
$(CC) $(CFLAGS) -o $# $<
Note: you could also use the VPATH variable instead of the vpath directive.
Pattern rules are used to factor similar rules, like, for instance, your compilation rules that differ only by the names of the source file and object file:
$(BIN)/%.o: %.c myLib.h
$(CC) $(CFLAGS) -o $# $<
All in all:
BIN = bin
SRC = src
CC = gcc
CFLAGS = -O3 -Wall -c -I$(SRC)
LDFLAGS = -L$(BIN)
LDLIBS = -lmyLib
AR = ar
ARFLAGS = rcs
vpath %.h $(SRC)
vpath %.c $(SRC)
.PHONY: all clean
all: $(BIN)/test.exe
$(BIN)/test.exe: $(BIN)/test.o $(BIN)/libmyLib.a
$(CC) $< -o $# $(LDFLAGS) $(LDLIBS)
$(BIN)/%.o: %.c myLib.h
$(CC) $(CFLAGS) -o $# $<
$(BIN)/libmyLib.a: $(BIN)/myLib.o
$(AR) $(ARFLAGS) $# $^
clean:
del $(BIN)\*.* /Q
Finally, if you really want to avoid the $(BIN)/ prefix in your rules you will have to move to the $(BIN) directory and call make from there. You can leave the Makefile in the main directory and use the -f ../Makefile option, if you wish.
But of course this is less convenient that just typing make [goals] from the main directory. There are ways to let make test from where it has been called, and if it is not from the build directory, re-call itself with the -C and -f options such that it does its job from the build directory. But it is probably a bit too complicated if you are new to make.
If you are however interested have a look at this post that covers this topic (and more). If we simplify as much as possible what the post suggests and specialize it for your case, the final Makefile could be something like:
# here starts the black magic that makes it possible
.SUFFIXES:
BIN := bin
SRC := src
ifneq ($(notdir $(CURDIR)),$(BIN))
.PHONY: $(BIN) clean
$(BIN):
#$(MAKE) --no-print-directory -C $# -f ../Makefile SRC=$(CURDIR)/$(SRC) $(MAKECMDGOALS)
Makefile: ;
% :: $(BIN) ; :
clean:
del $(BIN)\*.* /Q
else
# here ends the black magic that makes it possible
# here starts the Makefile you would really like to write
CC := gcc
CFLAGS := -O3 -Wall -c -I$(SRC)
LDFLAGS := -L.
LDLIBS := -lmyLib
AR := ar
ARFLAGS := rcs
vpath %.h $(SRC)
vpath %.c $(SRC)
.PHONY: all
all: test.exe
test.exe: test.o libmyLib.a
$(CC) $< -o $# $(LDFLAGS) $(LDLIBS)
%.o: %.c myLib.h
$(CC) $(CFLAGS) -o $# $<
libmyLib.a: myLib.o
$(AR) $(ARFLAGS) $# $^
# here ends the Makefile you would really like to write
# a last bit of black magic
endif
The Makefile you would really like to write is what you would write if your source files and target files were all in the source directory. No prefixes any more; vpath takes care of the $(SRC)/ prefix and $(BIN)/ is useless because when this part of the Makefile is used we are already inside $(BIN).
Note: I know nothing about Windows and its various command line interfaces so there are probably some things to adapt (backslashes instead of slashes for instance).

Compile multiple .c files with makefile

I would like to compile multiple .c files at once using a makefile.
I already made this:
CC= gcc
CPPFLAGS = -I.
CFLAGS = -W -Wall -ansi -pedantic
TARGET = test
RM = rm
OBJECTS = xxx.o yyy.o zzz.o
SOURCES = $(OBJECTS:.o =.c)
.PHONY: all clean
all: $(TAREGT)
clean:
$(RM) $(TARGET) $(OBJECTS)
$(TAREGT) : $(OBJECTS)
$(CC) $^ -o $#
$(OBJECTS) : $(SOURCES)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $^
I have no Idea why this does not work("nothing to be done for "all"). Someone has an idea?
This line is creating a circular dependency:
SOURCES = $(OBJECTS:.o =.c)
Try replacing it with this:
SOURCES = $(patsubst %.o,%.c,$(OBJECTS))
You forgot -o $# in your 'sources to objects' rule. Thus it doesn't create anything.
You have also spelling error - your $(TARGET) is 'test', but your 'all' rule depends on $(TAREGT) which is empty. You are also using $(TAREGT) as input to compile 'test'.
You don't need to specify $(SOURCES) or "sources to objects" rule - implicit rules will do the trick.
In fact your "sources to objects" rule is incorrect - it says that each object depends on all sources. If you want each object to depend on one source you should use either suffix rule, pattern rule or static pattern rule. Or just implicit rule.
$(OBJECTS) : $(SOURCES)
The above tells Make that every .o file depends on all sources, i.e. if you change one of your .c files Make will recompile all .o files. Not something what you really want, I guess. I'd rework this rule as follows:
$(foreach s,$(SOURCES),$(eval $(filter %$(basename $(notdir $s)).o,$(OBJECTS)): $s))
This will iterate every source in SOURCES, find corresponding .o file in OBJECTS and create correct rule: <obj>: <source>. It is that complicated to work in case of more complex mapping between source and object files. Say, when building object files in separate directory.
This cryptic code will work even for the following weird source to object file mapping:
SOURCES := a.cpp boo/b.c c.C
OBJECTS := foo/a.o bar/b.o c.o
$(foreach s,$(SOURCES),$(eval $(filter %$(basename $(notdir $s)).o,$(OBJECTS)): $s))
It will generate the following rules:
foo/a.o: a.cpp
bar/b.o: boo/b.c
c.o: c.C
Thank you guys for you help, it is working now
I just added some rules:
CC= gcc
CPPFLAGS = -I.
CFLAGS = -W -Wall -ansi -pedantic
TARGET = test
RM = rm
SOURCES = xxx.c yyy.c zzz.c
OBJECTS = $(SOURCES:.c=.o)
.PHONY: all clean
all: $(TARGET)
clean:
$(RM) $(TARGET) $(OBJECTS)
$(TARGET) : $(OBJECTS)
$(CC) $^ -o $#
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<

My Makefile always builds all files

This is running on FreeBSD which uses PMake instead of GMake.
This is my first Makefile. I used Google a lot to help create this as well as sources such as 'PMake — A Tutorial'. The only problem I can't solve is that every time I run the Makefile, it will compile every file even when there are no changes.
I have four directories. src for my source files, include for my headers, obj for the output and bin for the executable.
What I'm doing is scanning the source folder and creating a list of files to use for both the source and object as well as the headers. Typically I run 'make debug' for debugging and 'make myservice' otherwise.
If I run 'make clean', 'make debug', and 'make debug' it will clean my folders, make all files and then proceed to remake all files instead of doing nothing.
Based on my searching, I'm leaning towards the $(OBJ) rule being the problem, but I don't quite get that. In order for my target and debug rules to build they need to know how to build the objects.
CC = clang
BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include
CFLAGS = -Wall -I/usr/local/include -I$(INCDIR)
LFLAGS = -lm -lpq -lpthread
LIBDIR = -L/usr/local/lib
_SRC != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}
TARGET = myservice
$(TARGET): $(OBJ)
$(CC) -o $(BINDIR)/$# $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
debug: $(OBJ)
$(CC) -g -O0 -o $(BINDIR)/$(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
$(OBJ) : $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
$(CC) -c $< $(CFLAGS)
.PHONY: clean
clean:
rm -rf $(OBJDIR)/*.o $(BINDIR)/$(TARGET)
edit - New Makefile
New Makefile. Doesn't rebuild if no changes. Has no debug, still issues figuring out debug.
CC = clang
BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include
CFLAGS = -Wall -I/usr/local/include -I$(INCDIR)
LFLAGS = -lm -lpq -lpthread
LIBDIR = -L/usr/local/lib
TARGET = $(BINDIR)/myservice
_SRC != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
$(OBJ) : $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJDIR)/*.o $(TARGET)
edit - Working Makefile
Added if conditional for debugging purposes.
CC = clang
BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include
CFLAGS = -Wall -I/usr/local/include -I$(INCDIR)
.if make(debug)
CFLAGS += -g -O0
.endif
LFLAGS = -lm -lpq -lpthread
LIBDIR = -L/usr/local/lib
TARGET = $(BINDIR)/myservice
_SRC != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}
all: $(TARGET)
debug: $(TARGET)
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
$(OBJ): $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJDIR)/*.o $(TARGET)
The second make debug cannot do nothing, debug is phony target, not an actual output file, at least the link phase will be re-run.
Furthermore, re-running the link phase with -g -O0 would not recompile you source files with debug information and no optimizations.
Incidentally, the $(TARGET) rule is a phony rule too, it produces $(BINDIR)/$(TARGET), not $(TARGET).
You should rewrite your makefile with different rules to make object and binary output files in different directories for debug and release modes. gmake patterns make this easy to write, I don't know about pmake or cmake for this purpose.

Makefile for a single target with multiple .c and .h dependencies

I have this hello-world.c that I'd like to compile to hello-world binary. But hello-world.c depends on a few functions defined in ../helpers/a.c and ../helpers/b.c, and each of those helpers include ../helpers/a.h and ../helpers/b.h respectively.
My current Makefile looks like
CC = #gcc
CFLAGS = -g -Wall -Wextra -Werror
CFLAGS +=
LDLIBS =
LDLIBS +=
OBJS = ../helpers/a.o ../helpers/b.o
SOURCES = hello-world.c
DESTS = hello-world
new: clean all
clean:
#rm -rf *.o */*.o $(DESTS)
all: $(OBJS) $(DESTS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
%: %.c
$(CC) $(CFLAGS) -o $# $<
but it doesn't work, returning make: *** No rule to make target `../helpers/a.o', needed by `all'. Stop.
I understand that Makefile doesn't seem to see the rule for %.o, but I don't see why.
Edit: Makefile debug:
alexandernst#stupidbox:/media/sf_procmon/procmon$ make --debug=b
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-pc-linux-gnu
Reading makefiles...
Updating goal targets....
File `new' does not exist.
File `clean' does not exist.
Must remake target `clean'.
Successfully remade target file `clean'.
File `all' does not exist.
File `../helpers/a.o' does not exist.
Must remake target `../helpers/a.o'.
make: *** No rule to make target `../helpers/a.o', needed by `all'. Stop.
This is much easier to get working if you put the Makefile in the parent directory. Then you can write something like this:
CC = gcc
CFLAGS = -g -Wall -Wextra -Werror
CPPFLAGS = -Ihelpers
DESTS = hello-world/hello-world
OBJS = helpers/a.o helpers/b.o hello-world/hello-world.o
# Do not make 'all' depend directly on object files.
all: $(DESTS)
# Clean rules should always be prefixed with '-' to avoid
# errors when files do not exist. Do not use 'rm -r' when
# there shouldn't be directories to delete; do not delete
# wildcards when you can use explicit lists instead.
# Never use '#'.
clean:
-rm -f $(OBJS) $(DESTS)
# An explicit linkage rule is needed for each entry in DESTS.
hello-world/hello-world: hello-world/hello-world.o \
helpers/a.o helpers/b.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
# The main function of these dependency lists is to prevent
# Make from deleting object files after each build. We also
# take the opportunity to specify header dependencies.
# We rely on the built-in %.o:%.c rule for commands.
hello-world/hello-world.o: hello-world/hello-world.c \
helpers/a.h helpers/b.h
helpers/a.o: helpers/a.c helpers/a.h
helpers/b.o: helpers/b.c helpers/b.h
# This tells Make that 'all' and 'clean' are not files to be created.
.PHONY: all clean
For further exposition of this technique, see the watershed paper 'Recursive Make Considered Harmful' and the associated implementation notes.
I managed to fix my Makefile:
CC = gcc
CFLAGS = -g -Wall -Wextra -Werror
CFLAGS +=
LDLIBS =
LDLIBS +=
OBJS = ../helpers/a.o ../helpers/b.o hello-world.o
SOURCES = hello-world.c
DESTS = hello-world
new: clean all
clean:
#rm -rf *.o */*.o ../helpers/*.o $(DESTS)
all: $(DESTS)
hello-world: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
One of the problems was that a bad clean rule that I wrote had wiped a.c and b.c and Makefile was acting because of this.

How to use makefile to compile all sources (some only to object files)?

I'm getting an "undefined reference to main" error on one of my files when trying to compile. I know this is because this file doesn't have a main method. This is just an implementation file for some helper methods, so I only want it compiled to an object file not an executable. I know how to do this if I explicitly tell the makefile what to do for each file, but I'm trying to write a makefile that will compile all of my sources at once. I tried using the -c flag, but then it compiled all of my files to only object files rather than executables. How in the world do I do this?
Here it is:
CC = gcc
CFLAGS = -g -Wall
SRCS = ./src/server.c ./src/client_slave.c ./src/sockaddrAL.c
EXECS = ./bin/server ./bin/client_slave
OBJS = $(SRCS:.c=.o)
all: clean $(SRCS) server client
server: $(OBJS)
$(CC) $(CFLAGS) ./src/server.o -o ./bin/server
client: $(OBJS)
$(CC) $(CFLAGS) ./src/client_slave.o -o ./bin/client_slave
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You should add the -c flag to the rule that builds .o files (your .c.o suffix rule) and not add it to the rule that builds the executables (the $(EXECS) rule).
CC = gcc
CFLAGS = -g -Wall
EXECS = ./bin/server ./bin/client_slave
all: $(EXECS)
./bin/%: ./src/%.o ./src/sockaddrAL.o
$(CC) $(CFLAGS) -o $# $^
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You didn't show sockAddrAL at all in your question so I assumed it belonged in both executables. Also note that the above syntax assumes GNU make. If you want to use only features available in POSIX standard make you pretty much have to write it all out.
Let implicit rules be your friend. Your entire Makfefile should just be:
CC = clang
CFLAGS = -O0 -g -Wall
SRCS = server.c client_slave.c sockaddrAL.c
OBJS = $(SRCS:.c=.o)
EXECS = server
server: $(OBJS)
clean:
#rm -f $(EXECS) $(OBJS)
Invoke it from the src directory.

Resources