I'd like to write generic makefile that compiles and links all my modules.
Folders structure:
\include
----+Common.h
----+Graph.h
----+GraphColoringCPU.h
----+GraphColoringGPU.cuh
----+LogCreate.h
\obj <- initially empty, all .o files
---- ...
\src
----+Common.cu
----+Graph.cpp
----+GraphColoringCPU.cpp
----+GraphColoringGPU.cu
----+LogCreate.cpp
----+main.cu
+Makefile
+main <- target, missing before 'make'
Makefile:
CUDA_INSTALL_PATH ?= /usr/local/cuda
# Compilers
CXX := g++
LINK := g++ -fPIC
NVCC := nvcc -ccbin /usr/bin
# Includes
INCLUDES = -I. -I$(CUDA_INSTALL_PATH)/include
# Common flags
COMMONFLAGS += $(INCLUDES)
NVCCFLAGS := $(COMMONFLAGS) -gencode arch=compute_20,code=sm_20
CXXFLAGS += $(COMMONFLAGS)
CFLAGS += $(COMMONFLAGS)
# Compiler flags
DLINKFLAGS := -lcublas_device -lcudadevrt -lcublas -lcudart
# Debug mode
NVCCFLAGS += --compiler-options -Wall -G
#-arch=sm_35
# Libraries
LIB_CUDA := -L$(CUDA_INSTALL_PATH)/lib64 -lcudart
# Folder structure
OBJ = obj
SRC = src
INC = include
# Options
OBJS_CU = $(OBJ)/Common.ch.o $(OBJ)/GraphColoringGPU.cuh.o $(OBJ)/kernel.cu.o
OBJS = $(OBJ)/Graph.cpp.o $(OBJ)/LogCreate.cpp.o $(OBJ)/GraphColoringCPU.cpp.o $(OBJ)/link.o
TARGET = main
LINKLINE = $(LINK) -o $(TARGET) $(OBJS_CU) $(OBJS) $(LIB_CUDA)
.SUFFIXES: .c .cpp .h .cu .cuh .o
$(OBJ)/%.cuh.o: $(SRC)/%.cu $(INC)/%.cuh
$(NVCC) $(NVCCFLAGS) -dc $< -o $@
$(OBJ)/%.ch.o: $(SRC)/%.cu $(INC)/%.h
$(NVCC) $(NVCCFLAGS) -dc $< -o $@
$(OBJ)/%.cu.o: $(SRC)/%.cu
$(NVCC) $(NVCCFLAGS) -dc $< -o $@
$(OBJ)/link.o:
$(NVCC) -dlink $(NVCCFLAGS) $(DLINKFLAGS) $(OBJS_CU) -o $@
$(OBJ)/%.cpp.o: $(SRC)/%.cpp $(INC)/%.h
$(CXX) $(CXXFLAGS) -c $< -o $@
$(TARGET): $(OBJS_CU) $(OBJS) Makefile
$(LINKLINE)
# all:
# $(NVCC) $(NVCCFLAGS) -dc $(SRC)Common.cu $(SRC)GraphColoringGPU.cu $(SRC)kernel.cu
# $(NVCC) $(NVCCFLAGS) -dlink $(OBJ)Common.o $(OBJ)GraphColoringGPU.o $(OBJ)kernel.o -o $(OBJ)link.o
# $(CXX) $(CXXFLAGS) -c $(SRC)Graph.cpp -o $(OBJ)graph.o
# $(CXX) $(CXXFLAGS) -c $(SRC)LogCreate.cpp -o $(OBJ)logcreate.o
# $(CXX) $(CXXFLAGS) -c $(SRC)GraphColoringCPU.cpp -o $(OBJ)GraphColoringCPU.o
# $(LINK) -o main $(OBJ)Common.o $(OBJ)GraphColoringGPU.o $(OBJ)kernel.o $(OBJ)link.o $(OBJ)graph.o $(OBJ)logcreate.o $(OBJ)GraphColoringCPU.o $(LIB_CUDA)
clean:
rm -rf *.o log.txt
As you can see at the bottom there is some commented code. This code works fine without folders structure (all files in main dir).
Output of commented code:
nvcc -ccbin /usr/bin -I. -I/usr/local/cuda/include -gencode arch=compute_20,code=sm_20 --compiler-options -Wall -G -dc Common.cu GraphColoringGPU.cu kernel.cu
nvcc -ccbin /usr/bin -I. -I/usr/local/cuda/include -gencode arch=compute_20,code=sm_20 --compiler-options -Wall -G -dlink Common.o GraphColoringGPU.o kernel.o -o link.o
g++ -I. -I/usr/local/cuda/include -c Graph.cpp -o graph.o
g++ -I. -I/usr/local/cuda/include -c LogCreate.cpp -o logcreate.o
g++ -I. -I/usr/local/cuda/include -c GraphColoringCPU.cpp -o GraphColoringCPU.o
g++ -fPIC -o main Common.o GraphColoringGPU.o kernel.o link.o graph.o logcreate.o GraphColoringCPU.o -L/usr/local/cuda/lib64 -lcudart
Actual makefile produces output:
nvcc -ccbin /usr/bin -dlink -I. -I/usr/local/cuda/include -gencode arch=compute_20,code=sm_20 --compiler-options -Wall -G -lcublas_device -lcudadevrt -lcublas -lcudart obj/Common.ch.o obj/GraphColoringGPU.cuh.o obj/kernel.cu.o -o obj/link.o
nvlink fatal : Could not open input file 'obj/Common.ch.o'
make: *** [obj/link.o] Error 255
I know that it tries to compile with no proper order but I don't know how to change it.
Proper order rules:
1) Compile all '.cu' files using 'nvcc -dc' and places suitable '.o' files into \obj folder
2) Link all '.o' files (where sources are .cu files) using 'nvcc -dlink' into 'link.o' file (and place it into \obj folder)
3) Compile all '.cpp' files using 'g++ -c' and places suitable '.o' files into \obj folder
4) Links all '.o' files into target 'main' (and place it in main folder)
Thanks for advices.
I knew I had been pretty close to write correct make. I've tried command 'make main' and it... worked (some little changes was needed).
Here is working Makefile (unchanged code omitted):
# Options
OBJS_CU = $(OBJ)/Common.ch.o $(OBJ)/GraphColoringGPU.cuh.o $(OBJ)/main.cu.o
OBJS = $(OBJ)/Graph.cpp.o $(OBJ)/LogCreate.cpp.o $(OBJ)/GraphColoringCPU.cpp.o $(OBJ)/link.o
TARGET = main
LINKLINE = $(LINK) -o $(TARGET) $(OBJS_CU) $(OBJS) $(LIB_CUDA)
.SUFFIXES: .c .cpp .h .cu .cuh .o
$(OBJ)/%.cuh.o: $(SRC)/%.cu $(INC)/%.cuh
$(NVCC) $(NVCCFLAGS) -dc $< -o $@
$(OBJ)/%.ch.o: $(SRC)/%.cu $(INC)/%.h
$(NVCC) $(NVCCFLAGS) -dc $< -o $@
$(OBJ)/%.cu.o: $(SRC)/%.cu
$(NVCC) $(NVCCFLAGS) -dc $< -o $@
$(OBJ)/link.o:
$(NVCC) $(NVCCFLAGS) -dlink $(OBJS_CU) -o $@
$(OBJ)/%.cpp.o: $(SRC)/%.cpp $(INC)/%.h
$(CXX) $(CXXFLAGS) -c $< -o $@
$(TARGET): $(OBJS_CU) $(OBJS) Makefile
$(LINKLINE)
Also, if rule for $(TARGET) will be first rule, simple 'make' will be enough for working correctly.