diff --git a/coreneuron/CMakeLists.txt b/coreneuron/CMakeLists.txt index fff6b4549..aab407d74 100644 --- a/coreneuron/CMakeLists.txt +++ b/coreneuron/CMakeLists.txt @@ -167,13 +167,13 @@ set_target_properties( # ============================================================================= add_custom_target( nrniv-core ALL - COMMAND ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core -b STATIC - -m ${CORENRN_MOD2CPP_BINARY} - -p 1 + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core.py + --build-type=STATIC --binary ${CORENRN_MOD2CPP_BINARY} + --verbose -j 1 ${CORENEURON_PROJECT_SOURCE_DIR}/tests/integration/ring_gap/mod WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin - BYPRODUCTS + BYPRODUCTS ${CMAKE_BINARY_DIR}/bin/${CMAKE_SYSTEM_PROCESSOR}/special-core COMMENT "Running nrnivmodl-core with halfgap.mod") add_dependencies(nrniv-core scopmath coreneuron ${NMODL_TARGET_TO_DEPEND}) diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index a7cf482fa..0cc54ca10 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -68,8 +68,9 @@ set(nmodl_binary_name ${nmodl_name}) configure_file(nrnivmodl_core_makefile.in ${CMAKE_BINARY_DIR}/share/coreneuron/nrnivmodl_core_makefile @ONLY) -configure_file(nrnivmodl-core.in ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core @ONLY) +configure_file(nrnivmodl-core.py + ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core.py COPYONLY) install(FILES ${CMAKE_BINARY_DIR}/share/coreneuron/nrnivmodl_core_makefile DESTINATION share/coreneuron) -install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core DESTINATION bin) +install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core.py DESTINATION bin) diff --git a/extra/nrnivmodl-core.in b/extra/nrnivmodl-core.in deleted file mode 100755 index 697573517..000000000 --- a/extra/nrnivmodl-core.in +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/bash - -# ----------------------------------------------------------------------------- -# Copyright 2020 Blue Brain Project -# nrnivmodl-core is used to compile mod files for coreneuron -# ----------------------------------------------------------------------------- - -set -e - -# TODO : mod2c_core can be linked with (HPE-)MPI library -# and running that under slurm allocation result into -# runtime error. For now, unset PMI_RANK variable -# which is sufficint to avoid issue with HPE-MPI+SLURM. -unset PMI_RANK - -# name of the script -APP_NAME=$(basename $0) - -# directory and parent directory of this script -PARENT_DIR="$(dirname $BASH_SOURCE)/.." -ROOT_DIR=$(@PERL_EXECUTABLE@ -e "use Cwd 'abs_path'; print abs_path('$PARENT_DIR')") - -# default arguments : number of parallel builds and default mod file path -PARALLEL_BUILDS=4 -params_MODS_PATH="." -params_BUILD_TYPE="@COMPILE_LIBRARY_TYPE@" - -# prefix for common options : make sure to rename these if options are changed. -MAKE_OPTIONS="MECHLIB_SUFFIX MOD2CPP_BINARY MOD2CPP_RUNTIME_FLAGS DESTDIR INCFLAGS LINKFLAGS MODS_PATH VERBOSE BUILD_TYPE" - -# parse CLI args -while getopts "n:m:a:d:i:l:Vp:b:h" OPT; do - case "$OPT" in - n) - # suffix for mechanism library - params_MECHLIB_SUFFIX="$OPTARG";; - m) - # nmodl or mod2c binary to use - params_MOD2CPP_BINARY="$OPTARG";; - a) - # additional nmodl flags to be used - params_MOD2CPP_RUNTIME_FLAGS="$OPTARG";; - d) - # destination install directory - params_DESTDIR="$OPTARG";; - i) - # extra include flags - params_INCFLAGS="$OPTARG";; - l) - # extra link flags - params_LINKFLAGS="$OPTARG";; - V) - # make with verbose - params_VERBOSE=1;; - p) - # option for parallel build (with -j) - PARALLEL_BUILDS="$OPTARG";; - b) - # make with verbose - params_BUILD_TYPE="$OPTARG";; - h) - echo "$APP_NAME [options, ...] [mods_path]" - echo "Options:" - echo " -n The model name, used as a suffix in the shared library" - echo " -m NMODL/mod2c code generation compiler path" - echo " -a Runtime flags for NMODL/mod2c" - echo " -i Definitions passed to the compiler, typically '-I dir..'" - echo " -l Definitions passed to the linker, typically '-Lx -lylib..'" - echo " -d Install to dest_dir. Default: Off." - echo " -V Verbose: show commands executed by make" - echo " -p Number of parallel builds (Default: $PARALLEL_BUILDS)" - echo " -b libcorenrnmech library type" - exit 0;; - ?) - exit 1;; - esac -done - -# consume an option -shift $(($OPTIND - 1)) - -# only one mod files directory is supported in neuron and coreneuron -if [ $# -gt 1 ]; then - echo "[ERROR] $APP_NAME expects at most one mod dir. See syntax: '$APP_NAME -h' " - exit 1 -fi - -# if defined mods dir be in $1 -if [ $# -eq 1 ]; then - # Note: due to bug #712 makefile wont handle mod dir with spaces, so we let it fail here - params_MODS_PATH=$1 -fi - -# warn if no mod files provided -if [ -d $params_MODS_PATH ]; then - ls $params_MODS_PATH/*.mod &>/dev/null || echo "WARNING: No mod files found, compiling default ones only!" -else - echo "FATAL: Invalid mods directory: '$params_MODS_PATH'" - exit 1 -fi - -# temporary directory where mod files will be copied -temp_mod_dir=@CMAKE_HOST_SYSTEM_PROCESSOR@/core/mods -mkdir -p $temp_mod_dir - -# copy mod files with include files. note that ${ROOT_DIR}/share -# has inbuilt mod files and user provided mod files are in $params_MODS_PATH. -set +e -for mod_dir in ${ROOT_DIR}/share/modfile $params_MODS_PATH; -do - # copy mod files and include files - files=`ls $mod_dir/*.mod $mod_dir/*.inc 2>/dev/null` - for f in $files; - do - # copy mod files only if it's changed (to avoid rebuild) - target_file_path=$temp_mod_dir/`basename $f` - if ! diff -q $f $target_file_path &>/dev/null; then - cp $f $target_file_path - fi - done -done -set -e - -# use new mod files directory for compilation -params_MODS_PATH=$temp_mod_dir - -# build params to make command -make_params=("ROOT=${ROOT_DIR}") -for param in $MAKE_OPTIONS; do - var="params_${param}" - if [ "${!var+x}" ]; then - make_params+=("$param=${!var}") - fi -done - -# if -d (deploy) provided, call "make install" -if [ "$params_DESTDIR" ]; then - make_params+=("install") -fi - -if [ "$params_VERBOSE" ]; then - make_params+=("VERBOSE=1") -fi - -# run makefile -echo "[INFO] Running: make -j$PARALLEL_BUILDS -f ${ROOT_DIR}/share/coreneuron/nrnivmodl_core_makefile ${make_params[@]}" -make -j$PARALLEL_BUILDS -f "${ROOT_DIR}/share/coreneuron/nrnivmodl_core_makefile" "${make_params[@]}" -echo "[INFO] MOD files built successfully for CoreNEURON" diff --git a/extra/nrnivmodl-core.py b/extra/nrnivmodl-core.py new file mode 100644 index 000000000..b8feaf607 --- /dev/null +++ b/extra/nrnivmodl-core.py @@ -0,0 +1,223 @@ +#!/bin/python + +import argparse +import glob +import os +import shutil +import subprocess + +def get_root(): + parent_dir = os.path.dirname(os.path.realpath(__file__)) + return os.path.abspath(os.path.join(parent_dir, '..')) + +class ModFiles(): + def __init__(self, d, work_dir): + self.dir = d + self.work_dir = work_dir + self.basic_dir = os.path.join(get_root(), 'share', 'modfile') + + def get_files(self): + files = glob.glob(os.path.join(self.basic_dir, '*.mod')) + files.extend(glob.glob(os.path.join(self.dir, '*.mod'))) + return files + + """Artifical cell file cannot be processed by ispc so let's them be processed by GCC.""" + def get_ispc_files(self): + cpp_files = list() + ispc_files = list() + + for f in self.get_files(): + with open(f, "r") as h: + if "ARTIFICIAL_CELL" in h.read(): + cpp_files.append(f) + else: + ispc_files.append(f) + return (cpp_files, ispc_files) + + def get_ispc_files_for_rules(self, ispc_files): + l = list() + for f in ispc_files: + filename = os.path.basename(os.path.splitext(f)[0]) + l.append({'mod_file': f, 'ispc_file': filename+".ispc", 'obj_file': filename+".obj", 'cpp_file': filename+".cpp", 'o_file': filename+".o"}) + return l + + def get_cpp_files_for_rules(self, cpp_files): + l = list() + for f in cpp_files: + filename = os.path.basename(os.path.splitext(f)[0]) + l.append({'mod_file': f, 'cpp_file': filename+".cpp", 'o_file': filename+".o"}) + return l + +rules = { + 'ispc': r''' +$(MOD_TO_CPP_DIR)/{ispc_file}: {mod_file} + $(info Generating for {mod_file}) + $(MOD2CPP_ENV_VAR) $(MOD2CPP_BINARY_PATH) $< -o $(MOD_TO_CPP_DIR) $(MOD2CPP_BINARY_FLAG) + +$(MOD_OBJS_DIR)/{obj_file}: $(MOD_TO_CPP_DIR)/{ispc_file} + $(ISPC_COMPILE_CMD) $< -o $@ + +$(MOD_TO_CPP_DIR)/{cpp_file}: $(MOD_TO_CPP_DIR)/{ispc_file} + +$(MOD_OBJS_DIR)/{o_file}: $(MOD_TO_CPP_DIR)/{cpp_file} + $(CXX_COMPILE_CMD) -c $< -o $@ + +''', + 'cpp': r''' +$(MOD_TO_CPP_DIR)/{cpp_file}: {mod_file} + $(info Generating for {mod_file}) + $(MOD2CPP_ENV_VAR) $(MOD2CPP_BINARY_PATH) $< -o $(MOD_TO_CPP_DIR) $(NMODL_FLAGS_C) + +$(MOD_OBJS_DIR)/{o_file}: $(MOD_TO_CPP_DIR)/{cpp_file} $(KINDERIV_H_PATH) + $(CXX_COMPILE_CMD) -c $< -o $@ + +''', + 'general': r''' +MOD_FILES = {mod_files} +PRODUCED_OBJS_FROM_ISPC = {obj_ispc_files} +PRODUCED_OBJS_FROM_CPP = {obj_cpp_files} + +''' +} + +def parse_args(): + parser = argparse.ArgumentParser(description='') + parser.add_argument('--binary') + parser.add_argument('--nmodl', action='store_true') + + host_group = parser.add_mutually_exclusive_group() + host_group.add_argument('--cpp', action='store_const', dest='host_backend', const='cpp') + host_group.add_argument('--ispc', action='store_const', dest='host_backend', const='ispc') + host_group.add_argument('--omp', action='store_const', dest='host_backend', const='omp') + parser.set_defaults(host_backend='cpp') + + parser.add_argument('--gpu', choices=['cuda', 'OpenAcc'], const='OpenAcc', nargs='?') + + parser.add_argument('--work-dir', default=os.path.abspath(".")) + + parser.add_argument('--build-type', choices=['STATIC', 'SHARED']) + + parser.add_argument('--suffix') + + parser.add_argument('-j', '--jobs', type=int, default=4) + parser.add_argument('--output-dir') + parser.add_argument('-v', '--verbose', action='store_true') + + parser.add_argument('mod_dir') + + return parser.parse_args() + +"""Generate drop-in""" +class MakefileGenerator(): + def __init__(self, arguments, files): + self.arguments = arguments + self.files = files + + def generate(self): + s = str() + s += self.generateCompilers() + s += self.generateRules() + + return s + + def generateHost(self): + if self.arguments.nmodl: + if self.arguments.host_backend == 'cpp': + return 'host --c' + elif self.arguments.host_backend == 'ispc': + return 'host --ispc' + elif self.arguments.host_backend == 'omp': + return 'host --omp' + return '' + + def generateGPU(self): + if self.arguments.gpu: + if self.arguments.nmodl: + if self.arguments.gpu == 'OpenAcc': + return 'acc --oacc' + elif self.arguments.gpu == 'cuda': + return 'acc --cuda' + else: + raise "Error" + return '' + + def generatePasses(self): + if self.arguments.nmodl: + return 'passes --inline' + return '' + + def generateCompilers(self): + s = str() + if self.arguments.binary: + s += 'MOD2CPP_BINARY_PATH = {}'.format(self.arguments.binary) + else: + s += 'MOD2CPP_BINARY_PATH = {}'.format('$(NMODL_COMPILER)' if self.arguments.nmodl else '$(MOD2C_COMPILER)') + s += '\n' + s += 'MOD2CPP_BINARY_FLAG = ' + self.generateHost() + " " + self.generateGPU() + " " + self.generatePasses() + s += '\n' + + return s + + def generateRules(self): + s = str() + mod_files = [os.path.basename(x) for x in self.files.get_files()] + if self.arguments.host_backend == 'ispc': + cpp_files, ispc_files = self.files.get_ispc_files() + cpp_files = self.files.get_cpp_files_for_rules(cpp_files) + ispc_files = self.files.get_ispc_files_for_rules(ispc_files) + obj_ispc_files = ['$(MOD_OBJS_DIR)/' + x['obj_file'] for x in ispc_files] + obj_cpp_files = ['$(MOD_OBJS_DIR)/' + x['o_file'] for x in cpp_files] + obj_cpp_files.extend(['$(MOD_OBJS_DIR)/' + x['o_file'] for x in ispc_files]) + s += rules['general'].format(obj_ispc_files=' '.join(obj_ispc_files), obj_cpp_files=' '.join(obj_cpp_files), mod_files=' '.join(mod_files)) + for f in ispc_files: + s += rules['ispc'].format(work_dir=arguments.work_dir, **f) + else: + files = self.files.get_files() + cpp_files = self.files.get_cpp_files_for_rules(files) + obj_cpp_files = ['$(MOD_OBJS_DIR)/' + x['o_file'] for x in cpp_files] + s += rules['general'].format(obj_ispc_files='', obj_cpp_files=' '.join(obj_cpp_files), mod_files=' '.join(mod_files)) + + for f in cpp_files: + s += rules['cpp'].format(work_dir=arguments.work_dir, **f) + + return s + +if __name__ == '__main__': + arguments = parse_args() + if not os.path.exists(arguments.work_dir): + os.makedirs(arguments.work_dir) + files = ModFiles(arguments.mod_dir, arguments.work_dir) + print("Output dir = 'make -f {}'".format(arguments.work_dir)) + G = MakefileGenerator(arguments, files) + Makefile = G.generate() + with open(os.path.join(arguments.work_dir, "GeneratedMakefile.make"), "w") as h: + h.write(Makefile) + shutil.copy(os.path.join(get_root(), 'share', 'coreneuron', 'nrnivmodl_core_makefile'), arguments.work_dir) + + make_args = [ 'make' ] + make_args.append('-f{}'.format(os.path.join(arguments.work_dir, 'nrnivmodl_core_makefile'))) + make_args.append('-j{}'.format(arguments.jobs)) + make_args.append('ROOT={}'.format(get_root())) + + if arguments.verbose: + make_args.append('VERBOSE=1') + + if arguments.binary: + make_args.append('MOD2CPP_BINARY={}'.format(arguments.binary)) + + if arguments.build_type: + make_args.append('BUILD_TYPE={}'.format(arguments.build_type)) + + if arguments.suffix: + make_args.append('MECHLIB_SUFFIX={}'.format(arguments.suffix)) + + if arguments.output_dir: + make_args.append('DESTDIR={}'.format(arguments.output_dir)) + make_args.append('install') + else: + make_args.append('all') + + make_args.append('WORK_DIR={}'.format(arguments.work_dir)) + + print('Launching "{}"'.format(' '.join(make_args))) + subprocess.call(make_args) diff --git a/extra/nrnivmodl_core_makefile.in b/extra/nrnivmodl_core_makefile.in index fda9c7e41..51a71a199 100644 --- a/extra/nrnivmodl_core_makefile.in +++ b/extra/nrnivmodl_core_makefile.in @@ -2,6 +2,18 @@ # CoreNEURON executable called "special-core" from the provided mod files. # Mod files are looked up in the MODS_PATH directory. +OUTPUT_DIR = $(WORK_DIR)/@CMAKE_HOST_SYSTEM_PROCESSOR@ + +# 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 + +# Find the directory of the current makefile +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(SELF_DIR)/GeneratedMakefile.make + # Current system OS OS_NAME := $(shell uname) @@ -11,9 +23,8 @@ COMMA_OP =, # Default variables for various targets MECHLIB_SUFFIX = MODS_PATH = . -OUTPUT_DIR = @CMAKE_HOST_SYSTEM_PROCESSOR@ DESTDIR = -TARGET_LIB_TYPE = $(BUILD_TYPE) +BUILD_TYPE = @COMPILE_LIBRARY_TYPE@ # CoreNEURON installation directories CORENRN_BIN_DIR := $(ROOT)/bin @@ -28,11 +39,8 @@ DERIVIMPLICIT_CPP_FILE = $(CORENRN_SHARE_CORENRN_DIR)/dimplic.cpp # 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 +# By default, build $(SPECIAL_EXE) +all: $(SPECIAL_EXE) # Linked libraries gathered by CMake LDFLAGS = $(LINKFLAGS) @CORENRN_LINK_DEFS@ @@ -58,6 +66,18 @@ CXX_SHARED_LIB_CMD = $(CXX) $(CXXFLAGS) @CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS@ ISPC = @CMAKE_ISPC_COMPILER@ ISPC_COMPILE_CMD = $(ISPC) @CMAKE_ISPC_FLAGS@ -I$(CORENRN_INC_DIR) +# NMODL compiler +NMODL_COMPILER ?= $(ROOT)/bin/nmodl + +# MOD2C compiler +MOD2C_COMPILER ?= @CORENRN_MOD2CPP_BINARY@ + +# Binary of MOD2C/NMODL depending on CMake option activated +ifeq (@nmodl_FOUND@, TRUE) + INCLUDES += -I@CORENRN_MOD2CPP_INCLUDE@ + ISPC_COMPILE_CMD += -I@CORENRN_MOD2CPP_INCLUDE@ +endif + # env variables required for mod2c or nmodl MOD2CPP_ENV_VAR = PYTHONPATH=@CORENRN_NMODL_PYTHONPATH@:${CORENRN_LIB_DIR}/python MODLUNIT=$(CORENRN_SHARE_MOD2CPP_DIR)/nrnunits.lib @@ -74,7 +94,7 @@ DIMPLIC_OBJ = $(MOD_OBJS_DIR)/_dimplic.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) +ifeq ($(BUILD_TYPE), STATIC) LIB_SUFFIX = @CMAKE_STATIC_LIBRARY_SUFFIX@ corenrnmech_lib_target = coremech_lib_static else @@ -82,62 +102,13 @@ else 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)) # All objects used during build -ALL_OBJS = $(MOD_FUNC_OBJ) $(DIMPLIC_OBJ) $(mod_cpp_objs) $(mod_ispc_objs) +ALL_OBJS = $(MOD_FUNC_OBJ) $(DIMPLIC_OBJ) $(PRODUCED_OBJS_FROM_CPP) $(PRODUCED_OBJS_FROM_ISPC) # Colors for pretty printing C_RESET := \033[0m @@ -188,31 +159,15 @@ coremech_lib_static: $(ALL_OBJS) $(ENGINEMECH_OBJ) build_always 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 $(KINDERIV_H_PATH) | $(MOD_OBJS_DIR) - $(CXX_COMPILE_CMD) -c $< -o $@ - -# 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)/ $(NMODL_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) - @PERL_EXECUTABLE@ $(CORENRN_SHARE_CORENRN_DIR)/mod_func.c.pl $(mod_files_names) > $(MOD_FUNC_CPP).tmp + @PERL_EXECUTABLE@ $(CORENRN_SHARE_CORENRN_DIR)/mod_func.c.pl $(MOD_FILES) > $(MOD_FUNC_CPP).tmp diff -q $(MOD_FUNC_CPP).tmp $(MOD_FUNC_CPP) || \ mv $(MOD_FUNC_CPP).tmp $(MOD_FUNC_CPP) +$(MOD_FUNC_OBJ) $(DIMPLIC_OBJ): $(MOD_OBJS_DIR)/%.o: $(MOD_TO_CPP_DIR)/%.cpp $(KINDERIV_H_PATH) | $(MOD_OBJS_DIR) + $(CXX_COMPILE_CMD) -c $< -o $@ + # header to avoid function callbacks using function pointers $(KINDERIV_H_PATH): $(mod_cpp_files) build_always | $(MOD_TO_CPP_DIR) cd $(MOD_TO_CPP_DIR); \