This repository was archived by the owner on Mar 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathnrnivmodl_core_makefile.in
More file actions
288 lines (234 loc) · 11.5 KB
/
nrnivmodl_core_makefile.in
File metadata and controls
288 lines (234 loc) · 11.5 KB
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
# This Makefile has the rules necessary for making the custom version of
# CoreNEURON executable called "special-core" from the provided mod files.
# Mod files are looked up in the MODS_PATH directory.
# Current system OS
OS_NAME := $(shell uname)
# ","" is an argument separator, never as a literal for Makefile rule
COMMA_OP =,
# Default variables for various targets
MECHLIB_SUFFIX =
MODS_PATH = .
OUTPUT_DIR = @CMAKE_HOST_SYSTEM_PROCESSOR@
DESTDIR =
TARGET_LIB_TYPE = $(BUILD_TYPE)
# required for OSX to execute nrnivmodl-core
OSX_SYSROOT=@CMAKE_OSX_SYSROOT@
ifneq ($(OSX_SYSROOT),)
export SDKROOT := $(OSX_SYSROOT)
endif
# CoreNEURON installation directories
CORENRN_BIN_DIR := $(ROOT)/bin
CORENRN_LIB_DIR := $(ROOT)/lib
CORENRN_INC_DIR := $(ROOT)/include
CORENRN_SHARE_CORENRN_DIR:= $(ROOT)/share/coreneuron
CORENRN_SHARE_MOD2CPP_DIR := $(ROOT)/share/mod2c
# name of the CoreNEURON binary
SPECIAL_EXE = $(OUTPUT_DIR)/special-core
# Directory where cpp files are generated for each mod file
MOD_TO_CPP_DIR = $(OUTPUT_DIR)/corenrn/mod2c
# Directory where cpp files are compiled
MOD_OBJS_DIR = $(OUTPUT_DIR)/corenrn/build
# Linked libraries gathered by CMake
LDFLAGS = $(LINKFLAGS) @CORENRN_COMMON_LDFLAGS@
CORENRNLIB_FLAGS = -L$(CORENRN_LIB_DIR) -lcoreneuron
CORENRNLIB_FLAGS += $(if @reportinglib_LIB_DIR@, -W$(subst ;, -W,l,-rpath,@reportinglib_LIB_DIR@),)
CORENRNLIB_FLAGS += $(if @sonatareport_LIB_DIR@, -W$(subst ;, -W,l,-rpath,@sonatareport_LIB_DIR@),)
CORENRNLIB_FLAGS += $(if @caliper_LIB_DIR@, -W$(subst ;, -W,l,-rpath,@caliper_LIB_DIR@),)
CORENRNLIB_FLAGS += $(if @caliper_LIB_DIR@,-L@caliper_LIB_DIR@,)
# Includes paths gathered by CMake
# coreneuron/utils/randoms goes first because it needs to override the NEURON
# directory in INCFLAGS
INCLUDES = -I$(CORENRN_INC_DIR)/coreneuron/utils/randoms $(INCFLAGS) -I$(CORENRN_INC_DIR)
ifeq (@CORENRN_ENABLE_MPI_DYNAMIC@, OFF)
INCLUDES += $(if @MPI_CXX_INCLUDE_PATH@, -I$(subst ;, -I,@MPI_CXX_INCLUDE_PATH@),)
endif
INCLUDES += $(if @reportinglib_INCLUDE_DIR@, -I$(subst ;, -I,@reportinglib_INCLUDE_DIR@),)
# CXX is always defined. If the definition comes from default change it
ifeq ($(origin CXX), default)
CXX = @CMAKE_CXX_COMPILER@
endif
ifeq (@CORENRN_ENABLE_GPU@, ON)
ifneq ($(shell $(CXX) --version | grep -o nvc++), nvc++)
$(error GPU wheels are only compatible with the NVIDIA C++ compiler nvc++, but CXX=$(CXX) and --version gives $(shell $(CXX) --version))
endif
# nvc++ -dumpversion is simpler, but only available from 22.2
ifeq ($(findstring nvc++ @CORENRN_NVHPC_MAJOR_MINOR_VERSION@, $(shell $(CXX) --version)),)
$(error GPU wheels are currently not compatible across NVIDIA HPC SDK versions. You have $(shell $(CXX) -V | grep nvc++) but this wheel was built with @CORENRN_NVHPC_MAJOR_MINOR_VERSION@.)
endif
endif
# In case of wheel, python and perl exe paths are from the build machine.
# First prefer env variables set by neuron's nrnivmodl wrapper then check
# binary used during build. If they don't exist then simply use python and
# perl as the name of binaries.
CORENRN_PYTHONEXE ?= @PYTHON_EXECUTABLE@
CORENRN_PERLEXE ?= @PERL_EXECUTABLE@
ifeq ($(wildcard $(CORENRN_PYTHONEXE)),)
CORENRN_PYTHONEXE=python
endif
ifeq ($(wildcard $(CORENRN_PERLEXE)),)
CORENRN_PERLEXE=perl
endif
CXXFLAGS = @CORENRN_CXX_FLAGS@
CXX_COMPILE_CMD = $(CXX) $(CXXFLAGS) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ @CORENRN_COMMON_COMPILE_DEFS@ $(INCLUDES)
CXX_LINK_EXE_CMD = $(CXX) $(CXXFLAGS)
CXX_LINK_EXE_FLAGS = @CMAKE_EXE_LINKER_FLAGS@
CXX_SHARED_LIB_CMD = $(CXX) $(CXXFLAGS) @CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS@ @CMAKE_SHARED_LIBRARY_CXX_FLAGS@ @CMAKE_SHARED_LINKER_FLAGS@
# ISPC compilation and link commands
ISPC = @CMAKE_ISPC_COMPILER@
ISPC_COMPILE_CMD = $(ISPC) @CMAKE_ISPC_FLAGS@ -I$(CORENRN_INC_DIR)
# env variables required for mod2c or nmodl
MOD2CPP_ENV_VAR = @CORENRN_SANITIZER_ENABLE_ENVIRONMENT_STRING@ PYTHONPATH=@CORENRN_NMODL_PYTHONPATH@:${CORENRN_LIB_DIR}/python MODLUNIT=$(CORENRN_SHARE_MOD2CPP_DIR)/nrnunits.lib
# nmodl options
ifeq (@CORENRN_ENABLE_NMODL@, ON)
ifeq (@CORENRN_ENABLE_GPU@, ON)
nmodl_arguments_c=@NMODL_ACC_BACKEND_ARGS@ @NMODL_COMMON_ARGS@
else
nmodl_arguments_c=@NMODL_CPU_BACKEND_ARGS@ @NMODL_COMMON_ARGS@
endif
nmodl_arguments_ispc=@NMODL_ISPC_BACKEND_ARGS@ @NMODL_COMMON_ARGS@
endif
# name of the mechanism library with suffix if provided
COREMECH_LIB_NAME = corenrnmech$(if $(MECHLIB_SUFFIX),_$(MECHLIB_SUFFIX),)
COREMECH_LIB_PATH = $(OUTPUT_DIR)/lib$(COREMECH_LIB_NAME)$(LIB_SUFFIX)
# Various header and C++/Object file
MOD_FUNC_CPP = $(MOD_TO_CPP_DIR)/_mod_func.cpp
MOD_FUNC_OBJ = $(MOD_OBJS_DIR)/_mod_func.o
ENGINEMECH_OBJ = $(MOD_OBJS_DIR)/enginemech.o
# Depending on static/shared build, determine library name and it's suffix
ifeq ($(TARGET_LIB_TYPE), STATIC)
LIB_SUFFIX = @CMAKE_STATIC_LIBRARY_SUFFIX@
corenrnmech_lib_target = coremech_lib_static
else
LIB_SUFFIX = @CMAKE_SHARED_LIBRARY_SUFFIX@
corenrnmech_lib_target = coremech_lib_shared
endif
# Binary of MOD2C/NMODL depending on CMake option activated
ifeq (@nmodl_FOUND@, TRUE)
MOD2CPP_BINARY_PATH = $(if $(MOD2CPP_BINARY),$(MOD2CPP_BINARY), @CORENRN_MOD2CPP_BINARY@)
INCLUDES += -I@CORENRN_MOD2CPP_INCLUDE@
ISPC_COMPILE_CMD += -I@CORENRN_MOD2CPP_INCLUDE@
else
MOD2CPP_BINARY_PATH = $(if $(MOD2CPP_BINARY),$(MOD2CPP_BINARY), $(CORENRN_BIN_DIR)/@nmodl_binary_name@)
endif
# MOD files with full path, without path and names without .mod extension
mod_files_paths = $(sort $(wildcard $(MODS_PATH)/*.mod))
mod_files_names = $(sort $(notdir $(wildcard $(MODS_PATH)/*.mod)))
mod_files_no_ext = $(mod_files_names:.mod=)
# Find out artificial and non-artificial cells for ISPC backend
define check_file
# if ISPC is active then only separate mod files
ifeq (@CORENRN_ENABLE_ISPC@, ON)
ifeq ($(shell grep -q $(2) $(1); echo $$?), 0)
mod_art_files += $(MOD_TO_CPP_DIR)/$(notdir $(1))
else
mod_non_art_files += $(MOD_TO_CPP_DIR)/$(notdir $(1))
endif
else
mod_all_files += $(MOD_TO_CPP_DIR)/$(notdir $(1))
endif
endef
# Iterate over all available mod files and make group
$(foreach mod_file, $(mod_files_paths), $(eval $(call check_file, $(mod_file), ARTIFICIAL_CELL)))
# With ispc, artificial cells get translated as regular CPP backend
# Otherwise, all mod files are compiled as CPP backend
ifeq (@CORENRN_ENABLE_ISPC@, ON)
mod_files_for_cpp_backend = $(mod_art_files)
else
mod_files_for_cpp_backend = $(mod_all_files)
endif
# CPP files and their obkects
mod_cpp_files = $(patsubst %.mod,%.cpp,$(mod_files_for_cpp_backend))
mod_cpp_objs = $(addprefix $(MOD_OBJS_DIR)/,$(addsuffix .o,$(basename $(mod_files_no_ext))))
# For ISPC backend, we use all non-artificial cells
mod_ispc_srcs_names = $(notdir $(mod_non_art_files))
mod_ispc_files = $(patsubst %.mod,%.ispc,$(mod_non_art_files))
mod_ispc_cpp_files = $(patsubst %.mod,%.cpp,$(mod_non_art_files))
mod_ispc_objs = $(addprefix $(MOD_OBJS_DIR)/,$(addsuffix .obj,$(basename $(mod_ispc_srcs_names))))
# We use $ORIGIN (@loader_path in OSX)
ORIGIN_RPATH := $(if $(filter Darwin,$(OS_NAME)),@loader_path,$$ORIGIN)
SONAME_OPTION := -Wl,$(if $(filter Darwin,$(OS_NAME)),-install_name${COMMA_OP}@rpath/,-soname${COMMA_OP})$(notdir ${COREMECH_LIB_PATH})
LIB_RPATH = $(if $(DESTDIR),$(DESTDIR)/lib,$(ORIGIN_RPATH))
# When special-core is installed, it needs to find library in the
# lib folder of install prefix. We use relative path in order it
# to be portable when files are moved (e.g. python wheel)
INSTALL_LIB_RPATH = $(ORIGIN_RPATH)/../lib
# All objects used during build
ALL_OBJS = $(MOD_FUNC_OBJ) $(mod_cpp_objs) $(mod_ispc_objs)
# Colors for pretty printing
C_RESET := \033[0m
C_GREEN := \033[32m
# Default nmodl flags. Override if MOD2CPP_RUNTIME_FLAGS is not empty
ifeq (@CORENRN_ENABLE_NMODL@, ON)
MOD2CPP_FLAGS_ISPC = $(if $(MOD2CPP_RUNTIME_FLAGS),$(MOD2CPP_RUNTIME_FLAGS),$(nmodl_arguments_ispc))
MOD2CPP_FLAGS_C = $(if $(MOD2CPP_RUNTIME_FLAGS),$(MOD2CPP_RUNTIME_FLAGS),$(nmodl_arguments_c))
endif
ifeq (@CORENRN_ENABLE_ISPC@, ON)
$(info Default NMODL flags: @nmodl_arguments_ispc@)
else
$(info Default NMODL flags: @nmodl_arguments_c@)
endif
ifneq ($(MOD2CPP_RUNTIME_FLAGS),)
$(warning Runtime nmodl flags (they replace the default ones): $(MOD2CPP_RUNTIME_FLAGS))
endif
# ======== MAIN BUILD RULES ============
# main target to build binary
$(SPECIAL_EXE): coremech_lib_target
@printf " => $(C_GREEN)Binary$(C_RESET) creating $(SPECIAL_EXE)\n"
$(CXX_LINK_EXE_CMD) -o $(SPECIAL_EXE) $(CORENRN_SHARE_CORENRN_DIR)/coreneuron.cpp \
-I$(CORENRN_INC_DIR) $(INCFLAGS) \
-L$(OUTPUT_DIR) -l$(COREMECH_LIB_NAME) $(CORENRNLIB_FLAGS) $(LDFLAGS) $(CXX_LINK_EXE_FLAGS) \
-Wl,-rpath,'$(LIB_RPATH)' -Wl,-rpath,$(CORENRN_LIB_DIR) -Wl,-rpath,'$(INSTALL_LIB_RPATH)'
coremech_lib_target: $(corenrnmech_lib_target)
rm -rf $(OUTPUT_DIR)/.libs/lib$(COREMECH_LIB_NAME)$(LIB_SUFFIX); \
mkdir -p $(OUTPUT_DIR)/.libs; \
ln -s ../lib$(COREMECH_LIB_NAME)$(LIB_SUFFIX) $(OUTPUT_DIR)/.libs/lib$(COREMECH_LIB_NAME)$(LIB_SUFFIX)
$(ENGINEMECH_OBJ): $(CORENRN_SHARE_CORENRN_DIR)/enginemech.cpp | $(MOD_OBJS_DIR)
$(CXX_COMPILE_CMD) -c -DADDITIONAL_MECHS $(CORENRN_SHARE_CORENRN_DIR)/enginemech.cpp -o $(ENGINEMECH_OBJ)
# build shared library of mechanisms
coremech_lib_shared: $(ALL_OBJS) $(ENGINEMECH_OBJ) build_always
$(CXX_SHARED_LIB_CMD) $(ENGINEMECH_OBJ) -o ${COREMECH_LIB_PATH} $(ALL_OBJS) \
-I$(CORENRN_INC_DIR) $(INCFLAGS) \
$(LDFLAGS) $(CORENRN_LIB_DIR)/libscopmath.a \
${SONAME_OPTION} $(CORENRNLIB_FLAGS) -Wl,-rpath,$(CORENRN_LIB_DIR);
# build static library of mechanisms
coremech_lib_static: $(ALL_OBJS) $(ENGINEMECH_OBJ) build_always
mkdir -p $(MOD_OBJS_DIR)/scopmath; \
cd $(MOD_OBJS_DIR)/scopmath && ar -x $(CORENRN_LIB_DIR)/libscopmath.a && cd -;\
rm -f ${COREMECH_LIB_PATH}; \
ar cq ${COREMECH_LIB_PATH} $(ENGINEMECH_OBJ) $(ALL_OBJS) $(MOD_OBJS_DIR)/scopmath/*.o;
# compile cpp files to .o
$(MOD_OBJS_DIR)/%.o: $(MOD_TO_CPP_DIR)/%.cpp | $(MOD_OBJS_DIR)
$(CXX_COMPILE_CMD) -c $< -o $@ -DNRN_PRCELLSTATE=$(NRN_PRCELLSTATE) @CORENEURON_TRANSLATED_CODE_COMPILE_FLAGS@
# compile ispc files to .obj
$(MOD_OBJS_DIR)/%.obj: $(MOD_TO_CPP_DIR)/%.ispc | $(MOD_OBJS_DIR)
$(ISPC_COMPILE_CMD) $< -o $@
# translate MOD files to ISPC using NMODL
$(mod_ispc_files): $(MOD_TO_CPP_DIR)/%.ispc: $(MODS_PATH)/%.mod | $(MOD_TO_CPP_DIR)
$(MOD2CPP_ENV_VAR) $(MOD2CPP_BINARY_PATH) $< -o $(MOD_TO_CPP_DIR)/ $(MOD2CPP_FLAGS_ISPC)
# translate MOD files to CPP using mod2c/NMODL
$(mod_cpp_files): $(MOD_TO_CPP_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MOD_TO_CPP_DIR)
$(MOD2CPP_ENV_VAR) $(MOD2CPP_BINARY_PATH) $< -o $(MOD_TO_CPP_DIR)/ $(MOD2CPP_FLAGS_C)
# static pattern to set up the dependencies for the previous recipe
$(mod_ispc_cpp_files): $(MOD_TO_CPP_DIR)/%.cpp: $(MOD_TO_CPP_DIR)/%.ispc
# generate mod registration function. Dont overwrite if it's not changed
$(MOD_FUNC_CPP): build_always | $(MOD_TO_CPP_DIR)
$(CORENRN_PERLEXE) $(CORENRN_SHARE_CORENRN_DIR)/mod_func.c.pl $(mod_files_names) > $(MOD_FUNC_CPP).tmp
diff -q $(MOD_FUNC_CPP).tmp $(MOD_FUNC_CPP) || \
mv $(MOD_FUNC_CPP).tmp $(MOD_FUNC_CPP)
# symlink to cpp files provided by coreneuron
$(MOD_TO_CPP_DIR)/%.cpp: $(CORENRN_SHARE_MOD2CPP_DIR)/%.cpp | $(MOD_TO_CPP_DIR)
ln -s $< $@
# create directories needed
$(MOD_TO_CPP_DIR):
mkdir -p $(MOD_TO_CPP_DIR)
$(MOD_OBJS_DIR):
mkdir -p $(MOD_OBJS_DIR)
# install binary and libraries
install: $(SPECIAL_EXE) coremech_lib_target
install -d $(DESTDIR)/bin $(DESTDIR)/lib
install ${COREMECH_LIB_PATH} $(DESTDIR)/lib
install $(SPECIAL_EXE) $(DESTDIR)/bin
.PHONY: build_always
$(VERBOSE).SILENT:
# delete cpp files if mod2c error, otherwise they are not generated again
.DELETE_ON_ERROR: