Creating a makefile for CUDA programs - makefile

I want to automate the compilation of a toy library using CUDA and C++. Then I write a Makefile as follows
CC=g++
NVCC=nvcc
CXXFLAGS= -fopenmp -O3 -Wextra -std=c++11
CUDAFLAGS= -std=c++11 -c -arch=sm_20
LIBS= -lopenblas -lpthread -lcudart -lcublas
LIBDIRS=-L/usr/local/cuda-7.5/lib64
INCDIRS=-I/usr/local/cuda-7.5/include
matrix_cuda.o: marix_cuda.cu
$(NVCC) $(CUDAFLAGS) matrix_cuda.cu
all: matrix_cuda.o
$(CC) -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o $(LIBDIRS) $(INCDIRS) $(LIBS) $(CXXFLAGS)
clean:
rm -rf test *.o
Typing make I get
make: *** No rule to make target `marix_cuda.cu', needed by `matrix_cuda.o'. Stop.
I never wrote a Makefile before. Where did I go wrong?

I think you have a typo in the CUDA file name
matrix_cuda.o: marix_cuda.cu
$(NVCC) $(CUDAFLAGS) matrix_cuda.cu
IMHO it should be
matrix_cuda.o: matrix_cuda.cu
$(NVCC) $(CUDAFLAGS) matrix_cuda.cu

This may take a couple of iterations.
1) First try this:
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu
If that works (and produces matrix_cuda.o, I presume), remove matrix_cuda.o and
2) try this makefile:
matrix_cuda.o: matrix_cuda.cu
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu
If that works,
3) try this:
g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11
If that works, remove test and
4) try this makefile:
test: matrix_cuda.o
g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11
matrix_cuda.o: matrix_cuda.cu
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu
If that works, remove test and matrix_cuda.o and
5) try that makefile again.
If that works, there are further refinements we can make.

Also your first make rule corresponds to compiling the object file matrix_cuda.o. The all make rule should come first since the first rule in the make file is the one that gets updated first when invoking the command make. GNU Make has great documentation explaining how to make simple to complex makefiles. You can check it out here:
https://www.gnu.org/software/make/manual/make.html.
Also another issue you are going to run into is that in your make recipe for the all rule, you are supposed to be linking together only object files to create the final executable. However you are trying to include matrix_blas.cpp alg.cpp test.cpp in this linking step. Instead of .cpp versions of these files they need to be .o versions (the compiled objects). Make can generate these object files for you. You just need to have a make rule and recipe for each one. For example:
matrix_blas.o: matrix_blas.cpp
$(CC) $(CXXFLAGS) -c matrix_blas.cpp -o matrix_blas.o

I want to add some commentary on this Makefile for future reference and better automation :
1. NVCC=nvcc environment variable is superfluous. There is only one compiler for NVIDIA GPUs and you would nonetheless have to change a lot of flags to compile for other architectures like AMD.
-arch=native is better suited if you want to deploy your code on multiple machines with GPUs having different architectures
-dc is the flag for separate compilation. The architecture must be specified before -dc see (with a generic Makefile): https://developer.nvidia.com/blog/separate-compilation-linking-cuda-device-code/
You should add automatic rule to avoid these typos errors :
%.o: %.cu
nvcc -dc $(CUDAFLAGS) $< -o $#
The Makefile will look for all dependencies ending by .o. If it needs to build one, it looks if it has the corresponding .cu file. I would actually remove the -dc from flags and be explicit here that I want to build object files.
$# is the name of the rule target. $< is the first prerequisite. Only one file at a time can be passed to nvcc with the -dc flag, so here $< is better than $^.
You may add the name of the executable in a variable so that you delete the same executable that you generated (and facilitate name change).
I added a .PHONY rule. This only removes the confusion that happens whenever someone writes a file named clean in the directory.
The Makefile can not differenciate between the file and the make clean rule.
CC=g++
CXXFLAGS= -fopenmp -O3 -Wextra -std=c++11
CUDAFLAGS= -std=c++11 -arch=sm_20
LIBS= -lopenblas -lpthread -lcudart -lcublas
LIBDIRS=-L/usr/local/cuda-7.5/lib64
INCDIRS=-I/usr/local/cuda-7.5/include
PROGRAM= test
%.o: %.cu
nvcc -dc $(CUDAFLAGS) $< -o $#
all: matrix_cuda.o
$(CC) -o $(PROGRAM) matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o $(LIBDIRS) $(INCDIRS) $(LIBS) $(CXXFLAGS)
.PHONY: clean
clean:
rm -rf $(PROGRAM) *.o

