I recently tried to modify my makefile so that it will correctly rebuild files when a header is modified. However, I can't get it to work - it instead produces mysterious error messages about nonexistent files.
My current makefile is as follows
HEADER_FILES := $(wildcard src/*.h) $(wildcard src/*/*.h)
CPP_FILES := $(wildcard src/*.cpp) $(wildcard src/*/*.cpp)
OBJ_FILES := $(patsubst src/%.cpp,obj/%.o,$(CPP_FILES))
LD_FLAGS :=
CC_FLAGS := -Wall -fwrapv -std=c++0x -DNOMINMAX -DFLOAT_CONV -DNODEBUGLOGGING
# CC_FLAGS := -Wall -fwrapv -std=c++0x -DNOMINMAX -DFLOAT_CONV -DMUSIC
INC = src Box2D SDL-1.2.15/include SDL-1.2.15/include/SDL C:/Boost/boost_1_55_0
CC_FLAGS += $(foreach d, $(INC), -I$d)
LINK_PATHS = SDL-1.2.15/lib C:\Boost\boost_1_55_0\stage\lib Box2D\Build\Box2D
LINK = mingw32 SDLmain SDL_mixer SDL_image SDL_ttf SDL Box2d boost_system-mgw48-mt-d-1_55 boost_filesystem-mgw48-mt-d-1_55
LD_FLAGS += $(foreach d, $(LINK_PATHS), -L$d)
LD_FLAGS += $(foreach d, $(LINK), -l$d)
EXE_NAME := Pickory/Pickory.exe
depend: .depend
.depend: $(HEADER_FILES) $(CPP_FILES)
g++ $(CC_FLAGS) -MM $^>>./.depend;
include .depend
# main.exe: $(OBJ_FILES)
$(EXE_NAME): $(OBJ_FILES)
g++ -o $# $^ $(LD_FLAGS)
obj/%.o: src/%.cpp
-mkdir $(subst /,\,$(dir $#))
g++ $(CC_FLAGS) -c -o $# $<
run: $(EXE_NAME)
(cd Pickory && $(notdir $(EXE_NAME)))
.PHONY: run
However, the depend target is producing error messages
g++: error: src/CommonEntities/defaltgun.cpp: No such file or directory
g++: error: src/TutorialTunnel/roomdef_tt.cpp;: No such file or directory
makefile:21: recipe for target '.depend' failed
mingw32-make: *** [.depend] Error 1
This is rather strange, since there is no such "defaltgun" file, and in fact, "defaltgun" appears nowhere in the entire source code. What could be going on? And how can I fix my makefile?
P.S. The .depend file is empty. So presumably gcc isn't properly generating dependencies either.
Related
(updated for clarity) (solution added at bottom)
I found a makefile online which builds all the cpp files in that directory and compiles them.
But I can't work out how I can include files inside a subdirectory.
Here's a breakdown of what happens:
I create the files test.cpp & test.hpp and place them inside the sub-directory '/gui' which is contained within my working directory, they contain the function testFunction().
Without including test.hpp, I type "make" into terminal and I receive the error:
:
g++ -c -o main.o main.cpp
main.cpp: In function 'int main(int, char**)':
main.cpp:6:2: error: 'testFunction' was not declared in this scope
testFunction();
^~~~~~~~~~~~
make: *** [<builtin>: main.o] Error 1
If I include (#include "gui/test.hpp"), I then receive a different error:
:
g++ -c -o main.o main.cpp
g++ main.o -Wall -o testfile
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x14): undefined reference to `testFunction()'
collect2: error: ld returned 1 exit status
make: *** [makefile:34: testfile] Error 1
But if I then add "-I/gui" or (at a guess) "-I./gui" to CFLAGS, I get the exact same error message.
Here's the makefile for reference:
TARGET = testfile
LIBS =
CC = g++
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
HEADERS = $(wildcard *.hpp)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
Thanks in advance!
Updated makefile since accepted answer:
(Changes were to include directories, CC replaced with CXX, and %.c replaced with %.cpp)
TARGET = testfile
DIRS =
LDLIBS =
CXX = g++
CXXFLAGS= -g -Wall
# this ensures that if there is a file called default, all or clean, it will still be compiled
.PHONY: default all clean
default: $(TARGET)
all: default
# substitute '.cpp' with '.o' in any *.cpp
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp $(addsuffix /*.cpp, $(DIRS))))
HEADERS = $(wildcard *.h)
# build the executable
%.o: %.cpp $(HEADERS)
$(CXX) $(CXXFLAGS) -c $< -o $#
# if make is interupted, dont delete any object file
.PRECIOUS: $(TARGET) $(OBJECTS)
# build the objects
$(TARGET): $(OBJECTS)
$(CXX) $(OBJECTS) -Wall $(LDLIBS) -o $#
clean:
-rm -f *.o $(addsuffix /*.o, $(DIRS))
-rm -f $(TARGET)
To understand what's happening here you have to look up the definitions of declaration versus definition in C++ (and other languages). You should definitely do that.
A declaration (typically put into a header file) is like the address of your house. If someone wants to send you a letter, they need your address. If your main function wants to call another function like testFunction(), it needs the declaration of the function.
The first error happens because you don't have the header file included, so the compiler doesn't have the declaration of the function you want to call, which means it won't compile your calling function.
But for the letter to actually arrive, you need your actual house. The address is the declaration and your house is the definition... in this case the actual function implementation. That lives in test.cpp file. When you link your code together, the linker (in this scenario I guess the linker is like the postal service :p :) ) will try to link up the call to the definition.
However, you can see that you are not compiling the test.cpp file nor are you linking the object file:
g++ main.o -Wall -o testfile
here we see main.o, but not gui/test.o.
Why not? This line:
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
Matches all *.cpp files and converts them into .o files. But *.cpp matches only files in the current directory, like main.cpp. If you want to put files in a different directory you have to tell make where they are; for example:
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp gui/*.cpp))
Compiling with Makefile tells me that it can't find path to some include files.
Here's my directory layout:
build (empty directory)
include (directory)
tpu_uarch (directory)
buffer.hpp common.hpp controller.hpp cpu.hpp
dram.hpp interconnect.hpp mmu.hpp unit.hpp weightfetcher.hpp
obj (directory)
tpu_uarch (empty directory)
src (directory)
test_mmu.cpp test_tile.cpp
buffer.cpp common.cpp controller.cpp cpu.cpp
dram.cpp interconnect.cpp mmu.cpp weightfetcher.cpp
Makefile
And here's what Makefile looks like:
TESTTILE := ./build/testtile.exe
TEST3 := ./build/test3.exe
CC := g++
CPP_SUFFIX := cpp
INCLUDE_DIR := -I./include
SRC_DIR = ./src
OBJ_DIR = ./obj
CFLAGS := -g -Wall -std=c++11
LDFLAGS :=
LIBS :=
# all sources
SRC = $(wildcard $(SRC_DIR)/*.$(CPP_SUFFIX))
SRC += $(wildcard $(SRC_DIR)/**/*.$(CPP_SUFFIX))
# objects
OBJ = $(patsubst $(SRC_DIR)/%.$(CPP_SUFFIX), $(OBJ_DIR)/%.o, $(SRC))
DIR = $(dir $(OBJ))
# executables
testtile: dir $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(TESTTILE) $(LIBS)
test3: dir $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $(TEST3) $(LIBS)
dir:
mkdir -p $(DIR)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(CPP_SUFFIX)
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c $< -o $#
clean:
rm -rf $(OBJ_DIR)
rm $(TESTTILE)
rm $(TEST3)
When I write make test3 in command line, I get the following error.
mkdir -p ./obj/ ./obj/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/
g++ -I./include -g -Wall -std=c++11 -c src/test_tile.cpp -o obj/test_tile.o
src/test_tile.cpp:1:22: fatal error: common.hpp: No such file or directory
compilation terminated.
Makefile:44: recipe for target 'obj/test_tile.o' failed
make: *** [obj/test_tile.o] Error 1
In all of the *.cpp files, they add include files like #include "common.hpp" without adding directory information. As I understand, adding the -I flag in INCLUDE_DIR should solve problems of finding the include files.
I've checked earlier that the code compiles if I put all .cpp and .hpp files in one directory and type g++ -g -Wall -std=c++11 -o test3.exe buffer.cpp common.cpp controller.cpp cpu.cpp dram.cpp interconnect.cpp mmu.cpp weightfetcher.cpp test_mmu.cpp in the command line interface.
In making test3.exe, test_tile.cpp is not used but I don't think that should be a problem.
Is there something I'm missing or should look into?
Any help or push in the right direction would be greatly appreciated.
[Moved from comments]
You're telling g++ to look in ./include but, according to the directory hierarchy shown, common.hpp and the other headers are actually under ./include/tpu_uarch. You need...
INCLUDE_DIR := -I./include/tpu_uarch
For those who came to find an answer... Even after fixing the issue that G.M. pointed out, I still had some minor issues. (Such as conflict in that both test files include the main() function, etc.)
After that, I managed to fix the code to work.
Here is the working version of Makefile.
TESTTILE := ./build/testtile.exe
TESTMMU := ./build/testmmu.exe
CC := g++
CPP_SUFFIX := cpp
INCLUDE_DIR := -I./include/tpu_uarch
SRC_DIR = ./src
OBJ_DIR = ./obj
BUILD_DIR = ./build
CFLAGS := -g -Wall -std=c++11
LDFLAGS :=
LIBS :=
# all sources
SRC = $(wildcard $(SRC_DIR)/*.$(CPP_SUFFIX))
SRC += $(wildcard $(SRC_DIR)/**/*.$(CPP_SUFFIX))
# objects
OBJ = $(patsubst $(SRC_DIR)/%.$(CPP_SUFFIX), $(OBJ_DIR)/%.o, $(SRC))
DIR = $(dir $(OBJ))
# for tests
TESTTILE_OBJ := ./obj/test_tile.o
TESTMMU_OBJ := ./obj/test_mmu.o
# executables
testtile: dir $(OBJ) $(TESTTILE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(TESTTILE_OBJ) -o $(TESTTILE) $(LIBS)
testmmu: dir $(OBJ) $(TESTMMU_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(TESTMMU_OBJ) -o $(TESTMMU) $(LIBS)
dir:
mkdir -p $(DIR)
obj/test_tile.o: $(BUILD_DIR)/test_tile.cpp
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c ./build/test_tile.cpp -o ./obj/test_tile.o
obj/test_mmu.o: $(BUILD_DIR)/test_mmu.cpp
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c ./build/test_mmu.cpp -o ./obj/test_mmu.o
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(CPP_SUFFIX)
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c $< -o $#
clean:
rm -rf $(OBJ_DIR)
rm $(TESTTILE)
rm $(TEST3MMU)
The directory topology is as follows:
build (directory)
test_mmu.cpp test_tile.cpp
testmmu.exe testtile.exe (executables created after running make)
include (directory)
tpu_uarch (directory)
buffer.hpp common.hpp controller.hpp cpu.hpp
dram.hpp interconnect.hpp mmu.hpp unit.hpp weightfetcher.hpp
obj (directory, all contents here including directory are created after running make)
tpu_uarch (directory)
buffer.o common.o controller.o cpu.o
dram.o interconnect.o mmu.o weightfetcher.o
test_mmu.o
test_tile.o
src (directory)
tpu_uarch (directory)
buffer.cpp common.cpp controller.cpp cpu.cpp
dram.cpp interconnect.cpp mmu.cpp weightfetcher.cpp
Makefile
Hope this helps.
So I have been trying to use the answers and the idea of this published question: Makefile: Compiling from directory to another directory
In the following excerpt code, you can see the definition of the directories, for sources and compilation objects.
all : Mpois Mkvz MBJ Mlid
# Definitions
COMPILER := gfortran -O3
LIBS := -g -fbounds-check -ffast-math -lm
# Directories of object code
OBJDIR = objects
SRCDIR = src
SOURCES := $(SRCDIR)/lbm_const.f90 $(SRCDIR)/BORDERS.f90 $(SRCDIR)/CONVERGENCE.f90 $(SRCDIR)/FILESIO.f90 $(SRCDIR)/LBM.f90
OBJECTS := $(OBJDIR)/lbm_const.o $(OBJDIR)/BORDERS.o $(OBJDIR)/CONVERGENCE.o $(OBJDIR)/FILESIO.o $(OBJDIR)/LBM.o
SOURCES_pois := $(SRCDIR)/Main_pois.f90
OBJECTS_pois := $(OBJDIR)/Main_pois.o
# Linking
Mpois: $(OBJECTS) $(OBJECTS_pois)
$(COMPILER) $^ -o $# $(LIBS)
# Compiling
$(OBJECTS): $(OBJDIR)/%.o: %.f90
$(COMPILER) -c $< -o $#
# Compiling
$(OBJECTS_pois): $(OBJDIR)/%.o: %.f90
$(COMPILER) -c $< -o $#
clean:
rm -f $(OBJDIR)/*.o
rm -f $(OBJDIR)/*.mod
rm -f $(SRCDIR)/*.mod
When running the makefile script I get the following error:
make: *** No rule to make target 'lbm_const.f90', needed by 'objects/lbm_const.o'. Stop.
Interesting is to note that when SRCDIR = src changes to SRCDIR = . the makefile compiles even having files in folder src.
I'm on my path to study the wonderful world of Makefiles and this was my first attempt on my own makefile. However I have hit my small brains at a wall with errors and I can not figure the cause, I only know the issue is in the Makefile, I am doing something wrong, because when I compile my "project" manually, it compiles.
cxx := g++
dirs := obj bld_win32 bld_linux
cpp := $(wildcard src/*.cpp)
obj := $(addprefix obj/,$(notdir $(cpp:.cpp=.o)))
ifeq ($(OS), Windows_NT)
target := bld_win32/engine.exe
flags := -mwindows -lopengl32 -openal32 -lgdi32
else
target := bld_linux/engine
flags := -lX11 -lGL -lopenal -lalut
endif
all: precheck $(target)
precheck:
mkdir -p $(dirs)
$(target): $(obj)
$(cxx) -std=c++11 -Wall -o $# $^ $(flags)
obj/%.o: $(cpp)
$(cxx) -c -o $# $<
Your pattern rule is wrong, as you would have noticed if you'd tried to build object files one by one using this makefile. This rule:
obj/%.o: $(cpp)
$(cxx) -c -o $# $<
lists all source files as prerequisites of every object file, and when you try to build any object file, it compiles only the first source file in the list (src/aardvark.cpp, or whatever), so that all of your object files are the same, even though they have different names.
Change it to this:
obj/%.o: src/%.cpp
$(cxx) -c -o $# $<
Straight to the point:
I have the following file structure:
MapA: makefile, main.c, step.cu, step.h, mapB
mapB: model.cu, model.cuh, model_init.c, model_init.h
I compile this structure with the following makefile, with the command
"make MODEL=mapB":
MODELDIR := ./$(MODEL)
MODULES := $(MODELDIR)
CFLAGS += -I. $(patsubst %,-I%,$(MODULES))
NVCFLAGS += -I. $(patsubst %,-I%,$(MODULES))
NVCC += nvcc
NVCFLAGS += -arch=sm_30 --ptxas-options=-O1
CFLAGS += -Wall -pedantic
LDLIBS += -lz -lpthread
CFLAGS += -g
SRCS += step.cu $(MODELDIR)/model.cu $(MODELDIR)/model_init.c \
main.c
OBJS += step.o $(MODELDIR)/model.o $(MODELDIR)/model_init.o
all: .depend runmodel
dims.h: gen_dims.sh
./gen_dims.sh 1024 1024
runmodel: ${OBJS} main.o
${NVCC} ${NVCFLAGS} ${LDLIBS} $^ -o $#
%.o: %.cu
${NVCC} ${NVCFLAGS} -dc $<
.PHONY: depend clean test
depend:
${NVCC} ${NVCFLAGS} -M ${SRCS} > .depend
.depend: ${SRCS} makefile dims.h
${NVCC} ${NVCFLAGS} -M ${SRCS} > .depend
clean:
${RM} ${OBJS} runmodel compare *.cmo *.cmx *.cmi *.o
include .depend
This gives an nvlink error, namely " nvlink fatal : Could not open input file 'mapB/model.o "
I looked at where the .o files are placed and my file structure with the .o-files generated with this makefile looks like:
mapA: makefile, main.c, main.o, step.cu, step.o, step.h, model.o,
mapB
mapB: model.cu, model.cuh, model_init.c, model_init.o, model_init.h
Is there anybody that has an idea as to why the model.o file appears in the upper directory instead of in the subfolder, which makes that later on in the compilation process it cannot be found?
A solution to resolve this issue would also be welcomed.
I don't have nvcc to play with, so I can't be sure, but I suggest you try this, and tell us the result:
%.o: %.cu
${NVCC} ${NVCFLAGS} -dc $< -o $#