Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions CMake/OpenAccHelper.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,35 @@
# See top-level LICENSE file for details.
# =============================================================================

# Helper to parse X.Y[.{anything] into X.Y
function(cnrn_parse_version FULL_VERSION)
cmake_parse_arguments(PARSE_ARGV 1 CNRN_PARSE_VERSION "" "OUTPUT_MAJOR_MINOR" "")
if(NOT "${CNRN_PARSE_VERSION_UNPARSED_ARGUMENTS}" STREQUAL "")
message(
FATAL_ERROR
"cnrn_parse_version got unexpected arguments: ${CNRN_PARSE_VERSION_UNPARSED_ARGUMENTS}")
endif()
string(FIND ${FULL_VERSION} . first_dot)
math(EXPR first_dot_plus_one "${first_dot}+1")
string(SUBSTRING ${FULL_VERSION} ${first_dot_plus_one} -1 minor_and_later)
string(FIND ${minor_and_later} . second_dot_relative)
if(${first_dot} EQUAL -1 OR ${second_dot_relative} EQUAL -1)
message(FATAL_ERROR "Failed to parse major.minor from ${FULL_VERSION}")
endif()
math(EXPR second_dot_plus_one "${first_dot}+${second_dot_relative}+1")
string(SUBSTRING ${FULL_VERSION} 0 ${second_dot_plus_one} major_minor)
set(${CNRN_PARSE_VERSION_OUTPUT_MAJOR_MINOR}
${major_minor}
PARENT_SCOPE)
endfunction()

# =============================================================================
# Prepare compiler flags for GPU target
# =============================================================================
if(CORENRN_ENABLE_GPU)
# Get the NVC++ version number for use in nrnivmodl_core_makefile.in
cnrn_parse_version(${CMAKE_CXX_COMPILER_VERSION} OUTPUT_MAJOR_MINOR
CORENRN_NVHPC_MAJOR_MINOR_VERSION)
# Enable cudaProfiler{Start,Stop}() behind the Instrumentor::phase... APIs
add_compile_definitions(CORENEURON_CUDA_PROFILING CORENEURON_ENABLE_GPU)
# Plain C++ code in CoreNEURON may need to use CUDA runtime APIs for, for example, starting and
Expand All @@ -23,20 +48,7 @@ if(CORENRN_ENABLE_GPU)
if(NOT ${CMAKE_CUDA_COMPILER_ID} STREQUAL "NVIDIA")
message(FATAL_ERROR "Unsupported CUDA compiler ${CMAKE_CUDA_COMPILER_ID}")
endif()
# Parse CMAKE_CUDA_COMPILER_VERSION=x.y.z into CUDA_VERSION=x.y
string(FIND ${CMAKE_CUDA_COMPILER_VERSION} . first_dot)
math(EXPR first_dot_plus_one "${first_dot}+1")
string(SUBSTRING ${CMAKE_CUDA_COMPILER_VERSION} ${first_dot_plus_one} -1 minor_and_later)
string(FIND ${minor_and_later} . second_dot_relative)
if(${first_dot} EQUAL -1 OR ${second_dot_relative} EQUAL -1)
message(
FATAL_ERROR
"Failed to parse a CUDA_VERSION from CMAKE_CUDA_COMPILER_VERSION=${CMAKE_CUDA_COMPILER_VERSION}"
)
endif()
math(EXPR second_dot_plus_one "${first_dot}+${second_dot_relative}+1")
string(SUBSTRING ${CMAKE_CUDA_COMPILER_VERSION} 0 ${second_dot_plus_one}
CORENRN_CUDA_VERSION_SHORT)
cnrn_parse_version(${CMAKE_CUDA_COMPILER_VERSION} OUTPUT_MAJOR_MINOR CORENRN_CUDA_VERSION_SHORT)
else()
# This is a lazy way of getting the major/minor versions separately without parsing
# ${CMAKE_CUDA_COMPILER_VERSION}
Expand Down Expand Up @@ -91,7 +103,7 @@ if(CORENRN_ENABLE_GPU)
GLOBAL
PROPERTY
CORENEURON_LIB_LINK_FLAGS
"${NVHPC_ACC_COMP_FLAGS} -rdynamic -lrt -Wl,--whole-archive -L${CMAKE_HOST_SYSTEM_PROCESSOR} -lcorenrnmech -L${CMAKE_INSTALL_PREFIX}/lib -lcoreneuron -Wl,--no-whole-archive"
"${NVHPC_ACC_COMP_FLAGS} -rdynamic -lrt -Wl,--whole-archive -L${CMAKE_HOST_SYSTEM_PROCESSOR} -lcorenrnmech -L$(libdir) -lcoreneuron -Wl,--no-whole-archive"
)
else()
set_property(GLOBAL PROPERTY CORENEURON_LIB_LINK_FLAGS
Expand Down
26 changes: 23 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,12 @@ endif()
# =============================================================================
# Common CXX flags : ignore unknown pragma warnings
# =============================================================================
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IGNORE_UNKNOWN_PRAGMA_FLAGS}")
# Do not set this when building wheels. The nrnivmodl workflow means that we do not know what
# compiler will be invoked with these flags, so we have to use flags that are as generic as
# possible.
if(NOT DEFINED NRN_WHEEL_BUILD OR NOT NRN_WHEEL_BUILD)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IGNORE_UNKNOWN_PRAGMA_FLAGS}")
endif()

