# --------------------------------------------------------------- # Programmer(s): Cody J. Balos @ LLNL # --------------------------------------------------------------- # SUNDIALS Copyright Start # Copyright (c) 2002-2024, Lawrence Livermore National Security # and Southern Methodist University. # All rights reserved. # # See the top-level LICENSE and NOTICE files for details. # # SPDX-License-Identifier: BSD-3-Clause # SUNDIALS Copyright End # --------------------------------------------------------------- # CMake macro for adding libraries. # Wraps the add_library command for sundials specific needs. # --------------------------------------------------------------- # The macro: # # SUNDIALS_ADD_LIBRARY( # SOURCES source1 source2 ... # [HEADERS header1 header2 ...] # [OBJECT_LIBRARIES objlib1 objlib2 ...] # [LINK_LIBRARIES ... # [ ...] ] # [INCLUDE_DIRECTORIES ... # [ ...] ] # [COMPILE_DEFINITIONS ... # [ ...] ] # [COMPILE_OPTIONS ... # [ ...] ] # [COMPILE_FEATURES ... # [ ...] ] # [PROPERTIES ... [ ...] ] # [INCLUDE_SUBDIR] # [OUTPUT_NAME name] # [VERSION version] # [SOVERSION version] # [STATIC_ONLY | SHARED_ONLY] # [OBJECT_LIB_ONLY]) # # adds libraries to be built from the source files listed in the command # invocation. It is a convenient wrapper of the CMake add_library command that # is specific to our usage of add_library in SUNDIALS. # # By default, the macro uses the CMake add_library command to create the # targets: # - ${_SHARED_LIB_SUFFIX} (will be a shared library) # - ${_STATIC_LIB_SUFFIX} (will be a static library) # - _obj${_SHARED_LIB_SUFFIX} (an object library that is used to # create ${_SHARED_LIB_SUFFIX}) # - _obj${_STATIC_LIB_SUFFIX} (an object library that is used to # create ${_STATIC_LIB_SUFFIX}) # - (an alias to the shared library, if enabled, otherwise an # alias to the static library) # # The SOURCES input is a list of source files used to create the library. # # The option HEADERS is a list of header files to install with the library. The # option INCLUDE_SUBDIR can be used to specify a subdirectory in which the # header files should be installed. # # The option OBJECT_LIBRARIES is a list of object library to include when # building the target. This is similar to adding more source files, but its done # using the already compiled objects. # # The option LINK_LIBRARIES is a list that is passed to target_link_libraries on # all the targets generated by the macro. See the CMake target_link_libraries # documentation for more info. # # The option INCLUDE_DIRECTORIES is a list that is passed to # target_include_directories on all the targets generated by the macro. The # {{libtype}} keyword will be replaced with the appropriate library type string # (currently this only used by the sundials_add_f2003_library macro). See the # CMake target_include_directories documentation for more info. # # The option COMPILE_DEFINITIONS is a list that is passed to # target_compile_definitions on all the targets generated by the macro. See the # CMake target_compile_definitions documentation for more info. # # The option COMPILE_OPTIONS is a list that is passed to target_compile_options # on all the targets generated by the macro. See the CMake # target_compile_options documentation for more info. # # The option COMPILE_FEATURES is a list that is passed to # target_compile_features on all the targets generated by the macro. See the # CMake target_compile_features documentation for more info. # # The option PROPERTIES is a list that is passed to set_target_properties on all # the targets generated by the macro. See the CMake set_target_properties # documentation for more info. # # The option INCLUDE_SUBDIR sets a subdirectory in which the header files listed # in HEADERS should be installed. # # The option OUTPUT_NAME sets the actual name of the produced library. # # The option VERSION sets the library version number on the shared target. # # The option SOVERSION sets the library soversion number on the shared target. # # The option STATIC_ONLY will cause the macro to only create the static library # targets. # # The option SHARED_ONLY will cause the macro to only create the shared library # targets. # # The option OBJECT_LIB_ONLY will cause the macro to only create the object # library targets. macro(sundials_add_library target) set(options STATIC_ONLY SHARED_ONLY OBJECT_LIB_ONLY) set(oneValueArgs INCLUDE_SUBDIR OUTPUT_NAME VERSION SOVERSION) set(multiValueArgs SOURCES HEADERS OBJECT_LIBRARIES LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS COMPILE_OPTIONS COMPILE_FEATURES PROPERTIES) # parse keyword arguments/options cmake_parse_arguments(sundials_add_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # library types to create set(_libtypes "") if(BUILD_STATIC_LIBS AND (NOT sundials_add_library_SHARED_ONLY)) set(_libtypes "STATIC") endif() if(BUILD_SHARED_LIBS AND (NOT sundials_add_library_STATIC_ONLY)) set(_libtypes "${_libtypes};SHARED") endif() foreach(_libtype ${_libtypes}) # library suffix if(${_libtype} MATCHES "STATIC") set(_lib_suffix "${_STATIC_LIB_SUFFIX}") else() set(_lib_suffix "${_SHARED_LIB_SUFFIX}") endif() # source files set(sources ${sundials_add_library_SOURCES}) # give the object library its own target name set(obj_target ${target}_obj${_lib_suffix}) # -------------------------------------------------------------------------- # Create Object library # -------------------------------------------------------------------------- # create the target for the object library add_library(${obj_target} OBJECT ${sources} ${sundials_add_library_UNPARSED_ARGUMENTS}) set_target_properties(${obj_target} PROPERTIES FOLDER "obj") # add all object libraries to object library if(sundials_add_library_OBJECT_LIBRARIES) target_link_libraries(${obj_target} PRIVATE ${sundials_add_library_OBJECT_LIBRARIES}) endif() # add all link libraries to object library if(SUNDIALS_MATH_LIBRARY) target_link_libraries(${obj_target} PRIVATE "${SUNDIALS_MATH_LIBRARY}") endif() if(SUNDIALS_RT_LIBRARY) target_link_libraries(${obj_target} PRIVATE "${SUNDIALS_RT_LIBRARY}") endif() if(sundials_add_library_LINK_LIBRARIES) if(${_libtype} MATCHES "STATIC") append_static_suffix(sundials_add_library_LINK_LIBRARIES _all_libs) else() set(_all_libs ${sundials_add_library_LINK_LIBRARIES}) endif() # Due to various issues in CMake, particularly https://gitlab.kitware.com/cmake/cmake/-/issues/25365, # we create a fake custom target to enforce a build order. Without this, parallel builds # might fail with an error about a missing '.mod' file when Fortran is enabled (see GitHub #410). set(_stripped_all_libs ${_all_libs}) list(FILTER _stripped_all_libs EXCLUDE REGEX "PUBLIC|INTERFACE|PRIVATE") foreach(_item ${_stripped_all_libs}) if(NOT TARGET ${_item}) list(REMOVE_ITEM _stripped_all_libs ${_item}) endif() endforeach() add_custom_target(fake_to_force_build_order_${obj_target}) add_dependencies(fake_to_force_build_order_${obj_target} ${_stripped_all_libs}) add_dependencies(${obj_target} fake_to_force_build_order_${obj_target}) target_link_libraries(${obj_target} ${_all_libs}) endif() if(SUNDIALS_BUILD_WITH_PROFILING) if(ENABLE_CALIPER) target_link_libraries(${obj_target} PUBLIC caliper) endif() if(ENABLE_ADIAK) target_link_libraries(${obj_target} PUBLIC adiak::adiak ${CMAKE_DL_LIBS}) endif() endif() # add includes to object library target_include_directories(${obj_target} PUBLIC $ $ $ $ ) if(sundials_add_library_INCLUDE_DIRECTORIES) string(REPLACE "{{libtype}}" "${_libtype}" _includes "${sundials_add_library_INCLUDE_DIRECTORIES}") target_include_directories(${obj_target} ${_includes}) endif() # add compile definitions to object library for SUNDIALS_EXPORT if(${_libtype} MATCHES "STATIC") target_compile_definitions(${obj_target} PUBLIC SUNDIALS_STATIC_DEFINE) else() target_compile_definitions(${obj_target} PRIVATE sundials_core_EXPORTS) endif() # add all other compile definitions to object library if(sundials_add_library_COMPILE_DEFINITIONS) target_compile_definitions(${obj_target} ${sundials_add_library_COMPILE_DEFINITIONS}) endif() # add compile options to object library if(sundials_add_library_COMPILE_OPTIONS) target_compile_options(${obj_target} ${sundials_add_library_COMPILE_OPTIONS}) endif() # add compile features if(sundials_add_library_COMPILE_FEATURES) target_compile_features(${obj_target} ${sundials_add_library_COMPILE_FEATURES}) endif() # object files going into shared libs need PIC code set_target_properties(${obj_target} PROPERTIES POSITION_INDEPENDENT_CODE TRUE) # set any other properties if(sundials_add_library_PROPERTIES) string(REPLACE "{{libtype}}" "${_libtype}" _properties "${sundials_add_library_PROPERTIES}") set_target_properties(${obj_target} PROPERTIES ${_properties}) endif() # -------------------------------------------------------------------------- # Create Library # -------------------------------------------------------------------------- # now create the real library if(NOT sundials_add_library_OBJECT_LIB_ONLY) # set target name set(_actual_target_name ${target}${_lib_suffix}) set(_object_sources $) if(sundials_add_library_OBJECT_LIBRARIES) if(${_libtype} MATCHES "STATIC") append_static_suffix(sundials_add_library_OBJECT_LIBRARIES _all_objs) else() set(_all_objs ${sundials_add_library_OBJECT_LIBRARIES}) endif() foreach(_tmp ${_all_objs}) list(APPEND _object_sources $) endforeach() endif() add_library(${_actual_target_name} ${_libtype} ${_object_sources} ${sundials_add_library_UNPARSED_ARGUMENTS}) set_target_properties(${_actual_target_name} PROPERTIES FOLDER "src") # add all link libraries if(SUNDIALS_MATH_LIBRARY) target_link_libraries(${_actual_target_name} PRIVATE "${SUNDIALS_MATH_LIBRARY}") endif() if(SUNDIALS_RT_LIBRARY) target_link_libraries(${_actual_target_name} PRIVATE "${SUNDIALS_RT_LIBRARY}") endif() if(sundials_add_library_LINK_LIBRARIES) target_link_libraries(${_actual_target_name} ${sundials_add_library_LINK_LIBRARIES}) endif() if(SUNDIALS_BUILD_WITH_PROFILING) if(ENABLE_CALIPER) target_link_libraries(${_actual_target_name} PUBLIC caliper) endif() if(ENABLE_ADIAK) target_link_libraries(${_actual_target_name} PUBLIC adiak::adiak ${CMAKE_DL_LIBS}) endif() endif() # add common includes # Building: public, config/export generated, and shared private headers # Installing: installed include directory target_include_directories(${_actual_target_name} PUBLIC $ $ $ $ $) # add all other includes if(sundials_add_library_INCLUDE_DIRECTORIES) string(REPLACE "{{libtype}}" "${_libtype}" _includes "${sundials_add_library_INCLUDE_DIRECTORIES}") target_include_directories(${_actual_target_name} ${_includes}) endif() # add compile definitions for SUNDIALS_EXPORT if(${_libtype} MATCHES "STATIC") target_compile_definitions(${_actual_target_name} PUBLIC SUNDIALS_STATIC_DEFINE) else() target_compile_definitions(${obj_target} PRIVATE sundials_core_EXPORTS) endif() # add all other compile definitions if(sundials_add_library_COMPILE_DEFINITIONS) target_compile_definitions(${_actual_target_name} ${sundials_add_library_COMPILE_DEFINITIONS}) endif() # add all compile options if(sundials_add_library_COMPILE_OPTIONS) target_compile_options(${_actual_target_name} ${sundials_add_library_COMPILE_OPTIONS}) endif() # add compile features if(sundials_add_library_COMPILE_FEATURES) target_compile_features(${_actual_target_name} ${sundials_add_library_COMPILE_FEATURES}) endif() # exported targets are in the SUNDIALS:: namespace, so we remove the sundials_ prefix from the exported name string(REPLACE "sundials_" "" _export_name "${_actual_target_name}") set_target_properties(${_actual_target_name} PROPERTIES EXPORT_NAME ${_export_name}) # create an alias to match the exported target name, this way another projects can use it with either find_package() or add_subdirectory() add_library(SUNDIALS::${_export_name} ALIAS ${_actual_target_name}) # set the correct output name if(sundials_add_library_OUTPUT_NAME) if((MSVC OR ("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")) AND ${_libtype} MATCHES "STATIC") set_target_properties(${_actual_target_name} PROPERTIES OUTPUT_NAME "${sundials_add_library_OUTPUT_NAME}_static" CLEAN_DIRECT_OUTPUT 1 ) else() set_target_properties(${_actual_target_name} PROPERTIES OUTPUT_NAME ${sundials_add_library_OUTPUT_NAME} CLEAN_DIRECT_OUTPUT 1 ) endif() else() set_target_properties(${_actual_target_name} PROPERTIES OUTPUT_NAME ${target} CLEAN_DIRECT_OUTPUT 1 ) endif() # set the library versions if(sundials_add_library_VERSION) set_target_properties(${_actual_target_name} PROPERTIES VERSION ${sundials_add_library_VERSION} ) endif() if(sundials_add_library_SOVERSION) set_target_properties(${_actual_target_name} PROPERTIES SOVERSION ${sundials_add_library_SOVERSION} ) endif() # set any other properties if(sundials_add_library_PROPERTIES) string(REPLACE "{{libtype}}" "${_libtype}" _properties "${sundials_add_library_PROPERTIES}") set_target_properties(${_actual_target_name} PROPERTIES ${_properties}) endif() # install phase install(TARGETS ${_actual_target_name} EXPORT sundials-targets) endif() endforeach() # -------------------------------------------------------------------------- # Install header files # -------------------------------------------------------------------------- if(sundials_add_library_HEADERS) install(FILES ${sundials_add_library_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${sundials_add_library_INCLUDE_SUBDIR}") endif() # -------------------------------------------------------------------------- # Aliases to real library names without the suffixes. # -------------------------------------------------------------------------- if(TARGET ${target}_obj${_SHARED_LIB_SUFFIX}) add_library(${target}_obj ALIAS ${target}_obj${_SHARED_LIB_SUFFIX}) if(NOT sundials_add_library_OBJECT_LIB_ONLY) add_library(${target} ALIAS ${target}${_SHARED_LIB_SUFFIX}) set(_SUNDIALS_ALIAS_TARGETS "${target}->${target}${_SHARED_LIB_SUFFIX};${_SUNDIALS_ALIAS_TARGETS}" CACHE INTERNAL "" FORCE) # Namespaced alias for using build directory directly string(REPLACE "sundials_" "" _export_name "${target}") add_library(SUNDIALS::${_export_name} ALIAS ${target}${_SHARED_LIB_SUFFIX}) endif() else() add_library(${target}_obj ALIAS ${target}_obj${_STATIC_LIB_SUFFIX}) if(NOT sundials_add_library_OBJECT_LIB_ONLY) add_library(${target} ALIAS ${target}${_STATIC_LIB_SUFFIX}) set(_SUNDIALS_ALIAS_TARGETS "${target}->${target}${_STATIC_LIB_SUFFIX};${_SUNDIALS_ALIAS_TARGETS}" CACHE INTERNAL "" FORCE) # Namespaced alias for using build directory directly string(REPLACE "sundials_" "" _export_name "${target}") add_library(SUNDIALS::${_export_name} ALIAS ${target}${_STATIC_LIB_SUFFIX}) endif() endif() # -------------------------------------------------------------------------- # List of installed SUNDIALS components # -------------------------------------------------------------------------- if(NOT sundials_add_library_OBJECT_LIB_ONLY) string(REPLACE "sundials_" "" _comp_name "${target}") set(_SUNDIALS_INSTALLED_COMPONENTS "${_comp_name};${_SUNDIALS_INSTALLED_COMPONENTS}" CACHE INTERNAL "" FORCE) endif() endmacro(sundials_add_library) macro(sundials_add_f2003_library target) set(options ) set(oneValueArgs OUTPUT_NAME VERSION SOVERSION) set(multiValueArgs SOURCES OBJECT_LIBRARIES LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS COMPILE_OPTIONS PROPERTIES) # parse keyword arguments/options cmake_parse_arguments(sundials_add_f2003_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(CMAKE_Fortran_MODULE_DIRECTORY) set(_includes PUBLIC $ $ ) set(_properties PROPERTIES Fortran_MODULE_DIRECTORY "${CMAKE_Fortran_MODULE_DIRECTORY}_{{libtype}}" WINDOWS_EXPORT_ALL_SYMBOLS ON) else() set(_includes PUBLIC $ $ ) set(_properties PROPERTIES Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.dir" WINDOWS_EXPORT_ALL_SYMBOLS ON) endif() # get the name of the C library which the fortran library interfaces to string(REPLACE "sundials_f" "sundials_" _clib_name "${target}") string(REPLACE "_mod" "" _clib_name "${_clib_name}") if(TARGET ${_clib_name}) set(_clib_target ${_clib_name}) else() set(_clib_target ) endif() sundials_add_library(${target} SOURCES ${sundials_add_f2003_library_SOURCES} OBJECT_LIBRARIES ${sundials_add_f2003_library_OBJECT_LIBRARIES} LINK_LIBRARIES PUBLIC ${_clib_target} # depend on the c library ${sundials_add_f2003_library_LINK_LIBRARIES} INCLUDE_DIRECTORIES ${sundials_add_f2003_library_INCLUDE_DIRECTORIES} ${_includes} COMPILE_DEFINITIONS ${sundials_add_f2003_library_COMPILE_DEFINITIONS} PUBLIC "SUNDIALS_INT${SUNDIALS_INDEX_SIZE}_T" COMPILE_OPTIONS ${sundials_add_f2003_library_COMPILE_OPTIONS} PROPERTIES ${sundials_add_f2003_library_PROPERTIES} ${_properties} OUTPUT_NAME ${sundials_add_f2003_library_OUTPUT_NAME} VERSION ${sundials_add_f2003_library_VERSION} SOVERSION ${sundials_add_f2003_library_SOVERSION} ${sundials_add_f2003_library_UNPARSED_ARGUMENTS} ) endmacro() macro(append_static_suffix libs_in libs_out) set(${libs_out} "") foreach(_lib ${${libs_in}}) if(TARGET ${_lib}${_STATIC_LIB_SUFFIX}) list(APPEND ${libs_out} ${_lib}${_STATIC_LIB_SUFFIX}) else() list(APPEND ${libs_out} ${_lib}) endif() endforeach() endmacro()