Makefile builds target every time - c

I have written a makefile to compile all the sources in different directories and build a target. When I run make even when there is no change in the files, it does not re-compiles the unmodified files. But, it always builds the target. Why is the target alone getting built every time when I run make?
CC = gcc
CFLAGS = $(INCLUDES)
TARGET = FinalBin
OUTDIR := obj
INCLUDES = -Isrc/in
S1 = src/s1
S2 = src/s2
S1_SRC = $(wildcard $(S1)/*.c)
S2_SRC = $(wildcard $(S2)/*.c)
SRCS := $(S1_SRC) \
$(S2_SRC)
OBJS := $(patsubst %.c,$(OUTDIR)/%.o,$(SRCS))
SRCDIRS := $(S1) $(S2)
all: $(TARGET)
$(TARGET): builddir $(OBJS)
#echo "Building..." $#
#$(CC) $(OBJS) $(CFLAGS) -o $#
#echo "Build Complete!"
$(OUTDIR)/%.o: %.c
#echo "Compiling.." $(notdir $<)
#$(CC) $(CFLAGS) -MMD -c $< -o $#
clean:
-#rm -rf $(OUTDIR) FinalBin
#echo "Clean complete!"
builddir :
#$(call create-dir)
define create-dir
for dir in $(SRCDIRS); \
do \
mkdir -p $(OUTDIR)/$$dir; \
done
endef
-include $(wildcard $(OBJS:.o=.d))
The $(TARGET) gets built from the object files each time. Please guide me where I'm going wrong.
UPDATE:
CC = gcc
CFLAGS = $(INCLUDES)
TARGET = FinalBin
OUTDIR := obj
INCLUDES = -Isrc/in
S1 = src/s1
S2 = src/s2
S1_SRC = $(wildcard $(S1)/*.c)
S2_SRC = $(wildcard $(S2)/*.c)
SRCS := $(S1_SRC) \
$(S2_SRC)
OBJS := $(patsubst %.c,$(OUTDIR)/%.o,$(SRCS))
SRCDIRS := $(S1) $(S2)
OUTDIRS := $(addprefix $(OUTDIR)/,$(SRCDIRS))
all: $(TARGET)
$(TARGET): $(OBJS)
#echo "Building..." $#
#$(CC) $(OBJS) $(CFLAGS) -o $#
#echo "Build Complete!"
$(OUTDIR)/%.o: $(OUTDIRS) %.c
#echo "Compiling.." $(notdir $(filter %.c,$^))
#$(CC) $(CFLAGS) -MMD -c $(filter %.c,$^) -o $#
clean:
-#rm -rf $(OUTDIR) FinalBin
#echo "Clean complete!"
$(OUTDIRS):
mkdir -p $#
builddir :
#$(call create-dir)
define create-dir
for dir in $(SRCDIRS); \
do \
mkdir -p $(OUTDIR)/$$dir; \
done
endef
-include $(wildcard $(OBJS:.o=.d))
This builds all the files every time.
Final Solution:
CC = gcc
CFLAGS = $(INCLUDES)
TARGET = FinalBin
OUTDIR := obj
INCLUDES = -Isrc/in
S1 = src/s1
S2 = src/s2
S1_SRC = $(wildcard $(S1)/*.c)
S2_SRC = $(wildcard $(S2)/*.c)
SRCS := $(S1_SRC) \
$(S2_SRC)
OBJS := $(patsubst %.c,$(OUTDIR)/%.o,$(SRCS))
SRCDIRS := $(S1) $(S2)
OUTDIRS := $(addprefix $(OUTDIR)/,$(SRCDIRS))
all: $(TARGET)
$(TARGET): $(OUTDIRS) $(OBJS)
#echo "Building..." $#
#$(CC) $(OBJS) $(CFLAGS) -o $#
#echo "Build Complete!"
$(OUTDIR)/%.o: %.c
#echo "Compiling.." $(notdir $<)
#$(CC) $(CFLAGS) -MMD -c $< -o $#
clean:
-#rm -rf $(OUTDIR) FinalBin
#echo "Clean complete!"
$(OUTDIRS):
#mkdir -p $#
-include $(wildcard $(OBJS:.o=.d))
The final solution works as expected!

You can use the debug output of make to look for what it thinks needs rebuilding:
make -d | grep remake
You'll probably see something like this:
No need to remake target `Makefile'.
Must remake target `builddir'.
No need to remake target `src/s1/x.c'.
No need to remake target `obj/src/s1/x.o'.
Must remake target `FinalBin'.
Must remake target `all'.
Which shows that it always thinks that the builddir target needs to be remade. Since that is a dependency of $(TARGET) it rebuilds the latter as well.
If you use a rule to create your build directories instead of a function, make will know whether it needs create them or not. For example, adding the variable $(OUTDIRS), a rule for it, and making this a dependency of compiling:
SRCDIRS := $(S1) $(S2)
OUTDIRS := $(addprefix $(OUTDIR)/, $(SRCDIRS)) # <---------- Add this variable
All: $(TARGET)
$(TARGET): $(OBJS)
#echo "Building..." $#
#$(CC) $(OBJS) $(CFLAGS) -o $#
#echo "Build Complete!"
$(OUTDIR)/%.o: $(OUTDIRS) %.c # <--------------------------- Add dependency to $(OUTDIRS)
#echo "Compiling.." $(notdir $<)
#$(CC) $(CFLAGS) -MMD -c $< -o $#
clean:
-#rm -rf $(OUTDIR) FinalBin
#echo "Clean complete!"
$(OUTDIRS): # <--------------------------------------------- Add rule
mkdir -p $#
-include $(wildcard $(OBJS:.o=.d))

Related

How to produce a generic Makefile for various projects with the same folder structure?

I have to following folder structure in various projects :
myproject/
obj/
src/
file1.c
file2.c
file3.c
inc/
myproject.h
Makefile
I have the following Makefile :
NAME := myproject
CC := gcc
RM := rm
CFLAGS := -Wall -Wextra -Werror
LDFLAGS := -Wall
RMFLAGS := -f
SRCDIR := src
OBJDIR := obj
INCDIR := inc
HEADERS := $(INCDIR)/myproject.h
LINK.o := $(CC) $(LDFLAGS)
COMPILE.c := $(CC) -I$(INCDIR) $(CFLAGS) -c
SRCS := file1.c file2.c file3.c
SOURCES := $(addprefix $(SRCDIR)/, $(SRCS))
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) $< -o $#
all: $(NAME)
$(NAME): $(OBJECTS) $(HEADERS) Makefile
$(LINK.o) $< -o $#
clean:
$(RM) $(OBJECTS)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all clean fclean re
Here is what I am looking to achieve :
I would like to put all .o files under obj/.
The final executable should be at the root of the myproject/ folder.
If a .c file changes, only this file should be recompiled.
If the Makefile or the .h changes, I would like to recompile everything.
However, I when I run this Makefile I get make: *** No rule to make target obj/file1.o', needed by myproject'. Stop..
Could anyone help me fix this Makefile and give me advice on how to improve it?
EDIT
Here is a new version of the Makefile based on the comments.
NAME := myproject
CC := gcc
RM := rm
CFLAGS := -Wall -Wextra -Werror
LDFLAGS := -Wall
RMFLAGS := -f
SRCDIR := src
OBJDIR := obj
INCDIR := inc
HEADERS := $(INCDIR)/myproject.h
LINK.o := $(CC) $(LDFLAGS)
COMPILE.c := $(CC) -I$(INCDIR) $(CFLAGS) -c
REMOVE := $(RM) $(RMFLAGS)
SRCS := file1.c file2.c file3.c
SOURCES := $(addprefix $(SRCDIR)/, $(SRCS))
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) $< -o $#
all: $(NAME)
$(NAME): $(OBJECTS)
$(LINK.o) -o $(NAME) $^
clean:
$(REMOVE) $(OBJECTS)
fclean: clean
$(REMOVE) $(NAME)
re: fclean all
.PHONY: all clean fclean re
This version works, but I am still unsure how to trigger recompilation of the Makefile or the .h changes.
Thanks to #MadScientist and #HardcoreHenry I have managed to fix the Makefile. Here is the final version :
# Edit the $(NAME) and $(SRCS) variables as necessary.
NAME := myprogram
SRCS := file1.c file2.c file3.c
CC := gcc
RM := rm
CFLAGS := -Wall -Wextra -Werror
LDFLAGS := -Wall
RMFLAGS := -f
SRCDIR := src
OBJDIR := obj
INCDIR := inc
# Edit the $(HEADERS) variable as necessary.
HEADERS := $(INCDIR)/myprogram.h
LINK.o := $(CC) $(LDFLAGS)
COMPILE.c := $(CC) -I$(INCDIR) $(CFLAGS) -c
REMOVE := $(RM) $(RMFLAGS)
SOURCES := $(addprefix $(SRCDIR)/, $(SRCS))
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
$(OBJDIR)/%.o: $(SRCDIR)/%.c
#mkdir -p $(#D)
$(COMPILE.c) $< -o $#
all: $(NAME)
$(OBJECTS): $(HEADERS) Makefile
$(NAME): $(OBJECTS)
$(LINK.o) -o $(NAME) $^
clean:
$(REMOVE) $(OBJECTS)
fclean: clean
$(REMOVE) $(NAME)
re: fclean all
.PHONY: all clean fclean re

Generate executable file with makefile in linux

I want to generate two executable file from two sources.
What should i put in the Flag EXEC ?
Is this line correct? --> EXEC := amqp_consommateur amqp_producteur
CC := gcc
CFLAGS := -Wall -g
SRCDIR := src
OBJDIR := obj
INCLUDES := -I/usr/local/include/ -I/home/tvi/projets/RabbitMQ/libamqp/dlo -I/home/tvi/projets/RabbitMQ/rabbitmq-c/librabbitmq
LFLAGS := -L/usr/local/lib64
LDFLAGS :=
LIBS := -L. -lrabbitmq
SRCS_RAW := amqp_consommateur.c amqp_producteur.c
SRCS := $(addprefix $(SRCDIR)/,$(SRCS_RAW))
OBJS := $(addprefix $(OBJDIR)/,$(SRCS_RAW:.c=.o))
EXEC := amqp_consommateur amqp_producteur
$(info DEBUG: SRCS=$(SRCS))
$(info DEBUG: OBJS=$(OBJS))
$(info DEBUG: EXEC=$(EXEC))
.PHONY: all
all: $(EXEC)
#echo "$(MAKE) : Tout est généré"
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) -o $(EXEC) $(OBJS) $(LDFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS)
#rule to create object directory if it doesnt exist
$(OBJDIR):
mkdir $(OBJDIR)
#define implicit rule to build objects in their own directory
#(note -- order only dependency on object directory)
$(OBJS): $(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
.PHONY: clean
clean:
$(RM) *~ $(EXEC)
$(RM) -r $(OBJDIR)

Makefile is not creating a directory

Teacher gave us this makefile for compiling two C files and storing the objects into a directory called object. It compiles the programs fine however it doesn't store their objects into the directory, and it also doesn't even create the directory. Not sure what to do and could really use some help.
This is my make file
CC = clang
CFLAGS = -g -Wall
OBJDIR = object
HDRS = $(wildcard *.h)
SRCS = $(wildcard *.c)
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
.PHONY: all
all: client server
# WARNING: must have a tab before each definition
$(OBJDIR)/client.o: client.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c client.c -o object/client.o
$(OBJDIR)/server .o: server.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c server.c -o object/server.o
$(OBJDIR)/%.o: %.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c $*.c -o object/$*.o
$(OBJDIR):
mkdir $(OBJDIR)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)
All I had to do was add multiple targets to the makefile and change all to target the targets
CC = clang
CFLAGS = -g -Wall
# TODO: rename the target to something meaningful!
TARGET = client server
OBJDIR = object
HDRS = $(wildcard *.h)
SRCS = $(wildcard *.c)
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
.PHONY: all
all: $(TARGET)
# WARNING: *must* have a tab before each definition
$(TARGET): $(OBJDIR) $(OBJS)
$(CC) $(CFLAGS) $(OBJDIR)/protocol.o $(OBJDIR)/$#.o -o $#
$(OBJDIR)/%.o: %.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c $*.c -o object/$*.o
$(OBJDIR):
mkdir $(OBJDIR)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)

CUDA compilation errors on Mac

I'm using the following Makefile to compile a CUDA C program. This follows pretty much the same pattern that I use in most of my C projects.
TARGET = bfs
GCC = nvcc
CUDA_INSTALL_PATH := /Developer/NVIDIA/CUDA-7.5
LIBS := -I. -I$(CUDA_INSTALL_PATH)/include
CUDA_LIBS := -L$(CUDA_INSTALL_PATH)/lib -lcudart
SRCDIR = src
OBJDIR = obj
BINDIR = bin
INClDIR = includes
SOURCES := $(wildcard $(SRCDIR)/*.cu)
INCLUDES := $(wildcard $(INClDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.cu=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
mkdir -p $(BINDIR)
$(GCC) -o $# $(LIBS) -c $(OBJECTS)
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cu
#$(GCC) $(LIBS) -c *.cu -o $#
#echo "Compiled "$<" successfully!"
.PHONEY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"
I get the following error
mkdir -p bin
nvcc -o bin/bfs -I. -I/Developer/NVIDIA/CUDA-7.5/include -c obj/main.o obj/square.o
nvcc fatal : A single input file is required for a non-link phase when an outputfile is specified
make: *** [bin/bfs] Error 1
What am I doing wrong here.
This seemed to work for me:
TARGET = bfs
SRCDIR = src
OBJDIR = obj
BINDIR = bin
INClDIR = includes
CUDA_INSTALL_PATH := /usr/local/cuda
GCC := $(CUDA_INSTALL_PATH)/bin/nvcc
LIBS := -I. -I$(SRCDIR) -I$(CUDA_INSTALL_PATH)/include -I$(INClDIR)
CUDA_LIBS := -L$(CUDA_INSTALL_PATH)/lib64 -lcudart
SOURCES := $(wildcard $(SRCDIR)/*.cu)
INCLUDES := $(wildcard $(INClDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.cu=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET) : $(OBJECTS)
mkdir -p $(BINDIR)
$(GCC) -o $# $(OBJECTS)
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cu
#$(GCC) $(LIBS) -c $(SRCDIR)/*.cu -odir $(OBJDIR)
#echo "Compiled "$<" successfully!"
.PHONEY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"
I tested on linux. You will need to change CUDA_INSTALL_PATH back to wherever it is on your machine.
Note that your use of *.cu on the compile step results in a single invocation of nvcc to compile all the source files. There's nothing wrong with this per se, but it will only generate a single "Compiled ... successfully!" message, as there is only one invocation of nvcc to create all the objects.

Makefile always recompiling some sections

The directory structure for Example is something like this.
Example - Contains Makefile, main.c, xyz.c, xyz.h and sub-directories Hal and Interrupt_Config
Hal - Contains test2.c and test2.h Interrupt_Config - Contains try.h
EXE := Micro
CC := gcc
CPPFLAGS := -IHal -IInterruptConfig
VPATH := Hal:InterruptConfig
OUT_DIR := Output/
OUT_SRC := Output/source/
OUT_EXE := Output/output
LIBS = Hal InterruptConfig
MAIN_OBS := $(patsubst %.c,%.o,$(wildcard *.c))
INT_OBS := $(patsubst %.c,%.o,$(wildcard InterruptConfig/*.c))
HAL_OBS := $(patsubst %.c,%.o,$(wildcard Hal/*.c))
ALL_DEPS := $(patsubst %.o,%.d,$(MAIN_OBS) $(HAL_OBS) $(INT_OBS))
ALL_OBS := $(MAIN_OBS) $(INT_OBS) $(HAL_OBS)
all: $(OUT_DIR) $(EXE)
$(OUT_DIR):
mkdir -p $(OUT_DIR)
mkdir -p $(OUT_SRC)
mkdir -p $(OUT_EXE)
%.o: %.c
$(CC) -o $(OUT_SRC)$# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
$(EXE): $(MAIN_OBS) $(HAL_OBS) $(INT_OBS)
$(CC) -o $(OUT_EXE)$# $(LDFLAGS) $(OUT_SRC)*.o $(LDLIBS)
$(HAL_OBS): %.o: %.c
$(CC) -o $(OUT_SRC)$(notdir $#) -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
$(INT_OBS): %.o: %.c
$(CC) -o $(OUT_SRC)$(notdir $#) -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
-include $(ALL_DEPS)
clean:
rm -rf $(OUT_DIR) $(ALL_DEPS)
.PHONY: all clean
Whenever I do make, it successfully creates a directory called as Output with sub-directories source containing all the object files and output containing an executable named Micro . The first time if I do make it build everything successfully but if I do make again , I expected it should give make - has nothing to do but it builds everything except $(OUT_DIR) rule. I am not able to figure out what is the problem.
Repeated make -
Expected - nothing
Actual -
gcc -o Output/source/main.o -MD -MP -IHal -IInterrupt_Config -c main.c
gcc -o Output/source/xyz.o -MD -MP -IHal -IInterrupt_Config -c xyz.c
gcc -o Output/source/test2.o -MD -MP -IHal -IInterrupt_Config -c Hal/test2.c
gcc -o Output/output/nextgenrsm Output/source/*.o
Also I am not sure whether I am doing dependencies thing correctly or not.
Without knowing your build directory setup, its hard to give you an exact solution, but my build rules look something like this:
MAIN_OBS := $(add_prefix $(OUT_DIR), $(patsubst %.c,%.o,$(wildcard *.c)))
$(OUT_DIR):
mkdir -p $(OUT_DIR)
mkdir -p $(OUT_SRC)
mkdir -p $(OUT_EXE)
$(OUT_SRC)/%.o: %.c
$(CC) -o $# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
It gets complicated if you have a complicated directory structure because you will need to make more directories or get fancy with your object renaming.
Many thanks to mjr and Etan Reisner. I am just posting here the final Makefile for learning purposes for other people.
UPDATED
EXE :=nextgenrsm
CC := gcc
CPPFLAGS := -IHal -IInterrupt_Config
VPATH := Hal:Interrupt_Config
OUT_DIR := Output/
OUT_SRC := Output/source/
OUT_EXE := Output/output/$(EXE)
LIBS = Hal Interrupt_Config
MAIN_OBS := $(addprefix $(OUT_SRC), $(patsubst %.c,%.o, $(wildcard *.c)))
INT_OBS := $(addprefix $(OUT_SRC), $(notdir $(patsubst %.c,%.o,$(wildcard Interrupt_Config/*.c))))
HAL_OBS := $(addprefix $(OUT_SRC), $(notdir $(patsubst %.c,%.o,$(wildcard Hal/*.c))))
ALL_DEPS := $(patsubst %.o,%.d, $(MAIN_OBS) $(HAL_OBS) $(INT_OBS))
ALL_OBS = $(notdir $(MAIN_OBS) $(INT_OBS) $(HAL_OBS)))
all: $(OUT_DIR) $(OUT_EXE)
$(OUT_DIR):
mkdir -p $(OUT_DIR)
mkdir -p $(OUT_DIR)source/
mkdir -p $(OUT_DIR)output/
$(OUT_EXE): $(MAIN_OBS) $(HAL_OBS) $(INT_OBS)
$(CC) -o $# $(LDFLAGS) $(OUT_SRC)*.o $(LDLIBS)
$(OUT_SRC)%.o: %.c
$(CC) -o $# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
-include $(ALL_DEPS)
clean:
rm -rf $(OUT_DIR)
.PHONY: all clean

Resources