# =============================================================================
# Add main directories
Expand All @@ -436,7 +441,21 @@ add_subdirectory(coreneuron)
if(CORENRN_ENABLE_GPU)
get_target_property(CORENRN_LINK_LIBRARIES coreneuron INTERFACE_LINK_LIBRARIES)
foreach(LIB ${CORENRN_LINK_LIBRARIES})
set_property(GLOBAL APPEND_STRING PROPERTY CORENEURON_LIB_LINK_FLAGS " ${LIB}")
get_filename_component(dir_path ${LIB} DIRECTORY)
if(TARGET ${LIB})
# See, for example, caliper where the coreneuron target depends on the caliper target (so we
# get LIB=caliper in this loop), but -l and -L are already added manually here:
# https://github.com/BlueBrain/CoreNeuron/blob/856cea4aa647c8f2b0d5bda6d0fc32144c5942e3/CMakeLists.txt#L411-L412
message(
NOTICE
"Ignoring dependency '${LIB}' of 'coreneuron' and assuming relevant flags have already been added to CORENEURON_LIB_LINK_FLAGS."
)
elseif(NOT dir_path)
# In case LIB is not a target but is just the name of a library, e.g. "dl"
set_property(GLOBAL APPEND_STRING PROPERTY CORENEURON_LIB_LINK_FLAGS " -l${LIB}")
else()
set_property(GLOBAL APPEND_STRING PROPERTY CORENEURON_LIB_LINK_FLAGS " ${LIB}")
endif()
endforeach()
endif()

Expand Down Expand Up @@ -528,7 +547,6 @@ message(STATUS "COMPILE FLAGS | ${CORENRN_CXX_FLAGS}")
message(STATUS "Build Type | ${COMPILE_LIBRARY_TYPE}")
message(STATUS "MPI | ${CORENRN_ENABLE_MPI}")
if(CORENRN_ENABLE_MPI)
message(STATUS " INC | ${MPI_CXX_INCLUDE_PATH}")
message(STATUS " DYNAMIC | ${CORENRN_ENABLE_MPI_DYNAMIC}")
if(CORENRN_ENABLE_MPI_DYNAMIC AND NRN_MPI_LIBNAME_LIST)
# ~~~
Expand All @@ -543,6 +561,8 @@ if(CORENRN_ENABLE_MPI)
message(STATUS " LIBNAME | core${libname}")
message(STATUS " INC | ${include}")
endforeach(val)
else()
message(STATUS " INC | ${MPI_CXX_INCLUDE_PATH}")
endif()
endif()
message(STATUS "OpenMP | ${CORENRN_ENABLE_OPENMP}")
Expand Down
14 changes: 13 additions & 1 deletion extra/nrnivmodl_core_makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,26 @@ CORENRNLIB_FLAGS += $(if @caliper_LIB_DIR@,-L@caliper_LIB_DIR@,)
# 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)
INCLUDES += $(if @MPI_CXX_INCLUDE_PATH@, -I$(subst ;, -I,@MPI_CXX_INCLUDE_PATH@),)
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
Expand Down