diff --git a/.travis.yml b/.travis.yml index 52655d9d7..5622a29c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -171,7 +171,7 @@ script: else cmake ${cmake_option} -DCMAKE_INSTALL_PREFIX=$HOME/CoreNeuron -DPYTHON_EXECUTABLE=$(which python3) ..; fi - - cmake --build . + - make - ctest --output-on-failure - make install diff --git a/CMake/NmodlHelper.cmake b/CMake/NmodlHelper.cmake deleted file mode 100644 index 060a1a5cb..000000000 --- a/CMake/NmodlHelper.cmake +++ /dev/null @@ -1,95 +0,0 @@ -# ============================================================================= -# Copyright (C) 2016-2020 Blue Brain Project -# -# See top-level LICENSE file for details. -# ============================================================================= - -# ~~~ -# Macro sets up build rule for .cpp files from .mod files. Parameters: -# KEY name : An arbitrary name to keep track of output .c files -# MODFILE input : The path to the mod file -# OUTTYPE : The output type (optional, defaults to serial) -# -# Because nmodl/mod2c_core wants to write the .cpp file in the same directory as the mod file, -# we copy the mod file to the binary directory first -# -# The macro appends the names of the output files to NMODL_${name}_OUTPUTS and the names of the -# mod files (without directories) to NMODL_${name}_MODS -# ~~~ - -macro(nmodl_to_cpp_target) - # first parse the arguments - set(options) - set(oneValueArgs TARGET MODFILE KEY) - set(multiValueArgs) - cmake_parse_arguments(mod2c "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - if("${mod2c_MODFILE}" STREQUAL "") - message(FATAL_ERROR "mod2c_target requires a MODFILE argument") - endif() - if("${mod2c_KEY}" STREQUAL "") - message(FATAL_ERROR "mod2c_target requires a KEY argument") - endif() - - # get name of mod file and it's path - get_filename_component(mod2c_source_ ${mod2c_MODFILE} ABSOLUTE) - get_filename_component(mod2c_modname_ ${mod2c_MODFILE} NAME) - - # check for nmodl target - if("${mod2c_TARGET}" STREQUAL "serial") - string(REGEX REPLACE "\\.mod$" ".cpp" mod2c_outname_ "${mod2c_modname_}") - set(nmodl_modearg "--c") - elseif("${mod2c_TARGET}" STREQUAL "ispc") - file(STRINGS ${mod2c_MODFILE} mod2c_mod_artcell REGEX "ARTIFICIAL_CELL") - if(NOT "${mod2c_mod_artcell}" STREQUAL "") - string(REGEX REPLACE "\\.mod$" ".cpp" mod2c_outname_ "${mod2c_modname_}") - set(nmodl_modearg "--c") - else() - string(REGEX REPLACE "\\.mod$" ".ispc" mod2c_outname_ "${mod2c_modname_}") - string(REGEX REPLACE "\\.mod$" ".cpp" mod2c_wrapper_outname_ "${mod2c_modname_}") - set(nmodl_modearg "--ispc") - endif() - elseif("${mod2c_TARGET}" STREQUAL "") - # default case - string(REGEX REPLACE "\\.mod$" ".cpp" mod2c_outname_ "${mod2c_modname_}") - set(nmodl_modearg "--c") - else() - message( - SEND_ERROR - "mod2c_target only supports serial and ispc generation for now: \"${mod2c_TARGET}\"") - endif() - - set(mod2c_output_ "${CMAKE_CURRENT_BINARY_DIR}/${mod2c_outname_}") - list(APPEND NMODL_${mod2c_KEY}_OUTPUTS "${mod2c_output_}") - - if(DEFINED mod2c_wrapper_outname_) - set(mod2c_wrapper_output_ "${CMAKE_CURRENT_BINARY_DIR}/${mod2c_wrapper_outname_}") - list(APPEND NMODL_${mod2c_KEY}_OUTPUTS "${mod2c_wrapper_output_}") - unset(mod2c_wrapper_outname_) - endif() - - list(APPEND NMODL_${mod2c_KEY}_MODS "${mod2c_modname_}") - if(CORENRN_ENABLE_NMODL AND NMODL_FOUND) - string(FIND "${NMODL_EXTRA_FLAGS_LIST}" "passes" pos) - if(pos EQUAL -1) - set(NMODL_FLAGS "passes;--inline;${NMODL_EXTRA_FLAGS_LIST}") - else() - string(REPLACE "passes" "passes;--inline" NMODL_FLAGS "${NMODL_EXTRA_FLAGS_LIST}") - endif() - add_custom_command( - OUTPUT ${mod2c_output_} ${mod2c_wrapper_output_} - DEPENDS ${mod2c_MODFILE} ${CORENRN_NMODL_BINARY} - COMMAND ${CMAKE_COMMAND} -E copy "${mod2c_source_}" "${CMAKE_CURRENT_BINARY_DIR}" - COMMAND - ${CORENRN_NMODL_COMMAND} "${mod2c_modname_}" -o "${CMAKE_CURRENT_BINARY_DIR}" host - ${nmodl_modearg} ${NMODL_FLAGS} - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - else() - add_custom_command( - OUTPUT ${mod2c_output_} - DEPENDS ${mod2c_MODFILE} mod2c ${CORENRN_NMODL_BINARY} - COMMAND ${CMAKE_COMMAND} -E copy "${mod2c_source_}" "${CMAKE_CURRENT_BINARY_DIR}" - COMMAND ${CORENRN_NMODL_COMMAND} "${mod2c_modname_}" - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - endif() -endmacro() diff --git a/CMake/config/CompilerFlagsHelpers.cmake b/CMake/config/CompilerFlagsHelpers.cmake index f125aa6f0..df609f241 100644 --- a/CMake/config/CompilerFlagsHelpers.cmake +++ b/CMake/config/CompilerFlagsHelpers.cmake @@ -132,3 +132,12 @@ foreach(COMPILER_LANGUAGE ${SUPPORTED_COMPILER_LANGUAGE_LIST}) endif() endforeach() + +# =============================================================================== +# Allow undefined reference in shared library as mod files will be linked later +# =============================================================================== +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(UNDEFINED_SYMBOLS_IGNORE_FLAG "-undefined dynamic_lookup") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}") +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cf3a0090..b372e11a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ include(OpenAccHelper) # Common dependencies # ============================================================================= find_package(PythonInterp REQUIRED) +find_package(Perl REQUIRED) # ============================================================================= # ISPC should compile with --pic by default @@ -144,7 +145,11 @@ endif() # OpenACC needs to build static library in order to have global/routines working. # See https://www.pgroup.com/userforum/viewtopic.php?t=5350 # ~~~ -if(CORENRN_ENABLE_SHARED AND NOT CORENRN_ENABLE_GPU) +if(CORENRN_ENABLE_GPU) + set(CORENRN_ENABLE_SHARED OFF) +endif() + +if(CORENRN_ENABLE_SHARED) set(COMPILE_LIBRARY_TYPE "SHARED") else() set(COMPILE_LIBRARY_TYPE "STATIC") @@ -247,6 +252,7 @@ if(CORENRN_ENABLE_NMODL) set(ENV{PYTHONPATH} "$ENV{PYTHONPATH}") set(nmodl_PYTHONPATH "${CMAKE_BINARY_DIR}/lib") set(CORENRN_NMODL_PYTHONPATH "${nmodl_PYTHONPATH}:$ENV{PYTHONPATH}") + set(NMODL_TARGET_TO_DEPEND nmodl) endif() include_directories(${CORENRN_NMODL_INCLUDE}) # set correct arguments for nmodl for cpu/gpu target diff --git a/coreneuron/CMakeLists.txt b/coreneuron/CMakeLists.txt index f65e7e7da..d36eb483f 100644 --- a/coreneuron/CMakeLists.txt +++ b/coreneuron/CMakeLists.txt @@ -50,47 +50,10 @@ set(KINDERIV_PYTHON_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/kinderiv.py") set(KINDERIV_HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/_kinderiv.h") set(NMODL_UNITS_FILE "${CMAKE_BINARY_DIR}/share/nrnunits.lib") -set(INBUILT_MOD_PATH "mechanism/mech/modfile") -set(INBUILT_MOD_FILES - expsyn.mod - exp2syn.mod - hh.mod - netstim.mod - passive.mod - pattern.mod - stim.mod) - -# Has helper macro for generating cpp file from mod2c -include(NmodlHelper) -# ============================================================================= -# Command for MOD to CPP conversion -# ============================================================================= -set(CORENRN_NMODL_COMMAND env "MODLUNIT=${NMODL_UNITS_FILE}" - "PYTHONPATH=${CORENRN_NMODL_PYTHONPATH}" ${CORENRN_NMODL_BINARY}) - -if(${CORENRN_ENABLE_ISPC}) - set(NMODL_CODEGEN_TARGET ispc) -else() - set(NMODL_CODEGEN_TARGET serial) -endif() - -# configure every mod file to configure with mod2c/nmodl -foreach(MOD ${INBUILT_MOD_FILES}) - nmodl_to_cpp_target(KEY INBUILT_MOD MODFILE "${INBUILT_MOD_PATH}/${MOD}" TARGET - ${NMODL_CODEGEN_TARGET}) -endforeach() - -set_source_files_properties(${NMODL_INBUILT_MOD_OUTPUTS} PROPERTIES GENERATED TRUE) - -# for ispc generated files, we need add extra compilation flags -if(CORENRN_ENABLE_ISPC) - set(NMODL_ISPC_INBUILT_MOD_OUTPUTS ${NMODL_INBUILT_MOD_OUTPUTS}) - list(FILTER NMODL_ISPC_INBUILT_MOD_OUTPUTS INCLUDE REGEX ".*\.ispc$") - set_source_files_properties(${NMODL_ISPC_INBUILT_MOD_OUTPUTS} PROPERTIES LANGUAGE ISPC) - set_source_files_properties(${NMODL_ISPC_INBUILT_MOD_OUTPUTS} PROPERTIES COMPILE_FLAGS - "-I${CORENRN_NMODL_INCLUDE} --pic") -endif() +# copy inbuilt mod files to share +file(COPY ${CORENEURON_PROJECT_SOURCE_DIR}/coreneuron/mechanism/mech/modfile + DESTINATION ${CMAKE_BINARY_DIR}/share) # ============================================================================= # coreneuron GPU library @@ -155,7 +118,7 @@ add_custom_target(kin_deriv_header DEPENDS "${KINDERIV_HEADER_FILE}") # main coreneuron library add_library( coreneuron ${COMPILE_LIBRARY_TYPE} ${CORENEURON_HEADER_FILES} ${CORENEURON_TEMPLATE_FILES} - ${CORENEURON_CODE_FILES} ${cudacorenrn_objs} ${NMODL_INBUILT_MOD_OUTPUTS}) + ${CORENEURON_CODE_FILES} ${cudacorenrn_objs} ${NMODL_INBUILT_MOD_OUTPUTS}) # need to have _kinderiv.h for mod2c generated files add_dependencies(coreneuron kin_deriv_header) @@ -163,10 +126,6 @@ add_dependencies(coreneuron kin_deriv_header) # scopmath is created separately for nrnivmodl-core workflow add_library(scopmath STATIC ${CORENEURON_HEADER_FILES} ${SCOPMATH_CODE_FILES}) -# minimal main and dimplic file for nrnivmodl-core workflow -add_library(corenrnmech ${COMPILE_LIBRARY_TYPE} ${CORENEURON_HEADER_FILES} ${ENGINEMECH_CODE_FILE} - ${DIMPLIC_CODE_FILE}) - target_link_libraries( coreneuron ${MPI_C_LIBRARIES} @@ -182,35 +141,26 @@ target_include_directories(coreneuron SYSTEM target_include_directories(coreneuron SYSTEM PRIVATE ${CORENEURON_PROJECT_SOURCE_DIR}/external/CLI11/include) -target_link_libraries(corenrnmech scopmath coreneuron) - set_target_properties( - coreneuron corenrnmech scopmath ${link_cudacoreneuron} + coreneuron scopmath ${link_cudacoreneuron} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib POSITION_INDEPENDENT_CODE ON) # ============================================================================= # create special-core with halfgap.mod for tests # ============================================================================= -add_custom_command( - TARGET coreneuron POST_BUILD - COMMAND ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core +add_custom_target( + nrniv-core ALL + COMMAND ${CMAKE_BINARY_DIR}/bin/nrnivmodl-core -b STATIC ${CORENEURON_PROJECT_SOURCE_DIR}/tests/integration/ring_gap/mod - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin - BYPRODUCTS ${CMAKE_BINARY_DIR}/bin/${CMAKE_SYSTEM_PROCESSOR}/special-core + WORKING_DIRECTORY + ${CMAKE_BINARY_DIR}/bin + BYPRODUCTS + ${CMAKE_BINARY_DIR}/bin/${CMAKE_SYSTEM_PROCESSOR}/special-core COMMENT "Running nrnivmodl-core with halfgap.mod") -add_dependencies(coreneuron scopmath) +add_dependencies(nrniv-core scopmath coreneuron ${NMODL_TARGET_TO_DEPEND}) -# ============================================================================= -# create nrnivmodl-core -# ============================================================================= -# coreneuron executable include_directories(${CORENEURON_PROJECT_SOURCE_DIR}) -add_executable(nrniv-core "apps/coreneuron.cpp") - -target_link_libraries(nrniv-core corenrnmech ${reportinglib_LIBRARY} ${sonatareport_LIBRARY}) - -set_target_properties(nrniv-core PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # ============================================================================= # Extract link definitions to be used with nrnivmodl-core @@ -255,6 +205,7 @@ if(NOT CORENRN_ENABLE_NMODL) file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/share/mod2c/") add_custom_target(link_units ALL COMMAND ${CMAKE_COMMAND} -E create_symlink "${NMODL_UNITS_FILE}" "${CMAKE_BINARY_DIR}/share/mod2c/nrnunits.lib") + add_dependencies(nrniv-core link_units) endif() # main program required for building special-core @@ -266,7 +217,7 @@ file(COPY apps/coreneuron.cpp DESTINATION ${CMAKE_BINARY_DIR}/share/coreneuron) # coreneuron main libraries install( - TARGETS coreneuron corenrnmech ${link_cudacoreneuron} + TARGETS coreneuron ${link_cudacoreneuron} EXPORT coreneuron LIBRARY DESTINATION lib ARCHIVE DESTINATION lib @@ -297,8 +248,14 @@ if(NOT CORENRN_ENABLE_NMODL) endif() # install nrniv-core app -install(TARGETS nrniv-core DESTINATION bin) +install( + PROGRAMS ${CMAKE_BINARY_DIR}/bin/${CMAKE_HOST_SYSTEM_PROCESSOR}/special-core + DESTINATION bin + RENAME nrniv-core) install(FILES apps/coreneuron.cpp DESTINATION share/coreneuron) # install random123 and nmodl headers install(DIRECTORY ${CMAKE_BINARY_DIR}/include/ DESTINATION include) + +# install mod files +install(DIRECTORY ${CMAKE_BINARY_DIR}/share/modfile DESTINATION share) diff --git a/extra/nrnivmodl-core.in b/extra/nrnivmodl-core.in index 509d564e7..2529353ef 100755 --- a/extra/nrnivmodl-core.in +++ b/extra/nrnivmodl-core.in @@ -1,104 +1,135 @@ #!/bin/bash + # ----------------------------------------------------------------------------- -# nrnivmodl-core uses make to compile additonal mod files for coreneuron -# Copyright 2019 Blue Brain Project +# Copyright 2020 Blue Brain Project +# nrnivmodl-core is used to compile mod files for coreneuron # ----------------------------------------------------------------------------- + set -e +# name of the script APP_NAME=$(basename $0) -_PARENT="$(dirname $BASH_SOURCE)/.." -ROOTDIR=$(perl -e "use Cwd 'abs_path'; print abs_path('$_PARENT')") -MAKE_OPTIONS="MECH_NAME NMODL_BINARY DESTDIR INCFLAGS LINKFLAGS MODS_PATH VERBOSE" -PARALLELISM=4 -SAVE_FILE="@CMAKE_HOST_SYSTEM_PROCESSOR@/nrnivmodl_options.txt" + +# 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@" -# To support build + install later we save/restore options -# Attempt to load previous definitions -if [ -f "$SAVE_FILE" ]; then - echo "[INFO] Loading definitions from previous nrnivmodl-core execution" - while read line; do - echo " + $line" && eval "$line" - done < "$SAVE_FILE" -fi +# prefix for common options : make sure to rename these if options are changed. +MAKE_OPTIONS="MECHLIB_SUFFIX NMODL_BINARY DEST_DIR INCFLAGS LINKFLAGS MODS_PATH VERBOSE BUILD_TYPE" -# Parse args (overriding) -while getopts "n:m:v:d:i:l:p:hV" OPT; do +# parse CLI args +while getopts "n:m:v:d:i:l:p:b:hV" OPT; do case "$OPT" in n) - params_MECH_NAME="$OPTARG";; + # suffix for mechanism library + params_MECHLIB_SUFFIX="$OPTARG";; m) + # nmodl or mod2c binary to use params_NMODL_BINARY="$OPTARG";; d) - params_DESTDIR="$OPTARG";; + # destination install directory + params_DEST_DIR="$OPTARG";; i) + # extra include flags params_INCFLAGS="$OPTARG";; l) + # extra link flags params_LINKFLAGS="$OPTARG";; V) + # make with verbose params_VERBOSE=1;; p) - PARALLELISM="$OPTARG";; + # 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 code generation compiler path" - 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 - Only build in {ARCH}"\ - " Consider using this option on a second call. Params are preserved." - echo " -V Verbose: show commands executed by make" - echo " -p Make parallelism. Default: 4" + echo " -n The model name, used as a suffix in the shared library" + echo " -m NMODL code generation compiler path" + 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 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 - # warn if no mod files provided - ls $params_MODS_PATH/*.mod || echo "WARNING: No mods found!" + 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 -# Output options & populate make_params -mkdir -p "$(dirname "$SAVE_FILE")" -echo "# nrnivmodl-core options. Mods location: $params_MODS_PATH" > $SAVE_FILE +# 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 -# Build params to make command (and save them to file) -make_params=("ROOT=${ROOTDIR}") +# 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}") - echo "$var=\"${!var}\"" fi -done >> "$SAVE_FILE" +done -# If -d (deploy) provided, call "make install" -if [ "$params_DESTDIR" ]; then +# if -d (deploy) provided, call "make install" +if [ "$params_DEST_DIR" ]; then make_params+=("install") fi +# run makefile echo "[INFO] Running make with params: ${make_params[@]}" -make -j$PARALLELISM -f "${ROOTDIR}/share/coreneuron/nrnivmodl_core_makefile" "${make_params[@]}" +make -j$PARALLEL_BUILDS -f "${ROOT_DIR}/share/coreneuron/nrnivmodl_core_makefile" "${make_params[@]}" -echo "[INFO] mods built successfully." +echo "[INFO] MOD files built successfully for CoreNEURON" diff --git a/extra/nrnivmodl_core_makefile.in b/extra/nrnivmodl_core_makefile.in index 746e132e3..b010a499f 100644 --- a/extra/nrnivmodl_core_makefile.in +++ b/extra/nrnivmodl_core_makefile.in @@ -1,213 +1,231 @@ -# -# This makefile has the rules necessary for making the custom version of coreneuron -# executable called "special-core" from various mod files. -# Mod files are looked up in the cwd, unless MODS_PATH is set +# 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. -# Mechanisms version are by default 0.0, but should be overriden +# Current system OS +OS_NAME := $(shell uname) + +# ","" is an argument separator, never as a literal for Makefile rule +COMMA_OP =, -MECH_NAME = +# Default variables for various targets +MECHLIB_SUFFIX = MODS_PATH = . -OUTPUT = @CMAKE_HOST_SYSTEM_PROCESSOR@ -DESTDIR = -NMODL_BINARY = -# Coreneuron dirs -bindir := $(ROOT)/bin -libdir := $(ROOT)/lib -incdir := $(ROOT)/include -datadir:= $(ROOT)/share/coreneuron -datadir_mod2c := $(ROOT)/share/mod2c - -# Binary of MOD2C/NMODL depending on what was activated -ifeq (@nmodl_FOUND@, TRUE) - nmodl_binary_path = $(if $(NMODL_BINARY),$(NMODL_BINARY), @CORENRN_NMODL_BINARY@) -else - nmodl_binary_path = $(if $(NMODL_BINARY),$(NMODL_BINARY), $(bindir)/@nmodl_binary_name@) -endif +OUTPUT_DIR = @CMAKE_HOST_SYSTEM_PROCESSOR@ +DEST_DIR = +TARGET_LIB_TYPE = $(BUILD_TYPE) + +# 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_MOD2C_DIR := $(ROOT)/share/mod2c + +# file provided by coreneuron for solver +DERIVIMPLICIT_CPP_FILE = $(CORENRN_SHARE_CORENRN_DIR)/dimplic.cpp -# Additional variables set in CMAKE usable here -# - @CORENRN_COMPILE_DEFS -# - @CORENRN_LINK_DEFS +# 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)/core/mod2c + +# Directory where cpp files are compiled +MOD_OBJS_DIR = $(OUTPUT_DIR)/core/build + +# Linked libraries gathered by CMake LDFLAGS = $(LINKFLAGS) @CORENRN_LINK_DEFS@ -CORENRNLIB_FLAGS = -L$(libdir) -lcoreneuron +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@),) -OS_NAME := $(shell uname) -_cm =, -# We rebuild the include dirs since a lot of stuff changes place -INCLUDES = $(INCFLAGS) -I$(incdir) -I$(incdir)/coreneuron/utils/randoms +# Includes paths gathered by CMake +INCLUDES = $(INCFLAGS) -I$(CORENRN_INC_DIR) -I$(CORENRN_INC_DIR)/coreneuron/utils/randoms INCLUDES += $(if @MPI_C_INCLUDE_PATH@, -I$(subst ;, -I,@MPI_C_INCLUDE_PATH@),) INCLUDES += $(if @reportinglib_INCLUDE_DIR@, -I$(subst ;, -I,@reportinglib_INCLUDE_DIR@),) -CC = @CMAKE_C_COMPILER@ +# C++ compilation and link commands CXX = @CMAKE_CXX_COMPILER@ -CFLAGS = @BUILD_TYPE_C_FLAGS@ @CMAKE_C_FLAGS@ CXXFLAGS = @BUILD_TYPE_CXX_FLAGS@ @CMAKE_CXX_FLAGS@ @CXX14_STANDARD_COMPILE_OPTION@ @PGI_INLINE_FLAGS@ +CXX_COMPILE_CMD = $(CXX) $(CXXFLAGS) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ @CORENRN_COMPILE_DEFS@ $(INCLUDES) +CXX_LINK_EXE_CMD = $(CXX) $(CXXFLAGS) @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@ -COMPILE = $(CC) $(CFLAGS) @CORENRN_COMPILE_DEFS@ $(INCLUDES) -CXXCOMPILE = $(CXX) $(CXXFLAGS) @CORENRN_COMPILE_DEFS@ $(INCLUDES) -CXX_LINK_EXE = $(CXX) $(CXXFLAGS) @CMAKE_EXE_LINKER_FLAGS@ -CXX_LINK_SHARED = $(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_FLAGS = @CMAKE_ISPC_FLAGS@ -ISPC_COMPILE = $(ISPC) $(ISPC_FLAGS) -I$(incdir) +ISPC_COMPILE_CMD = $(ISPC) @CMAKE_ISPC_FLAGS@ -I$(CORENRN_INC_DIR) + +# env variables required for mod2c or nmodl +NMODL_ENV_VAR = PYTHONPATH=@CORENRN_NMODL_PYTHONPATH@:${CORENRN_LIB_DIR}/python MODLUNIT=$(CORENRN_SHARE_MOD2C_DIR)/nrnunits.lib + +# 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 +KINDERIV_H_PATH = $(MOD_TO_CPP_DIR)/_kinderiv.h +MOD_FUNC_CPP = $(MOD_TO_CPP_DIR)/_mod_func.cpp +MOD_FUNC_OBJ = $(MOD_OBJS_DIR)/_mod_func.o +DIMPLIC_CPP = $(MOD_TO_CPP_DIR)/_dimplic.cpp +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) + 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) -INCLUDES += -I@CORENRN_NMODL_INCLUDE@ -ISPC_COMPILE += -I@CORENRN_NMODL_INCLUDE@ + NMODL_BINARY_PATH = $(if $(NMODL_BINARY),$(NMODL_BINARY), @CORENRN_NMODL_BINARY@) + INCLUDES += -I@CORENRN_NMODL_INCLUDE@ + ISPC_COMPILE_CMD += -I@CORENRN_NMODL_INCLUDE@ +else + NMODL_BINARY_PATH = $(if $(NMODL_BINARY),$(NMODL_BINARY), $(CORENRN_BIN_DIR)/@nmodl_binary_name@) endif -# Variables used in the "ARTIFICIAL_CELL" detection -mod_c_srcs_path = -mod_ispc_srcs_path = -mod_c_srcs_names = -mod_ispc_srcs_names = +# 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_c_srcs_path += $(MODC_DIR)/$(notdir $(1)) - mod_c_srcs_names += $(notdir $(1)) + mod_art_files += $(MOD_TO_CPP_DIR)/$(notdir $(1)) else - mod_ispc_srcs_path += $(MODC_DIR)/$(notdir $(1)) - mod_ispc_srcs_names += $(notdir $(1)) + mod_non_art_files += $(MOD_TO_CPP_DIR)/$(notdir $(1)) endif else - mod_c_srcs_path += $(MODC_DIR)/$(notdir $(1)) - mod_c_srcs_names += $(notdir $(1)) + mod_all_files += $(MOD_TO_CPP_DIR)/$(notdir $(1)) endif endef -# File path config (internal) -MODC_DIR = $(OUTPUT)/core/mod2c -OBJS_DIR = $(OUTPUT)/core/build -mod_files = $(sort $(notdir $(wildcard $(MODS_PATH)/*.mod))) -mod_paths = $(sort $(wildcard $(MODS_PATH)/*.mod)) -mod_names = $(mod_files:.mod=) -mod_all_cpp_files = $(addprefix $(MODC_DIR)/,$(addsuffix .cpp,$(mod_names))) -mod_c_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(basename $(mod_names)))) $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(basename $(filter %.cpp, $(OPTMODS_OUTPUTS))))) -mod_ispc_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .obj,$(basename $(mod_ispc_srcs_names)))) $(addprefix $(OBJS_DIR)/,$(addsuffix .obj,$(basename $(filter %.ispc, $(OPTMODS_OUTPUTS))))) - -$(foreach ittxtfile, $(mod_paths), $(eval $(call check_file, $(ittxtfile), ARTIFICIAL_CELL))) - -mod_c_files = $(patsubst %.mod,%.cpp,$(mod_c_srcs_path)) -mod_ispc_files = $(patsubst %.mod,%.ispc,$(mod_ispc_srcs_path)) -mod_ispc_c_files = $(patsubst %.mod,%.cpp,$(mod_ispc_srcs_path)) - -kinderiv_h = $(MODC_DIR)/_kinderiv.h -mod_func_o = $(OBJS_DIR)/_mod_func.o -mod_func_c = $(MODC_DIR)/_mod_func.cpp -dimplic_src= $(datadir)/dimplic.cpp -dimplic_c = $(MODC_DIR)/_dimplic.cpp -dimplic_o = $(OBJS_DIR)/_dimplic.o - -special = $(OUTPUT)/special-core -coremech_libname = corenrnmech$(if $(MECH_NAME),_$(MECH_NAME),) -ifeq (@COMPILE_LIBRARY_TYPE@, STATIC) - library_suffix = @CMAKE_STATIC_LIBRARY_SUFFIX@ +# 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 - library_suffix = @CMAKE_SHARED_LIBRARY_SUFFIX@ + mod_files_for_cpp_backend = $(mod_all_files) endif -coremech_lib = $(OUTPUT)/lib$(coremech_libname)$(library_suffix) -# If no DESTDIR (we are probably just building) we use $ORIGIN (@loader_path in OSX) -_ORIGIN := $(if $(filter Darwin,$(OS_NAME)),@loader_path,$$ORIGIN) -_SONAME := -Wl,$(if $(filter Darwin,$(OS_NAME)),-install_name${_cm}@rpath/,-soname${_cm})$(notdir ${coremech_lib}) -DESTDIR_RPATH = $(if $(DESTDIR),$(DESTDIR)/lib,$(_ORIGIN)) +# 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)))) -C_RESET := \033[0m -C_GREEN := \033[32m +# 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)))) -# ======== MAIN BUILD RULES ============ - -# Take the main and link with nrnmech. -# RPATH is set for DESTDIR_RPATH and coreneuron lib -$(special): $(coremech_lib) - @printf " => $(C_GREEN)LINKING$(C_RESET) executable $(special)\n" - $(CXX_LINK_EXE) $(INCFLAGS) -I $(incdir) $(datadir)/coreneuron.cpp -o $(special) \ - -L $(OUTPUT) -l$(coremech_libname) $(CORENRNLIB_FLAGS) -Wl,-rpath,'$(DESTDIR_RPATH)' -Wl,-rpath,$(libdir) $(LDFLAGS) - - -$(coremech_lib): $(mod_func_o) $(dimplic_o) $(mod_c_objs) $(mod_ispc_objs) build_always - @printf " => $(C_GREEN)LINKING$(C_RESET) library $(coremech_lib) Mod files: $(mod_files)\n" - @rm -f ${coremech_lib} - $(CXXCOMPILE) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c -DADDITIONAL_MECHS $(datadir)/enginemech.cpp - @if [ "@COMPILE_LIBRARY_TYPE@" = "SHARED" ]; then\ - $(CXX_LINK_SHARED) $(INCFLAGS) -I $(incdir) enginemech.o -o ${coremech_lib} ${_SONAME} \ - $(mod_func_o) $(dimplic_o) $(mod_c_objs) $(mod_ispc_objs) $(libdir)/libscopmath.a $(CORENRNLIB_FLAGS) -Wl,-rpath,$(libdir) $(LDFLAGS);\ - else\ - mkdir -p $(OBJS_DIR)/scopmath_obj && cd $(OBJS_DIR)/scopmath_obj && ar -x $(libdir)/libscopmath.a && cd -;\ - ar cq ${coremech_lib} enginemech.o $(mod_func_o) $(dimplic_o) $(OBJS_DIR)/scopmath_obj/*.o $(mod_c_objs) $(mod_ispc_objs);\ - fi - (rm -f $(OUTPUT)/.libs/libcorenrnmech$(library_suffix) ; mkdir -p $(OUTPUT)/.libs ; ln -s ../../${coremech_lib} $(OUTPUT)/.libs/libcorenrnmech$(library_suffix)) - - -# Generic build cpp->.o Need PIC for shared lib -$(OBJS_DIR)/%.o: $(MODC_DIR)/%.cpp $(kinderiv_h) | $(OBJS_DIR) - @printf " -> $(C_GREEN)Compiling$(C_RESET) $<\n" - $(CXXCOMPILE) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@ - -# Generic build ispc->.obj Need PIC for shared lib -$(OBJS_DIR)/%.obj: $(MODC_DIR)/%.ispc | $(OBJS_DIR) - @printf " -> $(C_GREEN)Compiling with ISPC$(C_RESET) $<\n" - $(ISPC_COMPILE) @CMAKE_ISPC_COMPILE_OPTIONS_PIC@ $< -o $@ - -# Build ispc files with mod2c/nmodl -$(mod_ispc_files): $(MODC_DIR)/%.ispc: $(MODS_PATH)/%.mod | $(MODC_DIR) - @printf " -> $(C_GREEN)MOD2C$(C_RESET) $<\n" - PYTHONPATH=@CORENRN_NMODL_PYTHONPATH@:${libdir}/python \ - MODLUNIT=$(datadir_mod2c)/nrnunits.lib \ - $(nmodl_binary_path) $< -o $(MODC_DIR)/ @nmodl_arguments_ispc@ - -# Static pattern to set up the dependencies for the previous recipe. -$(mod_ispc_c_files): $(MODC_DIR)/%.cpp: $(MODC_DIR)/%.ispc - -# Build cpp files with mod2c/nmodl -$(mod_c_files): $(MODC_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MODC_DIR) - @printf " -> $(C_GREEN)MOD2C$(C_RESET) $<\n" - PYTHONPATH=@CORENRN_NMODL_PYTHONPATH@:${libdir}/python \ - MODLUNIT=$(datadir_mod2c)/nrnunits.lib \ - $(nmodl_binary_path) $< -o $(MODC_DIR)/ @nmodl_arguments_c@ - -# If .mod doesnt exist attempt from previously built opt mods in shared/ -$(MODC_DIR)/%.cpp: $(datadir_mod2c)/%.cpp | $(MODC_DIR) - ln -s $< $@ -$(MODC_DIR)/%.ispc: $(datadir_mod2c)/%.ispc | $(MODC_DIR) - ln -s $< $@ +# 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 $(DEST_DIR),$(DEST_DIR)/lib,$(ORIGIN_RPATH)) +# All objects used during build +ALL_OBJS = $(MOD_FUNC_OBJ) $(DIMPLIC_OBJ) $(mod_cpp_objs) $(mod_ispc_objs) -# Mod registration. Compiled by generic rule. Dont overwrite if not changed -$(mod_func_c): build_always | $(MODC_DIR) - @printf " -> $(C_GREEN)Generating$(C_RESET) $(mod_func_c)\n" - perl $(datadir)/mod_func.c.pl $(mod_files) > $(mod_func_c).tmp - diff -q $(mod_func_c).tmp $(mod_func_c) || { echo "Replacing mod_func.c"; mv $(mod_func_c).tmp $(mod_func_c); } +# Colors for pretty printing +C_RESET := \033[0m +C_GREEN := \033[32m -# Header to avoid function callbacks using function pointers -# Move all mods to temp and bring back only those required -$(kinderiv_h): $(mod_all_cpp_files) build_always | $(MODC_DIR) - @printf " -> $(C_GREEN)Generating$(C_RESET) $(kinderiv_h)\n" - cd $(MODC_DIR) && mkdir -p _tmp && mv [^_]*.cpp _tmp/ && \ - mv $(addprefix _tmp/,$(notdir $(mod_all_cpp_files))) ./ || true - rm -rf $(MODC_DIR)/_tmp - cd $(MODC_DIR) && @PYTHON_EXECUTABLE@ $(datadir)/kinderiv.py +# ======== MAIN BUILD RULES ============ -$(dimplic_c): $(dimplic_src) | $(MODC_DIR) - ln -s $(dimplic_src) $(dimplic_c) +# 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) \ + -Wl,-rpath,'$(LIB_RPATH)' -Wl,-rpath,$(CORENRN_LIB_DIR) + +coremech_lib_target: enginemech_object $(corenrnmech_lib_target) + rm -rf $(OUTPUT_DIR)/.libs; \ + mkdir -p $(OUTPUT_DIR)/.libs; \ + ln -s ${COREMECH_LIB_PATH} $(OUTPUT_DIR)/.libs/libcorenrnmech$(LIB_SUFFIX) + +enginemech_object: + mkdir -p $(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) 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) 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 $(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) + $(NMODL_ENV_VAR) $(NMODL_BINARY_PATH) $< -o $(MOD_TO_CPP_DIR)/ @nmodl_arguments_ispc@ + +# translate MOD files to CPP using mod2c/NMODL +$(mod_cpp_files): $(MOD_TO_CPP_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MOD_TO_CPP_DIR) + $(NMODL_ENV_VAR) $(NMODL_BINARY_PATH) $< -o $(MOD_TO_CPP_DIR)/ @nmodl_arguments_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 + diff -q $(MOD_FUNC_CPP).tmp $(MOD_FUNC_CPP) || \ + mv $(MOD_FUNC_CPP).tmp $(MOD_FUNC_CPP) + +# 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); \ + @PYTHON_EXECUTABLE@ $(CORENRN_SHARE_CORENRN_DIR)/kinderiv.py; + +# symlink to cpp files provided by coreneuron +$(MOD_TO_CPP_DIR)/%.cpp: $(CORENRN_SHARE_MOD2C_DIR)/%.cpp | $(MOD_TO_CPP_DIR) + ln -s $< $@ +# to recompile dimplic.cpp for solvers +$(DIMPLIC_CPP): $(DERIVIMPLICIT_CPP_FILE) | $(MOD_TO_CPP_DIR) + ln -s $(DERIVIMPLICIT_CPP_FILE) $(DIMPLIC_CPP) -install: $(special) $(coremech_lib) - install -d $(DESTDIR)/bin $(DESTDIR)/lib - install $(coremech_lib) $(DESTDIR)/lib - install $(special) $(DESTDIR)/bin +# create directories needed +$(MOD_TO_CPP_DIR): + mkdir -p $(MOD_TO_CPP_DIR) +$(MOD_OBJS_DIR): + mkdir -p $(MOD_OBJS_DIR) -# == INIT == -$(MODC_DIR): - mkdir -p $(MODC_DIR) -$(OBJS_DIR): - mkdir -p $(OBJS_DIR) +# install binary and libraries +install: $(SPECIAL_EXE) coremech_lib_target + install -d $(DEST_DIR)/bin $(DEST_DIR)/lib + install ${COREMECH_LIB_PATH} $(DEST_DIR)/lib + install $(SPECIAL_EXE) $(DEST_DIR)/bin .PHONY: build_always diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2de5d7a01..77b8618c5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,11 @@ if(NOT Boost_USE_STATIC_LIBS) add_definitions(-DBOOST_TEST_DYN_LINK=TRUE) endif() +set(CMAKE_BUILD_RPATH ${CMAKE_BINARY_DIR}/bin/${CMAKE_HOST_SYSTEM_PROCESSOR}) + +# mechanism library path +set(corenrn_mech_lib "${CMAKE_BINARY_DIR}/bin/${CMAKE_HOST_SYSTEM_PROCESSOR}/libcorenrnmech${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(Boost_NO_BOOST_CMAKE TRUE) find_package(Boost 1.41.0 QUIET COMPONENTS filesystem system atomic unit_test_framework) @@ -23,6 +28,7 @@ if(Boost_FOUND) add_subdirectory(unit/alignment) add_subdirectory(unit/queueing) endif() + message(STATUS "Boost found, unit tests enabled") else() message(STATUS "Boost not found, unit tests disabled") endif() diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index b4dfebfeb..70a44b555 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -54,10 +54,8 @@ endforeach() # base tests : ring, ring with gap and ring duplication foreach(data_dir "ring" "ring_gap") - file(COPY - "${CMAKE_CURRENT_SOURCE_DIR}/${data_dir}/out.dat.ref" - DESTINATION - "${CMAKE_CURRENT_BINARY_DIR}/${data_dir}/") + file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/${data_dir}/out.dat.ref" + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${data_dir}/") endforeach() # test for small spike buffer diff --git a/tests/unit/cmdline_interface/CMakeLists.txt b/tests/unit/cmdline_interface/CMakeLists.txt index 9f2837d27..7ccfa5834 100644 --- a/tests/unit/cmdline_interface/CMakeLists.txt +++ b/tests/unit/cmdline_interface/CMakeLists.txt @@ -8,10 +8,11 @@ file(GLOB cmd_interface_test_src "*.cpp") add_executable(cmd_interface_test_bin ${cmd_interface_test_src}) target_link_libraries( - cmd_interface_test_bin ${MPI_CXX_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} coreneuron + cmd_interface_test_bin ${MPI_CXX_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} coreneuron ${corenrn_mech_lib} ${reportinglib_LIBRARY} ${sonatareport_LIBRARY}) target_include_directories(cmd_interface_test_bin SYSTEM PRIVATE ${CORENEURON_PROJECT_SOURCE_DIR}/external/CLI11/include) +add_dependencies(cmd_interface_test_bin nrniv-core) add_test(NAME cmd_interface_test COMMAND ${TEST_EXEC_PREFIX} ${CMAKE_CURRENT_BINARY_DIR}/cmd_interface_test_bin) diff --git a/tests/unit/interleave_info/CMakeLists.txt b/tests/unit/interleave_info/CMakeLists.txt index c59a5804e..472dc6d68 100644 --- a/tests/unit/interleave_info/CMakeLists.txt +++ b/tests/unit/interleave_info/CMakeLists.txt @@ -8,7 +8,8 @@ file(GLOB interleave_info_src "*.cpp") add_executable(interleave_info_bin ${interleave_info_src}) target_link_libraries(interleave_info_bin ${MPI_CXX_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} - coreneuron ${reportinglib_LIBRARY} ${sonatareport_LIBRARY}) + coreneuron ${corenrn_mech_lib} ${reportinglib_LIBRARY} ${sonatareport_LIBRARY}) +add_dependencies(interleave_info_bin nrniv-core) add_test(NAME interleave_info_constructor_test COMMAND ${TEST_EXEC_PREFIX} ${CMAKE_CURRENT_BINARY_DIR}/interleave_info_bin) diff --git a/tests/unit/queueing/CMakeLists.txt b/tests/unit/queueing/CMakeLists.txt index b3994c46e..5ee9341a8 100644 --- a/tests/unit/queueing/CMakeLists.txt +++ b/tests/unit/queueing/CMakeLists.txt @@ -8,6 +8,7 @@ file(GLOB queuing_test_src "*.cpp") add_executable(queuing_test_bin ${queuing_test_src}) target_link_libraries(queuing_test_bin ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_SYSTEM_LIBRARY} - coreneuron ${reportinglib_LIBRARY} ${sonatareport_LIBRARY}) + coreneuron ${corenrn_mech_lib} ${reportinglib_LIBRARY} ${sonatareport_LIBRARY}) +add_dependencies(queuing_test_bin nrniv-core) add_test(NAME queuing_test COMMAND ${TEST_EXEC_PREFIX} ${CMAKE_CURRENT_BINARY_DIR}/queuing_test_bin)