So here is a Makefile I have been given, with comment I have added.
MF= Makefile_c #name of the makefile
CC= cc #compiler to use
CFLAGS= -g #flags to use
LFLAGS= -lm #flags to use after the thingy
EXE= hello #name to give the executable
INC= \ # ??? What's this for ???
# No user-defined include files at present - list here if required.
# name of the source file
SRC= \
hello.c
#delete default suffix
.SUFFIXES:
#define the suffixes we are interested in
.SUFFIXES: .c .o
OBJ= $(SRC:.c=.o) # names to give the object files
#The .o files depend on the .c files. Compile the object files.
.c.o:
$(CC) $(CFLAGS) -c $<
all: $(EXE) #The output is the executable
$(OBJ): $(INC) #The objects depend on whatever INC is
# The executable depends on the object files. build it from the object files.
$(EXE): $(OBJ)
$(CC) $(CFLAGS) -o $# $(OBJ) $(LFLAGS)
# ??? the object files depend on the makefile???
$(OBJ): $(MF)
# remove any old executables or object files.
clean:
rm -f $(OBJ) $(EXE) core
I am still learning about makefiles so please correct me if I have misidentified anything. The makefile works fine But I want to adapt it to work with my program that has multiple files and header files. I suspect that the variable $INC will somehow make this possible, but so far my attempts to use it have not worked.
For now I would like to understand what this makefile is trying to do, cn you tell me what $INC is for?
The makefile works fine But I want to adapt it to work with my program that has multiple files and header files. I suspect that the variable $INC will somehow make this possible
Unfortunately, no. The \ is just a line continuation, so you can write content for the variable in the next line. It's empty here. This is just a very simple (and ancient!) approach for dependencies: List them yourself. The intention is to list all files your C source file #includes there, so make will rebuild when any of these included files change.
There are much advanced patterns, gcc (and other compilers) allow to do automatic dependency information for make, but this is out of scope for this question. (*)
As for building with multiple source files, this Makefile already supports it, again using an "ancient" way, a suffix rule. It automatically considers all .c files in your directory part of your final program.
(*) As mentioned by Tormund Giantsbane in the comments, this document has nice information on the topic auf automatic dependencies
Related
This question already has answers here:
Makefile issue: smart way to scan directory tree for .c files
(4 answers)
Closed last year.
I need to create a static library using source files in different directories. I am able to create static library by specifying each and every source file in the Makefile. It increased more content in the Makefile.
Let me explain what I did with an example:
#Specifying the each and every source files to FILES is more complex to me. Trying to find out alternative to this problem
Files = Source1\A.c Source\B.c Source2\C.c Source3\D.c ........... Sorce3/Z.c
$(OUT_FILE_NAME): $(patsubst %.c,%.o,$(wildcard $(FILES)))
ar -r -o $# $^
#Compiling every *.c to *.o
%.o: %.c dirmake
arm-none-eabi-gcc -c -o $# $<
I'm trying to explore alternative way to specifying all source files in the Makefile. This will help us to not modify this Makefile again if any new source file added. Is it possible to do that?
I tried to search for this problem and many sources explain how to create static library but I don't see any alternative solution for this problem.
Without knowing the details of your development environment I would try these minimal changes first. Using the wildcard-function for the source directories will enable you to add more sources without having to edit the Makefile every time. Just keep the directories clean of any unused c-files to avoid including stuff in your library that you don't want.
I have also made the Files variable simply expanded (evaluated once) by using := for assignment. I also simplified the prerequisite of the first rule and fixed the case of the variable-name.
Files := $(wildcard Source1/*.c) $(Source2/*.c) $(Source3/*.c)
$(OUT_FILE_NAME): $(patsubst %.c,%.o,$(Files))
ar -r -o $# $^
#Compiling every *.c to *.o
%.o: %.c dirmake
arm-none-eabi-gcc -c -o $# $<
I am working on project, where i use couple of .c and .h files.
I created Makefile where i actualize executable program based on changes in all of these files.
Problem is, when i use make, program is compiled, but when i execute program, it runs without any change. I need to save ( working in vim so :w ) all included files, even when i changed only one.
If i don't save all these files, program is compiled, but executes the same thing as it did before change.
Could someone explain me why is that ?
Makefile code :
CC=gcc
CFLAGS=-WALL
execFile: execFile.o functions.h newDataTypes.h
Thank you.
The reason you are not getting execFile updated is because you're NOT updating it. Or at least you don't seem to be in this particular case.
There are many ways to get about doing this. However since you are using gcc and I assume you're using gnu make the following is probably the best solution you can execute1.
Given the files:
-rw-r--r-- 1 user sudo 73 Nov 4 22:54 exeFile.c
-rw-r--r-- 1 user sudo 74 Nov 4 22:54 exeFile.h
-rw-r--r-- 1 user sudo 90 Nov 4 22:55 hello_world.c
-rw-r--r-- 1 user sudo 888 Nov 4 23:03 Makefile
cat exeFile.c
#include <stdio.h>
#include "exeFile.h"
int main()
{
hello_world();
}
exeFile.h
#ifndef _EXEFILE_H
#define _EXEFILE_H
extern void hello_world();
#endif
hello_world.c
#include <stdio.h>
#include "exeFile.h"
void hello_world()
{
printf("Hello World\n");
}
you can set up a make file that generates dependencies and ensures that the program will always be compiled correctly:
CC=gcc
CFLAGS=-Wall
SOURCES=exeFile.c hello_world.c
EXE=exeFile
OBJ=$(SOURCES:%.c=%.o)
DEPDIR := .deps
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = #mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $#
%.o: %.c
%.o: %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cc
%.o : %.cc $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cxx
%.o : %.cxx $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
$(EXE): $(OBJ)
$(CC) -o $# $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) $(EXE)
dev-clean: clean
$(RM) -r $(DEPDIR)
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SOURCES))))
Let's go over the relevant parts about dependencies
DEPDIR =
This implementation places dependency files into a subdirectory named .deps .
$(shell mkdir -p $(DEPDIR) 2>/dev/null)
GCC does not create subdirectories for output, this line ensures that the DEPDIR directory always exists.
DEPFLAGS = ...
These are GCC-specific flags which tell the compiler to generate dependency info.
-MT $#
Set the name of the target in the generated dependency file.
-MMD
Generate dependency information in addition to compiling. -MMD omits system headers from the generated dependencies: if you prefer to preserve system headers as prerequisites, use -MD instead.
-MP
Adds a make target for each prerequisite in the list, this avoids errors when deleting files.
-MF $(DEPDIR)/$*.Td
Write the generated dependency file to a temporary file $(DEPDIR)/$*.Td e.g. hello_world.c will generate hello_world.Td as temp dependency content for use in Makefile.
POSTCOMPILE = ...
First rename the generated temporary dependency file to the real dependency file. We do this in a separate step to side-step compile errors. Next we explicitly touch the files to avoid a gcc bug.
%.o : %.c
Delete the built-in rules for building object files from .c files, so that our rule is used instead. Do the same for the other built-in rules.
... $(DEPDIR)/%.d
Declare the generated dependency file as a prerequisite of the target, so that if it’s missing the target will be rebuilt.
$(DEPDIR)/%.d: ;
Create a pattern rule with an empty recipe, so that make won’t fail if the dependency file doesn’t exist.
.PRECIOUS: $(DEPDIR)/%.d
Mark the dependency files precious to make, so they won’t be automatically deleted as intermediate files.
include ...
Include the dependency files that exist: translate each file listed in SOURCES into its dependency file. Use wildcard to avoid failing on non-existent files.
1 See Auto-Dependencies Generation for details.
Fix:
Tell make that the executable depends only on the object file and the object file depends on the header files:
execFile: execFile.o
execFile.o: functions.h newDataTypes.h
Explanation:
In order to build your executable two steps are needed:
compilation of C source files (that include header files) to produce object files,
linking of the object files to produce the executable.
So, when changing your header files you must re-compile, that is re-built the object files, not just re-link that would produce the same executable from the same object files.
In your Makefile the dependencies are not properly defined. You did not tell make that the object file (execFile.o) shall be rebuilt when your header files change. Instead, you told it that the executable (execFile) shall be rebuilt.
First of all, your dependencies are mistaken. Your executable does not depend on the .h header files, as they are using only at compilation time. The dependencies are normally between .o files and .h files, as when you modify one .h file, the including .c file must be compiled to generate the .o file. so in case you have execFile.o (which, on lack of complete information, I'll suppose it depends on execFile.c, which #includes functions.h and newDataTypes.h, the rule should be:
execFile.o: execFile.c functions.h newDataTypes.h
As it has been pointed out in other responses, there's no need to write the command to build the .o file, as there is a default rule like this:
.c.o:
$(CC) $(CFLAGS) -o $# -c $<
(observe there's a -c option to the compiler indicating to compile only and don't link, we'll return here below) which means that once you detect the .o is outdated (as the dependencies on .c and .hs mark) it will be compiled with the above command, which result in:
gcc -Wall -o execFile.o -c execFile.c
making the appropiate compilation.
Other thing is the dependencies of the executable file. These have to be included, as make(1) doesn't know which object files form your final executable. In this case, assuming you have your program execFile depend on execFile.o and a.o, b.o and c.o, I normally use to write:
execFile_objs = execFile.o a.o b.o c.o
execFile: $(execFile_objs)
$(CC) $(LDFLAGS) -o $# $(execFile_objs)
so any of the .os is changed (because an indirect change in a source file) the whole program is linked again (but only the touched files are compiled)
NOTE
In the case (not normal) that you have a Makefile to create a program that has only one source file and several include files you can compile each time the whole thing each time you modify one source file, in this way:
execFile: execFile.c functions.h newDataTypes.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# execFile.c
This will execute
gcc -Wall -o execFile execFile.c
Observe that there is no -c (compile only, don't link) option in this command.
There's no mention of the include files (they are included because of the #include directives in the code... and you only state here that the executable depends also (and have to be built) in case any of the .h files are modified.
Automatic dependency rules are a little confusing at first, as they induce you to think there are such rules to make any kind of file from any other kind of file (well, there are for .c -> .o files, and .c -> <nothing> to compile directly to an executable) normally you have to include dependencies in such cases when your target depends on more files than the automatic rule states. In such cases, it is very important not to include any command, so the compiler selects the automatic rule (when you don't include a command to generate the target, the make(1) program tries to use a default rule for it, or nothing at all if you have not included commands, it only assumes your dependencies are indirect through this fake target --- and, as this fake target is not built in the process, it will fail always and be followed)
I am working on a C project which contains around 200 .c files and some .h files. Not all of these 200 files are required in the final product. Currently around 180 files needs to be compiled. We have a file "compile_only_these.c" which includes these 180 *.c files required for the project. Our makefile compiles only this file instead of individual .c files.
/* file: compile_only_these.c*/
#include "file1.c"
#include "file2.c"
.
.
.
#include "file180.c"
But I think including .c files is a bad idea. Because every time I modify any of these files, all files are compiled again.
Can you suggest a better way to compile these files.
More info:
All .c files are in same folder "../project/src"
I keep adding new .c files which are required to be compiled. I dont want to modify Makefile every-time I add a new file.
I still want to keep those 20 .c files which I am not compiling right now. I may use it in future. Deleting these files are moving them to other directory is not a solution
What you need is a variable in the makefile, a list of required object files, like this:
OBJS := file1.o file2.o ... file180.o
You can have Make construct it from the compile_only_these.c file like this:
OBJS := $(shell sed -e '/\#include/!d' -e 's/\#include "\(.*\)\.c"/\1.o/' compile_only_these.c)
Do you also need a hand with the rule that uses these objects to construct the final product?
As already mentioned, it's sort of a weird way to manage a project, but given what you have to work with, you might try something along this approach...
CC = gcc
OBJFILE = myprog
# Tweak to match whatever you compile with normally
CFLAGS = -O2 -Wall -std=c89 -pedantic
LDFLAGS= # Extra flags here, for example -lm -pthread
RM = rm -f
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
$(OBJFILE):$(OBJS)
$(CC) -o $# $^ $(LDFLAGS)
clean:
$(RM) core *~ $(OBJS) $(OBJFILE)
You will obviously need to adjust the path(s) for the specifics of your build hierarchy if you want to do more in your make than just compile this list of files, but this is a general approach for grabbing all files with wildcard substitution.
I have implemented a binary tree program which includes the tree.c with the functions, the tree.h with the declarations of them and a main.c for testing.
Also, I have a makefile which is:
CC=gcc
CFLAGS=-g -Wall
DEPS = tree.h
OBJ = main.o tree.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
tree: $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
clean:
rm -f *.o tree
Now I want to make it generate a library not only an object file for the binary trees functions and afterwards to generate the documentation of doxygen inside the makefile. Any help would be helpful.
I know that my answer comes in a bit late, but i hope someone will benefit from this.
I have a makefile that generates Doxygen doc.
You have to twist Doxygen a tiny bit
Create the Doxygen setup file that fits Your need, then open that in an editor and remove the lines containg the following two settings (they will be added by the make file later)
INPUT
FILE_PATTERNS
add this line
#INCLUDE = doxyfile.inc
Save this file under a different name I use Doxyfile.mk
in You makefile You need a list of sources and the directories where they are located
example
SRCS = $(OBJS:.o=.c)
SRCDIRS = ./src
SRCDIRS += ./other_src
Now You can put this rule in the Makefile, it will create the file doxyfile.inc that contains the settings You removed from Doxyfile.mk.
.PHONY: all clean distclean doxy
# If makefile changes, maybe the list of sources has changed, so update doxygens list
doxyfile.inc: Makefile.mk
echo INPUT = $(SRCDIRS) > doxyfile.inc
echo FILE_PATTERNS = *.h $(SRCS) >> doxyfile.inc
doxy: doxyfile.inc $(SRCS)
doxygen.exe doxyfile.mk
Bonus: If run from inside an IDE like Eclipse the errors that Doxygen spits out becomes clickable and will jump to the bad comment.
Well, I don't really know the syntax for the doxygen command, so I'll make a generic answer:
in your Makefile, each
term: [dep]
action
is a target.
So if you add something like:
doc: $(OBJ)
doxygen with-correct-options
You will be able to generate the documentation using:
make doc
(doc being here the name of the target)
Now, if you add:
all: tree doc
#echo "Generating program and doc."
you will have the program and the documentation generated with simply invoking
make
In the end, there is an additional statment your Makefile could have use of: .PHONY. It's "A way to mark one of many targets as not directly producing files, and ensure their execution even if a file having the same name as the target exists". In other terms, it's to make sure doc, clean or all will always be executed even if files named doc, clean or all exist.
Its syntax is the following:
.PHONY: all clean doc
And is usually put at the end of the Makefile.
This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $#
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $# -c $<
# Now create a static library
all: $(OBJS)
#$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.
There are two different mechanisms for handling header files at work here:
When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.
When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.
If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:
A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.
B) You can tell Make where to find the header files:
vpath %.h inc my/inc/path
(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)
I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?
I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.
All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.