Makefile rule using variable name - makefile

I'm trying to write a makefile to build a release or debug version of my program using the same makefile (the version selection will be based on env. variable).
My first try was the following:
PROG := myProgram
ifdef DEBUG
BUILD := debug
else
BUILD := release
endif
BIN := $(BUILD)/$(PROG)
SRC := main.c
OBJDIR := $(BUILD)/obj/
OBJ := $(addprefix $(OBJDIR), $(SRC:%.c=%.o))
$(OBJDIR)/%.o: %.c
$(GCC) $(CFLAGS) -o $# $<
$(BIN): $(OBJ)
$(GCC) $(OBJ) -o $# $(LDFLAGS)
all: $(BIN)
When I try to make my project, I got the following error:
make: *** No rule to make target `release/obj/main.o', needed by `release/myProgram'. Stop.
When I replaced the rule $(OBJDIR)/%.o by $(BUILD)/obj/%.o, make is able to match the rule and build my objects file.
I am confused: why the first rule is not working?
My understanding is make will expand variables in rules before execution, so, in the end, both rules will looks the same?
What is the best practice in this case?
Thanks in advance for your help.

You put in an extra slash:
OBJDIR := $(BUILD)/obj/
$(OBJDIR)/%.o: %.c
...
The rule, as written, will match the target release/obj//main.o, but there is no rule that matches release/obj/main.o.
Just remove the offending slash:
OBJDIR := $(BUILD)/obj

Related

no rule make object file

