reduce Makefile redundancy - c

I currently have a Makefile that deals with small set of files that can be built separately. The naming scheme and structure is the same for each set of 3 files; header, implementation, and test driver. I'm going to have about 4 more groups like the 3 below.
What are some less redundant ways to structure this Makefile, to avoid the repetitive nature of each group?
flextest: flex_test.o flex.o
$(CC) $(CFLAGS) -o $# $^
flex_test.o: flex_test.c flex.o minunit.h
$(CC) $(CFLAGS) -c $<
flex.o: flex.c flex.h debug.h
$(CC) $(CFLAGS) -c $<
skiptest: skip_test.o skip.o
$(CC) $(CFLAGS) -o $# $^
skip_test.o: skip_test.c skip.o minunit.h
$(CC) $(CFLAGS) -c $<
skip.o: skip.c skip.h debug.h
$(CC) $(CFLAGS) -c $<
dynatest: dyna_test.o dyna.o
$(CC) $(CFLAGS) -o $# $^
dyna_test.o: dyna_test.c dyna.o minunit.h
$(CC) $(CFLAGS) -c $<
dyna.o: dyna.c dyna.h debug.h
$(CC) $(CFLAGS) -c $<

If you and anyone else who uses this makefile are using GNU make, you can take a ton of shortcuts. Something like this should work:
%test: %_test.o %.o
%_test.o: minunit.h
%.o: %.h debug.h
all: flextest skiptest dynatest

Related

Makefile how to use logical OR between prerequisites?

My source files are organized nicely in a folder, that contains subfolders, that also contains source files.
The subfolders don't branch any further.
All object files are just meant to be created and stored in the same folder.
I don't want to manually list the name of the subdirs in the prerequisites when writing the target that generates my object files:
Right now this works:
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -c $< -o $# $(CFLAGS)
$(OBJ)/%.o: $(SRC)/$(subdir1)/%.c
$(CC) -c $< -o $# $(CFLAGS)
$(OBJ)/%.o: $(SRC)/$(subdir2)/%.c
$(CC) -c $< -o $# $(CFLAGS)
...
But I want it to look something like this:
$(OBJ)/%.o: $(SRC)/%.c OR $(SRC)/*/%.c
$(CC) -c $< -o $# $(CFLAGS)
I understand that the title most likely isn't the real question to be asked, but I'm looking for any solution. Also, I know that the * doesn't work as a placeholder here.
First, you can simplify the makefile you have by using vpath:
$(OBJ)/%.o: %.c
$(CC) -c $< -o $# $(CFLAGS)
vpath %.c $(SRC) $(SRC)/$(subdir1) $(SRC)/$(subdir2)
Then, if you really don't want to specify the subdirectories:
vpath %.c $(shell find $(SRC) -type d)

passing target name to secondary targets

The makefile has multiple targets which will called for all files in the directory. The automatic variable does not get replaced for the target.
TARGETS += txyz_abc txyz_def
.PHONY: all clean
all: $(TARGETS)
txyz_abc: $(UY_DIR)/$(OBJ)/support.o \
$(UX_DIR)/$(OBJ)/%.o
$(CC) $(CFLAGS) -c $< -o $#
$(UX_DIR)/$(OBJ)/%.o: %.c
$(call mkdir, $(UX_DIR)/$(OBJ))
$(CC) $(CFLAGS) -c $< -o $#
$(UY_DIR)/$(OBJ)/support.o: $(UY_DIR)/src/support.c
$(call mkdir, $(UY_DIR)/$(OBJ))
$(CC) $(CFLAGS) -c -o $# $<
on make support.o is generated. but throws an error that no rule to make target '../ux_src/obj/%.o", needed by 'txyz_abc'.

Cannot find lpThread library in /usr/lib

I'm having problems with linking .so libraries. I've already copied them to both /usr/lib and /usr/local/lib
Below is a snippet of my makefile:
PROJ_LDFLAGS += -lpthread
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $^ $(LDFLAGS) $(PROJ_LDFLAGS) -o $#
%.o: %.c
$(CC) -I. $(CFLAGS) $(PROJ_CFLAGS) -c $<

Makefile doesn't rebuild objects on header modification

I have made a Makefile for compiling my C programm but it's not building object when i change one of the headers.
My MakeFile:
CC=gcc
CFLAGS=-O3 -Wall
LDFLAGS=-I/usr/include/mysql -L/usr/lib/x86_64-linux-gnu -lmysqlclient
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=bin/beta_parser
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) -o $# $^ $(CFLAGS) $(LDFLAGS)
%.o:%.c types.h cstes.h headers.h mysql.h
$(CC) -o $# -c $< $(CFLAGS)
.PHONY: clean mrproper
clean:
rm -rf *.o
mrproper:
rm -rf $(EXEC)
What have I done wrong ?
EDIT : Corection of the Makeil after a great comment.
Although there are other more elegant tricks, in your case, I think something like
$(OBJECTS): types.h cstes.h headers.h mysql.h
%.o: %.c
$(CC) -o $# -c $< $(CFLAGS)
should be sufficient.
Scanning your sources for dependencies is outside the scope of Make (although there are other tools, such as CMake which will do this automatically). You need to add an explicit rule to generate these dependencies, but this can be done in many different ways. I've sometimes used the following technique:
OBJECTS = ....
-include $(OBJECTS:.o=.d)
...
$(OBJECTS): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(CC) $(CFLAGS) $(DEPFLAGS) $< > $*.d
Google for "make automatic dependency generation" will show you other ways to do it as well.

How to extend makefile to compose library?

I have a makefile which does what I want with the compilation but I want it also to make a library instead of only object files.
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 the makefile to be something like this:
gcc -Wall -g -c tree.c
ar -r libtree.a tree.o
gcc main.c -o main -ltree -L.
./main
What I have to add to my existing makefile?
This should do what you want:
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
lib%.a: %.o
ar -r $# $^
main: $(OBJ) $(DEPS:%.h=lib%.a)
$(CC) -o $# $^ $(CFLAGS) $(DEPS:%.h=-l%) -L.
Note that this only works in GNU Make (in particular, the % in $(DEPS:%.h=lib%.a) is a GNU-specific extension).

Resources