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 $# $^
Related
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 $# $<
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/*
This is a part of my makefile :
SRC = ./
DIRS = src libs/maths libs/struct
BIN_DIR = ./bin/
SRC_DIRS= $(foreach dir, $(DIRS), $(addprefix $(SRC), $(dir)))
SRC_TEST= $(sort $(SRC_DIRS))
SRCS = $(foreach msrc, $(SRC_DIRS), $(wildcard $(msrc)/*.c))
DEL_PRE = $(foreach target, $(SRCS), $(notdir $(target)))
ADD_PRE = $(foreach target, $(DEL_PRE), $(addprefix $(BIN_DIR), $(target)))
OBJS = $(ADD_PRE:.c=.o)
.PHONY: all clean re
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) -o $# $(LDLIBS)
$(OBJS): $(SRCS)
$(CC) -o $# -c $<
When i use make all, i have in output :
gcc -o bin/main.o -c src/main.c
gcc -o bin/cosin.o -c src/main.c
gcc -o bin/pears.o -c src/main.c
gcc -o bin/outil.o -c src/main.c
gcc -o bin/verif.o -c src/main.c
But i would like to have for each target, it assigned dependency :
gcc -o bin/main.o -c src/main.c
gcc -o bin/cosin.o -c libs/maths/cosin.c
gcc -o bin/pears.o -c libs/maths/pears.c
gcc -o bin/outil.o -c libs/struct/outil.c
gcc -o bin/verif.o -c libs/struct/verif.c
How can i fix it ?
This seems like a very common misconception; I just answered effectively this same question yesterday. I'm not sure where it comes from or how to combat it.
This rule:
$(OBJS): $(SRCS)
$(CC) -o $# -c $<
does not somehow magically combine the contents of the OBJS variable and the SRCS variable to figure out how they match up. The variable references are simply expanded, and the result is this:
bin/main.o bin/cosin.o ... : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
which is the same as if you'd written this:
bin/main.o : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
bin/cosin.o : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
...
Now, you can hopefully see why you compile the same file: in every rule you have the same prerequisites, so $< is always the first one, which is always src/main.c.
There are multiple ways to work this but if you really want to have all the source files from different directories compiled into object files in the same directory your job is harder, because there's no common pattern that will match them all. In this case the simplest thing to do is use VPATH for directory search: replace the above rule with this:
$(BIN_DIR)/%.o : %.c
$(CC) -o $# -c $<
then tell make how to find your source files, like this:
VPATH := $(sort $(dir $(SRCS))
Be aware this method can't be used for any source files that are themselves generated output that make is expected to create.
I have add.c sub.c in current directory and compile them through makefile.
I do the following:
program 1:
objs=$(patsubst %.cpp, %.o, $(wildcard *.cpp))
$(objs): %.o : %.cpp
g++ -o $# -c $<
program 2:
objs=$(patsubst %.cpp, %.o, $(wildcard *.cpp))
$(objs): $(objs:.o=.cpp)
g++ -o $# -c $<
Program 1 compiles successfully. But program 2 gets the following command:
g++ -o sub.o -c sub.cpp
g++ -o add.o -c sub.cpp
So what's the diferrence between these two programs?
The rule in makefile 1 is equivalent to
sub.o: sub.cpp
g++ -o $# -c $<
add.o: add.cpp
g++ -o $# -c $<
which works correctly.
The rule in makefile 2 expands to
sub.o add.o: sub.cpp add.cpp
g++ -o $# -c $<
Which says that each of those two targets depends on both source files. Note that the automatic variable $< expands to the first prerequisite, which in this case is sub.cpp. So that's the only source file that the rule uses, even when attempting to build add.o.
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)