My question is about compiling error on linux. Every time I try to compile the program it gives me this error. I tried different things without luck.
*** No rule to make target '/pthread.d', needed by '/thread.exe'. Stop.
The makefile for the program ( pthread is as follow:
SOURCES=pthread.cpp
OBJECTS=$(addprefix $(BUILD_DIR)/, $(SOURCES:.cpp=.o))
DEPS=$(addprefix $(BUILD_DIR)/, $(SOURCES:.cpp=.d))
EXE=thread.exe
CXXFLAGS=-I.
LIBS=-pthread
//Making for host > make ARCH=host
ifeq ($(ARCH),host)
CXX=g++
BUILD_DIR=build/host
BIN_DIR=bin/host
endif
//Making for target > make ARCH= target
ifeq ($(ARCH),target)
CXX=arm-rpizw-g++
BUILD_DIR=build/target
BIN_DIR=bin/target
endif
all: $(BIN_DIR)/$(EXE)
$(BIN_DIR)/$(EXE): $(DEPS) $(OBJECTS)
mkdir -p $(BIN_DIR)
$(CXX) $(CXXFLAGS) -o $# $(OBJECTS)
$(BUILD_DIR)/%.d: %.cpp
mkdir -p $(BUILD_DIR)
$(CXX) -MT$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
$(BUILD_DIR)/%.o: %.cpp
mkdir -p $(BUILD_DIR)
$(CXX) -c $< -o $# $(CXXFLAGS)
ifneq ($(MAKECMDGOALS), $(filter $(MAKECMDGOALS),clean help))
-include $(DEPS)
endif
clean:
-rm -rf bin/
-rm -rf build/
You likely have spaces after BUILD_DIR=build/target. Thus, $(DEPS) resolves to:
build/target /pthread.d
..., and thus make will try to make /pthread.d (and build/target...). When assigning a value, make discards any preceding spaces, but not trailing spaces. It will drop a trailing comment, but it will not drop whitespace between the end of the line and the comment.
For debugging this type of problem, it's often useful to add $(info) lines into your makefile as so:
$(info DEPS=_$(DEPS)_)
and then run to see if there are any unexpected values.
Related
I'm working on a Makefile that i can use on most of my school projects.
I only did basics makefile before and never had a problem, but for this one i wanted to put some colors etc...
And it relink everytime i make it.
I think the relink come from my echos ? But i'm not sure.
Here is my makefile :
#GENERAL
CC = clang++
FLAGS = -Wall -Wextra -Werror -std=c++98
RM = rm -rf
#PROJET
EXEC = ClapTrap
#FILES
SRCS = ClapTrap.cpp main.cpp
OBJS = $(SRCS:.cpp=.o)
OBJSDIR = objects/
#REGLES
.cpp.o: $(SRCS)
mkdir -p $(OBJSDIR)
echo "$(BLUE)Compiling $^ ..$(CLEAR)"
$(CC) $(FLAGS) -c $< -o $(addprefix $(OBJSDIR), $#)
echo " $(YELLOW)$(addprefix $(OBJSDIR), $#)$(CLEAR) [$(GREEN)OK$(CLEAR)]"
all: $(EXEC)
$(EXEC): $(OBJS)
echo "$(BLUE)========================================$(CLEAR)"
echo "$(BLUE) Compiling binary file ..$(CLEAR)"
echo "$(BLUE)========================================$(CLEAR)"
$(CC) -o $(EXEC) $(addprefix $(OBJSDIR), $^) $(FLAGS)
echo "$(YELLOW)$(EXEC)$(GREEN) is now ready to use !$(CLEAR)"
clean:
#$(RM) $(OBJSDIR)
#echo "$(RED)Cleaning up..$(CLEAR)"
fclean: clean
#$(RM) $(EXEC)
#echo -n "$(RED)$(EXEC)$(CLEAR)"
re: fclean all
.PHONY: all
Thank's for reading !
EDIT :
So i removed SRCS from my .cpp.o rules dependencies, but still relinking.
Here the updated Makefile :
#FILES
SRCS = ClapTrap.cpp main.cpp
OBJS = $(SRCS:.cpp=.o)
OBJSDIR = objects
#REGLES
.cpp.o:
echo "$(BLUE)Compiling $(YELLOW)$^$(BLUE) ..$(CLEAR)"
mkdir -p $(OBJSDIR)
$(CC) $(FLAGS) -c $< -o $#
mv $# $(OBJSDIR)
echo "$(BLUE) - $(YELLOW)$#$(CLEAR) [$(GREEN)OK$(CLEAR)]"
all: $(EXEC)
$(EXEC): $(OBJS)
echo "$(BLUE)========================================$(CLEAR)"
echo "$(BLUE) Compiling binary file ..$(CLEAR)"
echo "$(BLUE)========================================$(CLEAR)"
$(CC) $(FLAGS) $(STD) $(addprefix $(OBJSDIR)/, $(OBJS)) -o $(EXEC)
echo "$(YELLOW)$(EXEC)$(GREEN) is now ready to use !$(CLEAR)"
This is wrong:
$(CC) $(FLAGS) -c $< -o $#
mv $# $(OBJSDIR)
When make runs your recipe it will put the file it expects you to build into the $# automatic variable. If your makefile builds some OTHER file, not the one it asked you to build, then the next time you run make it will see that the file it wants doesn't exist (because you didn't build it, you build some other file) and so it's always out of date.
Your rules must always build exactly the file $#, not some other file.
It's not actually possible to write a makefile that puts targets in a different directory, using suffix rules. They can only create files in the same directory. That's (one reason) why GNU make supports pattern rules which are much more flexible.
If you have to write a POSIX conforming makefile that doesn't support pattern rules, and you want to put the object files in some other directory, all you can do is write out all the targets and their rules explicitly.
I am very new to C++ makefiles and I have the makefile below which I mostly copied from somewhere on the internet. My contribution to the makefile is the "test" target, which is the problem.
My code is organized in include (for headers), src (for sources) and test (for test sources) directories. For the standard target I want to build all files in the src folder which also includes the main.cpp file. To make the test build I want to build all files in the src folder except main.cpp and additionally all files in the test folder. I hoped that my test target would achieve that, but it fails. It just build the files from the standard target.
How can I correct my mistakes.
Thank you
The makefile I use:
APP=myappname
SRC_DIR=src
INC_DIR=include
OBJ_DIR=obj
BIN_DIR=bin
TEST_SRC_DIR=test
MAIN_CPP_NAME=main.cpp
CC=g++
LD=g++
CFLAGS=-O2 -c -Wall -std=c++17
LFLGAS=
DFLAGS=-g3 -O0 -DDEBUG
INCFLAGS=-I$(INC_DIR)
SOURCES=$(wildcard $(SRC_DIR)/*.cpp)
HEADERS=$(wildcard $(INC_DIR)/*.hpp)
OBJECTS=$(SOURCES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
DEPENDS=$(OBJ_DIR)/.depends
.PHONY: all
all: $(BIN_DIR)/$(APP)
.PHONY: debug
debug: CFLAGS+=$(DFLAGS)
debug: all
.PHONY: test
test: SOURCES=$(wildcard $(SRC_DIR)/*.cpp)
test: SOURCES=$(filter-out $(SRC_DIR)/$(MAIN_CPP_NAME), $(SOURCES))
test: OBJECTS=$(SOURCES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
test: TEST_SOURCES=$(wildcard $(TEST_SRC_DIR)/*.cpp)
test: OBJECTS+=$(TEST_SOURCES:$(TEST_SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
test: all
$(BIN_DIR)/$(APP): $(OBJECTS) | $(BIN_DIR)
$(LD) $(LFLGAS) -o $# $^
$(OBJ_DIR)/%.o: | $(OBJ_DIR)
$(CC) $(CFLAGS) $(INCFLAGS) -o $# $<
$(DEPENDS): $(SOURCES) | $(OBJ_DIR)
$(CC) $(INCFLAGS) -MM $(SOURCES) | sed -e 's!^!$(OBJ_DIR)/!' >$#
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPENDS)
endif
$(BIN_DIR):
mkdir -p $#
$(OBJ_DIR):
mkdir -p $#
.PHONY: clean
clean:
rm -rf $(BIN_DIR) $(OBJ_DIR)
You're trying to write a sophisticated makefile without understanding the basics, which is almost impossible. Let's try a very simple approach.
First, suppose the source files are
src/main.cpp
src/func.cpp
test/unit.cpp
test/global.cpp
Now we need a list of the object files that test will need.
SOURCES:=$(wildcard $(SRC_DIR)/*.cpp) # this will be src/main.cpp src/func.cpp
NON_MAIN_SOURCES:=$(filter-out $(SRC_DIR)/$(MAIN_CPP_NAME), $(SOURCES)) # this will be src/func.cpp
TEST_DIR_SOURCES:=$(wildcard $(TEST_SRC_DIR)/*.cpp) # this will be test/unit.cpp test/global.cpp
TEST_SOURCES:=$(notdir $(NON_MAIN_SOURCES) $(TEST_DIR_SOURCES)) # this will be func.cpp unit.cpp global.cpp
TEST_OBJECTS:=$(patsubst %.cpp,$(OBJ_DIR)/%.o,$(TEST_SOURCES)) # this will be obj/func.o obj/unit.o obj/global.o
(Note that you must avoid name collisions between src/ and test/, e.g. having a src/func.cpp and also a test/func.cpp. This is a consequence of your directory structure; there's no way for the makefile to work around it.)
Now we must tell Make how to build those object files. We can start with a rule for the sources in src:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $(INCFLAGS) -o $# $<
(I have omitted the $(OBJ_DIR) prerequisite for simplicity. For now, you will be responsible for making sure that obj/ exists.)
Now for the sources in test. A crude but effective approach is to add a rule for them:
$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp
$(CC) $(CFLAGS) $(INCFLAGS) -o $# $<
There are more sophisticated ways, but you must master the basics first.
Finally, the rule to build bin/mytestname:
$(BIN_DIR)/mytestname: $(TEST_OBJECTS)
$(LD) $(LFLAGS) -o $# $^
That's enough for now.
Edit
After writing this I noticed some things and went back over the file. I changed the line:
$(CXX) -MT $(BUILD_DIR)/$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
To the following:
$(CXX) -MM $(CXXFLAGS) $^ > $#
Since it seemed kind of redundant to first take the generated dependency files, name them into .o files and then turn them back into .d files.
Now the target actually makes, but it will still not remake when the header files are changed.
Original
I have this makefile I created as part of a course, and everything works fine when running make, building for both the host and target. The problem arises when a change occurs in a header file(example: part1.h), this implementation was made specifically to take this into account, and it seemed to work.
A few weeks on now, and I finally realised it doesn't work as intended, as it will not recompile after a change to any of the header files. (part1.h or part2.h).
I took a look into the dependency files generated by the target:
$(BUILD_DIR)/%.d: %.cpp
An example of part1.d has the following contents:
build/host/build/host/part1.o: part1.cpp part1.h
To me, the double directory listing is an error, but so I tried changing the line:
$(CXX) -MT $(BUILD_DIR)/$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
To the following, removing the BUILD_DIR variable:
$(CXX) -MT $(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
Doing this solves the double directory listing problem, but gives me a linker error:
build/host/main.o: file not recognized: File format not recognized
I'm trying to find some solution to this, which will make sure that the program is recompiled when changes are made to the header files.
I'm trying to figure out what I'm missing, I've looked at the related literature and everything seems to match up.
SOURCES=main.cpp part1.cpp part2.cpp
OBJECTS=$(addprefix $(BUILD_DIR)/,$(SOURCES:.cpp=.o))
DEPS=$(addprefix $(BUILD_DIR)/,$(SOURCES:.cpp=.d))
EXE=prog
CXXFLAGS=-I.
#Make sure that default choice for make is the host
ifndef (${ARCH})
ARCH=host
endif
#Making for host
ifeq (${ARCH},host)
CXX=g++
BUILD_DIR=build/host
BIN_DIR=bin/host
endif
# Making for target
ifeq (${ARCH},target)
CXX=arm-devkit-g++
BUILD_DIR=build/target
BIN_DIR=bin/target
endif
$(BIN_DIR)/$(EXE): $(DEPS) $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $(OBJECTS)
#Generate dependency files. Place them in build/host or build/target depending on choice
$(BUILD_DIR)/%.d: %.cpp
$(CXX) -MT $(BUILD_DIR)/$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
#Generate object files. Place them in build/host or build/target, depending on choice.
$(BUILD_DIR)/%.o: %.cpp
$(CXX) -o $# -c $^
#Create the build dir,
${BUILD_DIR}:
mkdir -p ${BUILD_DIR}
#Create the bin dir
${BIN_DIR}:
mkdir -p ${BIN_DIR}
.PHONY:clean
clean:
rm -f $(BUILD_DIR)/*.o $(BIN_DIR)/$(EXE) $(BUILD_DIR)/*.d
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
If you generate the dependencies as part of the compilation not only do you avoid having to take the extra step, you also rely on the compiler to generate the correct paths. This entails a few other changes to your makefile but I found it simpler to just rewrite it, make has a number of features to simplify some of the other operations.
arch ?= host
build_dir := build/$(arch)
bin_dir := bin/$(arch)
ifeq ($(arch),target)
prefix := arm-devkit-
endif
sources := main.cpp part1.cpp part2.cpp
objects := $(sources:%.cpp=$(build_dir)/%.o)
deps := $(objects:.o=.d)
target := $(bin_dir)/prog
CXX := $(prefix)$(CXX)
CPPFLAGS := -MMD -MP
$(target): CC := $(CXX)
$(target): $(objects) | $(bin_dir)
$(LINK.o) $^ $(LDLIBS) -o $#
$(build_dir)/%.o: %.cpp | $(build_dir)
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
$(build_dir) $(bin_dir): ; mkdir -p $#
.PHONY: clean
clean: ; $(RM) $(target) $(objects) $(deps)
-include $(deps)
I'm new to Makefile. While trying to write a generic Makefile which could be used in most of my projects with least modification, I encountered a problem (simplified as the following):
My "project" looks like:
proj/
src1.cpp
subdir1/
src2.cpp
Makefile
Part of the Makefile:
OBJ := bin/src1.o bin/subdir1/src2.o
OBJ_DIR := bin/ bin/subdir1/
PROGRAMS := prog1
define compile_template =
$(1)/%.o: %.cpp
mkdir -p $$(#D)
$$(CXX) $$(CXXFLAGS) -c $$< -o $$#
endef
define PROGRAM_template =
$(1): $$(OBJ)
$$(CXX) $$(LDFLAGS) $$^ -o $$# $$(LDLIBS)
endef
$(foreach odir,$(OBJ_DIR),$(eval $(call compile_template,$(odir))))
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
And the error is:
gmake: *** No rule to make target `bin/src1.o', needed by `proj1'. Stop.
Another question is should I wrote my own Makefile or use automake etc if I only compile in particular machines (So I have control to the compiler, OS, ...)?
The best way to debug issues like this (problems with eval) is to replace the $(eval ...) function with a call to $(info ...). This will print out the text that make is parsing and it's usually pretty obvious what your problem is. If you rewrite your eval lines to this:
$(foreach odir,$(OBJ_DIR),$(info $(call compile_template,$(odir))))
$(foreach prog,$(PROGRAMS),$(info $(call PROGRAM_template,$(prog))))
(and fixing your obvious syntax error, the space between : and = in the first line) you see:
bin//%.o: %.cpp
mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
bin/subdir1//%.o: %.cpp
mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
prog1: $(OBJ)
$(CXX) $(LDFLAGS) $^ -o $# $(LDLIBS)
From this you can see the prog1 depends on bin/src1.o and bin/subdir1/src2.o so make wants to build bin/src1.o. It looks through your rules, but in make's internal matching syntax bin//%.o does not match bin/src1.o because of the extra slash.
Change your assignment to remove the trailing slash and it should work better:
OBJ_DIR := bin bin/subdir1
Consider the following Makefile:
# <include global configuration Makefile>
INCL = -I../include \
-I<whatever>
CPPFLAGS=$(DEFS) $(INCL)
CXXFLAGS = -O0 -g -Wall -fmessage-length=0
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
all: $(OBJS)
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
depend: .depend
.depend: $(SRCS)
$(CPP) $(CPPFLAGS) -M $^ > $#
clean:
rm -f $(OBJS)
rm .depend
-include .depend
This Makefile creates an #include dependency chain using the g++ -M command, and includes it. This can be a rather long process. The problem is that this file is generated even if make clean is called, when this file would be deleted anyway. Is ther a way to conditionally include this file, and not bother creating it if the clean target is run?
Something like this:
ifneq ($(MAKECMDGOALS),clean)
-include .depend
endif
See the make manual page on Goals for more information
Edit: -include cannot be tab indented, otherwise it is ignored.
You can do such dependencies for free (i.e., at no runtime cost) during the compile. When you run clean, the dependencies are naturally not remade. See the section Combining Compilation and Dependency Generation in Paul Smith's Advanced Auto-Dependency Generation paper.