Bypass default rule for make - c

I'm trying to compile several .c files through assembler:
%.S: %.c
$(XCC) -S -o $# $(XCFLAGS) -c $<
%.o: %.S
$(XCC) -o $# $(XCFLAGS) -c $<
test.a: test.o foo.o
$(LD) -o $# $^ $(XLDFLAGS)
$(XCC) is a cross-compile tool.
Actually, I see:
cc -c -o test0.o test0.c
cc -c -o foo.o foo.c
Native compilation runs instead of required cross compilation. I looks like some default rule for %.c to %.o translation is used instead of described chain rule.
If I change one pattern to direct description, compilation is ok:
test.S: test.c
$(XCC) -S -o $# $(XCFLAGS) -c $<
foo.S: foo.c
$(XCC) -S -o $# $(XCFLAGS) -c $<
%.o: %.S
$(XCC) -o $# $(XCFLAGS) -c $<
What is wrong with pattern chain? Is it possible to disable default rule for %.o ?

There is a default rule to generate .o files from .c files. That rule gets invoked when the first makefile is used.
You could add the following to the makefile to override the default rule:
%.o: %.c
$(XCC) -S -o $*.S $(XCFLAGS) -c $<
$(XCC) -o $# $(XCFLAGS) -c $*.S
You can also use:
%.o: %.c
without any recipes under it. This will invoke the other two rules to create the .S file and the .o file from there. However, it will delete the intermediate .S file after the .o is created. To prevent the .S file from getting deleted, you can use:
.PRECIOUS: test.S foo.S
You can read more on this subject at https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html#Implicit-Rules.

You can keep your rules and just cancel the builtin rule with %.o: %.c. See also this answer.

Related

makefile not changing input filename

I am trying to make a C program and have the following makefile:
CC=clang
CFLAGS=-std=c99 -Wall -pedantic
LDFLAGS=
LDLIBS=
OUT=nes_slop
SRC_DIR=src/
OBJ_DIR=obj/
SRCS=$(wildcard $(SRC_DIR)*.c)
OBJS=$(addprefix $(OBJ_DIR),$(notdir $(SRCS:.c=.o)))
MAKE=make
CLEAR=TRUE
all: clean $(OUT)
clean:
rm -i $(OUT) $(OBJS) -f
$(OUT): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(OUT)
$(OBJS): $(SRCS)
$(CC) -c $(CFLAGS) $(LDLIBS) $< -o $#
It was all well and good until I had more than 1 .c file:
clang -c -std=c99 -Wall -pedantic -lncurses src/gamestate.c -o obj/gamestate.o
clang -c -std=c99 -Wall -pedantic -lncurses src/gamestate.c -o obj/main.o
so, somehow the source file is not being updated, it's always gamestate.c... what's wrong with my makefile? any help is appreciated, thank you
In short, your rule should look something like this:
$(OBJS): %.o: %.c
$(CC) -c $(CFLAGS) $(LDLIBS) $< -o $#
You may also want to read this for how to generate automatic dependencies (so if you change a header file, your c files will automatically regenerate as needed) There's a TL;DR section at the top of that page, if you're not interested in the details.

How do I write a "selective" Makefile?

