##
# Models (to be passed through stanc)
##

STAN_TARGETS = $(patsubst %.stan,%$(EXE),$(wildcard $(patsubst %$(EXE),%.stan,$(MAKECMDGOALS))))

CMDSTAN_MAIN ?= src/cmdstan/main.cpp
CMDSTAN_MAIN_O = $(patsubst %.cpp,%$(STAN_FLAGS).o,$(CMDSTAN_MAIN))

$(CMDSTAN_MAIN_O) : $(CMDSTAN_MAIN)
	@echo ''
	@echo '--- Compiling the main object file. This might take up to a minute. ---'
	@mkdir -p $(dir $@)
	$(COMPILE.cpp) $(OUTPUT_OPTION) $<

##
# Precompiled model header
##
ifneq ($(PRECOMPILED_MODEL_HEADER),)
$(patsubst %.hpp.gch,%.d,$(PRECOMPILED_MODEL_HEADER)) : DEPTARGETS = -MT $(PRECOMPILED_MODEL_HEADER)
$(patsubst %.hpp.gch,%.d,$(PRECOMPILED_MODEL_HEADER)) : DEPFLAGS_OS = -M -E
$(patsubst %.hpp.gch,%.d,$(PRECOMPILED_MODEL_HEADER)) : $(STAN)src/stan/model/model_header.hpp
	@mkdir -p $(dir $@)
	$(COMPILE.cpp) $(DEPFLAGS) $<

$(PRECOMPILED_MODEL_HEADER) : $(STAN)src/stan/model/model_header.hpp
	@echo ''
	@echo '--- Compiling pre-compiled header. This might take a few seconds. ---'
	@mkdir -p $(dir $@)
	$(COMPILE.cpp) $< $(OUTPUT_OPTION)

ifeq ($(CXX_TYPE),clang)
CXXFLAGS_PROGRAM += -include-pch $(PRECOMPILED_MODEL_HEADER)
$(STAN_TARGETS) : %$(EXE) : $(PRECOMPILED_MODEL_HEADER)
endif
endif

ifneq ($(findstring allow-undefined,$(STANCFLAGS)),)

USER_HEADER ?= $(dir $(STAN_TARGETS))user_header.hpp
$(STAN_TARGETS) : CXXFLAGS_PROGRAM += -include $(USER_HEADER)
##
# Give a better error message if the USER_HEADER is not found
##
$(USER_HEADER):
	@echo 'ERROR: Missing user header.'
	@echo 'Because --allow-undefined is set, we need a C++ header file to include.'
	@echo 'We tried to find the user header at:'
	@echo '  $(USER_HEADER)'
	@echo ''
	@echo 'You can also set the USER_HEADER variable to the path of your C++ file.'
	@exit 1
endif

##
# Model executable
##

ifdef STAN_OPENCL
STANCFLAGS+= --use-opencl
endif

%.hpp : %.stan bin/stanc$(EXE)
	@echo ''
	@echo '--- Translating Stan model to C++ code ---'
	$(WINE) bin/stanc$(EXE) $(STANCFLAGS) --o=$(subst  \,/,$@) $(subst  \,/,$<)

%.d: %.hpp

ifeq ($(KEEP_OBJECT), true)
.PRECIOUS: %.o
endif

%.o : %.hpp $(USER_HEADER)
	@echo ''
	@echo '--- Compiling C++ code ---'
	$(COMPILE.cpp) $(CXXFLAGS_PROGRAM) -x c++ -o $(subst  \,/,$*).o $(subst \,/,$<)

%$(EXE) : %.o $(CMDSTAN_MAIN_O) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS) $(PRECOMPILED_MODEL_HEADER)
	@echo ''
	@echo '--- Linking model ---'
	$(LINK.cpp) $(subst \,/,$*.o) $(CMDSTAN_MAIN_O) $(LDLIBS) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS) $(subst \,/,$(OUTPUT_OPTION))

ifeq ($(OS),Windows_NT)
ifneq (,$(TBB_TARGETS))
ifeq (,$(findstring tbb.dll, $(notdir $(shell where tbb.dll))))
	@echo 'Intel TBB is not in PATH.'
	@echo 'Consider calling '
	@echo '$(MAKE) install-tbb'
	@echo 'to avoid copying Intel TBB library files.'
	@if ! [[ -f "$(@D)/tbb.dll" ]]; then \
		cp -v $(TBB_TARGETS) $(@D); \
	else \
		echo 'Using existing $(@D)/tbb.dll'; \
	fi
endif
endif
endif

$(patsubst %.cpp,%$(STAN_FLAGS).d,$(CMDSTAN_MAIN)) : $(CMDSTAN_MAIN)
	$(COMPILE.cpp) $(DEPFLAGS) $<

##
# Dependencies file
##
ifneq (,$(STAN_TARGETS))
$(patsubst %$(EXE),%.d,$(STAN_TARGETS)) : DEPTARGETS += -MT $(patsubst %.d,%$(EXE),$@) -include $< -include $(CMDSTAN_MAIN)
-include $(patsubst %$(EXE),%.d,$(STAN_TARGETS))
-include $(patsubst %.cpp,%$(STAN_FLAGS).d,$(CMDSTAN_MAIN))
ifneq (,$(PRECOMPILED_MODEL_HEADER))
-include $(patsubst %.hpp.gch,%.d,$(PRECOMPILED_MODEL_HEADER))
endif
endif
