makefile parse target to define dependencies - makefile

I have source files in several directories and I want to compile them in a one unique temporary directory, currently I use this target to create my object files :
$(BUILD_DIR)/%.o :
#echo "Compiling $#"
$(VERBOSE) $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) -o $# $(shell echo "$(SOURCES)" | sed 's/ /\n/g' | sed -nr '/\/$(*F)\.c/p')
It is working well but when I modify a source file, the object one is not recompiled. So I have to add the source file to the dependencies.
But this target doesn't work :
$(BUILD_DIR)/%.o : $(shell echo "$(SOURCES)" | sed 's/ /\n/g' | sed -nr '/\/$(*F)\.c/p')
#echo "Compiling $#"
$(VERBOSE) $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) -o $# $^
Is there any way to use target name in dependencies ?

Assuming you are using GNU Make...
Use a pattern rule like:
obj/%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
to tell make that an object file obj/<name>.o is to be compiled from a source file
<name>.c
In conjunction with this, use the VPATH special variable
to inform make of directories in which it should look for any <name>.c, if it is not
in the current directory.
Also, add an order-only prerequisite
to the pattern rule to ensure that the directory (obj) to which your object files are compiled
exists when needed:
obj/%.o: %.c | obj
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
So for example, with project structure:
./
-- Makefile
-- aa/
-- main.c
-- bb/
-- foo.c
-- obj/ #<-- Compile object files in here
-- prog #<- program to be built
And:
Makefile
VPATH := aa:bb
SRCS := foo.c main.c
OBJS := $(addprefix obj/, $(SRCS:.c=.o))
.PHONY: all clean
all: prog
prog: $(OBJS)
$(CC) $(LDFLAGS) -o $# $^ $(LDLIBS)
obj/%.o: %.c | obj
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
obj:
mkdir $#
clean:
$(RM) $(OBJS) prog
the build runs like:
$ make
cc -c -o obj/foo.o bb/foo.c
cc -c -o obj/main.o aa/main.c
cc -o prog obj/foo.o obj/main.o

Related

How to create rule for .o files from 2 different folders with .c files using makefile

