Makefile for cuda/c++, Cannot successfully compile - c++

I have spend quite some time trying to write a makefile to compile some c++ files along with some .cu files. I cannot successfully compile the target while I do get an output currently, it is not a proper binary file.
So, basically I have all my source files in a src directory, my makefile in the main project folder, one directory up from src. I have a main.cpp, a hostDeviceCom.cu, a myKernel.cu and a cudaErrorCheck.cu that I had tested in a previous project compiled by hand with nvcc in one step. The concept is to have a separate build folder where the .out will be.
So my question is: What am I doing so wrong in the following makefile?
TARGET_EXEC ?= cudaNestim.out
T_CUDA_O ?= cudaTMp.o
NVCC ?= nvcc
BUILD_DIR ?= ./build
SRC_DIRS ?= ./src
CUDA_ARCH ?= -arch=sm_52
NVCCFLAGS ?= $(CUDA_ARCH)
NVCCFLNK ?= $(CUDA_ARCH) --device-link
CXXFLAGS ?= --std=c++11 -MM -MT
CXXOPTS ?= -MM -MT
# System Libraries -------------------------------------------------------------------------------
OCV_DIR ?= -L/user/local/lib
OCV_LIB ?= -lopencv_core -lopencv_viz -lopencv_highgui -lopencv_features2d -lopencv_imgproc
OCV_INC ?= -I/usr/include
OCV_LINK ?= $(OCV_DIR) $(OCV_LIB)
CUDA_DIR ?= -L/user/local/cuda-8.0/lib64
CUDA_LIB ?= -lcutil -lcudpp -lcuda -lcudart
CUDA_INC ?= -I/usr/local/cuda-8.0/include
CUDA_LINK ?= $(CUDA_DIR) $(CUDA_LIB)
#--------------------------------------------------------------------------------------------------
# find all the source files
SRCS := $(shell find $(SRC_DIRS) -name *.cu -or -name *.cpp -or -name *.c -or -name *.s)
#go to build directory and create a .o file for each src file found
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# create a .d file from each .o file. SO one .d for each .source
DEPS := $(OBJS:.o=.d)
LIB_DIRS := $(OCV_LINK) $(CUDA_LINK)
INCS := $(CUDA_INC) $(OCV_INC)
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
$(NVCC) $(NVCCFLNK) $(OBJS) $(LIB_DIRS) -o $#
$(BUILD_DIR)/%.cu.o: %.cu
$(MKDIR_P) $(dir $#)
$(NVCC) $(NVCCFLAGS) -o $# -c $<
#echo ".cu.o rule:" $(NVCCFLAGS) -o $# -c $< $(OCV_INC) $(CUDA_INC)
#$(NVCC) $(NVCCFLAGS) -o $# -c $< $(OCV_INC) $(CUDA_INC)
$(BUILD_DIR)/%.cpp.o: %.cpp
$(MKDIR_P) $(dir $#)
$(CXX) $(CXXFLAGS) $(INCS) -o $# -c $<
# Phony rules -------------------------------------------------------------------------------
.PHONY: clean
clean:
$(RM) -r $(BUILD_DIR)
MKDIR_P ?= mkdir -p
-include $(DEPS)
I know, I am not using any .d rule, I am trying to make this work and figure out later how to incorporate a .d rule for more complex stuff.

it is not a proper binary file
The proximal reason for this is that you are specifying device-link as the final build (ie link phase) operation:
NVCCFLNK ?= $(CUDA_ARCH) --device-link
^^^^^^^^^^^
...
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
$(NVCC) $(NVCCFLNK) $(OBJS) $(LIB_DIRS) -o $#
^^^^^^^^
As a result, the last build step you do is a device link, which does not create an executable. Your Makefile is generally also not set up properly for device-linking, because when separating compile from link, if you want device linking (i.e. generation of relocatable device code) then you must specify -dc, not -c during compile:
$(BUILD_DIR)/%.cu.o: %.cu
$(MKDIR_P) $(dir $#)
$(NVCC) $(NVCCFLAGS) -o $# -c $<
^^
Since you have already specified that the link phase should be done at once, and with nvcc, we can make some relatively simple changes to your makefile to achieve a makefile that will do rdc linking. Here's a fully worked example, derived from yours:
$ cat Makefile
TARGET_EXEC ?= cudaNestim.out
NVCC ?= nvcc
BUILD_DIR ?= ./bld
SRC_DIRS ?= ./src
CUDA_ARCH ?= -arch=sm_61
NVCCFLAGS ?= $(CUDA_ARCH)
#NVCCFLNK ?= $(CUDA_ARCH) --device-link
NVCCFLNK ?= $(CUDA_ARCH)
CXXFLAGS ?= --std=c++11 -MM -MT
CXXOPTS ?= -MM -MT
# System Libraries -------------------------------------------------------------------------------
OCV_DIR ?= -L/user/local/lib
#OCV_LIB ?= -lopencv_core -lopencv_viz -lopencv_highgui -lopencv_features2d -lopencv_imgproc
OCV_LIB ?=
OCV_INC ?= -I/usr/include
OCV_LINK ?= $(OCV_DIR) $(OCV_LIB)
CUDA_DIR ?= -L/usr/local/cuda-8.0/lib64
#CUDA_LIB ?= -lcutil -lcudpp -lcuda -lcudart
CUDA_LIB ?= -lcuda -lcudart
CUDA_INC ?= -I/usr/local/cuda-8.0/include
CUDA_LINK ?= $(CUDA_DIR) $(CUDA_LIB)
#--------------------------------------------------------------------------------------------------
MKDIR_P ?= mkdir -p
# find all the source files
SRCS := $(shell find $(SRC_DIRS) -name *.cu -or -name *.cpp -or -name *.c -or -name *.s)
#go to build directory and create a .o file for each src file found
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# create a .d file from each .o file. SO one .d for each .source
DEPS := $(OBJS:.o=.d)
LIB_DIRS := $(OCV_LINK) $(CUDA_LINK)
INCS := $(CUDA_INC) $(OCV_INC)
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
$(NVCC) $(NVCCFLNK) $(OBJS) $(LIB_DIRS) -o $#
$(BUILD_DIR)/%.cu.o: %.cu
$(MKDIR_P) $(dir $#)
$(NVCC) $(NVCCFLAGS) -o $# -dc $<
#echo ".cu.o rule:" $(NVCCFLAGS) -o $# -c $< $(OCV_INC) $(CUDA_INC)
#$(NVCC) $(NVCCFLAGS) -o $# -c $< $(OCV_INC) $(CUDA_INC)
$(BUILD_DIR)/%.cpp.o: %.cpp
$(MKDIR_P) $(dir $#)
$(CXX) $(CXXFLAGS) $(INCS) -o $# -c $<
# Phony rules -------------------------------------------------------------------------------
.PHONY: clean
clean:
$(RM) -r $(BUILD_DIR)
$ ls
bld Makefile src
$ cat src/hello.cu
#include <stdio.h>
__device__ void hello(){
printf("hello!\n");
}
$ cat src/test.cu
#include <stdio.h>
__device__ void hello();
__global__ void my_hello(){
hello();
}
int main(){
my_hello<<<1,1>>>();
cudaDeviceSynchronize();
}
$ make clean
rm -f -r ./bld
$ make
mkdir -p bld/./src/
nvcc -arch=sm_61 -o bld/./src/hello.cu.o -dc src/hello.cu
mkdir -p bld/./src/
nvcc -arch=sm_61 -o bld/./src/test.cu.o -dc src/test.cu
nvcc -arch=sm_61 ./bld/./src/hello.cu.o ./bld/./src/test.cu.o -L/user/local/lib -L/usr/local/cuda-8.0/lib64 -lcuda -lcudart -o bld/cudaNestim.out
$ bld/cudaNestim.out
hello!
$
Note that if you actually didn't want RDC code generation, you could change the -dc back to -c in the Makefile above. However, for demonstration purposes, my particular code example depends on CUDA RDC.

More of a suggestion than a direct answer:
What you're doing wrong is trying to reinvent the wheel. Use a higher-level build system, don't bother writing the Makefile yourself. There's more than one of these around; I personally use CMake and am sort-of happy with it. CMake has a module for setting up things paths and other variables for CUDA. Here's a short tutorial you could check out:
How to build CUDA programs using CMake
Now, it's not that you'll never run into any issues, but:
There'll be less of them
They would likely be easier to debug (have look at some CMake+CUDA questions here on SO).

Related

How to use C++ modules with a Makefile?

I have a Makefile which is minimal, yet complete. It is the following:
OUT = example
INSTALL_DIR = /usr/local/bin
OBJECT = ./obj
SOURCE = ./src
SRC := $(shell find $(SOURCE) -name *.cc)
OBJ := $(SRC:%=$(OBJECT)/%.o)
DEPS := $(OBJ:.o=.d)
INC_DIRS := $(shell find $(SOURCE) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CC = gcc
CFLAGS = -pipe -fmodules-ts -std=c++2a
DEBUG_FLAGS := $(CFLAGS) -g -Wall -Wextra
RELEASE_FLAGS := $(CFLAGS) -O3 -flto
debug: $(OBJ)
#echo "Building the DEBUG binary..."
#$(CC) $(OBJ) -o $(OUT) $(DEBUG_FLAGS)
#echo "The binary was built successfully!"
release: $(OBJ)
#echo "Building the RELEASE binary..."
#$(CC) $(OBJ) -o $(OUT) $(RELEASE_FLAGS)
#echo "The binary was built successfully!"
install: $(OUT)
#cp $(OUT) $(INSTALL_DIR)
uninstall:
#rm $(INSTALL_DIR)/$(OUT)
$(OBJECT)/%.cc.o: %.cc
#mkdir -p $(dir $#)
#echo "Building $#..."
#$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJECT) $(OUT)
-include $(DEPS)
There is a directory called "src" which includes the source files. When I'm running make, I will get a compilation error about having to first create modules before using them. If I do create them manually, then I will be able to use "Make" and it will work then it will work. Is there a way to automatically create them?
I recommend using g++-11 instead of just gcc, since versions <=10 do not really include module support asides from the deprecated TS. Then also, use flag -std=c++20.
Also, I have (painful) experience using dependency files with gcc, since that particular feature is not really fully implemented. Last I checked (beginning of nov '21) the dependency files don't actually do anything as pertains to modules.
That being said, what you write should work. And it would, if the compiler-support for modules was finished.

How to write a makefile which has to generate two executables

I am learning how to use make. Recently I wrote a makefile to compile one of my projects, which structure is: src (which contains file.cpp and main.cpp) and include (which contains file.h) folders and the makefile, which is written as follows:
TARGET_EXEC := main
CC := g++
BUILD_DIR := .
SRC_DIR := src
OBJ_DIR := obj
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
OBJ := $(SRC:%=$(OBJ_DIR)/%.o)
DEPS := $(OBJ:.o=.d)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR))
CPPFLAGS := $(INC_FLAGS) -MMD -MP
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJ)
$(CC) $(OBJ) -o $# $(LDFLAGS)
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -r $(OBJ_DIR) main
-include $(DEPS)
Now I want to add a new folder (test) in which I'll host a tests.cpp code with doctest code. In this case I would like to obtain two executables: main and tests (not only main as before), one for the main and one for the testing. I tried everything, but I don't understand how to modify the previous makefile in order to implement the new test folder informations.
EDIT 1
I tried adding Andreas suggestions and also an all command to create both the executables:
TARGET_EXEC := main
TEST_EXEC := tests
CC := g++
BUILD_DIR := .
SRC_DIR := src
OBJ_DIR := obj
TEST_DIR := test
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
OBJ := $(SRC:%=$(OBJ_DIR)/%.o)
DEPS := $(OBJ:.o=.d)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR))
CPPFLAGS := $(INC_FLAGS) -MMD -MP
all: $(BUILD_DIR)/$(TARGET_EXEC) $(BUILD_DIR)/$(TEST_EXEC)
$(BUILD_DIR)/$(TARGET_EXEC): $(SRC_DIR)/$(TARGET_EXEC).o $(OBJ)
$(CC) $(OBJ) -o $# $(LDFLAGS)
$(BUILD_DIR)/$(TEST_EXEC): $(TEST_DIR)/$(TEST_EXEC).o $(OBJ)
$(CC) $(OBJ) -o $# $(LDFLAGS)
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
.PHONY: clean all
clean:
rm -r $(OBJ_DIR) main
-include $(DEPS)
Now two executables main and tests are created, but they do the same things (same of the previous main), so it is wrong. When compile my output is:
g++ -Isrc -MMD -MP -c src/osmanip.cpp -o obj/src/osmanip.cpp.o
g++ -Isrc -MMD -MP -c src/main.cpp -o obj/src/main.cpp.o
g++ obj/src/osmanip.cpp.o obj/src/main.cpp.o -o main
g++ obj/src/osmanip.cpp.o obj/src/main.cpp.o -o tests
I think that the error may be in:
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
What do you think?
EDIT 2
Ok, I think that I found a solution:
TARGET_EXEC := main
TEST_EXEC := tests
CC := g++
BUILD_DIR := .
SRC_DIR := src
OBJ_DIR := obj
TEST_DIR := test
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
TEST := $(shell find $(TEST_DIR) -name '*.cpp')
OBJ := $(SRC:%=$(OBJ_DIR)/%.o)
TEST_OBJ := $(TEST:%=$(OBJ_DIR)/%.o)
DEPS := $(OBJ:.o=.d)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR))
CPPFLAGS := $(INC_FLAGS) -MMD -MP
.PHONY: clean all
all: $(BUILD_DIR)/$(TARGET_EXEC) $(BUILD_DIR)/$(TEST_EXEC)
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJ)
$(CC) $(OBJ) -o $# $(LDFLAGS)
$(BUILD_DIR)/$(TEST_EXEC): $(TEST_OBJ)
$(CC) $(TEST_OBJ) -o $# $(LDFLAGS)
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
clean:
rm -r $(OBJ_DIR) main tests
-include $(DEPS)
With this makefile the compilation is good (I think), since the obj/src and obj/test folder are created. main executable is compiled correctly and works. Also tests executable is compiled (correclty I think), but I get another error, not related to makefile:
g++ -Isrc -MMD -MP -c src/osmanip.cpp -o obj/src/osmanip.cpp.o
g++ -Isrc -MMD -MP -c src/main.cpp -o obj/src/main.cpp.o
g++ obj/src/osmanip.cpp.o obj/src/main.cpp.o -o main
g++ -Isrc -MMD -MP -c test/tests.cpp -o obj/test/tests.cpp.o
g++ obj/test/tests.cpp.o -o tests
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [makefile:29: tests] Error 1
I think this is due to the fact that my test/tests.cpp file is
#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest/doctest.h"
#include <string>
I didn't give it any command for the moment. I implemented doctest without main and in fact it tells me that main function is missing (because it is implemented into the src/main.cpp file). I tried looking at this answer, but I didn't solve this problem.
Do you know how to correctly compile the doctest test.cpp file? Thanks.
EDIT 3
Thanks to Jarod42 answer I solved also this very last issue related to doctest. Now all seems working perfectly.
Many thanks to sll you guys! It is my first post on Stack Overflow and I alrealy love this site.
Have tried humble beginnings? Here is where I would start and build on, key being to separate the main.o from OBJ so that tests can have its main from tests.o:
# Adding include directories (weird way of doing it but ok)
CPPFLAGS := $(addprefix -I,$(shell find src -type d))
# object files
OBJ := src/file1.o src/file2.o
# main
main: src/main.o $(OBJ)
# the test program
tests: test/tests.o $(OBJ)
(Notice this relies on built-in recipes, should work out-of-the-box.)
From there you can re-introduce the other concepts step by step:
Out-of-tree build.
Overrated (at least for GNU Make for which it's all manual).
Glob source files.
If you know what files you have, best not glob.
Dependency file generation and inclusion.
Keep folders and such in variables.

C++ Makefile missing separator in .dep

On OS X Mavericks i am trying to build a project using the following Makefile:
CC=g++
EXECUTABLE=minigi
SRC_DIR=src
INTERM_DIR=obj
INCLUDES=-I $(SRC_DIR) -I /usr/local/Cg/examples/OpenGL/glew/include/
LIBS=-L/usr/local/lang/NVIDIA_GPU_Computing_SDK/sdk/C/common/lib/linux/ -lpng -stdc++ -lGL -lGLU -lGLEW -lSDLmain -lSDL -lgomp
CFLAGS_COMMON=$(INCLUDES)
CFLAGS=$(CFLAGS_COMMON) -O3 -DNDEBUG -fopenmp
#CFLAGS=$(CFLAGS_COMMON) -g -O0 -D_DEBUG
SOURCE_FILES=$(shell find $(SRC_DIR) -iname '*.cpp')
DEP_FILES=$(SOURCE_FILES:$(SRC_DIR)/%.cpp=./$(INTERM_DIR)/%.dep)
OBJ_FILES=$(SOURCE_FILES:$(SRC_DIR)/%.cpp=./$(INTERM_DIR)/%.o)
all: $(EXECUTABLE)
clean:
rm -rf obj $(EXECUTABLE)
.PHONY: clean all
.SUFFIXES:
.SUFFIXES:.o .dep .cpp .h
$(INTERM_DIR)/%.dep: $(SRC_DIR)/%.cpp
mkdir -p `dirname $#`
printf `dirname $#`/ > $#
$(CC) $(CFLAGS_COMMON) $< -MM | sed -r -e 's,^(.*)\.o\s*\:,\1.o $# :,g' >> $#
ifneq ($(MAKECMDGOALS),clean)
-include $(DEP_FILES)
endif
$(INTERM_DIR)/%.o: $(SRC_DIR)/%.cpp
mkdir -p $(INTERM_DIR)
$(CC) $(CFLAGS) -c $< -o $#
$(EXECUTABLE): $(OBJ_FILES)
$(CC) $^ $(LIBS) -o $#
However, when I type make I get the following error:
obj/app/sdl_gl_appliacation.dep:1: *** missing separator. Stop.
The file obj/app/sdl_gl_application.dep looks as follows:
-n obj/app/
As I know very little about makefiles (and did not write the posted one) every help would be appreciated.
P.S.
I modified the line printf dirname $#/ > $# . In the original file there was an echo -n but that is not working on OS X.
Well, let's clean this up a little bit.
The way the dependencies are handled really is ugly, GCC can do it for you automatically.
EXECUTABLE := minigi
SRC_DIR := src
OBJ_DIR := obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(SRC_FILES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
DEP_FILES := $(OBJ_FILES:.o=.d)
LDLIBS := -lpng -lstdc++ -lGL -lGLU -lGLEW -lSDLmain -lSDL -lgomp
LDFLAGS := -L/usr/local/lang/NVIDIA_GPU_Computing_SDK/sdk/C/common/lib/linux/
CPPFLAGS := -MMD -MP -DNDEBUG -fopenmp -I $(SRC_DIR) -I /usr/local/Cg/examples/OpenGL/glew/include/
CXXFLAGS := -O3
.PHONY: all clean
all: $(EXECUTABLE)
clean:
$(RM) -r $(OBJ_DIR) $(EXECUTABLE)
$(EXECUTABLE): $(OBJ_FILES)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
$(OBJ_DIR):
mkdir $#
ifeq "$(MAKECMDGOALS)" ""
-include $(DEP_FILES)
endif
Some quick notes :
You're using C++, so you should use $(CXX) instead of $(CC) which is used for C code.
Along with this, you should use $(CXXFLAGS) instead of $(CFLAGS).
$(CPPFLAGS) is meant for preprocessor flags (-I, -D, or -fopenmp which is a compile-time flag).
-MMD -MP preprocessor flags will auto-generate dependency files when compiling. Learn more.
$(LDFLAGS) is meant for linker flags such as -L flags.
$(LDLIBS) is meant for linker libs such as -l flags
Avoid using the $(shell ) function since it will be executed every time the variable is expanded when assigned with the = operator instead of the := operator. $(wildcard ) is more suited for the job of listing files.

Makefile C++11 - Compiling to static library

I am trying to compile my source files to a static library, however, it doesn't seem to want to work. Here is the code:
#-----------------------------------------------------------------------------
# Usage of make file
#-----------------------------------------------------------------------------
# Clean operation:
# make -f MakeClient clean
#
# Make operation:
# make -f MakeClient
#
#
#OBJ = $(SRC:.cpp=.o)
OBJ_DIR = ./obj
OUT_DIR= ../lib
OUT_FILE_NAME = libclient.a
# include directories
INCLUDES=-I. -I../common -I../../depends -I../../depends/zlib
# C++ compiler flags (-g -O2 -Wall)
CXXFLAGS := -Wall -Wextra -pedantic-errors -std+c++0x
# compiler
CCC = g++
# Enumerating of every *.cpp as *.o and using that as dependency
$(OUT_FILE_NAME): $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard *.cpp))
$(CCC) -o $(OUT_DIR)/$# $^ -static $(LIB_DIR) $(LIBS) -std=c++11
#Compiling every *.cpp to *.o
$(OBJ_DIR)/%.o: %.cpp dircreation
$(CCC) -c $(INCLUDES) $(CCFLAGS) -o $# $<
dircreation:
#mkdir -p $(OUT_DIR)
#mkdir -p $(OBJ_DIR)
.PHONY : clean
clean:
rm -f $(OBJ_DIR)/*.o $(OUT_DIR)/$(OUT_FILE_NAME) Makefile.bak
The problem seems to be recognising that I'm using C++11 since the actual code does not compile.
Any ideas?
Replace CCFLAGS with CXXFLAGS, or vice versa.
And the flag is spelled -std=c++0x (thanks, #Pixelchemist).

Improving makefile to look into subdirectories

Some time ago I had a need to create a makefile to work with a lot of small test projects that I was making. The whole scope was to simply compile all .cpp files in its directory, and to sort out object files and dependencies. However, one of those projects finally grew much enough that I'm in need of creating custom subfolders to keep all the code organized.
The problem is that I don't know all that much about makefiles, and the one I made is composed of bits and scraps I found around the internet. I was wondering how would I modify this code to be able to include files from different folders. What I have now is this:
SHELL=/bin/bash
CC=g++
EXECUTABLE=ruletheskies
CFLAGS=-std=c++0x -Wall -pedantic #-I/usr/include/boost_1_51_0/
LDFLAGS=-L./
LIBRARIES=-ljson_linux-gcc-4.6_libmt -lbprinter
WINLIBRARIES=-ljson_mingw_libmt -lbprinter_mingw
WINDEFINES=-DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -DSTRICT -DHAVE_W32API_H -D__WXMSW__ -D__WINDOWS__
WINLDFLAGS=-I./ # $(shell find /usr/include/ -maxdepth 1 -type d | sed 's/^/-I/g') #-L/usr/lib/ -I/usr/include/
WINBASELIBRARIES=-lodbc32 -lwsock32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lodbc32 -lwsock32 -lopengl32 -lglu32 -lole32 -loleaut32 -luuid
WINSTATIC=-static-libstdc++ -static-libgcc
WINOPTIONS=--verbose
SOURCES := $(wildcard *.cpp)
HEADERS := $(wildcard *.h)
OBJECTSFOLDER=objects
OBJECTS=$(addprefix $(OBJECTSFOLDER)/, $(SOURCES:.cpp=.o))
DEPFOLDER=dependencies
df=$(DEPFOLDER)/$(*F)
odf=$(OBJECTSFOLDER)/$(*F)
EXEFOLDER=bin
.PHONY : all
# Brute force compiling statement for simple compilation and no .o residual files
all: $(EXEFOLDER)
$(CC) $(CFLAGS) $(LDFLAGS) *.cpp $(LIBRARIES) -o $(EXEFOLDER)/$(EXECUTABLE)
.PHONY: debug
# Compiles using object files in OBJECTSFOLDER, only modified stuff
debug: folders $(SOURCES) $(EXEFOLDER)/$(EXECUTABLE)
.PHONY: windows
# cross-compilation: mingw has to be selected, adds libraries for windows, brute force
windows: $(EXEFOLDER)
$(CC) $(CFLAGS) $(WINDEFINES) $(WINSTATIC) $(LDFLAGS) $(WINLDFLAGS) *.cpp $(LIBRARIES) $(WINLIBRARIES) $(WINBASELIBRARIES) -o $(EXEFOLDER)/$(EXECUTABLE).exe $(WINOPTIONS)
# Final linking of the executable
$(EXEFOLDER)/$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBRARIES) -o $#
# Creation of object files
# ( Actual compilation is only last instruction, the rest is creating dependency header rules )
$(OBJECTSFOLDER)/%.o: %.cpp
#$(CC) -MMD -c $(CFLAGS) -o $# $<
#cp $(odf).d $(df).P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(odf).d >> $(df).P; \
rm -f $(odf).d
$(CC) -c $(CFLAGS) $< -o $#
-include $(DEPFOLDER)/*.P
# Creation of folders
.PHONY : folders
folders: $(OBJECTSFOLDER) $(DEPFOLDER) $(EXEFOLDER)
$(OBJECTSFOLDER):
mkdir $#
$(DEPFOLDER):
mkdir $#
$(EXEFOLDER):
mkdir $#
# Cleanup of object files
# ( .PHONY is to avoid calling the rule in case a file named clean exists )
.PHONY : clean
clean:
rm -rf $(OBJECTSFOLDER)
rm -rf $(DEPFOLDER)
I imagine I'll have to modify the SOURCES := $(wildcard *.cpp) line, but how would I include the subdirectories I have to look into, whatever they may be? I'm planning to keep corresponding header and source files together, if that simplifies things.