Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmake: export targets, allow to build models via CMake #2746

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions CMakeLists.txt
Expand Up @@ -491,6 +491,9 @@ endif()
# initialize CLI11 submodule
cpp_cc_git_submodule(CLI11 BUILD PACKAGE CLI11 REQUIRED)

# coreneuron targets will get appended here
set(NRN_INSTALL_TARGETS nrniv_lib)

# =============================================================================
# Enable CoreNEURON support
# =============================================================================
Expand Down Expand Up @@ -896,6 +899,24 @@ if(NRN_MACOS_BUILD)
nrn_macos_after_install()
endif()

# =============================================================================
# Install CMake glue
# =============================================================================
install(TARGETS ${NRN_INSTALL_TARGETS} ${CORENRN_INSTALL_TARGETS} EXPORT NeuronTargets)
install(
EXPORT NeuronTargets
FILE neuronTargets.cmake
NAMESPACE neuron::
DESTINATION lib/cmake/neuron)

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/neuronConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/neuronConfig.cmake @ONLY)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/neuronConfig.cmake DESTINATION lib/cmake/neuron)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mod_reg_nrn.cpp.in
${CMAKE_CURRENT_SOURCE_DIR}/cmake/mod_reg_corenrn.cpp.in DESTINATION share/nrn)

# =============================================================================
# Copy bash executable for windows
# =============================================================================
Expand Down
16 changes: 16 additions & 0 deletions cmake/mod_reg_corenrn.cpp.in
@@ -0,0 +1,16 @@
#include <cstdio>
namespace coreneuron {
extern int nrnmpi_myid;
extern int nrn_nobanner_;

@MECH_DECLARE@

void modl_reg() {
if (!nrn_nobanner_) if (nrnmpi_myid < 1) {
fprintf(stderr, " Additional mechanisms from files\n");
@MECH_PRINT@
fprintf(stderr, "\n\n");
}
@MECH_REGISTRE@
}
} //namespace coreneuron
16 changes: 16 additions & 0 deletions cmake/mod_reg_nrn.cpp.in
@@ -0,0 +1,16 @@
#include <stdio.h>
#include "hocdec.h"
extern int nrnmpi_myid;
extern int nrn_nobanner_;

@MECH_DECLARE@

extern "C" void modl_reg() {
if (!nrn_nobanner_) if (nrnmpi_myid < 1) {
fprintf(stderr, "Additional mechanisms from files\n");
@MECH_PRINT@
fprintf(stderr, "\n");
}
@MECH_REGISTRE@
}

128 changes: 128 additions & 0 deletions cmake/neuronConfig.cmake.in
@@ -0,0 +1,128 @@
include(CMakeFindDependencyMacro)

find_dependency(Threads)

include("${CMAKE_CURRENT_LIST_DIR}/neuronTargets.cmake")

get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_prefix "${_dir}/../../.." ABSOLUTE)

set(NRN_ENABLE_CORENEURON @NRN_ENABLE_CORENEURON@)

set(_NEURON_MAIN "${_prefix}/share/nrn/nrnmain.cpp")
set(_NEURON_MAIN_INCLUDE_DIR "${_prefix}/include/nrncvode")
set(_NEURON_MECH_REG "${_prefix}/share/nrn/mod_reg_nrn.cpp.in")

set(_CORENEURON_BASE_MOD "${_prefix}/share/modfile")
set(_CORENEURON_MAIN "${_prefix}/share/coreneuron/coreneuron.cpp")
set(_CORENEURON_MECH_REG "${_prefix}/share/nrn/mod_reg_corenrn.cpp.in")
set(_CORENEURON_MECH_ENG "${_prefix}/share/coreneuron/enginemech.cpp")
set(_CORENEURON_RANDOM_INCLUDE "${_prefix}/include/coreneuron/utils/randoms")
set(_CORENEURON_FLAGS "@CORENRN_CXX_FLAGS@")

find_program(NOCMODL nocmodl REQUIRED)
find_program(NMODL nmodl REQUIRED)

function(merge_modfile_lists)
cmake_parse_arguments(MERGE_MODS "" "" "MOD_FILES" ${ARGN})
endfunction()

