From ed0d8ce65334882dd15a20f2837e23a7986b5810 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Thu, 13 Feb 2020 14:06:30 +0100 Subject: [PATCH] added rudimentary CMake support --- CMakeLists.txt | 98 +++++++++++++++++ FindFFTW3.cmake | 232 ++++++++++++++++++++++++++++++++++++++++ src/main.cc | 27 +++-- src/region_generator.cc | 2 +- version.cmake | 51 +++++++++ 5 files changed, 401 insertions(+), 9 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 FindFFTW3.cmake create mode 100644 version.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..36e6de8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,98 @@ +cmake_minimum_required(VERSION 3.9) +set(PRGNAME MUSIC) +project(MUSIC) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -march=native -Wall -pedantic -DCMAKE_BUILD") +find_package(PkgConfig REQUIRED) + +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}") + +######################################################################################################################## +# Add a custom command that produces version.cc, plus +# a dummy output that's not actually produced, in order +# to force version.cmake to always be re-run before the build +ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.cc + ${CMAKE_CURRENT_BINARY_DIR}/_version.cc + COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_SOURCE_DIR}/version.cmake) + +######################################################################################################################## +# OpenMP +find_package(OpenMP REQUIRED) +if(OPENMP_FOUND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") +endif() + +######################################################################################################################## +# Pthreads +find_package(Threads REQUIRED) + +######################################################################################################################## +# FFTW +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() +if(ENABLE_MPI) + find_package(FFTW3 COMPONENTS SINGLE DOUBLE OPENMP THREADS MPI) +else() + find_package(FFTW3 COMPONENTS SINGLE DOUBLE OPENMP THREADS) +endif(ENABLE_MPI) + +######################################################################################################################## +# GSL +find_package(GSL REQUIRED) + +######################################################################################################################## +# HDF5 +find_package(HDF5) + +######################################################################################################################## +# INCLUDES +include_directories(${PROJECT_SOURCE_DIR}/src) + +# SOURCES +# get all the *.cc files in the subfolders +file( GLOB SOURCES + ${PROJECT_SOURCE_DIR}/src/*.cc +) +# add the auto generated version file +list (APPEND SOURCES "${CMAKE_CURRENT_BINARY_DIR}/version.cc") + +# PLUGINS +# get all the *.cc files in the plugin subfolder +file( GLOB PLUGINS + ${PROJECT_SOURCE_DIR}/src/plugins/*.cc +) + +add_executable(${PRGNAME} ${SOURCES} ${PLUGINS}) + +set_target_properties(${PRGNAME} PROPERTIES CXX_STANDARD 11) + +if(FFTW3_FOUND) + target_compile_options(${PRGNAME} PRIVATE "-DFFTW3") +endif(FFTW3_FOUND) + +if(FFTW3_DOUBLE_THREADS_FOUND) + target_link_libraries(${PRGNAME} ${FFTW3_DOUBLE_THREADS_LIBRARY}) + target_compile_options(${PRGNAME} PRIVATE "-DUSE_FFTW_THREADS") +endif(FFTW3_DOUBLE_THREADS_FOUND) + +if(HDF5_FOUND) + # target_link_libraries(${PRGNAME} ${HDF5_C_LIBRARY_DIRS}) + target_link_libraries(${PRGNAME} ${HDF5_LIBRARIES}) + target_include_directories(${PRGNAME} PRIVATE ${HDF5_INCLUDE_DIRS}) + target_compile_options(${PRGNAME} PRIVATE "-DHAVE_HDF5") + target_compile_options(${PRGNAME} PRIVATE "-DH5_USE_16_API") +endif(HDF5_FOUND) + +target_link_libraries(${PRGNAME} ${FFTW3_LIBRARIES}) +target_include_directories(${PRGNAME} PRIVATE ${FFTW3_INCLUDE_DIRS}) + +target_link_libraries(${PRGNAME} ${GSL_LIBRARIES}) +target_include_directories(${PRGNAME} PRIVATE ${GSL_INCLUDE_DIR}) + +target_link_libraries(${PRGNAME} ${HDF5_LIBRARIES}) +target_include_directories(${PRGNAME} PRIVATE ${HDF5_INCLUDE_DIR}) diff --git a/FindFFTW3.cmake b/FindFFTW3.cmake new file mode 100644 index 0000000..0c65570 --- /dev/null +++ b/FindFFTW3.cmake @@ -0,0 +1,232 @@ +# - Try to find FFTW +# +# By default, it will look only for the serial libraries with single, double, +# and long double precision. Any combination of precision (SINGLE, DOUBLE, +# LONGDOUBLE) and library type (SERIAL, [THREADS|OPENMP], MPI) is possible by +# using the COMPONENTS keyword. For example, +# +# find_package(FFTW3 COMPONENTS SINGLE DOUBLE OPENMP MPI) +# +# Once done this will define +# FFTW3_FOUND - System has FFTW3 +# FFTW3_INCLUDE_DIRS - The FFTW3 include directories +# FFTW3_LIBRARIES - The libraries needed to use FFTW3 +# FFTW3_DEFINITIONS - Compiler switches required for using FFTW3 +# FFTW3_$KIND_$PARALLEL_FOUND- Set if FFTW3 exists in KIND precision format for PARALLEL mode. +# where KIND can be: SINGLE, DOUBLE, LONGDOUBLE +# and PARALLEL: SERIAL, OPENMP, MPI, THREADS. +# FFTW3_$KIND_$PARALLEL_LIBRARY - The libraries needed to use. +# FFTW3_INCLUDE_DIR_PARALLEL - The FFTW3 include directories for parallels mode. + +cmake_policy(SET CMP0054 NEW) + +if(FFTW3_FOUND) + return() +endif() + +if(FFTW3_INCLUDE_DIR AND FFTW3_LIBRARIES) + set(FFTW3_FOUND TRUE) + foreach(component ${FFTW3_FIND_COMPONENTS}) + if("${FFTW3_${component}_LIBRARY}" STREQUAL "") + set(FFTW3_${component}_LIBRARY "${FFTW3_LIBRARIES}") + endif() + endforeach() + return() +endif() + +macro(find_specific_libraries KIND PARALLEL) + list(APPEND FFTW3_FIND_COMPONENTS ${KIND}_${PARALLEL}) + if(NOT (${PARALLEL} STREQUAL "SERIAL") AND NOT ${PARALLEL}_FOUND) + message(FATAL_ERROR "Please, find ${PARALLEL} libraries before FFTW") + endif() + + find_library(FFTW3_${KIND}_${PARALLEL}_LIBRARY NAMES + fftw3${SUFFIX_${KIND}}${SUFFIX_${PARALLEL}}${SUFFIX_FINAL} HINTS ${HINT_DIRS}) + if(FFTW3_${KIND}_${PARALLEL}_LIBRARY MATCHES fftw3) + list(APPEND FFTW3_LIBRARIES ${FFTW3_${KIND}_${PARALLEL}_LIBRARY}) + set(FFTW3_${KIND}_${PARALLEL}_FOUND TRUE) + + STRING(TOLOWER "${KIND}" kind) + STRING(TOLOWER "${PARALLEL}" parallel) + if(FFTW3_${kind}_${parallel}_LIBRARY MATCHES "\\.a$") + add_library(fftw3::${kind}::${parallel} STATIC IMPORTED GLOBAL) + else() + add_library(fftw3::${kind}::${parallel} SHARED IMPORTED GLOBAL) + endif() + + # MPI Has a different included library than the others + # FFTW3_INCLUDE_DIR_PARALLEL will change depending of which on is used. + set(FFTW3_INCLUDE_DIR_PARALLEL ${FFTW3_INCLUDE_DIR} ) + if(PARALLEL STREQUAL "MPI") + set(FFTW3_INCLUDE_DIR_PARALLEL ${FFTW3_${PARALLEL}_INCLUDE_DIR}) + endif() + + set_target_properties(fftw3::${kind}::${parallel} PROPERTIES + IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}") + + # adding target properties to the different cases + ## MPI + if(PARALLEL STREQUAL "MPI") + if(MPI_C_LIBRARIES) + set_target_properties(fftw3::${kind}::mpi PROPERTIES + IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}" + IMPORTED_LINK_INTERFACE_LIBRARIES "${MPI_C_LIBRARIES}") + endif() + endif() + ## OpenMP + if(PARALLEL STREQUAL "OPENMP") + if(OPENMP_C_FLAGS) + set_target_properties(fftw3::${kind}::${parallel} PROPERTIES + IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}" + INTERFACE_COMPILE_OPTIONS "${OPENMP_C_FLAGS}") + endif() + endif() + ## THREADS + if(PARALLEL STREQUAL "THREADS") + if(CMAKE_THREAD_LIBS_INIT) # TODO: this is not running + set_target_properties(fftw3::${kind}::${parallel} PROPERTIES + IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}" + INTERFACE_COMPILE_OPTIONS "${CMAKE_THREAD_LIBS_INIT}") + endif() + endif() + endif() +endmacro() + + + + +if(NOT FFTW3_FIND_COMPONENTS) + set(FFTW3_FIND_COMPONENTS SINGLE DOUBLE LONGDOUBLE SERIAL) +endif() + +string(TOUPPER "${FFTW3_FIND_COMPONENTS}" FFTW3_FIND_COMPONENTS) + +list(FIND FFTW3_FIND_COMPONENTS SINGLE LOOK_FOR_SINGLE) +list(FIND FFTW3_FIND_COMPONENTS DOUBLE LOOK_FOR_DOUBLE) +list(FIND FFTW3_FIND_COMPONENTS LONGDOUBLE LOOK_FOR_LONGDOUBLE) +list(FIND FFTW3_FIND_COMPONENTS THREADS LOOK_FOR_THREADS) +list(FIND FFTW3_FIND_COMPONENTS OPENMP LOOK_FOR_OPENMP) +list(FIND FFTW3_FIND_COMPONENTS MPI LOOK_FOR_MPI) +list(FIND FFTW3_FIND_COMPONENTS SERIAL LOOK_FOR_SERIAL) + +# FIXME - This may fail in computers wihtout serial +# Default serial to obtain version number +set(LOOK_FOR_SERIAL 1) + +# set serial as default if none parallel component has been set +if((LOOK_FOR_THREADS LESS 0) AND (LOOK_FOR_MPI LESS 0) AND + (LOOK_FOR_OPENMP LESS 0)) + set(LOOK_FOR_SERIAL 1) +endif() + +if(MPI_C_FOUND) + set(MPI_FOUND ${MPI_C_FOUND}) +endif() +unset(FFTW3_FIND_COMPONENTS) + + + + +if(WIN32) + set(HINT_DIRS ${FFTW3_DIRECTORY} $ENV{FFTW3_DIRECTORY}) +else() + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_FFTW QUIET fftw3) + set(FFTW3_DEFINITIONS ${PC_FFTW3_CFLAGS_OTHER}) + endif() + set(HINT_DIRS ${PC_FFTW3_INCLUDEDIR} ${PC_FFTW3_INCLUDE_DIRS} + ${FFTW3_INCLUDE_DIR} $ENV{FFTW3_INCLUDE_DIR} ) +endif() + +find_path(FFTW3_INCLUDE_DIR NAMES fftw3.h HINTS ${HINT_DIRS}) +if (LOOK_FOR_MPI) # Probably is going to be the same as fftw3.h + find_path(FFTW3_MPI_INCLUDE_DIR NAMES fftw3-mpi.h HINTS ${HINT_DIRS}) +endif() + +function(find_version OUTVAR LIBRARY SUFFIX) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fftw${SUFFIX}/main.c + # TODO: do we need to add include for mpi headers? + "#include + #include + int main(int nargs, char const *argv[]) { + printf(\"%s\", fftw${SUFFIX}_version); + return 0; + }" + ) +if(NOT CMAKE_CROSSCOMPILING) + try_run(RUN_RESULT COMPILE_RESULT + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fftw${SUFFIX}/" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fftw${SUFFIX}/main.c" + CMAKE_FLAGS + -DLINK_LIBRARIES=${LIBRARY} + -DINCLUDE_DIRECTORIES=${FFTW3_INCLUDE_DIR} + RUN_OUTPUT_VARIABLE OUTPUT + COMPILE_OUTPUT_VARIABLE COUTPUT + ) + endif() + if(RUN_RESULT EQUAL 0) + string(REGEX REPLACE + ".*([0-9]+\\.[0-9]+\\.[0-9]+).*" + "\\1" VERSION_STRING "${OUTPUT}" + ) + set(${OUTVAR} ${VERSION_STRING} PARENT_SCOPE) + endif() +endfunction() + +set(SUFFIX_DOUBLE "") +set(SUFFIX_SINGLE "f") +set(SUFFIX_LONGDOUBLE "l") +set(SUFFIX_SERIAL "") +set(SUFFIX_OPENMP "_omp") +set(SUFFIX_MPI "_mpi") +set(SUFFIX_THREADS "_threads") +set(SUFFIX_FINAL "") + +if(WIN32) + set(SUFFIX_FINAL "-3") +else() + set(HINT_DIRS ${PC_FFTW3_LIBDIR} ${PC_FFTW3_LIBRARY_DIRS} + $ENV{FFTW3_LIBRARY_DIR} ${FFTW3_LIBRARY_DIR} ) +endif(WIN32) + +unset(FFTW3_LIBRARIES) +set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR} ) # TODO what's for? +set(FFTW3_FLAGS_C "") +foreach(KIND SINGLE DOUBLE LONGDOUBLE) + if(LOOK_FOR_${KIND} LESS 0) + continue() + endif() + foreach(PARALLEL SERIAL MPI OPENMP THREADS) + if(LOOK_FOR_${PARALLEL} LESS 0) + continue() + endif() + find_specific_libraries(${KIND} ${PARALLEL}) + endforeach() +endforeach() + +if(FFTW3_INCLUDE_DIR) + list(GET FFTW3_FIND_COMPONENTS 0 smallerrun) + string(REPLACE "_" ";" RUNLIST ${smallerrun}) + list(GET RUNLIST 0 KIND) + list(GET RUNLIST 1 PARALLEL) + unset(smallerrun) + unset(RUNLIST) + # suffix is quoted so it pass empty in the case of double as it's empty + find_version(FFTW3_VERSION_STRING ${FFTW3_${KIND}_${PARALLEL}_LIBRARY} + "${SUFFIX_${KIND}}") +endif() + +# FIXME: fails if use REQUIRED. +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set FFTW3_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(FFTW3 + REQUIRED_VARS FFTW3_LIBRARIES FFTW3_INCLUDE_DIR + VERSION_VAR FFTW3_VERSION_STRING + HANDLE_COMPONENTS +) diff --git a/src/main.cc b/src/main.cc index b118c3d..81362ac 100644 --- a/src/main.cc +++ b/src/main.cc @@ -18,7 +18,14 @@ #include #include - +#if defined(CMAKE_BUILD) + extern "C" + { + extern const char* GIT_TAG; + extern const char* GIT_REV; + extern const char* GIT_BRANCH; + } +#endif #include "general.hh" #include "defaults.hh" @@ -75,14 +82,18 @@ void splash(void) { std::cout - << "\n __ __ __ __ ______ __ ______ \n" - << " /\\ \"-./ \\ /\\ \\/\\ \\ /\\ ___\\ /\\ \\ /\\ ___\\ \n" - << " \\ \\ \\-./\\ \\ \\ \\ \\_\\ \\ \\ \\___ \\ \\ \\ \\ \\ \\ \\____ \n" - << " \\ \\_\\ \\ \\_\\ \\ \\_____\\ \\/\\_____\\ \\ \\_\\ \\ \\_____\\ \n" - << " \\/_/ \\/_/ \\/_____/ \\/_____/ \\/_/ \\/_____/ \n\n" - << " this is " << THE_CODE_NAME << " version " << THE_CODE_VERSION << "\n\n\n"; - + << "\n __ __ __ __ ______ __ ______ \n" + << " /\\ \"-./ \\ /\\ \\/\\ \\ /\\ ___\\ /\\ \\ /\\ ___\\ \n" + << " \\ \\ \\-./\\ \\ \\ \\ \\_\\ \\ \\ \\___ \\ \\ \\ \\ \\ \\ \\____ \n" + << " \\ \\_\\ \\ \\_\\ \\ \\_____\\ \\/\\_____\\ \\ \\_\\ \\ \\_____\\ \n" + << " \\/_/ \\/_/ \\/_____/ \\/_____/ \\/_/ \\/_____/ \n\n" + << " this is " << THE_CODE_NAME << " version " << THE_CODE_VERSION << "\n\n"; + + #if defined(CMAKE_BUILD) + LOGINFO("Version built from git rev.: %s, tag: %s, branch: %s\n", GIT_REV, GIT_TAG, GIT_BRANCH); + #endif + std::cout << "\n\n"; } void modify_grid_for_TF( const refinement_hierarchy& rh_full, refinement_hierarchy& rh_TF, config_file& cf ) diff --git a/src/region_generator.cc b/src/region_generator.cc index 6402744..518bbbb 100644 --- a/src/region_generator.cc +++ b/src/region_generator.cc @@ -102,7 +102,7 @@ public: }else if( pcf_->containsKey("setup","ref_dims") ){ temp = pcf_->getValue("setup","ref_dims"); std::remove_if(temp.begin(),temp.end(),isspace); - if(sscanf( temp.c_str(), "%ld,%ld,%ld", &lnref_[0],&lnref_[1],&lnref_[2] )!=3){ + if(sscanf( temp.c_str(), "%lu,%lu,%lu", &lnref_[0],&lnref_[1],&lnref_[2] )!=3){ LOGERR("Error parsing triple for ref_dims"); throw std::runtime_error("Error parsing triple for ref_dims"); } diff --git a/version.cmake b/version.cmake new file mode 100644 index 0000000..5162ec7 --- /dev/null +++ b/version.cmake @@ -0,0 +1,51 @@ +# CMake script to get git repository version at compile time +# taken from Matt Keeter's blog and slightly adapted +# https://www.mattkeeter.com/blog/2018-01-06-versioning/ + +execute_process(COMMAND git log --pretty=format:'%h' -n 1 + OUTPUT_VARIABLE GIT_REV + ERROR_QUIET) + +# Check whether we got any revision (which isn't +# always the case, e.g. when someone downloaded a zip +# file from Github instead of a checkout) +if ("${GIT_REV}" STREQUAL "") + set(GIT_REV "N/A") + set(GIT_DIFF "") + set(GIT_TAG "N/A") + set(GIT_BRANCH "N/A") +else() + execute_process( + COMMAND bash -c "git diff --quiet --exit-code || echo +" + OUTPUT_VARIABLE GIT_DIFF) + execute_process( + COMMAND git describe --exact-match --tags + OUTPUT_VARIABLE GIT_TAG ERROR_QUIET) + execute_process( + COMMAND git rev-parse --abbrev-ref HEAD + OUTPUT_VARIABLE GIT_BRANCH) + + string(STRIP "${GIT_REV}" GIT_REV) + string(SUBSTRING "${GIT_REV}" 1 7 GIT_REV) + string(STRIP "${GIT_DIFF}" GIT_DIFF) + string(STRIP "${GIT_TAG}" GIT_TAG) + string(STRIP "${GIT_BRANCH}" GIT_BRANCH) +endif() + +if("${GIT_TAG}" STREQUAL "") + set(GIT_TAG "N/A") +endif() + +set(VERSION "const char* GIT_REV=\"${GIT_REV}${GIT_DIFF}\"; +const char* GIT_TAG=\"${GIT_TAG}\"; +const char* GIT_BRANCH=\"${GIT_BRANCH}\";") + +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/version.cc) + file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.cc VERSION_) +else() + set(VERSION_ "") +endif() + +if (NOT "${VERSION}" STREQUAL "${VERSION_}") + file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/version.cc "${VERSION}") +endif() \ No newline at end of file