-
Notifications
You must be signed in to change notification settings - Fork 0
/
Makefile
220 lines (183 loc) · 7.22 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# include paths
TINYSTAN_ROOT ?= .
# user customization
-include $(TINYSTAN_ROOT)/make/local
SRC ?= $(TINYSTAN_ROOT)/src/
STAN ?= $(TINYSTAN_ROOT)/stan/
STANC ?= $(TINYSTAN_ROOT)/bin/stanc$(EXE)
MATH ?= $(STAN)lib/stan_math/
RAPIDJSON ?= $(STAN)lib/rapidjson_1.1.0/
# required C++ includes
INC_FIRST ?= -I $(STAN)src -I $(RAPIDJSON)
# TinyStan always wants multithreading support
STAN_THREADS=true
# We can bump to C++17, even if Stan hasn't yet
STAN_HAS_CXX17 ?= true
CXXFLAGS_LANG ?= -std=c++17
# makefiles needed for math library
include $(MATH)make/compiler_flags
include $(MATH)make/libraries
include $(MATH)make/dependencies
# Set -fPIC globally since we're always building a shared library
override CXXFLAGS += -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
override CXXFLAGS_SUNDIALS += -fPIC
override CPPFLAGS += -DTINYSTAN_EXPORT
ifeq ($(OS),Windows_NT)
override CXXFLAGS += -Wa,-mbig-obj
endif
ifdef STAN_OPENCL
# set flags for stanc compiler
override STANCFLAGS += --use-opencl
STAN_FLAG_OPENCL=_opencl
else
STAN_FLAG_OPENCL=
endif
STAN_FLAGS=$(STAN_FLAG_OPENCL)
TINYSTAN_O = $(patsubst %.cpp,%$(STAN_FLAGS).o,$(SRC)tinystan.cpp)
TINYSTAN_DEPS := $(SRC)tinystan.cpp $(SRC)R_shims.cpp $(wildcard $(SRC)*.hpp) $(wildcard $(SRC)*.h)
include $(SRC)tinystan.d
$(TINYSTAN_O) : $(TINYSTAN_DEPS)
@echo '--- Compiling TinyStan C++ code ---'
@mkdir -p $(dir $@)
$(COMPILE.cpp) $(OUTPUT_OPTION) $(LDLIBS) $<
# support user header file for undefined functions
ifneq ($(findstring allow-undefined,$(STANCFLAGS)),)
USER_HEADER ?= $(dir $(MAKECMDGOALS))user_header.hpp
USER_INCLUDE = -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
# save compilation time by precompiling the model header
PRECOMPILED_HEADERS ?= false
ifeq ($(PRECOMPILED_HEADERS),true)
PRECOMPILED_MODEL_HEADER=$(STAN)src/stan/model/model_header.hpp.gch/model_header$(STAN_FLAGS)_$(CXX_MAJOR)_$(CXX_MINOR).hpp.gch
$(patsubst %.hpp.gch,%.d,$(PRECOMPILED_MODEL_HEADER)) : DEPTARGETS = -MT $@
$(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) $<
-include $(patsubst %.hpp.gch,%.d,$(PRECOMPILED_MODEL_HEADER))
$(PRECOMPILED_MODEL_HEADER): $(STAN)src/stan/model/model_header.hpp
@echo ''
@echo '--- Compiling pre-compiled header. ---'
@mkdir -p $(dir $@)
$(COMPILE.cpp) $< $(OUTPUT_OPTION)
ifeq ($(CXX_TYPE),clang)
PRECOMPILED_HEADER_INCLUDE = -include-pch $(PRECOMPILED_MODEL_HEADER)
endif
endif
# generate .hpp file from .stan file using stanc
%.hpp : %.stan $(STANC)
@echo ''
@echo '--- Translating Stan model to C++ code ---'
$(STANC) $(STANCFLAGS) --o=$(subst \,/,$@) $(subst \,/,$<)
%.o : %.hpp $(USER_HEADER) $(PRECOMPILED_MODEL_HEADER)
@echo '--- Compiling C++ code ---'
$(COMPILE.cpp) $(PRECOMPILED_HEADER_INCLUDE) $(USER_INCLUDE) -x c++ -o $(subst \,/,$*).o $(subst \,/,$<)
%_model.so : %.o $(TINYSTAN_O) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS)
@echo '--- Linking C++ code ---'
$(LINK.cpp) -shared -lm -o $(patsubst %.o, %_model.so, $(subst \,/,$<)) $(subst \,/,$*.o) $(TINYSTAN_O) $(LDLIBS) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS)
# build all test models at once
ALL_TEST_MODEL_NAMES = $(patsubst $(TINYSTAN_ROOT)/test_models/%/, %, $(sort $(dir $(wildcard $(TINYSTAN_ROOT)/test_models/*/))))
# these are for compilation testing in the interfaces
SKIPPED_TEST_MODEL_NAMES = syntax_error external
TEST_MODEL_NAMES := $(filter-out $(SKIPPED_TEST_MODEL_NAMES), $(ALL_TEST_MODEL_NAMES))
TEST_MODEL_LIBS = $(join $(addprefix test_models/, $(TEST_MODEL_NAMES)), $(addsuffix _model.so, $(addprefix /, $(TEST_MODEL_NAMES))))
.PHONY: test_models
test_models: $(TEST_MODEL_LIBS)
.PHONY: format
format:
clang-format -i src/*.cpp src/*.hpp src/*.h || true
isort clients/python || true
black clients/python || true
julia --project=clients/julia -e 'using JuliaFormatter; format("clients/julia/")' || true
Rscript -e 'formatR::tidy_dir("clients/R/", recursive=TRUE)' || true
.PHONY: clean
clean:
$(RM) $(SRC)*.o $(SRC)*.d
$(RM) -r $(STAN)src/stan/model/model_header.hpp.gch/
$(RM) $(TINYSTAN_ROOT)/test_models/**/*.so
$(RM) $(join $(addprefix $(TINYSTAN_ROOT)/test_models/, $(TEST_MODEL_NAMES)), $(addsuffix .hpp, $(addprefix /, $(TEST_MODEL_NAMES))))
$(RM) bin/stanc$(EXE)
.PHONY: stan-update stan-update-version
stan-update:
git submodule update --init --recursive
stan-update-remote:
git submodule update --remote --init --recursive
# print compilation command line config
.PHONY: compile_info
compile_info:
@echo '$(LINK.cpp) $(STANC_O) $(LDLIBS) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS)'
# print value of makefile variable (e.g., make print-TBB_TARGETS)
.PHONY: print-%
print-% : ; @echo $* = $($*) ;
# handles downloading of stanc
STANC_DL_RETRY = 5
STANC_DL_DELAY = 10
STANC3_TEST_BIN_URL ?=
STANC3_VERSION ?= nightly
ifeq ($(OS),Windows_NT)
OS_TAG := windows
else ifeq ($(OS),Darwin)
OS_TAG := mac
else ifeq ($(OS),Linux)
OS_TAG := linux
ifeq ($(shell uname -m),mips64)
ARCH_TAG := -mips64el
else ifeq ($(shell uname -m),ppc64le)
ARCH_TAG := -ppc64el
else ifeq ($(shell uname -m),s390x)
ARCH_TAG := -s390x
else ifeq ($(shell uname -m),aarch64)
ARCH_TAG := -arm64
else ifeq ($(shell uname -m),armv7l)
ifeq ($(shell readelf -A /usr/bin/file | grep Tag_ABI_VFP_args),)
ARCH_TAG := -armel
else
ARCH_TAG := -armhf
endif
endif
endif
ifeq ($(OS_TAG),windows)
$(STANC):
@mkdir -p $(dir $@)
$(shell echo "curl -L https://github.com/stan-dev/stanc3/releases/download/$(STANC3_VERSION)/$(OS_TAG)-stanc -o $(STANC) --retry $(STANC_DL_RETRY) --retry-delay $(STANC_DL_DELAY)")
else
$(STANC):
@mkdir -p $(dir $@)
curl -L https://github.com/stan-dev/stanc3/releases/download/$(STANC3_VERSION)/$(OS_TAG)$(ARCH_TAG)-stanc -o $(STANC) --retry $(STANC_DL_RETRY) --retry-delay $(STANC_DL_DELAY)
chmod +x $(STANC)
endif
##
# This is only run if the `include` statements earlier fail to find a file.
# We assume that means the submodule is missing
##
$(MATH)make/% :
@echo 'ERROR: Missing Stan submodules.'
@echo 'We tried to find the Stan Math submodule at:'
@echo ' $(MATH)'
@echo ''
@echo 'The most likely source of the problem is TinyStan was cloned without'
@echo 'the --recursive flag. To fix this, run the following command:'
@echo ' git submodule update --init --recursive'
@echo ''
@echo 'And try building again'
@exit 1
# EMSCRIPTEN is defined by emmake, so we can use it to detect if we're in an emscripten environment
ifneq (,$(EMSCRIPTEN))
%.js : %.o $(TINYSTAN_O) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS)
@echo '--- Linking C++ code ---'
$(LINK.cpp) -lm -o $(patsubst %.o, %.js, $(subst \,/,$<)) $(subst \,/,$*.o) $(TINYSTAN_O) $(LDLIBS) $(SUNDIALS_TARGETS) $(MPI_TARGETS) $(TBB_TARGETS)
else
%.js :
@echo 'ERROR: Emscripten is required to compile to WebAssembly.'
@echo 'Please install Emscripten and make sure you are using `emmake`.'
@exit 1
endif