function(create_nrnmech)
set(options CORENEURON INSTALL_CPP INSTALL_MOD SPECIAL)
set(oneValueArgs MECHANISM_NAME)
cmake_parse_arguments(NRN_MECH "${options}" "${oneValueArgs}" "MOD_FILES" ${ARGN})

set(CORE "")
set(INPUT_MAIN ${_NEURON_MAIN})
set(INPUT_MECH_REG ${_NEURON_MECH_REG})
set(RETURN_TYPE "\"C\" void")
set(TRANSPILER "${NOCMODL}")

if(NRN_MECH_CORENEURON)
if(NOT NRN_ENABLE_CORENEURON)
message(FATAL_ERROR "CoreNEURON support not enabled")
endif()
set(CORE "core")
set(INPUT_MAIN ${_CORENEURON_MAIN})
set(INPUT_MECH_REG ${_CORENEURON_MECH_REG})
set(RETURN_TYPE "int")
set(TRANSPILER "${NMODL}")
endif()

set(OUTDIR "${CORE}neuron")
set(LIBNAME "${CORE}nrnmech")
set(EXENAME "${CORE}special")

foreach(MOD_FILE IN LISTS NRN_MECH_MOD_FILES)
get_filename_component(MOD_STUB "${MOD_FILE}" NAME_WLE)
list(APPEND INPUT_STUBS "${MOD_STUB}")
list(APPEND MOD_FILES "${MOD_FILE}")
endforeach()

if(NRN_MECH_CORENEURON)
# CoreNEURON requires additional mod files. Only append them to the input list if similar named
# mods are _not yet present_
file(GLOB BASE_MOD_FILES "${_CORENEURON_BASE_MOD}/*.mod")
foreach(MOD_FILE IN LISTS BASE_MOD_FILES)
get_filename_component(MOD_STUB "${MOD_FILE}" NAME_WLE)
if("${MOD_STUB}" IN_LIST INPUT_STUBS)

else()
list(APPEND MOD_FILES "${MOD_FILE}")
endif()
endforeach()
endif()

foreach(MOD_FILE IN LISTS MOD_FILES)
# set(MOD_FILE common/mod/DetAMPANMDA.mod)
get_filename_component(MOD_STUB "${MOD_FILE}" NAME_WLE)
set(CPP_FILE "cpp/${OUTDIR}/${MOD_STUB}.cpp")

list(APPEND L_MECH_DECLARE "extern ${RETURN_TYPE} _${MOD_STUB}_reg(void)\;")
list(APPEND L_MECH_PRINT "fprintf(stderr, \" \\\"${MOD_FILE}\\\"\")\;")
list(APPEND L_MECH_REGISTRE "_${MOD_STUB}_reg()\;")

