I have this makefile below. While it compiles properly at the moment, I'm running into a really weird and tedious issue where I have to run make twice to compile the code.
The first time I call make, I get this error:
./src/gravity.cpp:1:31: fatal error: gravity.h: No such file or directory
compilation terminated.
I have a lot more source files added under OBJECTS = .., and that message repeats for each one of them. Of course, this would indicate that I didn't link the headers correctly, except that when I run make again, everything compiles smoothly.
An interesting observation may be that main.cpp doesn't complain about a missing gravity.h, but I'm not sure how it relates.
I have header guards on all my header files. If it helps, this is for a C++ SDL/OpenGL application.
My makefile is below. Thanks!
OUTPUT_NAME = output_file
INC_DIR = ./inc
SRC_DIR = ./src
BIN_DIR = ./bin
INCLUDES= \
-I${SRC_DIR}
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
INC := $(shell find $(INC_DIR) -name '*.h')
CXX = g++
CXXFLAGS = -g -Wall -std=c++0x -I${INC_DIR} -I./lib/glm
LIBFLAGS = -lSDL -lGL -lGLU -lglut
OBJECTS = \
${BIN_DIR}/main.o \
${BIN_DIR}/gravity.o
DEPS = $(BIN_DIR)/${OUTPUT_NAME}.deps
all: ${DEPS} ${OUTPUT_NAME}
${DEPS}: ${INC} ${SRC}
#${CXX} -M ${SRC} > ${DEPS}
${OUTPUT_NAME}: ${OBJECTS}
${CXX} ${CXXFLAGS} ${OBJECTS} -o ${OUTPUT_NAME} ${LIBFLAGS}
${OBJECTS}: ${BIN_DIR}/%.o : ${SRC_DIR}/%.cpp
${CXX} ${CXXFLAGS} $< -c -o $#
force:
$(MAKE) fullclean
$(MAKE)
clean:
rm ${OBJECTS} ${OUTPUT_NAME}
fullclean:
rm ${OBJECTS} ${DEPS} ${OUTPUT_NAME}
run:
clear
./${OUTPUT_NAME}
style:
astyle --style=java --indent=spaces=4 ${SRC} ${INC}
.PHONY: all clean fullclean run style force
include $(DEPS)
The rule to build your .deps file:
${DEPS}: ${INC} ${SRC}
#${CXX} -M ${SRC} > ${DEPS}
will unconditionally create the ${DEPS} file even if the invocation of the C++ compiler fails. (It probably would have been better to have used -o.)
It is also missing the -I options which would allow it to find the header files.
As a result of the second error, it will fail when run. As a result of the first error, it will nevertheless create a .deps file. The second time you invoke make, it will not trigger the ${DEPS} rule because the .deps file is newer than any dependency.
Also, I don't understand
INCLUDES= \
-I${SRC_DIR}
It's not correct (I think: it should be INC_DIR, and it's missing ./lib/glm), and you don't use it anywhere.
Related
I have the following project structure: a folder called "src" with all the .cpp, a folder called "include" with the .h, a folder called "build" for the .o (object files), another folder called "dep" for the .d files (dependencies) and finally another folder called "bin" for the executables.
Given that, I have done this makefile to carry out the build process
OPTIONS := -O2 -Wall
EXE_NAME = example.exe
BIN_PATH = bin/
BUILD_PATH = build/
DEP_PATH = dep/
INCLUDE_PATH = include/
SRC_PATH = src/
################################################################################
# get project files
ALL_CPP := $(shell find $(SRC_PATH) -type f -name "*.cpp")
ALL_H := $(shell find $(INCLUDE_PATH) -type f -name "*.h")
ALL_O := $(subst $(SRC_PATH),$(BUILD_PATH),$(subst .cpp,.o,$(ALL_CPP)))
ALL_D := $(subst $(SRC_PATH),$(DEP_PATH),$(subst .cpp,.d,$(ALL_CPP)))
all: $(BIN_PATH)$(EXE_NAME)
#linking
$(BIN_PATH)$(EXE_NAME): $(ALL_O)
g++ $(OPTIONS) -o $# $(ALL_O)
# generic build rule
$(BUILD_PATH)%.o: $(SRC_PATH)%.cpp
g++ $(OPTIONS) -c $< -o $(BUILD_PATH)$# -I$(INCLUDE_PATH) -MMD -MF $(DEP_PATH)$(#:.o=.d)
.PHONY: clean
clean:
rm $(ALL_D) $(ALL_O) $(BIN_PATH)$(EXE_NAME)
-include $(ALL_D)
But whenever I try to execute it, this error pops out:
make: *** No rule to make target 'build/file.o', needed by 'bin/example.exe'. Stop.
Which does not make sense, as there is a rule for building targets that end in ".o".
What might be going on here?
First, you should avoid using subst since it substitutes every instance of one set of text with another. Safer is to use patsubst:
ALL_O := $(patsubst $(SRC_PATH)%.cpp,$(BUILD_PATH)%.o,$(ALL_CPP))
ALL_D := $(patsubst $(SRC_PATH)%.cpp,$(DEP_PATH)%.d,$(ALL_CPP))
Second, your command line is wrong: $# already contains the path so you don't want to use $(BUILD_DIR)$#. You want just $# by itself. You'll have a similar problem for .d.
But I don't see any way to get the error you show (no rule to make target 'build/file.o') given the makefile you provide. Either there's something different about your makefile than what you have here or something mysterious is happening.
You can add the -d option to make to get some debug info.
Thanks to all who replied. As many of you suggested, the error I provided does not appear in the makefile version I posted, and that is because I did some code cleaning before posting which ironically end up solving the error (I had no idea the changes I made would be important). More precisely, I am sure the problem was with the line
$(BUILD_PATH)%.o: $(SRC_PATH)%.cpp
Which in the original makefile was
$(BUILD_PATH)%.o: %.cpp
I have also tried without the $(BUILD_PATH), which gave no luck, that's why I thought that line was not important.
I did some of the changes you suggested and the final working version of the Makefile is as follows
OPTIONS := -O2 -Wall -Wno-sign-compare -Wno-unused-parameter
EXE_NAME = example
BIN_PATH = bin/
BUILD_PATH = build/
DEP_PATH = dep/
INCLUDE_PATH = include/
SRC_PATH = src/
################################################################################
# get project files
ALL_CPP := $(shell find $(SRC_PATH) -type f -name "*.cpp")
ALL_H := $(shell find $(INCLUDE_PATH) -type f -name "*.h")
ALL_O := $(subst $(SRC_PATH),$(BUILD_PATH),$(subst .cpp,.o,$(ALL_CPP)))
ALL_D := $(subst $(SRC_PATH),$(DEP_PATH),$(subst .cpp,.d,$(ALL_CPP)))
all: $(BIN_PATH)$(EXE_NAME)
#linking
$(BIN_PATH)$(EXE_NAME): $(ALL_O)
#echo ' -> linking'
#g++ $(OPTIONS) -o $# $(ALL_O)
#echo Finished!
# generic build rule
$(BUILD_PATH)%.o: $(SRC_PATH)%.cpp
#echo ' -> building:' $<
#g++ $(OPTIONS) -c $< -o $# -I$(INCLUDE_PATH) -MMD -MF $(subst $(BUILD_PATH),$(DEP_PATH),$(#:.o=.d))
.PHONY: clean
clean:
#echo Removed files: $(ALL_D) $(ALL_O) $(BIN_PATH)$(EXE_NAME)
#rm $(ALL_D) $(ALL_O) $(BIN_PATH)$(EXE_NAME)
-include $(ALL_D)
I'm trying to write a makefile that contains some bash commands in order to collect the names of the cpp files from a folder.
SRC_FILES=""
CC = g++
CFLAGS = -g
gather-files:
for var in $$(cd ./src && (ls -all *.cpp | awk '{print $$9}')); \
do \
SRC_FILES+="./src/"+"$(var) "; \
done; \
game: gather-files
$(CC) -c $(CFLAGS) $(SRC_FILES)
The SRC_FILES and var variables seems not to update when I run the make game command.
What am I missing?
Ignore the relatively incomplete g++ command, I just want to know how to make the SRC_FILES variable contain all of the names of the cpp files in the src folder.
This is the output of make game:
g++ -c -g ""
clang: error: no input files
LATER EDIT:
Solution, as suggested:
SRC_FILES := $(wildcard src/*.cpp)
CC = g++
CFLAGS = -g
game: $(SRC_FILES)
$(CC) -c $(CFLAGS) $(SRC_FILES)
You are mixing shell commands with makefile commands. That's not valid. The entire recipe is sent to the shell to be run there. Once the recipe has been expanded (which happens once before the shell is invoked) the results cannot contain any make operations.
In short, it's not possible (technically it can be done but it's A Very Bad Idea (tm) so don't) to change make variables from within a shell recipe.
Why don't you use GNU make operations instead?
SRC_FILES := $(wildcard src/*.cpp)
game: $(SRC_FILES)
...
Of course, this is kind of a silly makefile because it will recompile ALL the source files if ANY source file changes. You could get equivalent behavior by just writing a script that ran the compiler.
Your 'Last Edit' is still not ideal, as it builds everthing every time. Try something like this:
SRC_FILES := $(wildcard src/*.cpp)
OBJ_FILES := $(SRC_FILES:.cpp=.o)
DEP_FILES := $(SRC_FILES:.cpp=.d)
#Important: this is =, not :=
DEP_FLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.d
game: $(OBJ_FILES)
$(CC) -o $# $(OBJ_FILES)
# Pattern rule to build .o files
$(OBJ_FILES): %.o : %.cpp %.d
$(CC) $(DEP_FLAGS) -c $(CFLAGS) $< -o $#
#dummy rule to prevent building .d files explicitly.
$(DEP_FILES):
include $(wildcard $(DEP_FILES))
As to what this does -- it first populates SRC_FILES with any cpp files it finds. It then generates a list of object and dependency files from that list. Then we do some magic dependency stuff, which is described here -- basically, when you compile a file, it generates a .d file with a list of all headers it depends on, so now, if anything changes, make knows to rebuild the .c file.
Then there's a static pattern rule to build all the .o files, and a rule to link them all together to the game. Last, but not least, it includes the DEP_FILES that happen to exist when you start make.
For this reason I downloaded the C++ library VTK and made a local build in the build subdirectory on a OSX environment.
I would like to compile a project using this library (particularly I am using the class vtkSmartPointer) with Makefile.
Consider for example the following source code:
#include<iostream>
#include<vtkSmartPointer.h>
#include<vtkCallbackCommand.h>
int main()
{
vtkSmartPointer<vtkCallbackCommand> keypressCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
std::cout<<"hello world\n";
return 0;
}
For the Makefile I started from the second answer in this post to which I aded VTK library path:
CXX = g++
# OpenCV trunk
CXXFLAGS = -std=c++11 \
-I ../VTK/Common/Core/ -I ../VTK/build/Common/Core/ -I ../VTK/build/Utilities/KWIML/ \
-I ../VTK/Utilities/KWIML/ \
-L../VTK/build/lib \
-lvtkCommon -lvtkFiltering -lvtkImaging -lvtkGraphics -lvtkGenericFiltering -lvtkIO
SOURCES := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $#
-include $(DEPENDS)
%.o: %.cpp Makefile
$(CXX) $(WARNING) $(CXXFLAGS) -MMD -MP -c $< -o $#
My environment variable DYLD_LIBRARY_PATH has the value ../cmake_bin_dir/instDir/lib:../VTK/build/lib/.
When I try to compile running make, I get the following error:
ld: library not found for -lvtkCommon
clang: error: linker command failed with exit code 1 (use -v to see invocation)
What part of the Makefile or program or step in the process is not correct?
Thank you in advance.
The current VTK library does not contain libVtkCommon.so (see package contents section https://www.archlinux.org/packages/community/x86_64/vtk/). Are you looking for libVtkCommonCore.so? If that is the case you have to change -lvtkCommon to -lvtkCommonCore in your Makefile. The same seems to be the case for some of the other included libraries.
I have read other questions asking similar things, alas I am still confused.
This is my current Makefile:
CC = g++
EXEFILE = template
IFLAGS= -I/usr/include/freetype2 -I../Camera
LFLAGS= -L/usr/lib/nvidia-375 -L/usr/local/lib -L/usr/include/GL -L/usr/local/include/freetype2 -L/usr/local/lib/
LIBS = -lglfw -lGL -lGLU -lOpenGL -lGLEW -pthread -lfreetype
SRC=*.cpp
DEPS=*.h
$(EXEFILE):
$(CC) -std=c++11 -o $(EXEFILE) -Wall -Wno-comment $(SRC) $(IFLAGS) $(LFLAGS) $(LIBS)
all: run clean
run: $(EXEFILE)
./$(EXEFILE)
clean:
rm $(EXEFILE)
Right now all of my .h files and .cpp files are on the working directory, and everything compiles and runs just fine. My issue is that I have already a large number of files, and it is getting quite messy. I want to create multiple directories (and maybe even directories inside these directories) to organize my files. But as soon as I move a header file and it's corresponding cpp file(s) to a directory inside of the current directory the compiler doesn't know how to link them anymore.
How do I tell my make file to compile and link everything under the current root?
Alternatively, is there a ELI5 guide to makefile syntax?
The quickest way to solve your problem is to add SRC and DEPS the files contains in all your sub-directories, something like:
SRC=*.cpp src/*.cpp
DEPS=*.h inc/*.h
Now you may consider writing a rule to first compile every file in a separate directory:
# Group compilation option
CXXFLAGS := -std=c++11 -Wall -Wno-comment $(IFLAGS)
# A directory to store object files (.o)
ODIR := ./objects
# Read this ugly line from the end:
# - grep all the .cpp files in SRC with wildcard
# - add the prefix $(ODIR) to all the file names with addprefix
# - replace .cpp in .o with patsubst
OBJS := $(patsubst %.cpp,%.o,$(addprefix $(ODIR)/,$(wildcard $(SRC)/*.cpp)))
# Compile all the files in object files
# $# refers to the rule name, here $(ODIR)/the_current_file.o
# $< refers to first prerequisite, here $(SRC)/the_current_file.cpp
$(ODIR)/%.o:$(SRC)/%.cpp $(DEPS)/%.h
$(CXX) $(CXXFLAGS) -c -o $# $<
# Finally link everything in the executable
# $^ refers to ALL the prerequisites
$(EXEFILE): $(OBJS)
$(CXX) $(CXXFLAGS) -o $# $^ $(LFLAGS) $(LIBS)
I found a solution, that, to my tastes seems elegant, or at least easy to trace using the wildcard operator. Here is my current makefile:
EXEFILE := $(shell basename $(CURDIR))
DIRECTORIES = $(filter-out ./ ./.%, $(shell find ./ -maxdepth 10 -type d))
IFLAGS= -I/usr/include/freetype2
LOCAL_I_DIRS =$(addprefix -I./, $(DIRECTORIES))
LFLAGS= -L/usr/lib/nvidia-375 -L/usr/local/lib -L/usr/include/GL -L/usr/local/include/freetype2 -L/usr/local/lib/
LIBS = -lglfw -lGL -lGLU -lOpenGL -lGLEW -pthread -lfreetype
SRC := $(wildcard *.cpp) $(wildcard **/*.cpp)
$(EXEFILE): $(EXEFILE).cpp
g++ -std=c++11 -o $(EXEFILE) -Wall -Wno-comment $(SRC) $(IFLAGS) $(LOCAL_I_DIRS) $(LFLAGS) $(LIBS)
all: run clean
run: $(EXEFILE)
./$(EXEFILE)
clean:
rm $(EXEFILE)
print-%: ; #echo $* = $($*)
So I get all directories up to depth 10. I then take out the current root (./) and any hidden directory (./.) leaving me with standard subdirectories stored under "DIRECTORIES", I then add -I to every directory to make it an include directory and store them in LOCAL_I_DIRS
So I can now create as many subdirectories as needed (up to 10 levels) and the compiler will be happy.
I have a makefile as follows:
CC = gcc
CFLAGS = -fmessage-length=0 -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" $(INCLUDES)
ifdef DEBUG
CFLAGS += -g3
endif
INCLUDES = \
-I../config.include \
-I../log.include \
-I../services.include
SRC_DIR = src
BIN_DIR = bin
BINARY = report
SRCS = $(shell ls $(SRC_DIR)/*.cpp)
OBJS = $(SRCS:%.cpp=%.o)
all: $(OBJS)
#mkdir -p $(BIN_DIR)
$(CC) $(OBJS) -o $(BIN_DIR)/$(BINARY)
clean:
rm -rf $(BIN_DIR) $(OBJS)
However, when I run make, I get the error:
g++ -c -o src/report.o src/report.cpp
src/report.cpp:40:20: error: log.h: No such file or directory
src/report.cpp:41:28: error: services.h: No such file or directory
src/report.cpp:41:28: error: config.h: No such file or directory
I know for a fact that the header files are there, and that they are included correctly. The paths are also correct. There is something wrong with the makefile, but I cannot figure out what.
Notice that even though I set CC = gcc, the output is always g++. This is not a typo, it is actually the output I am getting - again, not sure why.
Help!
You have to redefine CXXFLAGS and CXX and not CFLAGS and CC for .cpp files.
Check the output of make -p and search for %.o: %.cpp rule.
You have no target for the individual object files ($(OBJS)), so Make searches its list of implicit rules, one of which is to make .o files from .cpp files using the C++ compiler, which is set by CXX (which by default is probably g++).