aracyla
aracyla

Reputation: 58

Makefile implicit rule not working

I have this makefile and i'm trying to write some test targets

#This a make file of serial communication driver that i'm writing.
#serial_target would be a target to test this driver isolated.
 
CC = gcc
 
DISPLAY_STRING = -DDISPLAY_STRING
LFLAGS = 
CFLAGS = $(DISPLAY_STRING) 
 
#mains macros
BUILD_DIR =build
SOURCE_DIR =src
HEADER_DIR =src
BIN_DIR =bin
 
SOURCES = $(wildcard $(SOURCE_DIR)/*.c)
OBJECTS =  $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(SOURCES))
HEADERS =  $(patsubst $(SOURCE_DIR)/%.c, $(HEADER_DIR)/%.h, $(SOURCES))
 
 
#serial_tests
TEST_DIR=src/test
TEST_TARGET=serial_test
 
TEST_SOURCES = $(wildcard $(TEST_DIR)/*_test.c) \
    $(SOURCES)
TEST_OBJECTS = $(filter %.o ,$(patsubst %.c, $(BUILD_DIR)/%.o, $(subst /, , $(TEST_SOURCES))))
TEST_HEADERS = $(TEST_SOURCES:.c=.h)
 
 
all:
    
serial_test: $(TEST_OBJECTS)
    $(CC) $(CFLAGS) -I$(SOURCE_DIR) -I$(HEADER_DIR) -o $(BIN_DIR)/$@ $^
    
$(BUILD_DIR)/%.c.o: %.c $(HEADERS)
    $(CC) $(CFLAGS) -I$(HEADER_DIR) -I$(SOURCE_DIR) -c $< -o $@     
 
setup:
    mkdir $(BUILD_DIR)
    mkdir $(BIN_DIR)
    
clean:
    rm -rf $(EXEC) $(OBJECTS)

When running "make serial_test", I'm always getting this:

make: *** No rule to make target `build/serial_test.o', needed by `serial_test'. Stop.

Here's the doubt. Why I'm receiving this error if the rule $(BUILD_DIR)/%.c.o exists?

Edit

To make sure that everything else was working I've tried this(this works fine)

serial_test: $(TEST_OBJECTS)
    $(CC) $(CFLAGS) -I$(SOURCE_DIR) -I$(HEADER_DIR) -o $(BIN_DIR)/$@ $^
build/serial_test.o: src/test/serial_test.c
    $(CC) $(CFLAGS) -I$(HEADER_DIR) -I$(SOURCE_DIR) -c $< -o $@ 
build/serialCom_xsens.o: src/serialCom_xsens.c
    $(CC) $(CFLAGS) -I$(HEADER_DIR) -I$(SOURCE_DIR) -c $< -o $@

To make sure that the variable BUILD_DIR was note empty i did this:

$(BUILD_DIR)/serial_test.o: %.c
    $(CC) $(CFLAGS) -I$(HEADER_DIR) -I$(SOURCE_DIR) -c $< -o $@

With this code above, I got another error:

make: *** No rule to make target `%.c', needed by `build/serial_test.o'. Stop.

Upvotes: 0

Views: 1856

Answers (2)

user657267
user657267

Reputation: 21030

  • You're mixing pattern and suffix rules, stick with the pattern rule
  • Not entirely sure what you're trying to do with TEST_OBJECTS
  • You're making every object depend on every header, use dependency generation instead
  • The rule for serial_test is broken, always use $@ as the output of any given rule
  • Make the directories a prerequisite
  • Recycle the built-in recipes (COMPILE.c, LINK.o)
display_string := -Ddisplay_string

source_dir := src
header_dir := src
build_dir  := build
bin_dir    := bin
 
sources := $(wildcard $(source_dir)/*.c)
objects := $(sources:$(source_dir)/%.c=$(build_dir)/%.o)
 
test_dir    := src/test
test_target := serial_test
 
test_sources := $(wildcard $(test_dir)/*_test.c)
test_objects := $(test_sources:$(test_dir)/%.c=$(build_dir)/%.o) $(objects)
 
deps := $(test_objects:%.o=%.d)

CPPFLAGS := $(display_string) -I$(header_dir) -MMD -MP
    
$(bin_dir)/serial_test: $(test_objects) | $(bin_dir)
    $(LINK.o) $^ $(LDLIBS) -o $@
    
$(build_dir)/%.o: $(source_dir)/%.c | $(build_dir)
    $(COMPILE.c) $(OUTPUT_OPTION) $<
 
$(build_dir) $(bin_dir): ; mkdir $@
    
clean: ; $(RM) serial_test $(objects) $(deps)

-include $(deps)

Upvotes: 1

Colonel Thirty Two
Colonel Thirty Two

Reputation: 26609

Take a hard look at your pattern rule:

$(BUILD_DIR)/%.c.o: %.c $(HEADERS)

It matches filenames with a .c.o extension. The error message indicates that you're trying to build build/serial_test.o, which doesn't match the pattern because the path doesn't end in .c.o.

Fix your pattern in your build rule, or your patsubst to replace .c with .c.o, so that the pattern rule will match.

Upvotes: 1

Related Questions