noob question here.
I have a directory with a lot of .c files, they're basicely libc functions that I code myself as an exercice.
I write a little main() in these files to test the functions, and I want to write a Makefile that allow me to compile only the file I want to test, for exemple:
make memset.c
And get only the executable of the code wrote in memset.c.
I tried to do something like this:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
all : %.o
$(CC) $(CFLAGS) $<
%.o : %.c
$(CC) $(CFLAGS) $< -c -o $#
But obviously it doens't work. I don't what to put in place of the "all".
I know it's very basic, but I didn't manage to do it, and I did research but didn't find an answer to this specific question.
Thanks in advance for your help.
If you do make -n -p you get a dump of all of the built-in rules in make. In GNU Make 4.1, this includes:
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
So you might just needs a % in your makefile where you currently have all.
You also might find that you don't need those rules which are already built in. Suppose you have three C files, each with a main() as you specify: abs.c, div.c and fmax.c. Your Makefile needs to be no more than two lines:
CFLAGS = -Wall -Wextra -pedantic
all: abs div fmax
which would then allow you to do make abs to make the abs executable, and make all to make them all.
You can define static pattern rules to build the object files and the executables and then invoke make with the name of the executable you want as the goal:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
EXE := $(patsubst %.c,%,$(SRC))
.PHONY: all obj
all: $(EXE)
obj: $(OBJ)
$(EXE): %: %.o
$(CC) $(LDFLAGS) $< -o $#
$(OBJ): %.o: %.c
$(CC) $(CFLAGS) $< -c -o $#
.PHONY: clean
clean:
rm -f $(OBJ) $(EXE)
Then:
$ make memset.o
builds only memset.o,
$ make memset
builds only memset (and memset.o if needed),
$ make obj
builds all object files,
$ make # or make all
builds all executables (and object files if needed), and
$ make clean
deletes all executables and object files.
With wildcard, you can achieve what you want.
Note that if each program depends on only one .c file, you don't need %.o rules:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
SRC := $(wildcard *.c)
EXEC = $(SRC:%.c=%)
all: $(EXEC)
%: %.c
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
And just invoke this way for instance:
make memset
You already have most you to compile the executable selectively:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
%.o : %.c
$(CC) $(CFLAGS) $< -c -o $#
% : %.o
$(CC) $(LDLAGS) $< -o $#
Then you just need to call make with the target you want, the executable:
make select
If you have several sets of executable with different flags, you can use:
EX0 = drink clean
${EXE0}: % : %.o
$(CC) $(LDLAGS) -lwater $< -o $#
EX1 = burn melt
{EX1}: % : %.o
$(CC) $(LDLAGS) -lfire $< -o $#

Makefile not compiling all C files in directory

