change of header file detection for makefile - makefile

My makefile doesn't detect changes in header files. How can i add this functionality to my makefile? Here is my makefile:
CPP = g++
CC = gcc
RES =
OBJ = obj/main.o obj/customfunc1.o obj/customfunc2.o $(RES)
LINKOBJ = obj/main.o obj/customfunc1.o obj/customfunc2.o $(RES)
LIBS =
INCS = -I"lib1/inc" -I"lib2/inc"
CXXINCS = -I"lib1/inc" -I"lib2/inc"
BIN = out
CXXFLAGS = $(CXXINCS)
CFLAGS = $(INCS)
RM = rm -f
.PHONY: all all-before all-after clean clean-custom
all: all-before $(BIN) all-after
clean: clean-custom
${RM} $(OBJ) $(BIN)
$(BIN): $(OBJ)
$(CC) $(LINKOBJ) -o $(BIN) $(LIBS)
obj/main.o: main.c
$(CC) -c main.c -o obj/main.o $(CFLAGS)
obj/customfunc1.o: lib1/customfunc1.c
$(CC) -c lib1/customfunc1.c -o obj/customfunc1.o $(CFLAGS)
obj/customfunc2.o: lib2/customfunc2.c
$(CC) -c lib2/customfunc2.c -o obj/customfunc2.o $(CFLAGS)

Header files must be listed together with other dependencies. E.g.:
CPP = g++
CC = gcc
RES =
OBJ = obj/main.o obj/customfunc1.o obj/customfunc2.o $(RES)
LINKOBJ = obj/main.o obj/customfunc1.o obj/customfunc2.o $(RES)
LIBS =
INCS = -I"lib1/inc" -I"lib2/inc"
CXXINCS = -I"lib1/inc" -I"lib2/inc"
BIN = out
CXXFLAGS = $(CXXINCS)
CFLAGS = $(INCS)
RM = rm -f
.PHONY: all all-before all-after clean clean-custom
all: all-before $(BIN) all-after
clean: clean-custom
${RM} $(OBJ) $(BIN)
$(BIN): $(OBJ)
$(CC) $(LINKOBJ) -o $(BIN) $(LIBS)
obj/main.o: main.c header1.h header2.h
$(CC) -c main.c -o obj/main.o $(CFLAGS)
obj/customfunc1.o: lib1/customfunc1.c lib1/header.h
$(CC) -c lib1/customfunc1.c -o obj/customfunc1.o $(CFLAGS)
obj/customfunc2.o: lib2/customfunc2.c lib2/header.h
$(CC) -c lib2/customfunc2.c -o obj/customfunc2.o $(CFLAGS)

Related

makefile error: “make: *** No rule to make target …”

