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

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.

Related

Automatic rebuilding dependencies (makefiles)

I have a huge project which is compiled with GCC.
I know that usually preforming build should rebuilds all not up-to-date dependencies but some of the .h files that we change does not cause rebuilding of the files which uses them. There is a hierarchy of make files, the main make file include the needed make file according to the need.
is there a way to insure rebuilding of the files which "#include" recently modified .h files?
You have to make sure that your header-files are correctly listed in the prerequisites. For large projects, it's not feasible to do this by hand, but the combination of gcc (or clang) and GNU Make gives you a powerful way to automate it.
Assuming you have some pretty standard Makefile using pattern rules:
CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -pedantic
OBJS := main.o module.o
all: program
program: $(OBJS)
$(CC) -o$# $^
%.o: %.c
$(CC) -c $(CFLAGS) -o$# $<
clean:
rm -f *.o
.PHONY: all clean
Then you can use the automatic remaking of Makefiles capability of GNU Make to include files adding additional prerequisites that are generated by gcc:
CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -pedantic
OBJS := main.o module.o
all: program
program: $(OBJS)
$(CC) -o$# $^
# rule to create "dependency files", make the dependency file itself
# depend on the same prerequisites
%.d: %.c
$(CC) -MM -MT"$# $(#:.d=.o)" -MF$# $(CFLAGS) $<
# include dependency files except for targets not building anything
ifneq ($(filter-out clean,$(MAKECMDGOALS)),)
-include $(OBJS:.o=.d)
endif
# add Makefiles themselves to prerequisites here (with a changed Makefile,
# the only safe thing is to rebuild all):
%.o: %.c Makefile
$(CC) -c $(CFLAGS) -o$# $<
# remove dependency files on clean
clean:
rm -f *.o *.d
.PHONY: all clean
This is just an example, there are a lot of possibilities how you could use these features.

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 $<

makefile makes weird error

So I wrote a program to calculate Caesar cipher but I think it's not really matter - what matter is that when I'm trying to do make the compiler or who checks the syntax of my makefile is throw an error says :
make: *** No rule to make target 'clean.', needed by 'PHONY'. Stop.
In my directory I have 5 files:
main.c
ceasar.c
ceasar.h
parser.c
parser.h
and the makefile looks like:
PHONY : all clean.
CFLAGS = -c -g -Wall
CXXFLAGS = -o
CC = gcc
OBJECTS = main.o ceasar.o parser.o
EXTRA_SRCS = ceasear.h parser.h
all : ex1
ex1 : $(objects)
$(CC) $(CXXFLAGS) ex1 $(objects)
%.o : %.c $(wildcard $(EXTRA_SRCS))
$(CC) $(CFLAGS) $<
clean:
rm *.o
The makefile should clean the objects files when typed make clean
and the line $(wildcard $(EXTRA_SRCS)) should checks if the c file has header file(parser and caeser, not main).
I'm using ubuntu 15.10 and please help me :)
It's possible to specify fictitious target that has as purpose to execute a sequence of operations. These targets do not specify any dependency and must not appear as the first rule, to be carried out only if they are passed as arguments to make command explicitly. Fictitious target is not a file (the file does not exist) it is used to initiate the execution of the command in each case.
CFLAGS = -c -g -Wall
CXXFLAGS = -o
CC = gcc
OBJECTS = main.o ceasar.o parser.o
EXTRA_SRCS = ceasear.h parser.h
all : ex1
ex1 : $(objects)
$(CC) $(CXXFLAGS) ex1 $(objects)
%.o : %.c $(wildcard $(EXTRA_SRCS))
$(CC) $(CFLAGS) $<
.PHONY: clean
clean: rm *.o
Be careful because the fictitious target may be masked by existing files: if accidentally in the directory it creates a file called the same name of the fictitious target then, as the target has no dependencies, and the file already exists, that file does not need to be updated and then the command list will never be executed.

GDB doesn't see source files other than main, caused by makefile?

