diff --git a/CMakeLists.txt b/CMakeLists.txt index 719edc2a649a6dc2a1611b18ac7c942d034abca0..fefaff5543624bce21429b4367b16ed5f65f5ba2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") option(ENABLE_EXTRAE "Enable Extrae" OFF) option(ENABLE_DLB "Enable DLB" OFF) option(BUILD_C_FORTRAN "Enable C and Fortran Interfaces" ON) +option(GEN_BINDINGS "Use Shroud to Generate C/Fortran interface" OFF) add_library(sit SHARED) set(SIT_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include) @@ -26,6 +27,13 @@ target_include_directories(sit PUBLIC #set_target_properties(sit PROPERTIES PUBLIC_HEADER "${SIT_PUBLIC_HEADERS}") +if(BUILD_C_FORTRAN) + enable_language(Fortran) + set(CMAKE_Fortran_FORMAT FREE) + set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod) + add_library(sit_f) + add_library(sit::sit_f ALIAS sit_f) +endif() add_subdirectory(src) @@ -54,6 +62,8 @@ install(TARGETS sit sit_f PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sit INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sit ) + install(FILES ${CMAKE_Fortran_MODULE_DIRECTORY}/sit_mod.mod DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + else() install(TARGETS sit @@ -64,10 +74,11 @@ install(TARGETS sit PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sit INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sit ) -install(FILES ${SIT_PUBLIC_HEADERS}/sit/sit.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sit) + endif() +install(FILES ${SIT_PUBLIC_HEADERS}/sit/sit.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sit) # Export the Targets to install install(EXPORT sitTargets diff --git a/README.md b/README.md index 9e7f280e993c669c13d08dd8c6bf2da8a3ba2d76..74f35f56a5d1cfb3c9cce5caa54dcc86566a063b 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,34 @@ Also some backends require finalization, so please make sure to also call `final To add it to your code, currently just install it and use something similar to: `-I/include -L-I/lib -lsit` in the compiler options +## Fortran + +How to configure and install: + +1. `cmake .. -DCMAKE_INSTALL_PREFIX= -DBUILD_C_FORTRAN=ON` +2. `make install` + +### How to use + +```fortran +program test + use sit_mod + call init("Default") + call region_start("test") + call region_stop("test") + call finalize() + end program test +``` + + + +You **must** call `init` exactly once to init the datastructures before you can use the other functionality. +Also some backends require finalization, so please make sure to also call `finalize` in the end. + +To add it to your code, currently just install it and use something similar to: +`gfortran -I.//include .f90 -o /lib/libsit_f.a /lib/libsit.so` in the compiler of your choice. + + # Backends ## DLB diff --git a/src/bindings/CMakeLists.txt b/src/bindings/CMakeLists.txt index 69845ae9d2d656df3a8d557f8a61c8f408d83039..838d67563b708987f34aba9c8e7053c8b42706ae 100644 --- a/src/bindings/CMakeLists.txt +++ b/src/bindings/CMakeLists.txt @@ -1,34 +1,34 @@ -if(EXISTS ${SHROUD_EXECUTABLE}) - execute_process(COMMAND ${SHROUD_EXECUTABLE} - --cmake ${CMAKE_CURRENT_BINARY_DIR}/SetupShroud.cmake - ERROR_VARIABLE SHROUD_cmake_error - OUTPUT_STRIP_TRAILING_WHITESPACE ) - if(${SHROUD_cmake_error}) - message(FATAL_ERROR "Error from Shroud: ${SHROUD_cmake_error}") +if(GEN_BINDINGS) + if(EXISTS ${SHROUD_EXECUTABLE}) + execute_process(COMMAND ${SHROUD_EXECUTABLE} + --cmake ${CMAKE_CURRENT_BINARY_DIR}/SetupShroud.cmake + ERROR_VARIABLE SHROUD_cmake_error + OUTPUT_STRIP_TRAILING_WHITESPACE ) + if(${SHROUD_cmake_error}) + message(FATAL_ERROR "Error from Shroud: ${SHROUD_cmake_error}") + endif() + include(${CMAKE_CURRENT_BINARY_DIR}/SetupShroud.cmake) + + # Generate the headers + add_shroud( + YAML_INPUT_FILE sit.yaml + ) + else() + message(FATAL_ERROR "Cannot build Fortran and C bindings without -DSHROUD_EXECUTABLE specified") endif() - include(${CMAKE_CURRENT_BINARY_DIR}/SetupShroud.cmake) - add_shroud( - YAML_INPUT_FILE sit.yaml - C_FORTRAN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} - ) - - set_source_files_properties(wrap${_basename}.cpp PROPERTIES GENERATED TRUE) - set_source_files_properties(wrapf${_basename}.f PROPERTIES GENERATED TRUE) - set(CMAKE_Fortran_FORMAT FREE) - list (APPEND SIT_PUBLIC_HEADERS "${LIB_INC}") +endif() - - add_library(${_basename}_f wrapf${_basename}.f wrap${_basename}.cpp ${LIB_SRC}) +target_sources(sit_f PRIVATE wrapfsit.f) +target_sources(sit PRIVATE wrapsit.cpp) +#set( CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) +#set_source_files_properties(wrapsit.cpp PROPERTIES GENERATED TRUE) +#set_source_files_properties(wrapfsit.f PROPERTIES GENERATED TRUE) + +target_include_directories(sit_f PRIVATE ${SIT_PUBLIC_HEADERS}) +set_target_properties(sit_f PROPERTIES LINKER_LANGUAGE Fortran) +#set_target_properties(st_f PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +#set_target_properties(sit_f PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}) - target_include_directories(${_basename}_f PRIVATE ${SIT_PUBLIC_HEADERS}) - - set_target_properties(${_basename}_f PROPERTIES LINKER_LANGUAGE Fortran) - set_target_properties(${_basename}_f PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - set_target_properties(${_basename}_f PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/include) - add_dependencies(${_basename}_f generate_${_basename}) -else() -message(FATAL_ERROR "Cannot build Fortran and C bindings without -DSHROUD_EXECUTABLE specified") -endif() diff --git a/src/bindings/typessit.h b/src/bindings/typessit.h new file mode 100644 index 0000000000000000000000000000000000000000..5cac70495673e5c947f5b126ac0cd889ca381bc7 --- /dev/null +++ b/src/bindings/typessit.h @@ -0,0 +1,31 @@ +// typessit.h +// This file is generated by Shroud 0.13.0. Do not edit. +// For C users and C++ implementation + +#ifndef TYPESSIT_H +#define TYPESSIT_H + +// splicer begin types.CXX_declarations +// splicer end types.CXX_declarations + +#ifdef __cplusplus +extern "C" { +#endif + +// splicer begin types.C_declarations +// splicer end types.C_declarations + +// helper capsule_data_helper +struct s_sit_SHROUD_capsule_data { + void *addr; /* address of C++ memory */ + int idtor; /* index of destructor */ +}; +typedef struct s_sit_SHROUD_capsule_data sit_SHROUD_capsule_data; + +void sit_SHROUD_memory_destructor(sit_SHROUD_capsule_data *cap); + +#ifdef __cplusplus +} +#endif + +#endif // TYPESSIT_H diff --git a/src/bindings/utilsit.cpp b/src/bindings/utilsit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5e48998ca552f810e8ab4a9523e81c66c1770fd --- /dev/null +++ b/src/bindings/utilsit.cpp @@ -0,0 +1,20 @@ +// utilsit.cpp +// This file is generated by Shroud 0.13.0. Do not edit. + +#include "typessit.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// Release library allocated memory. +void sit_SHROUD_memory_destructor(sit_SHROUD_capsule_data *cap) +{ + cap->addr = nullptr; + cap->idtor = 0; // avoid deleting again +} + +#ifdef __cplusplus +} +#endif diff --git a/src/bindings/wrapfsit.f b/src/bindings/wrapfsit.f new file mode 100644 index 0000000000000000000000000000000000000000..0b6d712ee30a32463477cf7a30ca516b948bbe51 --- /dev/null +++ b/src/bindings/wrapfsit.f @@ -0,0 +1,108 @@ +! wrapfsit.f +! This file is generated by Shroud 0.13.0. Do not edit. +!> +!! \file wrapfsit.f +!! \brief Shroud generated wrapper for sit namespace +!< +! splicer begin file_top +! splicer end file_top +module sit_mod + ! splicer begin module_use + ! splicer end module_use + implicit none + + ! splicer begin module_top + ! splicer end module_top + + interface + + subroutine c_init(backend) & + bind(C, name="sit_init") + use iso_c_binding, only : C_CHAR + implicit none + character(kind=C_CHAR), intent(IN) :: backend(*) + end subroutine c_init + + subroutine c_init_bufferify(backend, SHT_backend_len) & + bind(C, name="sit_init_bufferify") + use iso_c_binding, only : C_CHAR, C_INT + implicit none + character(kind=C_CHAR), intent(IN) :: backend(*) + integer(C_INT), value, intent(IN) :: SHT_backend_len + end subroutine c_init_bufferify + + subroutine c_region_start(name) & + bind(C, name="sit_region_start") + use iso_c_binding, only : C_CHAR + implicit none + character(kind=C_CHAR), intent(IN) :: name(*) + end subroutine c_region_start + + subroutine c_region_start_bufferify(name, SHT_name_len) & + bind(C, name="sit_region_start_bufferify") + use iso_c_binding, only : C_CHAR, C_INT + implicit none + character(kind=C_CHAR), intent(IN) :: name(*) + integer(C_INT), value, intent(IN) :: SHT_name_len + end subroutine c_region_start_bufferify + + subroutine c_region_stop(name) & + bind(C, name="sit_region_stop") + use iso_c_binding, only : C_CHAR + implicit none + character(kind=C_CHAR), intent(IN) :: name(*) + end subroutine c_region_stop + + subroutine c_region_stop_bufferify(name, SHT_name_len) & + bind(C, name="sit_region_stop_bufferify") + use iso_c_binding, only : C_CHAR, C_INT + implicit none + character(kind=C_CHAR), intent(IN) :: name(*) + integer(C_INT), value, intent(IN) :: SHT_name_len + end subroutine c_region_stop_bufferify + + subroutine finalize() & + bind(C, name="sit_finalize") + implicit none + end subroutine finalize + end interface + + ! splicer begin additional_declarations + ! splicer end additional_declarations + +contains + + subroutine init(backend) + use iso_c_binding, only : C_INT + character(len=*), intent(IN) :: backend + ! splicer begin function.init + integer(C_INT) SHT_backend_len + SHT_backend_len = len(backend, kind=C_INT) + call c_init_bufferify(backend, SHT_backend_len) + ! splicer end function.init + end subroutine init + + subroutine region_start(name) + use iso_c_binding, only : C_INT + character(len=*), intent(IN) :: name + ! splicer begin function.region_start + integer(C_INT) SHT_name_len + SHT_name_len = len(name, kind=C_INT) + call c_region_start_bufferify(name, SHT_name_len) + ! splicer end function.region_start + end subroutine region_start + + subroutine region_stop(name) + use iso_c_binding, only : C_INT + character(len=*), intent(IN) :: name + ! splicer begin function.region_stop + integer(C_INT) SHT_name_len + SHT_name_len = len(name, kind=C_INT) + call c_region_stop_bufferify(name, SHT_name_len) + ! splicer end function.region_stop + end subroutine region_stop + + ! splicer begin additional_functions + ! splicer end additional_functions + +end module sit_mod diff --git a/src/bindings/wrapsit.cpp b/src/bindings/wrapsit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..681c08a9c9514f4f3f52cc81aec780f6dff7fbdd --- /dev/null +++ b/src/bindings/wrapsit.cpp @@ -0,0 +1,90 @@ +// wrapsit.cpp +// This file is generated by Shroud 0.13.0. Do not edit. + +#include "sit/sit.hpp" +#include +#include "wrapsit.h" + +// splicer begin CXX_definitions +// splicer end CXX_definitions + +extern "C" { + + +// helper ShroudLenTrim +// Returns the length of character string src with length nsrc, +// ignoring any trailing blanks. +static int ShroudLenTrim(const char *src, int nsrc) { + int i; + + for (i = nsrc - 1; i >= 0; i--) { + if (src[i] != ' ') { + break; + } + } + + return i + 1; +} + +// splicer begin C_definitions +// splicer end C_definitions + +void sit_init(const char * backend) +{ + // splicer begin function.init + const std::string SHCXX_backend(backend); + sit::init(SHCXX_backend); + // splicer end function.init +} + +void sit_init_bufferify(char *backend, int SHT_backend_len) +{ + // splicer begin function.init_bufferify + const std::string SHCXX_backend(backend, + ShroudLenTrim(backend, SHT_backend_len)); + sit::init(SHCXX_backend); + // splicer end function.init_bufferify +} + +void sit_region_start(const char * name) +{ + // splicer begin function.region_start + const std::string SHCXX_name(name); + sit::region_start(SHCXX_name); + // splicer end function.region_start +} + +void sit_region_start_bufferify(char *name, int SHT_name_len) +{ + // splicer begin function.region_start_bufferify + const std::string SHCXX_name(name, + ShroudLenTrim(name, SHT_name_len)); + sit::region_start(SHCXX_name); + // splicer end function.region_start_bufferify +} + +void sit_region_stop(const char * name) +{ + // splicer begin function.region_stop + const std::string SHCXX_name(name); + sit::region_stop(SHCXX_name); + // splicer end function.region_stop +} + +void sit_region_stop_bufferify(char *name, int SHT_name_len) +{ + // splicer begin function.region_stop_bufferify + const std::string SHCXX_name(name, + ShroudLenTrim(name, SHT_name_len)); + sit::region_stop(SHCXX_name); + // splicer end function.region_stop_bufferify +} + +void sit_finalize(void) +{ + // splicer begin function.finalize + sit::finalize(); + // splicer end function.finalize +} + +} // extern "C" diff --git a/src/bindings/wrapsit.h b/src/bindings/wrapsit.h new file mode 100644 index 0000000000000000000000000000000000000000..ce1dc6944a481a95fbc4f20409edef165a0d498d --- /dev/null +++ b/src/bindings/wrapsit.h @@ -0,0 +1,42 @@ +// wrapsit.h +// This file is generated by Shroud 0.13.0. Do not edit. +/** + * \file wrapsit.h + * \brief Shroud generated wrapper for sit namespace + */ +// For C users and C++ implementation + +#ifndef WRAPSIT_H +#define WRAPSIT_H + +#include "typessit.h" + +// splicer begin CXX_declarations +// splicer end CXX_declarations + +#ifdef __cplusplus +extern "C" { +#endif + +// splicer begin C_declarations +// splicer end C_declarations + +void sit_init(const char * backend); + +void sit_init_bufferify(char *backend, int SHT_backend_len); + +void sit_region_start(const char * name); + +void sit_region_start_bufferify(char *name, int SHT_name_len); + +void sit_region_stop(const char * name); + +void sit_region_stop_bufferify(char *name, int SHT_name_len); + +void sit_finalize(void); + +#ifdef __cplusplus +} +#endif + +#endif // WRAPSIT_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f5d1e18fd1ae040c601f8591640582f0305e8bfa..5641c326d49670c9832b3a4a41b79b6a51635971 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,14 +35,7 @@ if(BUILD_C_FORTRAN) add_executable(TestFortranLink fortran/TestFortranModule.f90) target_link_libraries(TestFortranLink sit sit_f) target_include_directories(TestFortranLink - PRIVATE ${SIT_PUBLIC_HEADERS}) - - message(STATUS ${SIT_PUBLIC_HEADERS}) - - target_include_directories(TestFortranLink - PRIVATE ${CMAKE_BINARY_DIR}/include) - - + PRIVATE ${CMAKE_Fortran_MODULE_DIRECTORY}) add_test(NAME TestFortranLink COMMAND TestFortranLink)