forked from elcritch/matrex
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Makefile
301 lines (251 loc) · 8.07 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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#-------------------------------------------------------------------------------
# DEPENDENCIES
#-------------------------------------------------------------------------------
# The location of the header file for the erlang runtime system.
#
# Example:
#
# /usr/lib/erlang/erts-8.2/include
#
ERL_INCLUDE_PATH = $(shell erl -eval 'io:format("~s", [lists:concat([code:root_dir(), "/erts-", erlang:system_info(version), "/include"])])' -s init stop -noshell)
#-------------------------------------------------------------------------------
# FLAGS
#-------------------------------------------------------------------------------
# Switches between different BLAS implementations
# Can be blas, openblas, atlas, noblas
ifdef MATREX_BLAS
BLAS = $(MATREX_BLAS)
else
BLAS = blas
endif
# For compiling and linking the final NIF shared objects.
CFLAGS = -fPIC -I$(ERL_INCLUDE_PATH) -O3 -std=gnu11 -Wall -Wextra
LDFLAGS =
ifeq ($(BLAS), blas)
LDFLAGS += -lblas
else ifeq ($(BLAS), noblas)
CFLAGS += -D MATREX_NO_BLAS
endif
# Determine Platform, and check for override $ARCH var
COMPILE_ARCH=linux
ifeq ($(shell uname -s), Darwin)
COMPILE_ARCH=darwin
endif
ifeq ($(findstring linux,$(CC)),linux)
COMPILE_ARCH=linux
endif
# MacOS needs extra flags to link successfully
ifeq ($(COMPILE_ARCH), darwin)
LDFLAGS += -flat_namespace -undefined suppress
## MacOS BLAS
ifeq ($(BLAS), openblas)
CFLAGS += -I/usr/local/opt/openblas/include
LDFLAGS += -L/usr/local/opt/openblas/lib
else ifeq ($(BLAS), blas)
CFLAGS += -I/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Versions/Current/Headers
endif
else ifeq ($(COMPILE_ARCH), linux) # Linux
CFLAGS += -shared
LDFLAGS += -lm
ifeq ($(BLAS), openblas)
LDFLAGS += -lopenblas
else ifeq ($(BLAS), atlas)
LDFLAGS += -latlas
endif
else
$(error var was not specified at commandline!)
endif
# For compiling and linking the test runner.
TEST_CFLAGS = -g -O0 -std=gnu11 -Wall -Wextra --coverage
TEST_LDFLAGS =# -lgcov
#-------------------------------------------------------------------------------
# DIRECTORIES
#-------------------------------------------------------------------------------
# Location of the root directory for the C code files.
SRC_DIRECTORY = ./native/src
# Location fo the root directory for the C header files.
INCLUDE_DIRECTORY = ./native/include
# Location of the root directory for the object files created from the C code
# files.
OBJ_DIRECTORY = ./_build/obj
# Location of the root directory for the NIF code files.
NIFS_DIRECTORY = ./native/nifs
# Location of the `priv` directory where the final shared objects are placed.
PRIV_DIRECTORY = ./priv
# A list of all the subdirectories containing C code files.
SOURCES_DIRECTORIES := $(shell find $(SRC_DIRECTORY) -type d)
# A list of all the subdirectories containing object files created from the C
# code files. The list is a mirror of the directory structure in which the C
# code files reside.
OBJECTS_DIRECTORIES := $(subst $(SRC_DIRECTORY),$(OBJ_DIRECTORY),$(SOURCES_DIRECTORIES))
# Location of the root directory for the test object files created from the
# C source files with the test specific flags.
TEST_OBJ_DIRECTORY = ./test/c/obj
# A list of all the subdirectories containing object files created from the C
# code files with the test specific flags. The list is a mirror of the directory
# structure in which the C code files reside.
TEST_OBJECTS_DIRECTORIES := $(subst $(SRC_DIRECTORY),$(TEST_OBJ_DIRECTORY),$(SOURCES_DIRECTORIES))
#-------------------------------------------------------------------------------
# FILES
#-------------------------------------------------------------------------------
# Lists of all the C source files.
SOURCES := $(shell find $(SRC_DIRECTORY) -name *.c)
# Lists of all the C header files.
HEADERS := $(shell find $(INCLUDE_DIRECTORY) -name *.h)
# List of all the object files created from the C code files. The list is a
# mirror of the directory structure in which the C code files reside.
OBJECTS := $(SOURCES:$(SRC_DIRECTORY)/%.c=$(OBJ_DIRECTORY)/%.o)
# A list of all the NIF code files.
NIFS_SOURCES := $(wildcard $(NIFS_DIRECTORY)/*.c)
# A list of all the helpers used by the NIF code files.
NIFS_HELPERS := $(shell find $(NIFS_DIRECTORY) -name *_helper.c)
# A list of all the shared objects created by compiling the NIF code files.
NIFS_OBJECTS := $(NIFS_SOURCES:$(NIFS_DIRECTORY)/%.c=$(PRIV_DIRECTORY)/%.so)
# A list of all the shared objects created from the C code files with the test
# specific flags.
TEST_OBJECTS := $(SOURCES:$(SRC_DIRECTORY)/%.c=$(TEST_OBJ_DIRECTORY)/%.o)
#-------------------------------------------------------------------------------
# TARGETS
#-------------------------------------------------------------------------------
# Use the `build` target when executing make without arguments.
#
# Example:
#
# Executing:
# ```bash
# make
# ```
#
# Is equivalent to executing:
# ```bash
# make build
# ```
#
.DEFAULT_GLOBAL := build
# Targets that do not depend on files.
.PHONY: build ci clean test
# Compiles and links the C nifs.
#
# Example
#
# ```bash
# make build
# ```
#
build: $(OBJECTS_DIRECTORIES) $(OBJECTS) $(PRIV_DIRECTORY) $(NIFS_OBJECTS)
# Target for creating directories for the C object files.
$(OBJECTS_DIRECTORIES):
@mkdir -p $(OBJECTS_DIRECTORIES)
@echo 'Compile Arch: '$(COMPILE_ARCH)
@echo 'Library BLAS: '$(BLAS)
# Target for creating object files from C source files.
# Each object file depends on it's corresponding C source file for compilation.
#
# Example:
# native/obj/matrix.o
#
# Depends on:
# native/src/matrix.c
# native/include/matrix.h
#
# Output:
# ```
# Compiling: native/src/matrix.c
# ```
#
$(OBJECTS): $(OBJ_DIRECTORY)/%.o : $(SRC_DIRECTORY)/%.c $(INCLUDE_DIRECTORY)/%.h
@echo 'Compiling: '$<
@$(CC) $(CFLAGS) -c $< -o $@
# Target for creating the `priv` directory for the NIF shared objects.
$(PRIV_DIRECTORY):
@mkdir -p $(PRIV_DIRECTORY)
# Target for creating the NIF shared objects.
#
# Example:
# priv/worker_nifs.so
#
# Depends on:
# priv/
# native/nifs/matrix_nifs.c
# native/nifs/helpers/network_state_helper.c
# _build/obj/matrix.o
#
# Output:
# ```
# Creating NIF: priv/worker_nifs.so
# ```
#
$(NIFS_OBJECTS): $(PRIV_DIRECTORY)/%.so : $(NIFS_DIRECTORY)/%.c $(OBJECTS) $(NIFS_HELPERS)
@echo 'Creating NIF: '$@
@$(CC) $(CFLAGS) $(OBJECTS) -o $@ $< $(LDFLAGS)
# Builds the C code with debugging and testing flags and runs the tests.
#
# Example:
#
# ```bash
# make test
# ```
#
test: $(TEST_OBJECTS_DIRECTORIES) $(TEST_OBJECTS)
@find test/c/temp/ ! -name '.keep' -type f -exec rm -f {} +
@lcov --directory . -z --rc lcov_branch_coverage=1
$(CC) $(TEST_CFLAGS) $(TEST_OBJECTS) -o test/c/temp/test test/test_helper.c $(LDFLAGS) $(TEST_LDFLAGS)
./test/c/temp/test
@lcov --directory . -c -o cover/lcov.info-file --rc lcov_branch_coverage=1
@lcov --list cover/lcov.info-file --rc lcov_branch_coverage=1
@genhtml --branch-coverage -o cover cover/lcov.info-file > /dev/null
@rm -rf *.gcda *.gcno
# Target for creating directories for the C object files compiled with test
# specific flags.
$(TEST_OBJECTS_DIRECTORIES):
@mkdir -p $(TEST_OBJECTS_DIRECTORIES)
# Target for creating object files from C source files with test specific flags.
# Each object file depends on it's corresponding C source file for compilation.
#
# Example:
# test/c/obj/matrix.o
#
# Depends on:
# native/src/matrix.c
# native/include/matrix.h
#
# Output:
# ```
# Compiling: native/src/matrix.c
# ```
#
$(TEST_OBJECTS): $(TEST_OBJ_DIRECTORY)/%.o : $(SRC_DIRECTORY)/%.c $(INCLUDE_DIRECTORY)/%.h
@echo 'Compiling: '$<
@$(CC) $(TEST_CFLAGS) -c $< -o $@
# Remove build artifacts.
# Run this when you want to ensure you run a fresh build.
#
# Example:
#
# To remove all artifacts:
# ```bash
# make clean
# ```
#
# To create a fresh build:
# ```
# make clean build
# ```
#
clean:
@$(RM) -rf $(OBJ_DIRECTORY) $(PRIV_DIRECTORY) $(TEST_OBJ_DIRECTORY)
# Run the complete suite of tests and checks.
#
# Example:
#
# ```bash
# make ci
# ```
#
ci:
@make
@mix deps.get
@mix dialyzer --plt
@make test
@mix coveralls.travis
@mix dialyzer --halt-exit-status