#  cudadl version 0.9: Compute discrete logs in smooth group orders
#                      using CUDA
#  Copyright (C) 2012 by Ryan Henry and Ian Goldberg
#                        {rhenry,iang}@cs.uwaterloo.ca
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of version 3 of the GNU General Public License as
#  published by the Free Software Foundation.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

-include Makefile.local

CUDA_ARCH ?= sm_80

GMP ?= /usr/local
NTL ?=
CUDA ?= /usr/local/cuda
LIBEVENT ?= /usr/local
MPI ?= /usr/local
CXX ?= g++

GMP_LIB = $(if $(strip $(GMP)), -L$(GMP)/lib)
GMP_INC = $(if $(strip $(GMP)), -I$(GMP)/include)

NTL_LIB = $(if $(strip $(NTL)), -L$(NTL)/lib)
NTL_INC = $(if $(strip $(NTL)), -I$(NTL)/include)

CUDA_LIB = $(if $(strip $(CUDA)), -L$(CUDA)/lib64)
CUDA_INC = $(if $(strip $(CUDA)), -I$(CUDA)/include)

LIBEVENT_LIB = $(if $(strip $(LIBEVENT)), -L$(LIBEVENT)/lib)
LIBEVENT_INC = $(if $(strip $(LIBEVENT)), -I$(LIBEVENT)/include)

MPI_LIB = $(if $(strip $(MPI)), -L$(MPI)/lib)
MPI_INC = $(if $(strip $(MPI)), -I$(MPI)/include)

WORDS = 24
MACROS := -UVERBOSE $(MACROS)
# options: VERBOSE DERANDOMIZE SAVE_DPS MAKE_VERSIONS_COMPARABLE RIPPLE GRAHAM DPFREQ_DIVISOR

CXXFLAGS=-g -Wall -O2
CPPFLAGS=-DWORDS=$(WORDS) $(LIBEVENT_INC) $(GMP_INC) $(NTL_INC) -std=c++11 $(MACROS)
NVCCOPTS=-g -arch $(CUDA_ARCH) --ptxas-options=-v -O2
NVCC=nvcc $(NVCCOPTS)

CXXFILES = dlrho.cc gen_N.cc
CUFILES = parrhoasm.cu dpstream.cu
OFILES = dlrho.o gen_N.o cudadl.o controller.o controller_main.o evutils.o dpnode.o dpnode_main.o worker.o worker_main.o
PTX_TARGETS = parrhoasm.ptx
NOMPI_TARGETS = gen_N dlrho controller dpnode worker desres
TARGETS = $(NOMPI_TARGETS) mpi

all: $(TARGETS)

nompi: $(NOMPI_TARGETS)

ptx: $(PTX_TARGETS)

gen_N: gen_N.o
	g++ -g -Wall $^ -o $@ $(NTL_LIB) -lntl $(GMP_LIB) -lgmp -lpthread

dlrho: dlrho.o cudadl.o desired_resources.o
	g++ -g -Wall $^ -o $@ $(NTL_LIB) -lntl $(GMP_LIB) -lgmp $(CUDA_LIB) -lcudart -lpthread

dlrho.o: dlrho.cc
	g++ $(CXXFLAGS) $(CPPFLAGS) $(CUDA_INC) $^ -c -o $@

parrhoasm.ptx: parrhoasm.cu cios.asm dpstream.cu
	$(NVCC) $(CPPFLAGS) -c $< -o $@ --ptx

cudadl.o: parrhoasm.cu cios.asm dpstream.cu
	$(NVCC) $(CPPFLAGS) -c $< -o $@

test_cuda: parrhoasm.cu cios.asm dpstream.cu
	$(NVCC) -DTEST_CUDA $(CPPFLAGS) $< -o $@ $(NTL_LIB) -lntl $(GMP_LIB) -lgmp $(CUDA_LIB) -lcudart -lpthread

cios.asm: gencios_reg_20
	./gencios_reg_20 $(WORDS) > $@

controller: controller.o evutils.o controller_main.o desired_resources.o
	g++ -g -Wall $^ -o $@ $(NTL_LIB) -lntl $(LIBEVENT_LIB) -Wl,-rpath=$(LIBEVENT)/lib -levent $(GMP_LIB) -lgmp -lpthread

dpnode: dpnode.o evutils.o dpnode_main.o
	g++ -g -Wall $^ -o $@ $(NTL_LIB) -lntl $(LIBEVENT_LIB) -Wl,-rpath=$(LIBEVENT)/lib -levent $(GMP_LIB) -lgmp -lpthread

worker: worker.o evutils.o cudadl.o worker_main.o
	g++ -g -Wall $^ -o $@ $(NTL_LIB) -lntl $(LIBEVENT_LIB) -Wl,-rpath=$(LIBEVENT)/lib -levent -levent_pthreads $(GMP_LIB) -lgmp -lpthread $(CUDA_LIB) -lcudart

worker.o: worker.cc
	g++ $(CXXFLAGS) $(CPPFLAGS) -I$(CUDA)/include $^ -c -o $@

desres: desired_resources.cc
	g++ $(CXXFLAGS) $(CPPFLAGS) -DTEST_DESIRED_RESOURCES $^ -o $@ $(NTL_LIB) -lntl $(LIBEVENT_LIB) -Wl,-rpath=$(LIBEVENT)/lib -lgmp -lpthread

mpi: mpi.o
	mpiCC -g -Wall $^ -o $@ -L/work/iang/sw/lib $(NTL_LIB) -lntl $(GMP_LIB) -lgmp -lpthread

mpi.o: mpi.cc
	mpiCC $(CXXFLAGS) $(CPPFLAGS) $^ -c -o $@

clean:
	-rm -f $(OFILES) $(PTX_TARGETS)

veryclean: clean
	-rm -f $(TARGETS) cios.asm