I'm trying to use GCC (linux) with a makefile to compile my project.
I get the following error
"No rule to make target 'output/src/main.o', needed by 'test'. Stop."
This is the makefile:
COMPILE_PREX ?=
CC = $(COMPILE_PREX)gcc
SOURCE = $(wildcard src/*.c)
OBJS = $(addprefix ./output/, $(patsubst %.c, %.o, $(SOURCE)))
INCLUDES = -I ./src
CFLAGS += -O2 -Wall -g
LDFLAGS += -lpthread
TARGET = test
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $(TARGET)
%.o: %.c
#mkdir -p ./output
$(CC) $(CFLAGS) $(INCLUDES) -o $(addprefix ./output/, $#) -c $<
clean:
rm -rf ./output
This should work. Note the use of mkdir $(#D) to create output directories as needed.
COMPILE_PREX ?=
CC = $(COMPILE_PREX)gcc
SOURCE = $(wildcard src/*.c)
OBJS = $(addprefix output/, $(patsubst %.c, %.o, $(SOURCE)))
INCLUDES = -I src
CFLAGS += -O2 -Wall -g
LDFLAGS += -lpthread
TARGET = test
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $(TARGET)
output/%.o: %.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) $(INCLUDES) -o $# -c $<
clean:
rm -rf output
Running it here with make clean test:
rm -rf output
gcc -O2 -Wall -g -I src -o output/src/hello.o -c src/hello.c
gcc output/src/hello.o -lpthread -o test

Makefile: How to place auto-generated files in a separate directory?

You can see my Makefile here:
....
PHY_SRCS = ../LwMesh/phy/at86rf212/src/phy.c
HAL_SRCS = ../LwMesh/hal/atmega1281/src/hal.c ../LwMesh/hal/atmega1281/src/halPhy.c ../LwMesh/hal/atmega1281/src/halTimer.c
SYS_SRCS = ../LwMesh/sys/src/sys.c ../LwMesh/sys/src/sysEncrypt.c ../LwMesh/sys/src/sysTimer.c
....
# define the C object files
PHY_OBJS = $(PHY_SRCS:.c=.o)
HAL_OBJS = $(HAL_SRCS:.c=.o)
....
# define the executable file
PHY = phy_cc
HAL = hal_cc
SYS = sys_cc
.....
OBJDIR := obj
$(OBJDIR):
mkdir $(OBJDIR)
all: $(PHY) $(HAL) $(SYS) $(DRV) $(NWK) $(SRV) $(VELA)
#echo Alles wurde Kompiliert
$(PHY): $(PHY_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(PHY) $(PHY_OBJS) $(LFLAGS)
$(HAL): $(HAL_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(HAL) $(HAL_OBJS) $(LFLAGS)
....
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
...
I have tried too much to place auto-generated files (e.g. object files) in a separate directory(OBJDIR), but I did not find any solution.
I referred to this tutorial, but it is not suitable for my Makefile.
Could you please help me?
Let's take this in small steps.
You already have a rule for building object files:
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
Which can be written out as:
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
This will use ../LwMesh/phy/at86rf212/src/phy.c to build ../LwMesh/phy/at86rf212/src/phy.c. But imagine for a moment that phy.c were in the working directory. Then Make could use that rule to build phy.o from phy.c. In that case we could make a small change in the rule:
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
and Make would build obj/phy.o.
How do we tell Make where to find phy.c? There are two good ways. One is using vpath:
vpath %.c ../LwMesh/phy/at86rf212/src
After we confirm that this works, we can add other directories for other sets of objects (such as PHY and SYS):
vpath %.c ../LwMesh/phy/at86rf212/src ../LwMesh/hal/atmega1281/src ../LwMesh/sys/src ...
Now all we have to do is construct the lists of objects correctly:
PHY_OBJS = phy.o
HAL_OBJS = hal.o halPhy.o halTimer.o
SYS_OBJS = sys.o sysEncrypt.o sysTimer.o
...
Once this much is working correctly, further refinements are possible.
You can see the corrected Makefile here:
# define compiler type
CC = avr-gcc
# define any compile-time flags
CFLAGS = -Wall -g -funsigned-char -funsigned-bitfields -DPHY_AT86RF212 -DHAL_ATMEGA1281 -DPLATFORM_ANY900_STICK -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega1281 -c -std=gnu99 -MD -MP -MF "$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -MT"$(#:%.o=%.o)"
# define any directories containing header files other than /usr/include
INCLUDES += \
-I"../LwMesh/hal/atmega1281/inc" \
-I"../LwMesh/hal/drivers/atmega1281" \
-I"../LwMesh/phy/at86rf212/inc" \
-I"../LwMesh/nwk/inc" \
-I"../LwMesh/sys/inc" \
-I"../LwMesh/service/inc" \
-I"../common" \
-I".." \
-I.
# define library paths in addition to /usr/lib
LFLAGS = -L/home/newhall/lib -L../lib
# define any libraries to link into executable:
LIBS = -lmylib -lm
# define the C source files
PHY_SRCS = ../LwMesh/phy/at86rf212/src/phy.c
HAL_SRCS = ../LwMesh/hal/atmega1281/src/hal.c ../LwMesh/hal/atmega1281/src/halPhy.c ../LwMesh/hal/atmega1281/src/halTimer.c
SYS_SRCS = ../LwMesh/sys/src/sys.c ../LwMesh/sys/src/sysEncrypt.c ../LwMesh/sys/src/sysTimer.c
DRV_SRCS = ../LwMesh/hal/drivers/atmega1281/halUart.c ../LwMesh/hal/drivers/atmega1281/halTwi.c
NWK_SRCS += \
../LwMesh/nwk/src/nwk.c \
../LwMesh/nwk/src/nwkDataReq.c \
../LwMesh/nwk/src/nwkSecurity.c \
../LwMesh/nwk/src/nwkFrame.c \
../LwMesh/nwk/src/nwkGroup.c \
../LwMesh/nwk/src/nwkRoute.c \
../LwMesh/nwk/src/nwkRouteDiscovery.c \
../LwMesh/nwk/src/nwkRx.c \
../LwMesh/nwk/src/nwkTx.c
SRV_SRCS = ../LwMesh/service/src/otaClient.c ../LwMesh/service/src/otaServer.c
VELA_SRCS += \
base-commands.c \
bus-commands.c \
bus-interface.c \
host-interface.c \
measurement.c \
VelaMain.c \
otaInterface.c \
persistence.c \
shell.c
PHY_OBJS = $(addprefix $(OBJDIR)/PHY/,phy.o)
HAL_OBJS = $(addprefix $(OBJDIR)/HAL/,hal.o halPhy.o halTimer.o)
SYS_OBJS = $(addprefix $(OBJDIR)/SYS/,sys.o sysEncrypt.o sysTimer.o)
DRV_OBJS = $(addprefix $(OBJDIR)/DRV/,halUart.o halTwi.o)
NWK_OBJS = $(addprefix $(OBJDIR)/NWK/,nwk.o nwkDataReq.o nwkSecurity.o nwkFrame.o nwkGroup.o nwkRoute.o nwkRouteDiscovery.o nwkRx.o nwkTx.o)
SRV_OBJS = $(addprefix $(OBJDIR)/SRV/,otaClient.o otaServer.o)
VELA_OBJS = $(addprefix $(OBJDIR)/VELA/,base-commands.o bus-commands.o bus-interface.o host-interface.o measurement.o VelaMain.o otaInterface.o persistence.o shell.o)
# define the executable file
PHY = phy_cc
HAL = hal_cc
SYS = sys_cc
DRV = drv_cc
NWK = nwk_cc
SRV = srv_cc
VELA = vela_cc
OBJDIR := objdir
OUTPUT_FILE_PATH +=Vela2.elf
OUTPUT_FILE_PATH_AS_ARGS +=Vela2.elf
OUTPUT_FILE_DEP:=
ALL_OBJS := $(PHY_OBJS) $(HAL_OBJS) $(SYS_OBJS) $(DRV_OBJS) $(NWK_OBJS) $(SRV_OBJS) $(VELA_OBJS)
ALL_SRCS := $(PHY_SRCS) $(HAL_SRCS) $(SYS_SRCS) $(DRV_SRCS) $(NWK_SRCS) $(SRV_SRCS) $(VELA_SRCS)
$(OUTPUT_FILE_PATH): $(ALL_OBJS) $(OUTPUT_FILE_DEP)
#echo Invoking: AVR/GNU Linker
$(CC) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(ALL_OBJS) -Wl,-Map="Vela2.map" -Wl,-u,vfprintf -Wl,--start-group -Wl,--end-group -Wl,--gc-sections -mrelax -mmcu=atmega1281
#echo Finished building target: $#
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "Vela2.elf" "Vela2.hex"
avr-objcopy -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "Vela2.elf" "Vela2.eep" || exit 0
avr-objdump -h -S "Vela2.elf" > "Vela2.lss"
avr-objcopy -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "Vela2.elf" "Vela2.srec"
avr-size "Vela2.elf"
$(OBJDIR)/PHY/%.o : ../LwMesh/phy/at86rf212/src/%.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
$(OBJDIR)/HAL/%.o : ../LwMesh/hal/atmega1281/src/%.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
$(OBJDIR)/SYS/%.o : ../LwMesh/sys/src/%.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
$(OBJDIR)/DRV/%.o : ../LwMesh/hal/drivers/atmega1281/%.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
$(OBJDIR)/NWK/%.o : ../LwMesh/nwk/src/%.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
$(OBJDIR)/SRV/%.o : ../LwMesh/service/src/%.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
$(OBJDIR)/VELA/%.o : %.c
$(CC) $(CFLAGS) $(INCLUDES) $(OUTPUT_OPTION) $<
all: $(ALL_OBJS) $(OUTPUT_FILE_PATH)
$(ALL_OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p objdir/PHY
mkdir -p objdir/HAL
mkdir -p objdir/SYS
mkdir -p objdir/DRV
mkdir -p objdir/NWK
mkdir -p objdir/SRV
mkdir -p objdir/VELA
$(PHY): $(PHY_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(PHY) $(PHY_OBJS) $(LFLAGS)
$(HAL): $(HAL_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(HAL) $(HAL_OBJS) $(LFLAGS)
$(SYS): $(SYS_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(SYS) $(SYS_OBJS) $(LFLAGS)
$(DRV): $(DRV_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(DRV) $(DRV_OBJS) $(LFLAGS)
$(NWK): $(NWK_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(NWK) $(NWK_OBJS) $(LFLAGS)
$(SRV): $(SRV_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(SRV) $(SRV_OBJS) $(LFLAGS)
$(VELA): $(VELA_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(VELA) $(VELA_OBJS) $(LFLAGS)
clean:
-$(RM) $(OBJS_AS_ARGS) $(EXECUTABLES)
-$(RM) $(C_DEPS_AS_ARGS)
rm -rf "Vela2.elf" "Vela2.a" "Vela2.hex" "Vela2.lss" "Vela2.eep" "Vela2.map" "Vela2.srec" "Vela2.usersignatures"
depend: $(PHY_SRCS) $(HAL_SRCS) $(SYS_SRCS) $(DRV_SRCS) $(NWK_SRCS) $(SRV_SRCS) $(VELA_SRCS)
makedepend $(INCLUDES) $^

makefile with 2 executables, how?

My project is organized like this :
src/plateau.c plateau.h tuile.c tuile.h main.c
tests/tests.c
obj/
bin/
I'm trying to do a makefile with 2 executables. I can't figure out why it doesn't works.
The makefile with one executable only works fine, it looks like this :
CC = gcc -Wall -Wextra -ansi
SRCDIR = src
OBJDIR = obj
BINDIR = bin
DOXYGEN = doxygen
all: honshu
honshu: $(OBJDIR)/main.o $(OBJDIR)/plateau.o $(OBJDIR)/tuile.o
$(CC) $(OBJDIR)/main.o $(OBJDIR)/plateau.o $(OBJDIR)/tuile.o -o honshu
$(OBJDIR)/plateau.o: $(SRCDIR)/plateau.c $(SRCDIR)/plateau.h
$(CC) -c $(SRCDIR)/plateau.c -o $(OBJDIR)/plateau.o
$(OBJDIR)/tuile.o: $(SRCDIR)/tuile.c $(SRCDIR)/tuile.h
$(CC) -c $(SRCDIR)/tuile.c -o $(OBJDIR)/tuile.o
$(OBJDIR)/main.o: $(SRCDIR)/main.c
$(CC) -c -I src $(SRCDIR)/main.c $# -lm
doxygen:
$(DOXYGEN) -g
$(DOXYGEN) Doxyfile
clean:
rm *.o
rm honshu
And with two executables, I tried like this :
CC = gcc -Wall -Wextra -ansi
SRCDIR = src
OBJDIR = obj
BINDIR = bin
DOXYGEN = doxygen
all: honshu tests
honshu: $(OBJDIR)/main.o $(OBJDIR)/plateau.o $(OBJDIR)/tuile.o
$(CC) $(OBJDIR)/main.o $(OBJDIR)/plateau.o $(OBJDIR)/tuile.o -o honshu
tests: $(OBJDIR)/test_honshu.o $(OBJDIR)/plateau.o $(OBJDIR)/tuile.o
$(CC) $(OBJDIR)/test_honshu.o $(OBJDIR)/plateau.o $(OBJDIR)/tuile.o -o tests
$(OBJDIR)/plateau.o: $(SRCDIR)/plateau.c $(SRCDIR)/plateau.h
$(CC) -c $(SRCDIR)/plateau.c -o $(OBJDIR)/plateau.o
$(OBJDIR)/tuile.o: $(SRCDIR)/tuile.c $(SRCDIR)/tuile.h
$(CC) -c $(SRCDIR)/tuile.c -o $(OBJDIR)/tuile.o
$(OBJDIR)/main.o: $(SRCDIR)/main.c
$(CC) -c -I src $(SRCDIR)/main.c $# -lm
$(OBJDIR)/test_honshu.o: $(SRCDIR)/test_honshu.c
$(CC) -c -I src $(SRCDIR)/test_honshu.c $# -lm
doxygen:
$(DOXYGEN) -g
$(DOXYGEN) Doxyfile
clean:
rm *.o
rm honshu
But I have the following message "no rules to make "src/test_honshu.c", necessary for "obj.test_honshu.o", do you have an idea ? Thanks !

Makefile objects from .c .cpp and .S sources

I am facing a problem with my makefile. I am trying to compile .c; .cpp and .S files from ./src/. The objects should go into ./obj/ and the binaries into ./bin/. With my current file, it tries to searches for files in ./src/, but tries to compile objectfiles for each extension. So for example, if it finds kernel.cpp, it will try to compile kernel.S and kernel.c, but they are not there, so i get an error.
Here is my code:
TARGET = kernel
CC = gcc
LD = ld
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SRCS = $(wildcard $(SRCDIR)/*.c) $(wildcard $(SRCDIR)/*.cpp) $(wildcard $(SRCDIR)/*.S)
HDR = $(wildcard $(SRCDIR)/*.h)
OBJS = $(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) $(SRCS:$(SRCDIR)/%.S=$(OBJDIR)/%.o)
rm = rm -f
ASFLAGS = -m64
CFLAGS = -m64 -Wall -g -fno-stack-protector -nostdinc
LDFLAGS = -m elf_x86_64 -Ttext=0x100000
$(BINDIR)/$(TARGET): $(OBJS)
$(LD) $(OBJS) $(LDFLAGS) -o $#
$(OBJS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
$(OBJS): $(OBJDIR)/%.o : $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $#
$(OBJS): $(OBJDIR)/%.o : $(SRCDIR)/%.S
$(CC) $(ASFLAGS) -c $< -o $#
.PHONY: clean
clean:
$(rm) $(OBJS)
.PHONY: remove
remove:
$(rm) $(BINDIR)/$(TARGET)
I might try to separate SRCS into SRCS_Cpp and so on... But i don't know if that's the best solution. I am pretty new to makefiles^^
I think i found the solution^^
TARGET = kernel
CC = gcc
LD = ld
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SRCS_c = $(wildcard $(SRCDIR)/*.c)
SRCS_cpp = $(wildcard $(SRCDIR)/*.cpp)
SRCS_S = $(wildcard $(SRCDIR)/*.S)
HDR = $(wildcard $(SRCDIR)/*.h)
OBJS = $(SRCS_c:$(SRCDIR)/%.c=$(OBJDIR)/%_c.o) $(SRCS_cpp:$(SRCDIR)/%.cpp=$(OBJDIR)/%_cpp.o) $(SRCS_S:$(SRCDIR)/%.S=$(OBJDIR)/%_S.o)
rm = rm -f
ASFLAGS = -m64
CFLAGS = -m64 -Wall -g -fno-stack-protector -nostdinc
LDFLAGS = -m elf_x86_64 -Ttext=0x100000
$(BINDIR)/$(TARGET): $(OBJS)
$(LD) $(OBJS) $(LDFLAGS) -o $#
$(OBJDIR)/%_c.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR)/%_cpp.o : $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR)/%_S.o : $(SRCDIR)/%.S
$(CC) $(ASFLAGS) -c $< -o $#
.PHONY: clean
clean:
$(rm) $(OBJS)
.PHONY: remove
remove:
$(rm) $(BINDIR)/$(TARGET)
Is there something i do wrong? I am trying to compile a kernel without the use of a cross-compiler^^

Object files are not created in sub directory but in main directory

I have the following code in my makefile:
#Compiler
CC = g++
IDIR = headers
SRCDIR = sources
ODIR = obj
LIBS = -lncurses
CFLAGS = -I$(IDIR)
DE = Cow.h Sheep.h
DES = $(patsubst %,$(IDIR)/%,$(DE))
_O = Cow.o Sheep.o
OB = $(patsubst %,$(ODIR)/%,$(_O))
all: make
./make
make: $(OB) $(ODIR)/main.o $(DES)
$(CC) -W -Wall -o $# $^ $(CFLAGS) $(LIBS)
$(ODIR)/%.o: $(SRCDIR)/%.c $(DES)
$(CC) -W -Wall -c -o $# $< $(CFLAGS)
$(ODIR)/main.o: $(SRCDIR)/main.cpp
$(CC) -c -o $# $< $(CFLAGS)
But when I run make in the terminal, the object files are being created, but in the project directory (where the makefile is saved) and not in the obj sub directory.

Resources