diff --git a/cmake/CMakeListsNrnMech.cmake b/cmake/CMakeListsNrnMech.cmake index 6d53842273..a5e0a9f39f 100644 --- a/cmake/CMakeListsNrnMech.cmake +++ b/cmake/CMakeListsNrnMech.cmake @@ -14,69 +14,7 @@ string(JOIN " " NRN_COMPILE_FLAGS_STRING ${NRN_COMPILE_FLAGS} ${NRN_EXTRA_MECH_C string(JOIN " " NRN_LINK_FLAGS_STRING ${NRN_LINK_FLAGS} ${NRN_LINK_FLAGS_FOR_ENTRY_POINTS}) string(JOIN " " NRN_NOCMODL_SANITIZER_ENVIRONMENT_STRING ${NRN_NOCMODL_SANITIZER_ENVIRONMENT}) -# extract link defs to the whole project -get_target_property(NRN_LINK_LIBS nrniv_lib LINK_LIBRARIES) -if(NOT NRN_LINK_LIBS) - set(NRN_LINK_LIBS "") -endif() - -# Interview might have linked to libnrniv but we don't want to link to special -list(REMOVE_ITEM NRN_LINK_LIBS "interviews") - -function(get_link_libraries libs) - # CMake does some magic to transform sys libs to -l. We replicate it - foreach(link_lib ${libs}) - # skip static readline library as it will be linked to nrniv (e.g. with wheel) also stub - # libraries from OSX can be skipped - if("${link_lib}" MATCHES "(libreadline.a|/*.tbd)") - continue() - endif() - - get_filename_component(dir_path ${link_lib} DIRECTORY) - if(TARGET ${link_lib}) - get_property( - sublink_flag - TARGET ${link_lib} - PROPERTY INTERFACE_LINK_LIBRARIES) - set(description - "Extracting link flags from target '${link_lib}', beware that this can be fragile.") - # Not use it yet because it can be generator expressions get_property(compile_flag TARGET - # ${link_lib} PROPERTY INTERFACE_COMPILE_OPTIONS) string(APPEND NRN_COMPILE_DEFS - # ${compile_flag}) - foreach(sublink_lib ${sublink_flag}) - if(TARGET ${sublink_lib}) - message(NOTICE "For '${link_lib}' going to see TARGET '${sublink_lib}' recursively.") - get_link_libraries(${sublink_lib}) - else() - set(link_flag "${link_flag} ${sublink_flag}") - endif() - endforeach() - elseif(NOT dir_path) - set(link_flag "-l${link_lib}") - set(description - "Generating link flags from name '${link_lib}', beware that this can be fragile.") - # avoid library paths from special directory /nrnwheel which used to build wheels under docker - # container - elseif("${dir_path}" MATCHES "^/nrnwheel") - continue() - elseif("${dir_path}" MATCHES "^(/lib|/lib64|/usr/lib|/usr/lib64)$") - # NAME_WLE not avaialble with CMake version < 3.14 - get_filename_component(libname ${link_lib} NAME) - string(REGEX REPLACE "\\.[^.]*$" "" libname_wle ${libname}) - string(REGEX REPLACE "^lib" "" libname_wle ${libname_wle}) - set(link_flag "-l${libname_wle}") - set(description - "Extracting link flags from path '${link_lib}', beware that this can be fragile.") - else() - set(link_flag "${link_lib} -Wl,-rpath,${dir_path}") - set(description "Generating link flags from path ${link_lib}") - endif() - message(NOTICE "${description} Got: ${link_flag}") - string(APPEND NRN_LINK_DEFS " ${link_flag}") - endforeach() -endfunction(get_link_libraries) - -get_link_libraries("${NRN_LINK_LIBS}") +get_link_libraries(NRN_LINK_DEFS NOT_USE_INCLUDE_HERE nrniv_lib interviews) # Compiler flags depending on cmake build type from BUILD_TYPE__FLAGS string(TOUPPER "${CMAKE_BUILD_TYPE}" _BUILD_TYPE) diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index fa0623c81c..d49628b5e9 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -199,3 +199,95 @@ macro(nrn_mpi_find_package) find_package(MPI REQUIRED) endif() endmacro() + +function(get_for_a_not_target link_defs lib) + if(NOT lib OR TARGET ${lib}) + set(${link_defs} + "" + PARENT_SCOPE) + endif() + # CMake does some magic to transform sys libs to -l. We replicate it + set(link_flag "") + # skip static readline library as it will be linked to nrniv (e.g. with wheel) also stub libraries + # from OSX can be skipped + if("${lib}" MATCHES "(libreadline.a|/*.tbd)") + return() + endif() + + get_filename_component(dir_path ${lib} DIRECTORY) + if(NOT dir_path) + set(link_flag "-l${lib}") + # avoid library paths from special directory /nrnwheel which used to build wheels under docker + # container + elseif("${dir_path}" MATCHES "^/nrnwheel") + + elseif("${dir_path}" MATCHES "^(/lib|/lib64|/usr/lib|/usr/lib64)$") + get_filename_component(libname_wle ${lib} NAME_WLE) + string(REGEX REPLACE "^lib" "" libname_wle ${libname_wle}) + set(link_flag "-l${libname_wle}") + else() + set(link_flag "${lib} -Wl,-rpath,${dir_path}") + endif() + set(${link_defs} + "${link_flag}" + PARENT_SCOPE) +endfunction() + +function(get_link_libraries link_defs include_defs target exclude) + if(NOT TARGET ${target}) + set(${link_defs} + "" + PARENT_SCOPE) + set(${include_defs} + "" + PARENT_SCOPE) + message(WARNING "${target} is not a target, get_link_libraries aborted") + return() + endif() + message(STATUS "Will look recursively to includes and libs of ${target}") + set(link_flag "") + set(include_flag "") + get_target_property(target_imported ${target} IMPORTED) + if(target_imported) + get_target_property(target_location ${target} LOCATION) + if(target_location) + get_for_a_not_target(link_flag_ ${target_location}) + string(APPEND link_flag " ${link_flag_}") + endif() + endif() + get_property( + include_flag_ + TARGET ${target} + PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + foreach(include_def ${include_flag_}) + string(APPEND include_flag " -I${include_def}") + endforeach() + # Not use it yet because it can be generator expressions get_property(compile_flag TARGET + # ${target} PROPERTY INTERFACE_COMPILE_OPTIONS) string(APPEND NRN_COMPILE_DEFS ${compile_flag}) + get_property( + sublink_flag + TARGET ${target} + PROPERTY INTERFACE_LINK_LIBRARIES) + foreach(sublink_lib ${sublink_flag}) + if(${sublink_lib} IN_LIST exclude) + message(STATUS "Excluding ${sublink_lib} from ${target}") + continue() + endif() + message(STATUS "${target} is composed of ${sublink_lib}") + if(TARGET ${sublink_lib}) + get_link_libraries(link_flag_ include_flag_ ${sublink_lib} "${exclude}") + string(APPEND link_flag " ${link_flag_}") + string(APPEND include_flag " ${include_flag_}") + else() + get_for_a_not_target(link_flag_ "${sublink_lib}") + string(APPEND link_flag " ${link_flag_}") + endif() + endforeach() + set(${link_defs} + "${link_flag}" + PARENT_SCOPE) + set(${include_defs} + "${include_flag}" + PARENT_SCOPE) + message(STATUS "For ${target} got '${link_flag}' and '${include_flag}'") +endfunction(get_link_libraries) diff --git a/cmake/coreneuron/MakefileBuildOptions.cmake b/cmake/coreneuron/MakefileBuildOptions.cmake index 1ab2de8e92..be2dfff45c 100644 --- a/cmake/coreneuron/MakefileBuildOptions.cmake +++ b/cmake/coreneuron/MakefileBuildOptions.cmake @@ -35,70 +35,15 @@ set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_FLAGS " -lcorenrnmec if(NOT CORENRN_ENABLE_SHARED) set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_FLAGS " -Wl,--no-whole-archive") endif() -# Essentially we "just" want to unpack the CMake dependencies of the `coreneuron-core` target into a -# plain string that we can bake into the Makefiles in both NEURON and CoreNEURON. -function(coreneuron_process_library_path library) - get_filename_component(library_dir "${library}" DIRECTORY) - if(NOT library_dir) - # In case target is not a target but is just the name of a library, e.g. "dl" - set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_DEP_FLAGS " -l${library}") - elseif("${library_dir}" MATCHES "^(/lib|/lib64|/usr/lib|/usr/lib64)$") - # e.g. /usr/lib64/libpthread.so -> -lpthread TODO: consider using - # https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.html, or - # dropping this special case entirely - get_filename_component(libname ${library} NAME_WE) - string(REGEX REPLACE "^lib" "" libname ${libname}) - set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_DEP_FLAGS " -l${libname}") - else() - # It's a full path, include that on the line - set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_DEP_FLAGS - " -Wl,-rpath,${library_dir} ${library}") - endif() -endfunction() -function(coreneuron_process_target target) - if(TARGET ${target}) - if(NOT target STREQUAL "coreneuron-core") - # This is a special case: libcoreneuron-core.a is manually unpacked into .o files by the - # nrnivmodl-core Makefile, so we do not want to also emit an -lcoreneuron-core argument. - get_target_property(target_inc_dirs ${target} INTERFACE_INCLUDE_DIRECTORIES) - if(target_inc_dirs) - foreach(inc_dir_genex ${target_inc_dirs}) - string(GENEX_STRIP "${inc_dir_genex}" inc_dir) - if(inc_dir) - set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_EXTRA_COMPILE_FLAGS " -I${inc_dir}") - endif() - endforeach() - endif() - get_target_property(target_imported ${target} IMPORTED) - if(target_imported) - # In this case we can extract the full path to the library - get_target_property(target_location ${target} LOCATION) - coreneuron_process_library_path(${target_location}) - else() - # This is probably another of our libraries, like -lcoreneuron-cuda. We might need to add -L - # and an RPATH later. - set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_DEP_FLAGS " -l${target}") - endif() - endif() - get_target_property(target_libraries ${target} LINK_LIBRARIES) - if(target_libraries) - foreach(child_target ${target_libraries}) - coreneuron_process_target(${child_target}) - endforeach() - endif() - return() - endif() - coreneuron_process_library_path("${target}") -endfunction() -coreneuron_process_target(coreneuron-core) -get_property(CORENRN_LIB_LINK_DEP_FLAGS GLOBAL PROPERTY CORENRN_LIB_LINK_DEP_FLAGS) + +get_link_libraries(CORENRN_LIB_LINK_DEP_FLAGS CORENRN_EXTRA_COMPILE_FLAGS coreneuron-core "") + set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_FLAGS " ${CORENRN_LIB_LINK_DEP_FLAGS}") # In static builds then NEURON uses dlopen(nullptr, ...) to look for the corenrn_embedded_run # symbol, which comes from libcoreneuron-core.a and gets included in libcorenrnmech. if(NOT CORENRN_ENABLE_SHARED) set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_FLAGS " -rdynamic") endif() -get_property(CORENRN_EXTRA_COMPILE_FLAGS GLOBAL PROPERTY CORENRN_EXTRA_COMPILE_FLAGS) get_property(CORENRN_LIB_LINK_FLAGS GLOBAL PROPERTY CORENRN_LIB_LINK_FLAGS) # Detect if --start-group and --end-group are valid linker arguments. These are typically needed diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index 3594329de6..286aefacc0 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -492,7 +492,7 @@ endforeach() # we can link to MPI libraries in non-dynamic-mpi build if(NRN_ENABLE_MPI AND NOT NRN_ENABLE_MPI_DYNAMIC) - target_link_libraries(coreneuron-core PUBLIC ${MPI_CXX_LIBRARIES}) + target_link_libraries(coreneuron-core PUBLIC ${MPI_C_LIBRARIES}) endif() # ~~~