Iam working with gcc and MinGW on a Windows platform. I have a directory containing two *.c files:
main.c and funcs.c
I am using the following makefile:
CC=gcc
CFLAGS=-c
LDFLAGS=
SOURCEDIR = src
BUILDDIR = build
SOURCES=$(wildcard $(SOURCEDIR)/*.c)
OBJECTS=$(patsubst $(SOURCEDIR)/%.c,$(BUILDDIR)/%.o,$(SOURCES))
LIBRARIES=-L/mingw64/lib
INC= -I./include
EXECUTABLE=testLink
VPATH = src include build
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBRARIES) -o ./dist/$#
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
Which should take the *.c files and generate *.o files with the same name. However I get the following output on make -
$ make
gcc -I./include -c src/funcs.c -o build/funcs.o
gcc -I./include -c src/funcs.c -o build/main.o
gcc build/funcs.o build/main.o -L/mingw64/lib -o ./dist/testLink
followed of course by a bunch of multiple definition errors. As you can see from the first two lines it is taking the same *.c file and compiling it twice into two different *.o files.
I am new to makefiles but I assume it is something wrong with my $(OBJECTS) rule and I'm pretty sure it's the $< which is causing the problem. I'm trying to create a generic makefile which will always work on my projects which have the same directory structure and take .c files turn them into .o files and link. Am I going about this entirely the wrong way or is there a simple fix to my makefile?
Thanks!
James
This rule:
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
expands to:
funcs.o main.c: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
which is equivalent to:
funcs.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
main.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
$< refers to the first dependency (funcs.c) so your Makefile is trying to generate both funcs.o and main.o from the same source.
You just want a generic rule using % wildcard matching:
%.o: %.c
$(CC) $(INC) $(CFLAGS) $< -o $#
See https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
Jeff pointed the mistake in his answer (all objects depend on all sources: that isn't a generic compilation rule for c sources).
However, the generic rule must have source & object paths. To sum it up, just replace
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
by
$(BUILDDIR)/%.o : $(SOURCEDIR)/%.c
$(CC) $(INC) $(CFLAGS) $< -o $#
(as explained in How to generate a Makefile with source in sub-directories using just one makefile)
note that this kind of dependency test doesn't take included .h files into account, so it's only intended for first builds. Modifying .h files afterwards doesn't trigger a compilation since the header files are not listed as dependencies.

Make different executables one library used by all

I have a project with the following structure:
- main1.c
- main2.c
- main3.c
- lib.h
- lib.c
All the mains use the import lib.
How can I write a Makefile that creates 3 executables (one per each main)?
First Approach
I created a Makefile that does that, but you'd need to append the name of the executable after calling the make command (i.e. make main1, make main2, etc), However if I try using only make (without arguments), it only makes the first main (main1).
CC=gcc
CFLAGS=-g -O2 -Wall
LDFLAGS=-framework OpenCL
DEPS=lib.h
OBJS=main1.o main2.o main3.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
main1: lib.o main1.o
$(CC) $(CFLAGS) -o $# $^
main2: lib.o main2.o
$(CC) $(CFLAGS) -o $# $^
main3: lib.o main3.o
$(CC) $(CFLAGS) -o $# $^ $(LDFLAGS)
clean:
rm -f *.o main1 main2 main3
Makefile
https://www.gnu.org/software/make/manual/html_node/Goals.html
By default, the goal is the first target in the makefile (not counting
targets that start with a period). Therefore, makefiles are usually
written so that the first target is for compiling the entire program
or programs they describe.
So just add the below line as the first target in your makefile:
all: main1 main2 main3

Understanding Makefile syntax

Can someone help me understand the below makefile?
I have comment on the bits I am not sure on. I have used make files but not extensively and I do not believe I have followed good practises so any advice is welcome.
CC=gcc #is CC, libs, deps, obj, etc predefined keywords or could I use something else
CFLAGS=-I. -g -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse #same with CFlags
LIBS = -luuid -lfuse -pthread
DEPS = fs.h unqlite.h
OBJ = unqlite.o fs.o
TARGET1 = test
TARGET2 = test2
TARGET3 = test3
TARGET4 = test4
TARGET5 = main
all: $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5)
%.o: %.c $(DEPS) #not sure on this line
$(CC) -c -o $# $< $(CFLAGS) #same here
$(TARGET1): $(TARGET1).o $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS) #what are $# and $^
$(TARGET2): $(TARGET2).o $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS)
$(TARGET3): $(TARGET3).o $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS)
$(TARGET4): $(TARGET4).c
gcc -o test test.c
$(TARGET5): $(TARGET5).c
gcc -o uuid uuid.c -luuid
.PHONY: clean
clean:
rm -f *.o *~ core $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5)
CC, CFLAGS, LIBS, DEPS, OBJ and TARGETs are not predefined keywords. They are variables. You can change the name into any you feel appropriate. Just make sure you also change their reference names: $(CC) $(CFLAGS) etc.
%.o: %.c $(DEPS) -
It is a pattern rule: https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
In brief, it says: any .o file depends on .c file with the same prefix and $(DEPS) (which are fs.h and unqlite.h)
$#, $<, $^ are automatic variables for the rules: https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
If works the following way: when making test.o object file from source, the rule
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
Is interpreted as:
test.o: test.c fs.h unqlite.h
gcc -c -o test.o test.c -I. -g -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
Then, when making test binary, the rule
$(TARGET1): $(TARGET1).o $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS)
Becomes:
test: test.o unqlite.o fs.o
gcc -o test test.o unqlite.o fs.o -I. -g -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse -luuid -lfuse -pthread
So, we can see, CFLAGS reference is useless in the rule, as it defines compilation flags, and the rule actually performs linking. So the right one would be:
$(TARGET1): $(TARGET1).o $(OBJ)
gcc -o $# $^ $(LDFLAGS) $(LIBS)
Where LDFLAGS would be defined to some useful value, or can be left empty:
LDFLAGS =

Resources