Makefile not doing what I want - Compiling same thing twice - c++

CXX := g++
CXX_FLAGS := -std=c++17
SRC_DIR := ./src
LIB_DIR := $(SRC_DIR)/lib
OBJ_DIR := $(SRC_DIR)/obj
BIN_DIR := $(SRC_DIR)/bin
BIN_DEBUG := $(BIN_DIR)/Test-debug
BIN_RELEASE := $(BIN_DIR)/Test
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
LIB_FILES := $(wildcard $(LIB_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES)) $(patsubst $(LIB_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(LIB_FILES))
$(BIN_RELEASE): $(OBJ_FILES)
$(CXX) $(CXX_FLAGS) -o $# $^
$(OBJ_FILES): $(SRC_FILES) $(LIB_FILES)
$(CXX) $(CXX_FLAGS) -c -o $# $<
clean:
rm ./src/obj/*.o
rm ./bin/*
run:
$(BIN_RELEASE)
This is my Makefile and it is doing the same g++ -c command in a row and then failing in the linking because it tries to link the a file to it self. Or can someone say how you debug a Makefile.

This is wrong:
$(OBJ_FILES): $(SRC_FILES) $(LIB_FILES)
$(CXX) $(CXX_FLAGS) -c -o $# $<
Say you have src/foo.cpp and src/bar.cpp in SRC_FILES. Now OBJ_FILES is src/obj/foo.o and src/obj/bar.o. Now the above rule expands like this:
src/obj/foo.o src/obj/bar.o: src/foo.cpp src/bar.cpp
$(CXX) $(CXX_FLAGS) -c -o $# $<
It's not the case that make will intuit what you want to do here and match up each object file with the source file, or something like that. The above means exactly the same thing as if you'd written these rules:
src/obj/foo.o: src/foo.cpp src/bar.cpp
$(CXX) $(CXX_FLAGS) -c -o $# $<
src/obj/bar.o: src/foo.cpp src/bar.cpp
$(CXX) $(CXX_FLAGS) -c -o $# $<
Now you can see why every compile line compiles the same source file: the $< variable expands to the first prerequisite, and for every object file the first prerequisite is always the same (here, src/foo.cpp).
You need to use a pattern rule here, telling make how to build one single file. And since you're building things in two different ways, you actually need two pattern rules.
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXX_FLAGS) -c -o $# $<
$(OBJ_DIR)/%.o: $(LIB_DIR)/%.cpp
$(CXX) $(CXX_FLAGS) -c -o $# $<

Related

How do I create object files into a different directory than Makefile's one?

I'm new on using Makefiles because I've been programming with VS2019 on Windows, solving all my compilation and linking problems.
This is the result:
BUILD_DIR:= ./build
SRC_DIRS := ./src
INCL_DIR := ./includes
CC := /usr/bin/g++ #Compiler used
LVERSION := -std=c++17 #Language Version
CXXFLAGS := -g #Cpp flags
CFLAGS := -Wall #Compiler Flags
LFLAGS := -lstdc++fs #Linker Flags
SRCS := Audio.cpp Song.cpp Visual.cpp VisualSong.cpp
LIBS :=
INCLUDES := $(SRCS:%.cpp=$(INCL_DIR)/%.h)
OBJS := $(SRCS:%.cpp=$(BUILD_DIR)/%.o)
PROG := progName.exe
progName: $(OBJS)
$(CC) $(CFLAGS) $(CXXFLAGS) -o $(INCLUDES) $(PROG) $(OBJS)
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
.PHONY: progName
clean:
/bin/rm -rf build/*.o $(PROG) includes/*.gch
This makefile works until is trying to look on objects file, supposedly created on build directory but, in the end, they're created in Makefile's directory, which is an inconvenient since all what i want is to have separated files for organization purposes.
I know that somehow using implicit rules that are using the dst's directory should do the trick, but i think that I'm missing something on the way...
I'm on a Windows 10 machine with WSL for Ubuntu, but this shouldn't be a problem at all for this problem.
Could anyone explain to me what am I missing?
Look at this rule:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
Ostensibly it is the rule to build build/foo.o, but the recipe ($(CC)...) actually builds foo.o. There is an easy fix:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^ -o $#
Once that works I suggest you make one further change:
$(BUILD_DIR)/%.o: $(SRC_DIRS)/%.cpp $(INCL_DIR)/%.h
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $< -o $#

Compile each cpp file in separate directory

The results for this topic strangely all did not work.
Finally I found a variant that is logical for me and works from the same order.
CC := g++
CFLAGS := -g -Wall
objects = test helloworld
all: $(objects)
$(objects): %: %.cpp
$(CC) $(CFLAGS) -o $# $<
I have tried a lot and probably fail to fully understand the line %: %.cpp.
My interpretation is: I take from every object the dependency which in turn is based on a file which is then traceable to a .cpp file.
My theory is test expects test.o and then test.cpp.
How do I rewrite this to directory?
I have already read some things with wildcards and a pattern replace.
Like
SRC_DIR := src
OBJ_DIR := obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...
main.exe: $(OBJ_FILES)
g++ $(LDFLAGS) -o $# $^
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
But the behavior was not the expected.
When 2 cpp files were in the folder the result was
g++ -o helloworld.o helloworld.cpp
g++ -o helloworld.o test.cpp
Or vice versa that only the cpp file was always the same.
I have the feeling to miss something extremely.
Update:
The make version is
GNU Make 4.3
Built for aarch64-unknown-linux-android
The Goal
What I would like to achieve is
src/
Test.cpp
Helloworld.cpp
Obj/
Make :
Obj/
Helloworld.out
Test.out
Try this:
CXX := g++
CXXFLAGS := -g -Wall
TARGETS=obj/test.out obj/helloworld.out
all:$(TARGETS)
obj/%.out:src/%.cpp
$(CXX) $(CXXFLAGS) -o $# $^
clean:
rm obj/*

Makefile not updating one particular file

I have a makefile which works fine for all other files, but not for the main.cpp file. When I change the main.cpp file, it does not update main.o.
here is the makefile:
CXX = g++
SRCF = main.cpp Animal.cpp
SRC = $(addprefix src/, $(SRCF))
VER = Debug
CXXFLAGS = -Wall -std=c++17
EXE = Animal
OBJF = $(subst .cpp,.o, $(SRCF))
OBJ = $(addprefix src/obj/, $(OBJF) )
#PKG = `pkg-config --libs --cflags sdl2`
$(VER)/$(EXE) : $(OBJ)
$(CXX) $(CXXFLGS) -o $# $< $(PKG)
src/obj/%.o:src/%.cpp src/%.h
$(CXX) $(CXXFLGS) -c -o $# $< $(PKG)
clean:
rm -rf $(EXE) $(OBJ)
print-% : ; #echo $* = $($*)
When I change Animal.h or Animal.cpp it updates Animals.o and the Animal executable. But why does it not work for main ?? I have specified how to update main.o in this line :-
src/obj/%.o:src/%.cpp src/%.h
$(CXX) $(CXXFLGS) -c -o $# $< $(PKG)
Please help me and thanks it advance :)
In the Introduction to Pattern Rules section of GNU Make's manual:
In order for the pattern rule to apply, its target pattern must match the file name under consideration and all of its prerequisites (after pattern substitution) must name files that exist or can be made.
Therefore, if there is no src/main.h (or can't be made), the following pattern rule will not match against src/obj/main.o:
src/obj/%.o: src/%.cpp src/%.h
$(CXX) $(CXXFLGS) -c -o $# $< $(PKG)
You need an additional pattern rule without the src/%.h prerequisite:
src/obj/%.o: src/%.cpp
$(CXX) $(CXXFLGS) -c -o $# $< $(PKG)

make objects in Makefile

I have the following Makefile:
CXX = g++
CXXFLAGS = -Wall -g
SOURCES := divisor.cpp multiplier.cpp
OBJECTS := ${SOURCES:.cpp=.o}
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
%: %.o $(OBJECTS)
$(CXX) $(CXXFLAGS) $#.o -o $#.out
$(OBJECTS): %.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
clean:
rm -f *.o
What I want this make file is the following:
If I add a source file called 123.cpp to the working directory, I want it to generate its object file and then link the compiled sources specified in $(SOURCES), this means:
g++ -c -Wall -g 123.cpp
g++ multipler.o divisor.o 123.o -o 123
If multiplier.cpp or divisor.cpp has to be generated or updated, I want make to do it.
But I'm failing, because divisor.o and multiplier.o are not automatically generated
How may I achieve this?
Edit
Just to clarify, there are two types of source code files in the working directory: divisor.cpp, multipler.cpp is one type, and any other file, say, 123.cpp is the other type. In a sense, divisor.cpp and multiplier.cpp are requisites to the other source files.
I want to automate the process of compiling the prerequisites and link them when compiling the other files
g++ -c multiplier.cpp
g++ -c divisor.cpp
g++ -c -Wall -g 123.cpp
g++ multipler.o divisor.o 123.o -o 123
Use the wildcard function:
SOURCES := $(wildcard *.cpp)
Then, you can remove your "special" source files:
SPECIAL_SOURCES := divisor.cpp multiplier.cpp
SOURCES := $(filter-out $(SPECIAL_SOURCES),$(SOURCES))
And change your rules to build the stuff you actually want:
$(SPECIAL_OBJECTS) := $(SPECIAL_SOURCES:.cpp=.o)
$(BINARIES) := $(patsubst .cpp,,$(SOURCES))
$(SPECIAL_OBJECTS) : %.o : %.cpp
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BINARIES) : % : %.cpp $(SPECIAL_OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^

Refactoring Makefile for object files with different flags

I have some source .cpp files in the same directory, and I want to compile them as object file.
Some of them needs "extra" libraries (same libs for all files) to be linked with and some of them don't, I'd like to write general rules to match the right files, without writing specific rule for each file with extra flags.
More in detail I want to refactor my Makefile so that I don't have to specify different rules for the source files SourceFileOpenCVNeeded.cpp OCVAlsoHere.cpp TheSameForMe.cpp (now they're few, but they could be many more).
Here is what my makefile actually looks like:
CPP_FILES := $(wildcard src/*.cpp)
OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
MAIN_SRC := main.cpp
OCV_LIBS := `pkg-config opencv --libs`
OCV_PATH := `pkg-config opencv --cflags`
MY_LIB := launcher
LD_FLAGS := $(MAIN_SRC) -L. -l$(MY_LIB) $(OCV_LIBS)
CC_FLAGS := -c -fPIC
AR_FLAGS := rcs
STATIC_LIB := lib$(MY_LIB).a
CC := g++
EXEC := test
all: lib main
main:
$(CC) $(LD_FLAGS) -o $(EXEC)
lib: $(OBJ_FILES)
ar $(AR_FLAGS) $(STATIC_LIB) $^
obj/SourceFileOpenCVNeeded.o: src/SourceFileOpenCVNeeded.cpp
$(CC) $(OCV_PATH) $(CC_FLAGS) $(OCV_LIBS) -c -o $# $<
obj/OCVAlsoHere.o: src/OCVAlsoHere.cpp
$(CC) $(OCV_PATH) $(CC_FLAGS) $(OCV_LIBS) -c -o $# $<
obj/TheSameForMe.o: src/TheSameForMe.cpp
$(CC) $(OCV_PATH) $(CC_FLAGS) $(OCV_LIBS) -c -o $# $<
obj/%.o: src/%.cpp
$(CC) $(CC_FLAGS) -c -o $# $<
clean:
rm -f $(OBJ_FILES) $(STATIC_LIB) $(EXEC)
PS: any other improvements that can be added to my Makefile?
You might be able to use target-specific variables, e.g. (not tested)
EXTRA_FLAGS=
obj/TheSameForMe.o: EXTRA_FLAGS="$(OCV_PATH) $(OCV_LIBS)"
obj/%.o: src/%.cpp
$(CC) $(CC_FLAGS) $(EXTRA_FLAGS) -c -o $# $<