add_custom_command(COMMAND "${TRANSPILER}" -o "${CMAKE_CURRENT_BINARY_DIR}/cpp/${OUTDIR}"
"${MOD_FILE}" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${CPP_FILE}")

list(APPEND L_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/${CPP_FILE}")
endforeach()

list(JOIN L_MECH_DECLARE "\n" MECH_DECLARE)
list(JOIN L_MECH_PRINT " \n" MECH_PRINT)
list(JOIN L_MECH_REGISTRE " \n" MECH_REGISTRE)

get_filename_component(MECH_REG "${INPUT_MECH_REG}" NAME_WLE)
configure_file(${INPUT_MECH_REG} ${MECH_REG} @ONLY)

if(NRN_MECH_CORENEURON)
add_library(${LIBNAME} SHARED ${_CORENEURON_MECH_ENG} ${L_SOURCES})
target_include_directories(${LIBNAME} PRIVATE ${_CORENEURON_RANDOM_INCLUDE})
target_compile_definitions(${LIBNAME} PRIVATE ADDITIONAL_MECHS NRN_PRCELLSTATE=0
CORENEURON_BUILD)
target_compile_definitions(${LIBNAME} PRIVATE "${_CORENEURON_FLAGS}")
target_link_libraries(${LIBNAME} PUBLIC neuron::corenrn)
else()
add_library(${LIBNAME} SHARED ${L_SOURCES})
target_link_libraries(${LIBNAME} PUBLIC neuron::nrniv)
endif()

if(NRN_MECH_INSTALL_CPP)
install(FILES ${L_SOURCES} DESTINATION "share/${LIBNAME}$<$<BOOL:${NRN_MECH_MECHANISM_NAME}>:_${NRN_MECH_MECHANISM_NAME}>/cpp")
endif()

if(NRN_MECH_INSTALL_MOD)
install(FILES ${MOD_FILES} DESTINATION "share/${LIBNAME}$<$<BOOL:${NRN_MECH_MECHANISM_NAME}>:_${NRN_MECH_MECHANISM_NAME}>/mod")
endif()

install(TARGETS ${LIBNAME} DESTINATION lib)
set_target_properties(${LIBNAME} PROPERTIES OUTPUT_NAME "${LIBNAME}$<$<BOOL:${NRN_MECH_MECHANISM_NAME}>:_${NRN_MECH_MECHANISM_NAME}>")

if(NRN_MECH_SPECIAL)
add_executable(${EXENAME} ${INPUT_MAIN} ${MECH_REG})
target_include_directories(${EXENAME} PUBLIC ${_NEURON_MAIN_INCLUDE_DIR})
target_link_libraries(${EXENAME} ${LIBNAME})
set_target_properties(${EXENAME} PROPERTIES OUTPUT_NAME "special$<$<BOOL:${NRN_MECH_CORENEURON}>:-core>")
install(TARGETS ${EXENAME} DESTINATION bin)
endif()
endfunction()
9 changes: 9 additions & 0 deletions src/coreneuron/CMakeLists.txt
Expand Up @@ -479,10 +479,16 @@ endif()
# https://forums.developer.nvidia.com/t/cannot-dynamically-load-a-shared-library-containing-both-openacc-and-cuda-code/210972
add_library(coreneuron-core STATIC ${CORENEURON_CODE_FILES} ${CORENRN_MPI_OBJ})
add_dependencies(coreneuron-core coreneuron-copy-nrnivmodl-core-dependencies)
set_target_properties(coreneuron-core PROPERTIES EXPORT_NAME corenrn)
set(CORENRN_INSTALL_TARGETS
coreneuron-core
PARENT_SCOPE)
if(CORENRN_ENABLE_GPU)
set(coreneuron_cuda_target coreneuron-cuda)
add_library(coreneuron-cuda ${COMPILE_LIBRARY_TYPE} ${CORENEURON_CUDA_FILES})
set_target_properties(coreneuron-cuda PROPERTIES EXPORT_NAME corenrn-cuda)
target_link_libraries(coreneuron-core PUBLIC coreneuron-cuda)
list(APPEND CORENRN_INSTALL_TARGETS coreneuron-cuda)
endif()

foreach(target coreneuron-core ${coreneuron_cuda_target})
Expand Down Expand Up @@ -561,6 +567,9 @@ endif()
target_compile_options(coreneuron-core PRIVATE ${CORENEURON_CXX_WARNING_SUPPRESSIONS})
target_link_libraries(coreneuron-core PUBLIC ${sonatareport_LIBRARY} ${CORENRN_CALIPER_LIB}
${CORENRN_LIKWID_LIB})
set_target_properties(coreneuron-core PROPERTIES EXPORT_NAME corenrn)
target_compile_features(coreneuron-core PUBLIC cxx_std_17)
target_include_directories(coreneuron-core INTERFACE $<INSTALL_INTERFACE:include>)

# TODO: fix adding a dependency of coreneuron-core on CLI11::CLI11 when CLI11 is a submodule. Right
# now this doesn't work because the CLI11 targets are not exported/installed but coreneuron-core is.
Expand Down
2 changes: 1 addition & 1 deletion src/ivoc/nrnmain.cpp
@@ -1,6 +1,6 @@
#include "nrnconf.h"
#include "nrnmpi.h"
#include "../nrncvode/nrnneosm.h"
#include "nrnneosm.h"

#include <errno.h>
#include <stdio.h>
Expand Down
45 changes: 25 additions & 20 deletions src/nrniv/CMakeLists.txt
Expand Up @@ -399,43 +399,48 @@ include_directories(${NRN_INCLUDE_DIRS})
# All source directories to include
# =============================================================================
add_library(nrniv_lib ${NRN_LIBRARY_TYPE} ${NRN_NRNIV_LIB_SRC_FILES})
target_link_libraries(nrniv_lib nrngnu)
target_link_libraries(nrniv_lib sparse13)
target_include_directories(nrniv_lib SYSTEM PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen)
target_link_libraries(nrniv_lib PRIVATE nrngnu)
target_link_libraries(nrniv_lib PRIVATE sparse13)
# We feel at liberty to include across various subdirectories without clear interfaces, thus this
# should be public at _build_ time, but not at install time.
target_include_directories(
nrniv_lib SYSTEM PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen>)
cpp_cc_configure_sanitizers(TARGET nrniv_lib)
# Source-directory .cpp needs to find generated .hpp.
target_include_directories(nrniv_lib PUBLIC "${NRN_OC_GEN}")
target_include_directories(nrniv_lib PUBLIC $<BUILD_INTERFACE:${NRN_OC_GEN}>)
target_include_directories(nrniv_lib INTERFACE $<INSTALL_INTERFACE:include>)
if(NRN_ENABLE_PYTHON AND NOT NRN_ENABLE_PYTHON_DYNAMIC)
target_link_libraries(nrniv_lib nrnpython)
target_link_libraries(nrniv_lib PRIVATE nrnpython)
endif()
if(NRN_ENABLE_THREADS)
target_link_libraries(nrniv_lib Threads::Threads)
target_link_libraries(nrniv_lib PUBLIC Threads::Threads)
endif()
if(NRN_WINDOWS_BUILD)
target_link_libraries(nrniv_lib ${TERMCAP_LIBRARIES} ${Readline_LIBRARY})
target_link_libraries(nrniv_lib PUBLIC ${TERMCAP_LIBRARIES} ${Readline_LIBRARY})
else()
if(READLINE_FOUND)
target_link_libraries(nrniv_lib ${Readline_LIBRARY})
target_link_libraries(nrniv_lib PUBLIC ${Readline_LIBRARY})
else()
target_link_libraries(nrniv_lib readline)
target_link_libraries(nrniv_lib PUBLIC readline)
endif()

if(CURSES_FOUND)
target_link_libraries(nrniv_lib ${CURSES_LIBRARIES})
target_link_libraries(nrniv_lib PUBLIC ${CURSES_LIBRARIES})
elseif(TERMCAP_FOUND)
target_link_libraries(nrniv_lib ${TERMCAP_LIBRARIES})
target_link_libraries(nrniv_lib PUBLIC ${TERMCAP_LIBRARIES})
endif()
endif()

if(NRN_ENABLE_MUSIC AND NOT NRN_ENABLE_MPI_DYNAMIC)
target_link_libraries(nrniv_lib ${MUSIC_LIBRARY})
target_link_libraries(nrniv_lib PUBLIC ${MUSIC_LIBRARY})
endif()

if(NRN_ENABLE_PROFILING)
target_link_libraries(nrniv_lib ${likwid_LIBRARIES} ${CALIPER_LIB} ${LIKWID_LIB})
target_link_libraries(nrniv_lib PUBLIC ${likwid_LIBRARIES} ${CALIPER_LIB} ${LIKWID_LIB})
endif()

set_property(TARGET nrniv_lib PROPERTY OUTPUT_NAME nrniv)
set_target_properties(nrniv_lib PROPERTIES EXPORT_NAME nrniv OUTPUT_NAME nrniv)
target_compile_features(nrniv_lib PUBLIC cxx_std_17)

# =============================================================================
# Link with backward-cpp if enabled
Expand Down Expand Up @@ -480,16 +485,16 @@ if(NRN_ENABLE_MPI)
install(TARGETS ${libnrnmusic}_lib DESTINATION ${NRN_INSTALL_SHARE_LIB_DIR})
endif()
else()
target_link_libraries(nrniv_lib ${MPI_C_LIBRARIES})
target_link_libraries(nrniv_lib PUBLIC ${MPI_C_LIBRARIES})
target_include_directories(nrniv_lib PUBLIC ${MPI_INCLUDE_PATH})
endif()
endif()

if(NRN_ENABLE_INTERVIEWS)
include_directories(${IV_INCLUDE_DIR})
target_link_libraries(nrniv_lib interviews)
target_link_libraries(nrniv_lib PRIVATE interviews)
else()
target_include_directories(nrniv_lib PUBLIC ${NRN_IVOS_SRC_DIR})
target_include_directories(nrniv_lib PUBLIC $<BUILD_INTERFACE:${NRN_IVOS_SRC_DIR}>)
endif()

if(IV_ENABLE_X11_DYNAMIC)
Expand Down Expand Up @@ -520,11 +525,11 @@ if(IV_ENABLE_X11_DYNAMIC)
${PROJECT_BINARY_DIR}/lib/${LIBIVX11DYNAM_NAME})
endif()
else()
target_link_libraries(nrniv_lib ${X11_LIBRARIES})
target_link_libraries(nrniv_lib PRIVATE ${X11_LIBRARIES})
endif()

if(NRN_COVERAGE_FILES)
target_link_libraries(nrniv_lib ${NRN_COVERAGE_LIB})
target_link_libraries(nrniv_lib PRIVATE ${NRN_COVERAGE_LIB})
target_link_libraries(modlunit ${NRN_COVERAGE_LIB})
target_link_libraries(nocmodl ${NRN_COVERAGE_LIB})
endif()
Expand All @@ -542,7 +547,7 @@ if(NRN_ENABLE_THREADS)
target_link_libraries(nrniv Threads::Threads)
endif()
if(NOT MINGW)
target_link_libraries(nrniv_lib ${CMAKE_DL_LIBS})
target_link_libraries(nrniv_lib PUBLIC ${CMAKE_DL_LIBS})
endif()

# TODO: unset in top level CMake is not working
Expand Down
4 changes: 2 additions & 2 deletions src/nrnoc/hh.mod
Expand Up @@ -30,7 +30,7 @@ NEURON {
NONSPECIFIC_CURRENT il
RANGE gnabar, gkbar, gl, el, gna, gk
: `GLOBAL minf` will be replaced with `RANGE minf` if CoreNEURON enabled
GLOBAL minf, hinf, ninf, mtau, htau, ntau
RANGE minf, hinf, ninf, mtau, htau, ntau
THREADSAFE : assigned GLOBALs will be per thread
}

Expand Down Expand Up @@ -94,7 +94,7 @@ PROCEDURE rates(v(mV)) { :Computes rate and other constants at current v.
:Call once from HOC to initialize inf at resting v.
LOCAL alpha, beta, sum, q10
: `TABLE minf` will be replaced with `:TABLE minf` if CoreNEURON enabled)
TABLE minf, mtau, hinf, htau, ninf, ntau DEPEND celsius FROM -100 TO 100 WITH 200
:TABLE minf, mtau, hinf, htau, ninf, ntau DEPEND celsius FROM -100 TO 100 WITH 200

UNITSOFF
q10 = 3^((celsius - 6.3)/10)
Expand Down
4 changes: 4 additions & 0 deletions src/nrnpython/CMakeLists.txt
Expand Up @@ -45,6 +45,10 @@ endif()

# user has selected dynamic python support (could be multiple versions)
if(NRN_ENABLE_PYTHON_DYNAMIC)
# set(INCLUDE_DIRS . .. ../oc ../nrnoc ../ivoc ../nrniv ../gnu ../nrnmpi
# ${PROJECT_BINARY_DIR}/src/nrnpython ${PROJECT_BINARY_DIR}/src/ivos ${PROJECT_BINARY_DIR}/src/oc
# ${NRN_OC_GENERATED_SOURCES}) if(NRN_ENABLE_INTERVIEWS) list(APPEND INCLUDE_DIRS
# ${IV_INCLUDE_DIR}) else() list(APPEND INCLUDE_DIRS ../ivos) endif()
foreach(val RANGE ${NRN_PYTHON_ITERATION_LIMIT})
list(GET NRN_PYTHON_VERSIONS ${val} pyver)
list(GET NRN_PYTHON_INCLUDES ${val} pyinc)
Expand Down