I have a semi-large project that I am trying to debug and for some reason gdb is only willing to show the source code of the main.c file and refuses to list any of the other files.
Here are the relevant lines in my makefile:
DEFINES= #...
BASE_CFLAGS= #...
BASE_LIBS= #...
#Load the required source files
HEADERS=$(wildcard *.h) $(wildcard subdir/*.h)
SOURCES=$(HEADERS:.h=.c)
OBJECTS=$(SOURCES:.c=.o)
#Flags for each compilation type
CFLAGS=-Wall $(DEFINES)
main: CFLAGS+=$(BASE_CFLAGS) $(BASE_LIBS)
debug: CFLAGS+=$(BASE_CFLAGS) $(BASE_LIBS) -g -DDEBUG_MODE
#Compilation rules for objects
%.o: %.c %.h
$(CC) -c $(CFLAGS) $< -o $#
#main compilation
main:$(OBJECTS) main.c
$(CC) main.c $(OBJECTS) $(CFLAGS) -o ../main.out
#debug compilation
debug:$(OBJECTS) main.c
$(CC) main.c $(OBJECTS) $(CFLAGS) -o ../debug.out
clean:
rm $(OBJECTS)
For some reason when I run make debug then try to debug the resulting output it acts as though main.c is the only file compiled with the -g flag even though I ran make clean beforehand and inspected make's output to ensure that it did compile each object with the -g flag.
Before my most recent change I had a Makefile that looked more like this:
DEFINES= #...
BASE_CFLAGS= #...
BASE_LIBS= #...
#Load the required source files
HEADERS=$(wildcard *.h) $(wildcard subdir/*.h)
SOURCES=$(HEADERS:.h=.c)
OBJECTS=$(SOURCES:.c=.o)
#main compilation
main:$(SOURCES) main.c
$(CC) $(SOURCES) main.c -Wall $(DEFINES) $(BASE_CFLAGS) $(BASE_LIBS) -o ../main.out
#debug compilation
debug:$(SOURCES) main.c
$(CC) $(SOURCES) main.c -Wall $(DEFINES) $(BASE_CFLAGS) $(BASE_LIBS) -g -DDEBUG_MODE -o ../debug.out
Which was obviously less efficient than my new solution but it did have a few advantages. Firstly I didn't have to run make clean between each main and debug compilation (I actually have a total of 8 different compilation rules, so having to clean between most of them to get the individual sources to be recompiled with the new options is a pain). Secondly and most importantly, GDB was able to see all of the source files when I ran the debug compilation. Now, as I said, it can only see main.c and lists the rest as "No source file named ???.c".
Therefore I have two questions:
(not really important) Is there a way to compile each source independently, but force them to be recompiled with new options when a different compilation rule is selected in make.
(very important, please help!) Why can't gdb see my other source files and what can I do to have it load them?
the following makefile can be invoked with make or with make -Ddebug depending on if you want to produce the main.out file or the debug.out file.
Note: the <tab> will need to be replaced with an actual tab char in your makefile
CC := /usr/lib/gcc
RM := /usr/lib/rm
ifndef debug
target := main.out
debugInfo :=
else
target := debug.out
debugInfo := -g -DDEBUG_MODE
endif
#Load the required source files
HEADERS=$(wildcard *.h) $(wildcard subdir/*.h)
SOURCES=$(HEADERS:.h=.c)
OBJECTS=$(SOURCES:.c=.o)
#Flags for each compilation type
CFLAGS+= $(debugInfo) -c -Wall -Wextra -Wconversion -std=gnu99
.PHONY : all
all : $(TARGET)
$(TARGET):$(OBJECTS)
<tab>$(CC) $(debugInfo) $^ -o $# $(LFLAGS)
#Compilation rules for objects
%.o:%.c %.h
<tab>$(CC) $(CFLAGS) $< -o $#
.PHONY : clean
clean:
<tab>$(RM) $(OBJECTS)

I need some assistance with Makefile in my project

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.

Resources