I want to have the possibility to build output files from different folders depending on the command.
./source_files/ - folder with *.c files for make build2 and make unit_test commands.
./source_files/unit_test/ - folder with *.c files for make unit_testcommands
I have 2 commands:
this works - command make build2 should take files ./source_files/*.c, make ./build/*.o from them and create <name.a> library;
this doesn't work - command make unit_test should take files ./source_files/*.c and also ./source_files/unit_tests/*.c make ./build/*.o from them and create test.out file.
make unit_test generates the output:
make: *** No rule to make target 'build/test_main.o', needed by 'unit_test'. Stop.
I have 2 rules for *.o files. I guess I have to combine them into one, but I have no idea how to do that. Can you help me with it, please?
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | $(BUILDDIR)
$(CC) -c $< $(INCLDIR) -o $#
$(BUILDDIR)/%.o: $(UNITSRCS)/%.c | $(BUILDDIR)
$(CC) -c $< $(INCLDIR) -o $#
makefile:
#Compiler flags
CC := gcc
INCLDIR := -I./includes
LIBS := -lcunit
#Directories and files
BUILDDIR := build
SRCDIR := source_files
SRCS := $(wildcard $(SRCDIR)/*.c)
OBJS := $(SRCS:$(SRCDIR)/%.c=$(BUILDDIR)/%.o)
UNITDIR := $(SRCDIR)/unit_tests
UNITSRCS := $(wildcard $(UNITDIR)/*.c)
UNITOBJS := $(UNITSRCS:$(UNITDIR)/%.c=$(BUILDDIR)/%.o)
STLIB := $(BUILDDIR)/libbinary_tree.a
$(BUILDDIR):
mkdir $(BUILDDIR)
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | $(BUILDDIR)
$(CC) -c $< $(INCLDIR) -o $#
$(BUILDDIR)/%.o: $(UNITSRCS)/%.c | $(BUILDDIR)
$(CC) -c $< $(INCLDIR) -o $#
.PHONY: unit_test
unit_test: $(OBJS) $(UNITOBJS)
$(CC) $(OBJS) $(UNITOBJS) $(INCLDIR) $(LIBS) -o $(BUILDDIR)/test_main.out
.PHONY: build2
build2: $(OBJS)
ar -rcs $(STLIB) $(OBJS)
.PHONY: clean
clean:
rm -r $(BUILDDIR)
This rule is OK:
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | $(BUILDDIR)
$(CC) -c $< $(INCLDIR) -o $#
But this rule is wrong:
$(BUILDDIR)/%.o: $(UNITSRCS)/%.c | $(BUILDDIR)
$(CC) -c $< $(INCLDIR) -o $#
Just as in the first rule, you want to have $(UNITDIR)/%.c not $(UNITSRCS)/%.c. After make expands the variable the latter will clearly be wrong.

How to make N .o files from N .c files using makefile?

I have 2 .c files that defined in the makefile:
SOURCES = main.c \
memory.c
and I want to build 2 .o files using 1 command "make compile-all" (and don't link them), but can't understand how to do this.
I could create var for objective files and add .PHONY command:
OBJS=$(SOURCES:.c=.o)
.PHONY: compile-all
But what should be written next?
I guess it should be something similar with this:
%.o: %.c $(INCLUDES)
$(CC) -c $< $(CFLAGS) -o $#
But there's no way I can succeed.
Thank you in advance!
BASENAME := main
TARGET := $(BASENAME).out
OBJS=$(SOURCES:.c=.o)
%.i: %.c
$(CC) -E $< $(CFLAGS) -o $#
%.asm: %.c
$(CC) -S $< $(CFLAGS) -o $#
%.o: %.c
$(CC) -c $< $(CFLAGS) -o $#
.PHONY: build
build:$(TARGET)
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(CFLAGS) $(PLATFORM_FLAGS) $(LDFLAGS) -o $#
.PHONY: clean
clean:
rm -f $(OBJS) $(TARGET) *.i *.asm $(BASENAME).map
.PHONY: compile-all
compile-all: $(OBJS)
make compile-all creates .o files from all .c files.

How to move .o on project folder?

I wrote this Makefile to move all .o of the project inside a directory 'obj' in the main folder.
Directories
.:
actor/ lib/ Controller.cpp Controller.h Controller.o doc.txt main.cpp main.o Makefile uno VRP*
./actor:
Customer.cpp Customer.h Customer.o Depot.cpp Depot.h Depot.o Route.cpp Route.h Route.o Vehicle.cpp Vehicle.h Vehicle.o
./lib:
Search.cpp Search.h Search.o Utils.cpp Utils.h Utils.o VRP.cpp VRP.h VRP.o
Makefile
CXX=g++
RM=rm -rf
BIN_NAME=VRP
CPPFLAGS=-s -O2 -std=gnu++11 -Wall
SRCS=$(wildcard *.cpp actor/*.cpp lib/*.cpp)
OBJS=$(subst .cpp,.o,$(SRCS))
all: $(OBJS_DIR) $(BIN_NAME)
$(OBJS_DIR):
mkdir $(OBJS_DIR)
$OBJS_DIR)/%.o : $(SRCS)
$(CXX) $(CPPFLAGS) -c $< -o $#
$(BIN_NAME) : $(OBJS)
$(CXX) -o $# $^
debug:
$(CXX) -g $(CPPFLAGS) -o $(BIN_NAME) $(OBJS)
.PHONY : all clean
clean:
$(RM) $(OBJS) $(OBJS_DIR)
dist-clean: clean
$(RM) $(BIN_NAME)
How can I make it works?
This line $OBJS_DIR)/%.o : $(SRCS) sets the prerequisites of every file that matches $OBJS_DIR)/%.o to all the files in $(SRCS) that's not even close to what you want. (It is also a typo. You are missing the opening ().
You can't write a single rule for what you are trying to do here you need three pattern rules (or one with a vpath/VPATH setup).
$(OBJS_DIR)/%.o: %.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
$(OBJS_DIR)/%.o: actor/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
$(OBJS_DIR)/%.o: lib/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
That being said you don't actually have any targets that match $(OBJS_DIR)/%.o since the value of $(OBJS) is Controller.o ... actor/Customer.o ... lib/Search.o. To fix that you also need:
OBJS=$(addprefix $(OBJS_DIR)/,$(patsubst %.cpp,%.o,$(notdir $(SRCS))))
$(notdir) to get just the filename from the source files.
$(patsubst) instead of $(subst) just for correctness (subst would have modified a Bar.cpp.cpp file to Bar.o.o).
$(addprefix) to add the $(OBJS_DIR) prefix to the bare object file names.

Makefile does not work properly

I've this folder structure
project
|_src
| |_test
| |_main.cpp
|_Makefile
This is my makefile (trying to adapt from this link):
CC = g++
RM = rm
WFLAGS = -c -Wall -W
LDFLAGS =
SRCTESTD = src/test
EXECUTABLE = test
OBJD = .obj
DEPD = .dep
SRCSTEST = $(SRCTESTD)/main.cpp
OBJECTSTEST = $(patsubst %.cpp, $(OBJD)/test/%.o, $(notdir $(SRCSTEST)))
DEPDSTEST = $(patsubst %.cpp, $(DEPD)/test/%.d, $(notdir $(SRCSTEST)))
all: $(SRCSTEST) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTSTEST)
$(CC) $(LDFLAGS) $(OBJECTSTEST) -o $#
.cpp.o:
$(CC) $(WFLAGS) $< -o $#
It does not work, and I've this error
make: *** No rule to make target `.obj/test/main.o', needed by `test'. Stop.
What I'm doing wrong? Sorry for trivial question, but I'm a make newbie.
The link shows outdated methods, such as suffix rules. Making dependencies can also be done during compilation by gcc/g++.
As for the rest, here is it :
EXE := test
SRCDIR := src
OBJDIR := .obj
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEP := $(OBJ:.o=.d)
LDLIBS := # -l flags
LDFLAGS := # -L flags
CPPFLAGS := -MMD -MP # -I flags also
CXXFLAGS := -W -Wall # no -c flag here
.PHONY: all clean fclean re
all: $(EXE)
clean:
$(RM) -r $(OBJDIR)
fclean: clean
$(RM) $(EXE)
re: fclean all
-include $(DEP)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
No redefinition of internally defined variables, no suffix rules, correct linking step and dependencies generation.
Update: To avoid calling mkdir for every source file, one should use order-only prerequisites and the special target .SECONDEXPANSION.
Change this block:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
To this:
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(#D)/
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
%/:
mkdir $*
The error means make can't find a correct rule to build your object files. Your tree structure lacks some informations: only one file ? Where are the others ? Anyway, here are some hints:
In the last two lines, you are using an obsolete feature of make: suffix rules. I suggest you switch to a pattern rule, which is functionaly equivalent.
Say something like:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
Another thing (that shouldn't be a problem here): you are using the variable CC which is internally defined as the default C compiler. It's okay because you redefine it, but as your sources seem to be C++ files, why not use the variable CXX, that is internally defined as the C++ compiler ?
Lastly, to make sure your set of files are correctly defined, you can print them with a dummy show target, see here.
show:
#echo "OBJECTSTEST=$(OBJECTSTEST)"
...

Automatic dependency list not generated in a different setting of directory structure

I have the following directory structure:
root-----Makefile
|-----src #all source files here.
|-----obj #all object files here.
|-----bin #the final target.
The contents of Makefile is given below:
TARGET = exec
CC = gcc
CFLAGS = -g -I.
LINKER = gcc -o
LFLAGS = -I. -lm -lpthread
BINDIR = bin
OBJDIR = obj
SRCDIR = src
INTERFACE = interface
STD = -std=c99
PROGRAMSOURCES := $(wildcard $(SRCDIR)/*.c)
PROGRAMINTERFACE:= $(wildcard $(INTERFACE)/*.h)
OBJECTS := $(PROGRAMSOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $(OBJECTS) $(STD)
#pull the dependencies to the .o files
-include $(OBJECTS:.o=.d)
$(OBJECTS) : $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $# $(STD)
$(CC) $(CFLAGS) -MM $< > $*.d
#mv -f $*.d $*.d.tmp
#sed -e 's|.*:|$(OBJDIR)/$*.o:|' < $*.d.tmp > $*.d
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d`
#rm -f $*.d.tmp`
.PHONY : run
run :`
./$(BINDIR)/$(TARGET) ${TYPE} ${INP_FILE}
I have used the tutorial here have been modified to suit the corresponding directory structure. But something has got wrong in the modification and I cannot understand what. The dependency list generated in the .d files is not taken into account i.e. if I change a .h the rules are not compiling.
You appear to be producing the dependency files in root/, but looking for them in obj/.
Try changing this:
-include $(OBJECTS:.o=.d)
to this:
-include *.d
There are other improvements you can make, once the makefile is working.
EDIT: further improvements
1) The choice of where to put the dependency files is mainly arbitrary, but if we put them in obj/, we can simplify the $(OBJECTS) rule quite a lot:
-include $(OBJDIR)/*.d
$(OBJECTS): $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -MMD -MP -c $< -o $# $(STD)
2) PROGRAMINTERFACE and INTERFACE aren't used, so we can remove them.
3) Putting -o in LINKER like that is dangerous. And don't forget the automatic variable $^:
LINKER = gcc
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $^ $(STD)
4) It would be wise to give run a prerequisite:
run: $(BINDIR)/$(TARGET)
./$< ${TYPE} ${INP_FILE}

Resources