Creating a generic makefile - c

I'm trying to create a makefile which would have as little command repetition as possible. Basic idea is to have variable name assigned at the target, like so:
CC = gcc
CFLAGS = -std=c99 -pedantic-errors -Wall
some_target:
P = some_target
some_other_target:
P = some_other_target
...
#common compilation command
$(CC) $(CFLAGS) $(P).c -o $(P).o
So there's only one compilation command which receives variable P which is unique for each target. Obviously example above doesn't work, what do i need to change to make it correct?

This is already built in. The variable $< expands to the first dependency and $^ expands to all dependencies. There is also $? which expands to only those dependencies which are newer than the target. See the documentaion for a full list.
Make already knows how to compile a .c file into an .o file, but if you want to see how it's done, the pattern looks a bit different from yours.
some_command.o: some_command.c
other.o: other.c
%.o: %.c
$(CC) $(CCFLAGS) $< -o $#

Related

Makefile object file generation, variable substitution, and other questions

I'm currently trying to create a Makefile for a c university project, but reading through the tutorials hasn't quite helped me (also, the makefile is not part of the evaluation process, and we aren't taught how to do it)
My objective is making the makefile automatic, so it automatically creates object files from .c files in src (src/*.c), puts the object files in the bin folder, and links them into an executable in the main directory.
project/
bin/
(object files)
src/
(source files)
executable
Makefile
So far, I've roughly put together this makefile and test source code, but it doesn't work the way I intend it to, which I'll explain how just ahead:
#compiler used
COMPILER = gcc
#flags for individual object file compilation
FLAGS = -Wall -ansi -g
#RELEASE
# -Wall -ansi -O3
#DEVELOPMENT
# -Wall -ansi -g
#source .c files
SOURCE = $(wildcard src/*.c)
#object files created
OBJECTS = $(SOURCE:.c=.o)
OBJECTS = $(SOURCE: src/=bin/)
#executable name
EXECUTABLE = app
############################################################
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(COMPILER) $(FLAGS) -o $(EXECUTABLE) $(OBJECTS)
%.o: %.c
$(COMPILER) $(FLAGS) -c %< -o %#
The result is the following command:
user#user-lenovo:~/Desktop/C Projects/AED/project$ make
gcc -Wall -ansi -g -o app src/main.c src/test.c
Ironically, it works, but really shouldn't. It also defeats the purpose of having a makefile, as everything is compiled again once one change is detected.
First of all, what I noticed is OBJECTS directly copied SOURCE, and didn't substitute .c for .o, or src/ for bin/. I've tried substituting the '=' for ':=' but the result is the same, and I don't quite understand what the difference between them is in the first place. My idea would be src/main.c becoming bin/main.o, for example.
%.o: %.c
$(COMPILER) $(FLAGS) -c %< -o %#
This part is my also failed attempt at generating all the object files individually with a single target. I tried reading up on it, but couldn't figure out how these work: '%<', '%#' or the '%.o' and '%.c'
I do believe it isn't being run at all though, since no object files showed up.
I hope you can help me fix this mess up, thanks in advance!
OBJECTS = $(SOURCE:.c=.o)
OBJECTS = $(SOURCE: src/=bin/)
You're assigning to OBJECTS twice there - the first result gets overwritten by the second which doesn't work. You want to combine them into one statement like this
OBJECTS=$(SOURCE:src/%.c=bin/%.o)
Your next problem is you need to tell make that "bin/whatever.o" is built from "src/whatever.c". Currently it'll look for "whatever.c" in "bin/"
So your recipe for building .o files needs the directories added
bin/%.o: src/%.c
$(COMPILER) $(FLAGS) -c $< -o $#
You also should have $# instead of %# and $< instead of %<
Automatic variables are expanded with the $ prefix, as any other variable, not %.
As your object and source files are in different directories you cannot simply %.o: %.c.
Try:
CC = gcc
CFLAGS = -Wall -ansi -g
OBJECTS = $(patsubst src/%.c,bin/%.o,$(SOURCE))
bin/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $#
Note: the standard make variable for the C compiler is CCand CFLAGS for the flags. It is better to use them.

Makefile for C Program

I am trying to use this Makefile for a C Program. Could you please share with me a way how I can understand the Make utility better? I am trying the following:
# stack/Makefile
CC := gcc
CFLAGS += -std=c99
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -g
VPATH = main src
all: bin/main.exe clean run
bin/main.exe: bin/main.o bin/stack.o
$(CC) -o $# $^ $(LDFLAGS) $(LDLIBS)
bin/main.o: main.c
bin/stack.o: stack.c stack.h
bin/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
demo:
../bin/main.exe
clean:
rm -f bin/*.o
run:
bin/main.exe
.PHONY: all clean run
And I getting this message:
gcc -std=c99 -Wall -Wextra -g -c -o bin/main.o main.c
error: unable to open output file 'bin/main.o': 'No such file or directory'
1 error generated.
make: *** [bin/main.o] Error 1
The error stems from the fact that your Makefile wants to
generate the executable and object files in subdirectory bin but it
contains no rule to ensure that bin exists when it is
needed. As #JonathanLeffler comments, you can solve that
just by manually creating bin yourself.
But it is often desired that a Makefile itself will ensure
that a subdirectory, or some other resource, exists when it
is needed, and you probably assumed that the pattern-rule
bin/%.o: %.c
would create bin as needed. It won't.
Your Makefile can ensure the existence of bin if you
amend it like this:
Somewhere below the all rule, add a new target:
bin:
mkdir -p $#
This is to make the bin subdirectory if it doesn't exist.
Then change the rule:
bin/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
to:
bin/%.o: %.c | bin
$(CC) $(CFLAGS) -c -o $# $<
The additional | bin is an example of an order-only prequisite
It means: If any of the targets (the bin/%.o things) needs to be remade from any of preceding prequisites (the ones before |, i.e. the %.c
things), then bin must be made first. So, as soon as anything needs to be made in bin, bin will be made first.
There is another more basic flaw in your Makefile. all is dependent on clean, so every time you successfully build
your program the object files are deleted. I understand that you intend this, but it entirely
defeats the purpose of make, which is to avoid the need to rebuild everything (object files, executables) every
time by instead just rebuilding those things that have become out-of-date with respect to their prerequisites.
So all should not depend on clean, and then an object file will be recompiled only if it needs to
be recompiled, i.e. is older than the corresponding source file. If and when you want to clean out the
object files, run make clean.
Finally, your demo rule:
demo:
../bin/main.exe
is inconsistent with the others. The others assume that the bin where the executable
is put is in the current directory. The demo rule assumes it is in the parent of
the current directory. If you correct the demo rule then it will be identical to
the run rule, so it is superfluous, but if it were not superfluous then it should
be added it to the .PHONY targets.
The best way to learn the proper way to use makefiles is to read the manual. Also, you can Google for some simple tutorials.

Creating a Makefile in Raspbian

I'm trying to create a Makefile for my C program in Raspbian (Raspberry Pi).
My program consists of a bunch of .c and .h Files. I've looked at countless Makefiles, but I just don't unterstand how it works with multiple files. There are always .o files in the Makefile but as I understand object files are the result of compiling, so I dont have any o. Files as I am trying to compile my .c Files.
Please explain to me how this works.
Edit:
Thank you. So I tried this and it starts compiling but there are errors 'multiple definition'. Example:
These are my Files:
main.c main.h
calibration.c calibration.h
file.c file.h
frame.c frame.h
gamepad.c gamepad.h
gpio.c gpio.h
uart.c uart.h
types.h
this is my makefile:
all: main
main: main.o calibration.o file.o frame.o gamepad.o gpio.o uart.o
%.o: %.c
gcc -c -std=c99 -Wall $< -o $# -lncurses
Where can i put 'types.h'?
With every file I get errors 'multiple definitions'
A very simple but typical makefile could look like this
SOURCES = source1.c source2.c source3.c
OBJECTS = $(SOURCES:%.c=%.o)
TARGET = myExecutable
$(TARGET): $(OBJECTS)
gcc $^ -o $#
%.o: %.c
gcc -c $< -o $#
The complicated parts:
SOURCES = source1.c source2.c source3.c This is a variable definition, it assigns the string "source1.c source2.c source3.c to the variable SOURCES.
$(SOURCES:%.c=%.o) This is a shorthand for the patsubst text function. It takes all text from the $(SOUCES) variable, and replaces the pattern %.c with %.o, i.e. it takes e.g. the string source1.c and replace it with source1.o.
$(TARGET): $(OBJECTS) This makes myExecutable depend on all object files, meaning if one object file is modified then the command in the rule will be executed.
gcc $^ -o $# This calls the gcc command, passing all dependencies ($^) as arguments (that is, all object files), and tells gcc to output a file with the name of the target ($#).
%.o: %.c This is the rule that makes object files depend in their source file. So if you have source1.c then source1.o will depend on that source file.
gcc -c $< -o $# This is the command that compiles the source file (the first dependency, $<) to an object file (with the -c option) and name it as the target of the rule ($#).
Also note that if you invoke make without a specific target, then the first rule will be selected. In the case of the above makefile, it will be the $(TARGET): $(OBJECTS) rule which will make sure that all object files are build from the source files, and then link the object files into the resulting executable.
The basic syntax of a make rule is:
target … : prerequisites …
recipe
…
…
On the left of the semicolon are the targets. The targets are your object files(.o). On the right of the semicolon are the files that you will need to create this file. Those files are the source files(.c).
Lets give a basic example of what such a rule could look like.
%.o: %.c
gcc -c $< -o $#
The % sign is a wildcard. %.o means everything that ends with .o. So, if you want to make an object file, you can say make file.o, and make will try to find a rule with which it can make this target. This happens to be the rule I just showed as an example, because file.o matches %.o.
Then the recipe. This is what will be executed. Usually it's about invoking the compiler(gcc), and feeding it the source file to generate the object file. That's what we do with gcc -c $< -o $#. The $< and $# mean target and prerequisites respectively.
So, what happens when you 'just' want to build your program? You usually will type make, and it will build. The default rule that's used when you type make, is all. So, if you make a rule about all, then you can specify what files you want to create to build your program. Example of such a rule:
all: main
Then, when make is invoked, it will find that rule and finds out it needs main. To create main you need another rule:
main: file.o
This rule says that to build main, you need file.o. So, when you put all of the example rules together you get this:
all: main
main: file.o
%.o: %.c
gcc -c $< -o $#
Note that you can specify more than one file, so instead of file.o, you can say file.o main.o other_file.o etc. Every prerequisite that you specify will be made, if they can find a rule to make it.

Using the make command without makefiles?

I was compiling some C code for an assignment and I ran "make codeFile", where "codeFile" was the name of my C program, and even though I didn't have a makefile, an executable was created, and it ran and worked correctly.
Does anyone know why this worked? Why does make compile something even if I don't have a makefile? The only reference I could find was this:
http://daly.axiom-developer.org/TimothyDaly_files/class5/node5.html
Make has an internal database with implicit rules. You can use make -p to list them. Also make -d will tell you which rules are being applied, so that would help you discover which implicit rules are being used in this case.
Make has several pre-defined implicit rules. In particular, in your case, it uses two such rules when trying to determine what to do for the target codeFile:
%: %.o # Link object file
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
%.o: %.c # Compile C source code
$(CC) $(CPPFLAGS) $(CFLAGS) -c
Using the make command without makefiles?
make has implicit rules that work as defaults unless you override them.
According to the make man page:
make -p -f/dev/null
will list all of the implicit rules (and relevant environment variables) without attempting to actually remake files.
To demonstrate the usage, I ran make in Cygwin, which gave me an exe file. Note no .c on the name passed to make:
$ ls
hello.c
$ make hello
cc hello.c -o hello
$ ls
hello.c hello.exe
I also ran this in Ubuntu Linux, and my result was nearly the same as above, but the .exe extension was not there, instead I had the plain hello executable:
$ ls
hello.c hello
Step by step derivation
I believe the relevant pieces of the make implicit rules are as follows:
CC = cc
cc is aliased to CC
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
a LINK format is created, where the flags will be empty, and the TARGET_ARCH variable is also empty (to allow users to set values for various target architectures.) Then we have:
%: %.c
# recipe to execute (built-in):
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $#
The ^ variable is the prerequisite, hello.c. The other variables are empty. These are followed by the -o flag and the target name. The empty variables explain the extra spaces in the command make ran:
cc hello.c -o hello
And the %: %.c matched the target given to make with the filename of the same target name ending in .c, which caused the recipe to execute.

makefile aliases [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
makefile aliases
Please explain $# $^ in the makefile below
LIBS = -lkernel32 -luser32 -lgdi32 -lopengl32
CFLAGS = -Wall
# (This should be the actual list of C files)
SRC=$(wildcard '*.c')
test: $(SRC)
gcc -o $# $^ $(CFLAGS) $(LIBS)
These are special variables:
$# means the target so in your case it is test.
$^ means the names of all the prerequisites, with spaces between them. In your case its the list of all the .c files.
SRC=$(wildcard '*.c') makes use of the wildcard function to get the list of all the .c files in the directory, which is then assigned to the variable SRC.
Lets say there are two C source file foo.c and bar.c. Your makefile effectively gets expanded to:
test: foo.c bar.c
gcc -o test foo.c bar.c -Wall -lkernel32 -luser32 -lgdi32 -lopengl32
(Just in case some of the other great explanations didn't quite hit the spot)
The "make" program allows you to use, what are called automatic variables. For every rule that it executes the action for, it parses the shell statements specified in the action, and expands any of these automatic variables that it finds. The variables expand to values in the context of the particular rule being executed at that point.
So, in your case, the rule being executed is:
test: $(SRC)
In this rule, "test" is the target, and whatever $(SRC) expands to, are the dependencies. Now, as "make" parses the following shell statement specified in the action part of the rule,
gcc -o $# $^ $(CFLAGS) $(LIBS)
it recognizes $# and $^ as automatic variables. $# is expanded to the target for the current rule, and $^ is expanded to the dependencies, which is "test" and expansion of $(SRC), respectively. It executes the shell statements after the variables have been expanded. You can see the final expanded version that is executed by watching the output of "make".
$(SRC) will, in turn, expand to the result of the "make" function "wildcard". Keep in mind that the syntax for a function call in "make" is $(function param ...), and is expanded to the result of the function call, in this case the list of files with ".c" as the suffix.
SRC is equal to a wildcard function in gnu make. It is a list of files that match that path. For example, it could be
SRC=a.c b.c
For the rule, it depends on all the source files, and the target is test, so we can expand the rule as follows:
gcc -o $# $^ $(CFLAGS) $(LIBS
gcc -o test $(SRC) $(CFLAGS) $(LIBS)
and then following up by replacing CFLAGS, LIBS and SRC with the correct expansions.
For some documentation on this, take a look at this: http://www.gnu.org/software/autoconf/manual/make/Automatic-Variables.html

Resources