diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..062a117 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.16) + +# =========== SETUP THE PROJECT ============= + +# Initialize the CMake project. +project(Trexio + VERSION 2.0.0 + DESCRIPTION "TREX I/O library" + LANGUAGES C Fortran + ) + +# Request the C99 standard. +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# Optional configure for developer mode to generate source code from org-mode files. +option(TREXIO_DEVEL "TREXIO developer mode (for code generation)." OFF) + +if(EXISTS ".git/config") + set(TREXIO_DEVEL ON) + find_package(Python3 REQUIRED) + if(Python3_FOUND) + if(Python3_VERSION_MINOR LESS 6) + message(FATAL_ERROR "Required Python3 version :: >= 3.6; Found :: ${Python3_VERSION}") + else() + message(STATUS "Python3 version :: ${Python3_VERSION}") + endif() + endif() + find_program(EMACS NAMES emacs REQUIRED) + if(NOT EMACS-NOTFOUND) + message(STATUS "EMACS detected :: ${EMACS}") + else() + message(FATAL_ERROR "EMACS not found. It is required to produce TREXIO source code from org-mode files.") + endif() +endif() + +# Set directories to be included at build time. +include_directories(include) + +# Add subdirectory with add_library(trexio) specifications. +add_subdirectory(src) + +# Add subdirectory with unit tests. +enable_testing() +add_subdirectory(tests) + diff --git a/Makefile.am b/Makefile.am index 3935e1f..98486a8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,6 +76,13 @@ ORG_FILES = \ src_libtrexio_la_SOURCES = $(SOURCES) +# Include CMake-related files in the distribution. +dist_data_DATA = CMakeLists.txt \ + src/CMakeLists.txt \ + tests/CMakeLists.txt \ + cmake/cmake_uninstall.cmake.in \ + cmake/FindTREXIO.cmake + # =============== TESTS =============== # TESTS_C = \ @@ -174,8 +181,8 @@ dist_html_DATA = $(HTML_FILES) $(HTML_TANGLED): $(htmlizer) -html: $(dist_html_DATA) -doc: html +html-local: $(dist_html_DATA) +doc: html-local # =============== DEVELOPER MODE =============== # diff --git a/cmake/FindTREXIO.cmake b/cmake/FindTREXIO.cmake new file mode 100644 index 0000000..9c847a3 --- /dev/null +++ b/cmake/FindTREXIO.cmake @@ -0,0 +1,77 @@ +#=========================================== + +# Try to find TREXIO library; +# If found, it will define the following variables (note the plural form): +# TREXIO_FOUND - System has libtrexio; +# TREXIO_INCLUDE_DIRS - The TREXIO include directories; +# TREXIO_LIBRARIES - The libraries needed to use TREXIO; + +# If TREXIO has been installed in a non-standard location, one can set an +# environment variable $TREXIO_DIR in the current shell: +# $ export TREXIO_DIR= +# to indicate the prefix used during the TREXIO installation +# (typically `./configure prefix= ..` or `cmake -DCMAKE_INSTALL_DIR= ..`) + +# This file should be located WITHIN your project source tree. +# (e.g. in cmake/FindTREXIO.cmake) +# How to use it in your project CMakeLists.txt: + +# This is needed to locate FindTREXIO.cmake file, modify it according to your source tree. +# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/") + +# find_package(TREXIO) +# if (TREXIO_FOUND) +# include_directories(${TREXIO_INCLUDE_DIRS}) +# target_link_libraries(your_target ${TREXIO_LIBRARIES}) +# endif() + +#=========================================== + +# This file is distirbuted under the BSD 3-Clause License. +# Copyright (c) 2021, TREX Center of Excellence + +#=========================================== + +message("") + +set(TREXIO_SEARCH_PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +find_path(TREXIO_INCLUDE_DIR + NAMES trexio.h + HINTS $ENV{TREXIO_DIR} + PATH_SUFFIXES include/trexio include + PATHS ${TREXIO_SEARCH_PATHS} + ) + + +# No need to specify platform-specific prefix (e.g. libtrexio on Unix) or +# suffix (e.g. .so on Unix or .dylib on MacOS) in NAMES. CMake takes care of that. +find_library(TREXIO_LIBRARY + NAMES trexio + HINTS $ENV{TREXIO_DIR} + PATH_SUFFIXES lib64 lib + PATHS ${TREXIO_SEARCH_PATHS} + ) + +message("") + +# Handle the QUIETLY and REQUIRED arguments and set TREXIO_FOUND to TRUE if +# all listed variables are TRUE. +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TREXIO DEFAULT_MSG TREXIO_LIBRARY TREXIO_INCLUDE_DIR ) +MARK_AS_ADVANCED(TREXIO_INCLUDE_DIR TREXIO_LIBRARY) + +# Mot setting _INCLUDE_DIR and _LIBRARIES is considered a bug, +# see https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How-To-Find-Libraries +set(TREXIO_LIBRARIES ${TREXIO_LIBRARY}) +set(TREXIO_INCLUDE_DIRS ${TREXIO_INCLUDE_DIR}) + diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in new file mode 100644 index 0000000..f779906 --- /dev/null +++ b/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,24 @@ +# Needed to make uninstall target in CMake, see the CMake FAQ: +# https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake + +if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") +endif() + +file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif() + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif() +endforeach() diff --git a/configure.ac b/configure.ac index c5f13e2..defb8ba 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,18 @@ AC_PREREQ([2.69]) AC_INIT([trexio],[2.0.0],[https://github.com/TREX-CoE/trexio/issues]) + +AC_CONFIG_SRCDIR([Makefile.in]) +AC_CONFIG_HEADERS([include/config.h]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-config]) + AM_INIT_AUTOMAKE([subdir-objects color-tests parallel-tests silent-rules 1.11]) AM_MAINTAINER_MODE() +AM_PROG_AR + +LT_PREREQ([2.2]) +LT_INIT # Activate developer mode when the source is the git repository. # Otherwise, it is the source distribution and the developer mode should not be activated. @@ -13,13 +23,6 @@ AC_CHECK_FILE([$TEST_IFEXISTS], [enable_maintainer_mode="yes"], ) -AM_MAINTAINER_MODE() -LT_PREREQ([2.2]) -LT_INIT -AC_CONFIG_SRCDIR([Makefile.in]) -AC_CONFIG_HEADERS([include/config.h]) -AC_CONFIG_MACRO_DIR([m4]) - VERSION_MAJOR=`echo ${PACKAGE_VERSION} | cut -d. -f1` VERSION_MINOR=`echo ${PACKAGE_VERSION} | cut -d. -f2` VERSION_PATCH=`echo ${PACKAGE_VERSION} | cut -d. -f3 | cut -d- -f1` @@ -60,7 +63,6 @@ PKG_CFLAGS="" PKG_LIBS="" AC_PROG_INSTALL -AM_PROG_AR AC_PROG_LN_S AC_PROG_GREP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..9e87cd9 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,147 @@ + +# ========= DEFINE TREXIO C LIBRARY ========= + +# Set a list of TREXIO source and header files that are always compiled. +set(TREXIO_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/trexio.c + ${CMAKE_CURRENT_SOURCE_DIR}/trexio_text.c + ) +set(TREXIO_PUBLIC_HEADERS ${CMAKE_SOURCE_DIR}/include/trexio.h) +set(TREXIO_PRIVATE_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/trexio_s.h + ${CMAKE_CURRENT_SOURCE_DIR}/trexio_private.h + ${CMAKE_CURRENT_SOURCE_DIR}/trexio_text.h + ) + +# By default, the shared TREXIO library is built (even without -DBUILD_SHARED_LIBS=ON). +# To change this behaviour, append -DBUILD_STATIC_LIBS=ON to the cmake call. +option(BUILD_SHARED_LIBS "Build the shared library" ON) +option(BUILD_STATIC_LIBS "Build the static library" OFF) + +if(BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS) + set(BUILD_SHARED_LIBS OFF) +endif() + +# Conditional SHARED/STATIC build for TREXIO library. +if(BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) + + message(STATUS "TREXIO :: shared C library will be built") + add_library(trexio SHARED) + +elseif(NOT BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS) + + message(STATUS "TREXIO :: static C library will be built") + add_library(trexio STATIC) + # Static TREXIO has to be compiled with -fPIC flag. For Shared it is done by default. + set_property(TARGET trexio PROPERTY POSITION_INDEPENDENT_CODE ON) + +else() + message(FATAL_ERROR "Building both static and shared TREXIO simultaneously is not supported.") +endif() + +# Set TREXIO version and include files. +set_target_properties(trexio PROPERTIES + VERSION ${PROJECT_VERSION} + PUBLIC_HEADER ${TREXIO_PUBLIC_HEADERS} + ) + +# ============= CONFIGURE HDF5 ============== + +# By defaulti, TREXIO is configured with the HDF5 support. +# To change this, append -DENABLE_HDF5=OFF to the cmake call. +option(ENABLE_HDF5 "Enable HDF5 support" ON) + +if(ENABLE_HDF5) + # Try to detect HDF5 installation using built-in FindHDF5.cmake macro. + find_package(HDF5 REQUIRED COMPONENTS C HL) + + if(HDF5_FOUND) + message(STATUS "HDF5 version :: ${HDF5_VERSION}") + message(STATUS "HDF5 include dir :: ${HDF5_INCLUDE_DIRS}") + else() + # Download and install HDF5 library using FetchContent + # ... + # For now - raise a FATAL_ERROR + message(FATAL_ERROR "HDF5 is enabled but not found.") + endif() + + # If HDF5 found: + # - append the trexio_hdf5.c source file with the HDF5 back end to the list TREXIO_SOURCES + list(APPEND TREXIO_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/trexio_hdf5.c) + list(APPEND TREXIO_PRIVATE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/trexio_hdf5.h) + # - define symbol HAVE_HDF5=1 (used to activate HDF5 back end in the preprocessor conditionals) + target_compile_definitions(trexio PUBLIC "HAVE_HDF5") + # - include directories with HDF5 header files + target_include_directories(trexio PRIVATE ${HDF5_C_INCLUDE_DIRS}) + # - link to HDF5 C libraries + target_link_libraries(trexio PRIVATE + ${HDF5_C_HL_LIBRARIES} + ${HDF5_C_LIBRARIES}) +endif() + +# Private headers have to be listed as sources, otherwise they are installed +# with public headers upon make install (when using PRIVATE_HEADER property). +target_sources(trexio PRIVATE ${TREXIO_SOURCES} ${TREXIO_PRIVATE_HEADERS}) + +# ============= FORTRAN SUPPORT ============== + +include(FortranCInterface) +# Check that C and Fortran compilers can talk to each other. +FortranCInterface_VERIFY() + +# Fortran module +set(TREXIO_MOD_FILE ${CMAKE_SOURCE_DIR}/include/trexio_f.f90) +# Add TREXIO Fortran module as a library. +add_library(trexio_f SHARED) +target_sources(trexio_f PUBLIC ${TREXIO_MOD_FILE}) +target_link_libraries(trexio_f PUBLIC trexio) + +# ====== CODE GENERATION FOR DEVEL MODE ===== + +if(TREXIO_DEVEL) + set(ORG_FILES + templates_front/templator_front.org + templates_text/templator_text.org + ${CMAKE_SOURCE_DIR}/trex.org + ) + if(ENABLE_HDF5) + list(APPEND ORG_FILES templates_hdf5/templator_hdf5.org) + endif() + + add_custom_command(OUTPUT + ${TREXIO_SOURCES} + ${TREXIO_PUBLIC_HEADERS} + ${TREXIO_PRIVATE_HEADERS} + ${TREXIO_MOD_FILE} + COMMAND ./build_trexio.sh + DEPENDS ${ORG_FILES} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tools + COMMENT "Generating TREXIO source code from org-mode files." + VERBATIM) +endif() + +# ============= INSTALL TREXIO ============== + +include(GNUInstallDirs) +# Use standard GNU directories for installation of TREXIO (e.g. /usr/local/lib|include). +# The installation prefix can be modified using -DCMAKE_INSTALL_PREFIX= option of cmake. +install(TARGETS trexio + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) +# Also install trexio_f.f90 file with TREXIO Fortran module. +install(FILES ${TREXIO_MOD_FILE} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Uninstall target, copied from CMake FAQ: +# https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif() + +# =========================================== diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..cf2d896 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,46 @@ + +# ================= TESTING ================= + +# Create a list of tests for TEXT back end. +set(Tests_text + open_text + io_dset_float_text + io_dset_str_text + io_safe_dset_float_text + io_dset_int_text + io_num_text + io_str_text + overwrite_all_text + ) + +if(ENABLE_HDF5) +# Create a list of tests for HDF5 back end. + set(Tests_hdf5 + open_hdf5 + io_dset_float_hdf5 + io_dset_str_hdf5 + io_safe_dset_float_hdf5 + io_dset_int_hdf5 + io_num_hdf5 + io_str_hdf5 + overwrite_all_hdf5 + ) + +# Set ${Tests} variable to the complete list of tests. + set(Tests io_all ${Tests_text} ${Tests_hdf5}) +else() + set(Tests ${Tests_text}) +endif() + +# Compile each TREXIO test as an executable and add them to CTest using add_test. +foreach(Test ${Tests}) + add_executable(${Test} ${Test}.c) + target_link_libraries(${Test} PRIVATE trexio) + add_test(NAME ${Test} COMMAND $) +endforeach() + +# Add Fortran test and link it with trexio_f (Fortran module) library. +add_executable(test_f test_f.f90) +target_link_libraries(test_f PRIVATE trexio_f) +add_test(NAME test_f COMMAND $) + diff --git a/tools/trexio.scm b/tools/trexio.scm new file mode 100644 index 0000000..5f8deb9 --- /dev/null +++ b/tools/trexio.scm @@ -0,0 +1,34 @@ +(define-module (gnu packages trexio) + #:use-module (guix packages) + #:use-module (gnu packages pkg-config) + #:use-module (gnu packages glib) + #:use-module (gnu packages gcc) + #:use-module (gnu packages autotools) + #:use-module (gnu packages maths) + #:use-module (guix download) + #:use-module (guix build-system gnu) + #:use-module (guix licenses)) + +(define-public trexio + (package + (name "trexio") + (version "2.0") + (source (origin + (method url-fetch) + (uri (string-append "https://github.com/TREX-CoE/trexio/releases/download/v" version + "/trexio-" version ".0" + ".tar.gz")) + (sha256 + (base32 + "1d2cn4w2r9gfid5b9wrq9q290kqdnbjdmvli76s1i5r58kdg5vkf" + )))) + (build-system gnu-build-system) + (arguments '(#:configure-flags '("--enable-silent-rules"))) + (inputs `(("hdf5" ,hdf5-1.12) ("gfortran", gfortran))) + (synopsis "TREX I/O lbrary: trexio package") + (description "APIs in C and Fortran to exchange wavefunction data. + Supports HDF5 and TEXT back ends.") + (home-page "https://trex-coe.github.io/trexio") + (license bsd-3))) + +trexio