How to produce different objects with the same file - makefile

I am trying to modify a Makefile, and I can't find the rule for that.
The following doesn't work. I don't know how to write the src to obj rules.
# foo.c bar.c main.c
SRC = $(wildcard *.c)
OBJ_1 = $(patsubst %.c,%_1.o,$(SRC))
OBJ_2 = $(patsubst %.c,%_2.o,$(SRC))
GCC1 = vtcc
GCC2 = vtcc
LD_FLAGS= -lm -lpthread
all: a1 a2
# executables :
a1: $(OBJ_1)
$(GCC1) $(LDFLAGS) $^ -o $#
a2: $(OBJ_2)
$(GCC2) $(LDFLAGS) $^ -o $#
# objects :
$(OBJ_1) : $(SRC)
$(GCC1) -c $< -o $#
$(OBJ_2) : $(SRC)
$(GCC2) -c $< -o $#

It's hard tell what your question is, but I think the last two rules should be:
# objects :
$(OBJ_1) : %_1.o : %.c
$(GCC1) -c $< -o $#
$(OBJ_2) : %_2.o : %.c
$(GCC2) -c $< -o $#

Related

Makefile specify different compilation flags based on two groups of objects

In my makefile I compile files like shown below:
a_SRCS = $(shell find $(DIR1) -name '*.c')
b_SRCS = $(shell find $(DIR2) -name '*.c')
a_OBJS = $(patsubst $(SRC)/%.c,$(OBJ)/%.o,$(a_SRCS))
b_OBJS = $(patsubst $(SRC)/%.c,$(OBJ)/%.o,$(b_SRCS))
$(BIN): $(a_OBJS) $(b_OBJS)
$(CC) $^ -o $# $(LIBS)
$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $#
I would like to specify different compilation flags based on if the current object to be generated $(OBJ)/%.o belongs to $a_OBJS or $b_OBJS. Something like below. Is it possible to do?
#for a_OBJS
$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(INCLUDES) $(a_CFLAGS) -c $< -o $#
#for b_OBJS
$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(INCLUDES) $(b_CFLAGS) -c $< -o $#
You can use target-specific variables:
$(a_OBJS) : EXTRA_FLAGS = -DA_OBJ
$(b_OBJS) : EXTRA_FLAGS = -DB_OBJ
$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(INCLUDES) $(EXTRA_FLAGS) -c $< -o $#

How to build apps in subfolders with Makefile

I'm trying to write a Makefile that will build apps stored in subfolders. So structure of the folders is as follows:
examples/
Makefile
hello_world/
file1.c
main.c
**hello_world** <- expected build result
example1/
otherfile.c
main.c
**example1** <- expected build result
example2/
main.c
...
**example2** <- expected build result
My Makefile (simplified) looks like this:
EXAMPLES := hello_world example1 example2
SRC = $(wildcard */*.c)
OBJ = ${SRC:.c=.o}
OUT = $(foreach e, $(EXAMPLES), $(addprefix $(e)/,$(e)) )
CC := gcc
all: examples
$(OBJ): $(SRC)
#$(CC) -c $< -o $#
$(OUT): $(OBJ)
$(CC) $(filter $(dir $#)%,$^) -o $# $(LDFLAGS)
clean:
#rm -f $(OUT) $(OBJ)
Is there a way to make it work? Or maybe I should have Makefile in each folder separately?
This rule seems to solve my problem, matches outputs to .o, but filters files that are passed for linking with filter function
$(OUT): $(OBJ)
$(CC) $(filter $(dir $#)%,$^) -o $# $(LDFLAGS)
Replaced old rule:
$(OUT): $(OBJ)
$(CC) $^ -o $#
with
examples: $(OBJ)
$(foreach e, $(EXAMPLES), \
$(CC) $(wildcard $(e)/*.o) -o $(e)/$(e) $(LDFLAGS); \
)
almost works now, after clean, the compilation works as expected, only linking fails ($(wildcard $(e)/*.o) is empty?), after second run examples are created as expected
Inspired by comments by Beta and MadScientist, I think I have a solution:
EXAMPLES := hello_world example1 example2
SRC = $(wildcard */*.c)
OBJ = ${SRC:.c=.o}
OUT = $(foreach e, $(EXAMPLES), $(addprefix $(e)/,$(e)) )
CC := gcc
all: $(OUT)
%.o: %.c
#$(CC) $(CFLAGS) -c $< -o $#
$(OUT): $(OBJ)
#$(CC) $(filter $(dir $#)%,$^) -o $# $(LDFLAGS)
clean:
#rm -f $(OUT) $(OBJ)
.PHONY: all clean

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^^

Project Makefile problems with Google Test

For the life of me I cannot figure out how to remove the mv statements in the following makefile
TEST_DIR = ../gtest
USER_DIR = src
TESTS_DIR = tests
OBJ_DIR = obj
CPPFLAGS += -isystem $(GTEST_DIR)/include -I$(USER_DIR)
CXXFLAGS += -g -Wall -Wextra
TESTS = test
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
all : $(TESTS)
clean :
rm -rf obj
rm -rf bin
mkdir obj
mkdir bin
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
$(OBJ_DIR)/gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc
mv gtest-all.o obj/gtest-all.o
$(OBJ_DIR)/gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc
mv gtest_main.o obj/gtest_main.o
$(OBJ_DIR)/gtest.a : $(OBJ_DIR)/gtest-all.o
$(AR) $(ARFLAGS) $# $^
$(OBJ_DIR)/gtest_main.a : $(OBJ_DIR)/gtest-all.o $(OBJ_DIR)/gtest_main.o
$(AR) $(ARFLAGS) $# $^
$(OBJ_DIR)/addition.o : $(USER_DIR)/addition.cpp $(USER_DIR)/addition.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
mv addition.o obj/addition.o
$(OBJ_DIR)/test.o : $(TESTS_DIR)/test.cpp $(USER_DIR)/addition.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TESTS_DIR)/test.cpp
mv test.o obj/test.o
test : $(OBJ_DIR)/addition.o $(OBJ_DIR)/test.o $(OBJ_DIR)/gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $#
The problem is the mv test.o obj/test.o line and the others like it. I know there is a way to have make do this automatically for you but for the life of me I cannot find/figure it out.
This is the precanned makefile that comes with google test that I have modified to work for me.
Something like
CPPFLAGS += -MMD -MP
gtest_objs := $(OBJ_DIR)/gtest_all.o $(OBJ_DIR)/gtest_main.o
my_objs := $(OBJ_DIR)/addition.o $(OBJ_DIR)/test.o
all_objs := $(gtest_objs) $(objs)
deps := $(all_objs:.o=.d)
$(gtest_objs): CPPFLAGS += -I$(GTEST_DIR)
$(gtest_objs): $(OBJ_DIR)/gtest_%.o: $(GTEST_DIR)/src/gtest_%.cc
$(my_objs): $(OBJ_DIR)/%.o: $(USER_DIR)/%.cpp
$(all_objs):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
-include $(deps)
The rule for all_objs is copied from the builtin rule, and the deps-related stuff will generate dependencies for you automatically.

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