I need help, simply because I need help:
SRC=src/main.c
OBJ_PATH=bin
OBJS := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
all:$(OBJ_PATH)/target.exe
$(OBJ_PATH)/target.exe: $(OBJ_PATH) $(OBJS)
$(CC) $(OBJS) -o $(OBJ_PATH)/target.exe
$(OBJ_PATH):
mkdir -p bin
$(OBJ_PATH)/%.o:%.c
mkdir -p bin
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
.PHONY: clean
clean:
rm -f $(OBJ_PATH)/*
when running it gives this:
make: *** No rule to make target 'bin/main.o', needed by 'bin/target.exe'. Stop.
If I leave the objects in the same folder as the c files, it works.
I just need some help, maybe it is something simple that I am not seeing.
Thanks guys.
This is wrong:
$(OBJ_PATH)/%.o: %.c
When make wants to build a file bin/main.o. It matches the target pattern bin/%.o, with a stem of main (the part that matches the %). After replacing the prerequisite pattern %.c with main, make will try to find the prerequisite main.c.
But, that file doesn't exist and make has no idea how to create it. So, that pattern doesn't match and make tries to find a different pattern that will build bin/main.o, but there isn't one, so make says there's no way to build that target.
You need to make your pattern rule:
$(OBJ_PATH)/%.o: src/%.c
so that when make replaces % in the prerequisite pattern it yields src/main.c, which exists, and this will work.
There are other problems with your makefile; for example this is a bad idea:
$(OBJ_PATH)/target.exe: $(OBJ_PATH) $(OBJS)
You never(*) want to use a directory like $(OBJ_PATH) as a simple prerequisite.
Also, this:
OBJS := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
can be more easily written:
OBJS := $(patsubst src/%.c,$(OBJ_PATH)/%.o,$(SRC))
(*) There can indeed be very specific situations where having a directory as a prerequisite can be useful but they are rare and you shouldn't do it unless you fully understand why it's usually not what you want.

gmake wildcard function not generating target

I'm using gmake on Windows with MinGW. This is a snippet of the makefile:
SRCS = ..\path\to\srcs\*.c*
SRCS := $(wildcard $(SRCS))
OBJS := $(addsuffix .o,$(basename $(SRCS)))
$(OBJS) : $(SRCS)
$(CC) $(FLGAS) $(INCLUDES) "$<"
I'm getting the following:
gmake: *** No targets. Stop.
If I define SRCS, for instance, as ..\path\to\srcs\a.c, it works.
Am I using wildcard in the correct manner?
I'm using GNU Make 3.81.
make doesn't cope well with backslashes; you need to double each, or (better) switch to forward slashes instead.
Your recipe overrides the built-in rules for creating object files from C files with a broken one, though.
Your recipe claims that all $(OBJS) will be produced from a single compilation which has all the $(SRCS) as dependencies, but only reads the first one ($< pro $^). It's probably better to just say what you want and let make take it from there.
.PHONY: all
all: $(OBJS)
%.o: ../path/to/srcs/%.c

makefile how to output to separate build directory

I have this directory structure:
makefile
src
foo.c
build
My goal is simply to build foo.c and output the build files to the build directory.
I have the following makefile:
SRCS_DIR := ./src
BUILD_DIR := ./build
SRCS := $(shell find $(SRCS_DIR) -name "*.c")
OBJS := $(subst $(SRCS_DIR),$(BUILD_DIR),$(SRCS))
OBJS := $(OBJS:.c=.o)
test.exe: $(OBJS)
gcc $(OBJS) -o $#
%.o: %.c
gcc -c $< -o $#
The problem is the pattern rule. One of the object files is build/foo.o. The problem is that %.c gets turned into build/foo.c, which doesn't exist. What I want %.c to be is src/foo.c instead, but I have no idea how to do that.
The stem of the pattern must match exactly. So if you want a pattern that will put things into a different directory, you have to modify the pattern so that the non-matching parts are not part of the stem. So you can write:
build/%.o : src/%.o
gcc -c $< -o $#
so that the % matches only the common string.

Automatic makefile with source and object files in different directories

I'm attempting to put together a makefile that will take source files from a directory (eg. src), compile them into object files in another directory (eg. build), and then take those files and create a static library from them in the main directory.
Here's my effort so far:
LIBNAME := test
LIBNAME := lib$(LIBNAME).a
CC = g++
CFLAGS := -O0 -Wall -g -fPIC
INCLUDE := include
SOURCE := src
BUILD := build
CPPFILES := $(foreach dir, $(SOURCE)/, $(notdir $(wildcard $(SOURCE)/*.cpp)))
OBJFILES := $(addprefix $(BUILD)/, $(CPPFILES:.cpp=.o))
all: $(LIBNAME) $(OBJFILES)
$(LIBNAME): $(OBJFILES)
ar rcs $(LIBNAME) $(OBJFILES)
.cpp.o:
$(CC) $(CFLAGS) -I$(INCLUDE) -c $< -o $#
clean:
rm -rf $(BUILD)
Which gives me this:
make: *** No rule to make target `build/point.o', needed by `libtest.a'. Stop
You seem do be requiring GNU make anyway (foreach function), so rewriting the old-style suffix rule .cpp.o to
$(BUILD)/%.o : $(SOURCE)/%.cpp
should do the trick. You might also try using the VPATH variable or the vpath directive, see the make manual for these.
In general, you might just tackle this problem with automake, which does most of this stuff for you.

Makefile mirror build directory

I need to create Makefile that compiles .c files with a lot of subdirs (sources directory goes in around 5 level depth) and I need to place the object files in the mirrored build directory. So far, I have created this Makefile:
CC := gcc.exe
AS := as.exe
CFLAGS = -DCORE_SW_VERSION='"$(CORE_SW_VERSION)"' -Wall -mA6 -c -fmessage-length=0 -Hsdata0
CFLAGS += -fgnu89-inline -mno-volatile-cache $(INCLUDE) -Hon=each_function_in_own_section -Xcrc -std=c99 -O1
CORE_SW_VERSION:=CORE.07.01.04.01.03.01.R
HAL_SW_VERSION:=16.01.06.01.06.00
MODE_CORE := dev
MODE_HAL := dev
OBJDIR := $(shell pwd)/$(TARGET12) #TARGET12 is a make parameter
INCLUDE := $(shell cat ./$(TARGET12)_include.txt)
SOURCEDIR := ../sources
CSRC := $(shell find $(SOURCEDIR) -name '*.c')
EXCLUDES := $(shell cat ./$(TARGET12)_exclude.txt)
OBJ := $(CSRC:.c=.o)
OBJS := $(patsubst ../%.c,$(OBJDIR)/%.o,$(CSRC))
.PHONY: $(TARGET12)
$(TARGET12): $(OBJS)
$(AR) -r $(CORE_SW_VERSION).a $(OBJS)
$(OBJS): $(CSRC)
mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $(patsubst ../%,$(OBJDIR)/%,$#)
If I define rule for $(OBJS) this way, $< is always the first .c file in $(CSRC).
If I define $(OBJS) this way:
$(OBJS): %.o: %.c
mkdir -p $(dir $#)
$(CP) $< $#
I get error that there is no rule to make target for .c file. But I see that make is looking for .c file in build mirrored directory, and it should look at the source dir. Do you maybe know how this could be arranged?
Thanks you in advance!
The rule $(OBJS): %.o: %.c means something like this: when trying to create a .o file, use this rule if the corresponding .c file exists. For example: when make is looking for a way to create $(OBJDIR)/foo.o, it will look for $(OBJDIR)/foo.c.
In your case this file does not exists, so the rule is ignored.
What you want is rather something like this:
$(OBJS): $(OBJDIR)/%.o: $(SOURCEDIR)/%.c
mkdir -p $(dir $#)
$(CP) $< $#
The first rule for $(OBJS) you tried, states that every object file individually depends on all source files. Surely that's not correct.
Your second attempt is better, although the recipe is weird. Fix that and use VPATH to make make find the sources.

Resources