Related

Does Make create rules for the dependencies if they are not available?

The below makefile does not have target for making OBJECTS but still the make is forming the rule and makes the OBJECTS and makes the final all.exe. I am not sure how does it work. Does make have mechanism to create rules if they are not available in the makefile for the dependencies?
SOURCE=$(wildcard Source/\*.cpp)
TEST=$(wildcard Source/Tests/\*.cpp)
OBJECTS=$(SOURCE:.cpp=.o) $(TEST:.cpp=.o)
CXXFLAGS= -O3 -fstack-usage -MMD
all:$(OBJECTS)
g++ $(CXXFLAGS) -o $# $(OBJECTS)
print::
#echo $(SOURCE)
#echo $(OBJECTS)
#echo $(TEST)
clean:
rm -rf Source/*.o Source/Tests/*.o *.exe
Console Output:
$ make
g++ -O3 -fstack-usage -MMD -c -o Source/main.o Source/main.cpp
g++ -O3 -fstack-usage -MMD -c -o Source/Tests/TestList.o Source/Tests/TestList.cpp
g++ -O3 -fstack-usage -MMD -c -o Source/Tests/TestLinkedlist.o Source/Tests/TestLinkedlist.cpp
g++ -O3 -fstack-usage -MMD -o all Source/main.o Source/Tests/TestList.o Source/Tests/TestLinkedlist.o
Folder Structure:
Yes, GNU make has a full suite of built-in rules.
See the manual: https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html

the correct usage of `LDFLAGS` in makefile

First, the makefile in question roughly looks like this (I'm writing off my memory):
CXX=g++
CXXFLAGS=-c -Wall -std=c++11 -O3
LDFLAGS=-Wall -std=c++11 -O3
all: clean car.out
clean:
rm -f *.o *.out
car.out: a.o b.o
$(CXX) -o $# $(LDFLAGS) $^
a.o: a.cpp
$(CXX) $(CXXFLAGS) $<
b.o: b.cpp
$(CXX) $(CXXFLAGS) $<
Basically this will make some object files first and then link them together. I think this is semantically unreasonable because:
As its name suggests, LDFLAGS is for ld, but there is no flags for it here. If we need some external library like OpenGL, then a flag like -LGL is passed to g++, and then g++ would pass it to the linker. In that case, it would be reasonable to put -LGL in LDFLAGS.
Even if it's the case where we put flags such as -Wall into LDFLAGS, it doesn't make much sense. This kind of flags are intuitively for the compilation process, not linking (unless I understand this process wrong).
In https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html, there is a piece of code $(CC) -c $(CFLAGS) $(CPPFLAGS), which passes -c explicitly. I think this is the better way to do this--putting all compilation flags (e.g. -Wall) into CXXFLAGS, and pass in -c explicitly for object file compilation. Of course, the web page does not say that this piece of code is definitely better or the only way to do it.
So the only reason I can think of to use LDFLAGS there is because "there's a linking step," which doesn't make much sense to me. In my opinion, the makefile above should look like:
CXX=g++
CXXFLAGS=-Wall -std=c++11 -O3
all: clean car.out
clean:
rm -f *.o *.out
car.out: a.o b.o
$(CXX) -o $# $(LDFLAGS) $^
a.o: a.cpp
$(CXX) -c $(CXXFLAGS) $<
b.o: b.cpp
$(CXX) -c $(CXXFLAGS) $<
LDFLAGS defaults to an empty string, so we can still have it there for the linking step.
However I'm not sure if I'm right.
You are right that compilation flags have nothing to do in LDFLAGS. Just define LDFLAGS explicitly so that another editor -or yourself, when some time has passed- can figure out at a glance that 1. it is empty and 2. where to modify it (like adding -s to it, which is quite common).

makefile which get also the name of the file compile

I need a makefile which get also the name of the file compile
For example:
make foo
and the makefile should compile foo.c to foo.
This is my makefile. How to change it?
all: out
out: out.o
gcc -g -m32 -Wall -o out out.o
out.o: out.c
gcc -m32 -g -Wall -ansi -c -o out.o out.c
.PHONY: clean
#Clean the build directory
clean:
rm -f *.o out
There is no direct way where you can pass arguments to the Makefile but instead you can take advantage of variables to achieve what you want. Check the modifications done to the Makefile below
NAME ?=out #Default binary generated is out if you dont pass any argument
${NAME}: ${NAME}.o
gcc -g -m32 -Wall -o ${NAME} ${NAME}.o
${NAME}.o: ${NAME}.c
gcc -m32 -g -Wall -ansi -c -o ${NAME}.o out.c
.PHONY: clean
#Clean the build directory
clean:
`rm -f *.o ${NAME}`
And you should call the Makefile by typing
$ make NAME=foo
$ make clean NAME=foo
Passing arguments directly to Make is trivially easy.
Your current makefile can be invoked with make foo, and will compile foo.c to produce foo, because Make has implicit rules for handling cases like foo.c => foo; there will be no error even though "foo" is not the target of any rule. (At least, this is the case with GNU Make 3.81, which is what I am using.)
If you want to control the choice of compiler and flags (as in your out rule), there is more than one way to do it. The simplest (though not strictly the best) is to modify a couple of variables in the makefile:
CC = gcc
CFLAGS = -g -m32 -Wall -ansi
Another option is to override the implicit rule with a pattern rule of your own:
%: %.c
gcc -g -m32 -Wall -ansi -o $# $<
If you want it to build foo.o in a separate step, you must split the rule into two rule-- and also put in a rule with no recipe to cancel Make's implicit rule:
%: %.o
gcc -g -m32 -Wall -o $# $^
%.o: %.c
gcc -m32 -g -Wall -ansi -c -o $# $<
%: %.c
Further refinements are possible, once you have mastered the basics.

How to get g++ to ignore warnings from included projects

I'm making a new project that is dependent on two other projects (written by others). While I'm developing my code I would like to use g++ options such as -Wall -pedantic -Werror but when I use these options I get a flood of warnings by including files from the other two projects.
Is there any way I can ignore the warnings from those two projects but still see the warnings from my own project?
If you're compiling their source directly via a makefile, you can make optional CPPFLAGSwhich you can use for conditional compilation parameters. For example:
CPPFLAGS=-Wall -pedantic -Werror for your project and CPPFLAGS=-g for their project files (or something).
Take the following sample makefile. Assume you wrote factorial.cpp and hello.cpp and they wrote main.cpp:
CPPFLAGS+=-Wall -pedantic -Werror
all: hello
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello
main.o: main.cpp
g++ -c main.cpp
factorial.o: factorial.cpp
g++ -c $(CPPFLAGS) factorial.cpp
hello.o: hello.cpp
g++ -c $(CPPFLAGS) hello.cpp
clean:
rm -rf *o hello
Try something like that and get back to me.

How to define rules in the Makefile to compile only that *.cpp files which was modified (and their dependencies), not all *.cpp files

Lets say I have files:
Libs:
one.cpp, one.h
two.cpp, two.h
three.cpp, three.h
Program:
program.cpp
Is there way, to create Makefile which will compile only that *.cpp which were modified from last compilation?
Currently I have something like that:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: $(OBJS) program
.cpp.o:
g++ -Wall -c $<
program:
g++ -Wall $(OBJS) program.cpp -o program
clean:
rm -f $(OBJS) program
I works fine, but when I compile my program and then change two.cpp or two.h I need to run "make clean" first, because when I secondly run "make" I get:
Nothing to be done for 'all'.
I would like to change my Makefile in that way, it would recognize my changes and recompile that file and its dependencies (if one.cpp uses code from two.cpp which was modified, both files should be recompiled).
So if I modify two.cpp, make should do:
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
But if one.cpp uses code from two.cpp which was modified, make shold do:
g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
First we make the object files prerequisites of the executable. Once this is done, Make will rebuild program whenever one of the SRCS changes, so we don't need OBJS as an explicit target:
all: program
program: $(OBJS)
g++ -Wall $(OBJS) program.cpp -o program
Then we make the header files prerequisites of the objects, so that if we change three.h, Make will rebuild three.o:
$(OBJS): %.o : %.h
And finally since one.cpp uses code from two.cpp by means of two.h (I hope), we make two.h a prerequisite of one.o:
one.o: two.h
And to make things cleaner and easier to maintain we use automatic variables:
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
Put it all together and we get:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: program
$(OBJS): %.o : %.h
one.o: two.h
.cpp.o:
g++ -Wall -c $<
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
clean:
rm -f $(OBJS) program
There are a few more things we could do (like adding program.o to OBJS), but this is enough for today.
Add the files a command depends upon to run to the right of the target name.
Example:
default: hello.c
gcc -o hello.bin hello.c
install: hello.bin
cp hello.bin ../
All you need to do is tell make that the .o file depends on the .cpp file:
%.cpp.o: %.cpp
g++ -Wall -c -o $# $<

Resources