diff --git a/.travis.yml b/.travis.yml index 60b929f48..cb8f49f7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ python: script: - cd bld; ./cvmix_setup gfortran $(dirname $(dirname $(which nc-config))) - cd ../CVMix_tools; ./run_test_suite.sh --already-ran-setup + - cd ../reg_tests/Bryan-Lewis/; ./Bryan-Lewis-test.sh --cmake branches: only: diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..ee9a1e8a5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required( VERSION 3.9 ) + +project( cvmix VERSION 4.0.1 LANGUAGES Fortran ) + +# Use solution folders in IDEs +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +# Use standard GNU installation directories +if ( NOT WIN32 ) + include( GNUInstallDirs ) +endif() + +# Configuration options +option( CVMIX_USE_NetCDF "Enable NetCDF format" OFF ) +if(CVMIX_USE_NetCDF) + add_compile_definitions(_NETCDF) + include_directories($ENV{NetCDF_INCLUDE}) +endif(CVMIX_USE_NetCDF) +option( CVMIX_BUILD_STATIC_LIBS "Build static library" ON ) +option( CVMIX_BUILD_SHARED_LIBS "Build shared library" ON ) +option( CVMIX_BUILD_DRIVER "Build CVMix example/test driver" OFF ) + +# Check if shared or static builds are turned off +if( NOT CVMIX_BUILD_STATIC_LIBS ) + message( STATUS "Turning STATIC builds OFF" ) +endif() +if( NOT CVMIX_BUILD_SHARED_LIBS ) + message( STATUS "Turning SHARED builds OFF" ) +endif() + +# Set default build type to Release if not specified +if( NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE ) + message( STATUS "Setting default build type to 'Release'. Set CMAKE_BUILD_TYPE variable to change build types." ) + set_property( CACHE CMAKE_BUILD_TYPE PROPERTY VALUE "Release" ) +endif() + +set( CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules ) +set( CMAKE_POSITION_INDEPENDENT_CODE ON ) + +add_subdirectory( src ) + +# Note - KB: +# Building static and shared libs require an ugly construct to build on both +# Windows and Linux. Windows will not create the libraries unless a Fortran +# file is explicitly given - and Linux complains (I think due to a race +# condition) if it is. Therefor the construct below - a proper solution is +# most welcome. + +# Add static lib target +if( CVMIX_BUILD_STATIC_LIBS ) + if ( WIN32 ) + add_library( cvmix_static STATIC ${CMAKE_SOURCE_DIR}/src/dummy.F90 $ ) + else() + add_library( cvmix_static STATIC $ ) + endif() + list( APPEND LIB_TARGETS cvmix_static ) +endif() + +# Add shared lib target +if( CVMIX_BUILD_SHARED_LIBS ) + if ( WIN32 ) + add_library( cvmix_shared SHARED ${CMAKE_SOURCE_DIR}/src/dummy.F90 $ ) + else() + add_library( cvmix_shared SHARED $ ) + endif() + list( APPEND LIB_TARGETS cvmix_shared ) +endif() + +# Set common lib target properties +foreach( _lib IN LISTS LIB_TARGETS ) + target_compile_definitions( ${_lib} PUBLIC "${PUBLIC_FLAGS}" ) + target_include_directories( ${_lib} + PUBLIC + $ + PRIVATE + $ ) + set_target_properties( ${_lib} PROPERTIES OUTPUT_NAME cvmix) +endforeach() + +if(CVMIX_BUILD_DRIVER) + + add_executable( cvmix_driver . ) + target_sources( cvmix_driver PRIVATE src/cvmix_driver.F90 ) + set_property( TARGET cvmix_driver PROPERTY FOLDER driver ) + target_include_directories( cvmix_driver PRIVATE ${CMAKE_BINARY_DIR}/modules ) + target_link_libraries( cvmix_driver PRIVATE cvmix_drivers ) + +endif() + +# Install +if(CVMIX_BUILD_DRIVER) +install( TARGETS cvmix_driver EXPORT cvmixConfig + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) +endif() +install( TARGETS ${LIB_TARGETS} EXPORT cvmixConfig + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +install( DIRECTORY ${CMAKE_BINARY_DIR}/modules/ EXPORT cvmixConfig + DESTINATION include/cvmix + FILES_MATCHING + PATTERN "*.mod" ) +install(EXPORT cvmixConfig DESTINATION cmake) + diff --git a/README.md b/README.md index bb35506a8..78af0d981 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,12 @@ goes into details about how to contribute, but basically we ask three things: INSTALLATION NOTES ------------------ +CVMix can be installed using two different methods. The original uses Make +and a set of Makefiles. The new method uses CMake and two CMakelists.txt +files. + +#### Building/installing using Make + The src directory contains a Makefile and a simple 'make' should be sufficient to build the standalone driver. The first time you build, the 'cvmix_setup' utility will run and prompt you for compiler and netcdf information - it will @@ -58,6 +64,52 @@ $ make FC=[compiler] \ And then use -I$(INC_DIR) -L$(LIB_DIR) -lcvmix when you build software using the CVMix library. +#### Building/installing using CMake + +[CMake](https://cmake.org/) can be used in GUI mode. Further information can +be found on the CMake web-page. Below is provided the command line commands +to configure and compile CVMix. Note that CVMix has been build on Windows using +VisualStudio and the Intel Fortran compiler but NetCDF support has not been +tested. + +1. cd $CVMix/bld/cmake_bld + * [CMake](https://cmake.org/) promotes out of source compilation, + any such directory will do. +2. cmake $CVMix + * The simplest configuration - using default Fortran compiler +3. cmake $CVMix -DCMAKE\_Fortran\_COMPILER=ifort + * Specifying a Fortran compiler +4. cmake $CVMix -DCVMIX\_BUILD\_DRIVER=on + * Build the CVMix driver program - off by default +5. cmake $CVMix -DCVMIX\_BUILD\_DRIVER=on CVMIX\_USE\_NetCDF=on + * Include support for NetCDF in the driver model(1) + * Note that this requires proper configuration of the installed NetCDF library. + * Setting NetCDF\_INCLUDE and NetCDF\_LIBRARIES might help. +6. cmake $CVMix -DCMAKE\_INSTALL\_PREFIX=$CVMix/bin + * Providing an installation folder (again, any such directory will do) + +Combination of the above commands is possible. + +After configuration has been done compilation is as simple as: + +``` +make +``` + +and installation by: + +``` +make install +``` + +After installation the build directory can be removed. + +The support for CMake builds provides sufficient infrastructure for CVMix +being included in ocean models using the GIT submodule feature. This has +been used in the [GOTM](https:/gotm.net) inclusion of the CVMix mixing +models as a supplement to the original turbulence models in GOTM. + +1): There is unfortunately not an official NetCDF module finder in CMake. DIRECTORY STRUCTURE ------------------- @@ -65,7 +117,7 @@ DIRECTORY STRUCTURE bin/ -- Default location for the cvmix executable. bld/ -- Contains auxiliary files needed by the build system. CompileFlags.mak - has default compile flags for 5 different compilers -- gfortran, + has default compile flags for 5 different compilers -- gfortran, pgf90, ifort, xlf90, and nagfor, as well as ftn (the Cray wrapper for pgf90). At this time, no other compilers are supported on Cray systems. cvmix_setup is a python script that saves information about what @@ -179,7 +231,7 @@ src/ -- Contains the source code, organized as follows. The top directory src/drivers/ -- Subroutines called by the driver (one per test). - src/shared/ -- Where all the modules that are needed to use CVMix with an + src/shared/ -- Where all the modules that are needed to use CVMix with an outside model are stored. Also contains the Makefile used to build the libcvmix.a library. diff --git a/bld/cmake_bld/.gitignore b/bld/cmake_bld/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/bld/cmake_bld/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/cmake_bin/.gitignore b/cmake_bin/.gitignore new file mode 100644 index 000000000..01319b51b --- /dev/null +++ b/cmake_bin/.gitignore @@ -0,0 +1,4 @@ +bin +include +lib +cmake diff --git a/reg_tests/common/build.sh b/reg_tests/common/build.sh index 200be0e6d..32e5896fb 100644 --- a/reg_tests/common/build.sh +++ b/reg_tests/common/build.sh @@ -2,8 +2,20 @@ build () { if [ -z ${NO_BUILD} ]; then - make -f $CVMix/src/Makefile CVMIX_ROOT=$CVMix ${USE_NETCDF} - if [ $? != 0 ]; then + if [ "${CMAKE_BUILD}" == "TRUE" ]; then + CWD=$PWD + cd $CVMix/bld/cmake_bld + cmake $CVMix -DCVMIX_BUILD_DRIVER=on \ + -DCMAKE_Fortran_COMPILER=gfortran \ + -DCMAKE_INSTALL_PREFIX=$CVMix/cmake_bin \ + && make && make install + STATUS=$? + cd $CWD + else + make -f $CVMix/src/Makefile CVMIX_ROOT=$CVMix ${USE_NETCDF} + STATUS=$? + fi + if [ $STATUS != 0 ]; then echo "Build error!" exit 2 fi @@ -12,7 +24,7 @@ build () { if [ "`cat ../../bld/.netcdf_info`" == "YES" ]; then USE_NETCDF=netcdf fi - fi + fi fi } diff --git a/reg_tests/common/parse_inputs.sh b/reg_tests/common/parse_inputs.sh index c62a9f0a5..100a6e3d2 100644 --- a/reg_tests/common/parse_inputs.sh +++ b/reg_tests/common/parse_inputs.sh @@ -43,6 +43,9 @@ while [ $# -gt 0 ]; do bad_input $1 fi ;; + -cm|--cmake) + CMAKE_BUILD=TRUE + ;; * ) bad_input $1 ;; diff --git a/reg_tests/common/run.sh b/reg_tests/common/run.sh index ed279dc29..db0e89ee5 100644 --- a/reg_tests/common/run.sh +++ b/reg_tests/common/run.sh @@ -2,7 +2,12 @@ run () { - $CVMix/bin/cvmix < $NAMELIST + if [ "${CMAKE_BUILD}" == "TRUE" ]; then + CVMIX_EXE=$CVMix/cmake_bin/bin/cvmix_driver + else + CVMIX_EXE=$CVMix/bin/cvmix + fi + ${CVMIX_EXE} < $NAMELIST if [ $? != 0 ]; then echo "Error in execution!" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 000000000..b456cd394 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,41 @@ +# CVMix library +add_library(cvmix_objects OBJECT .) +set_property( TARGET cvmix_objects PROPERTY FOLDER cvmixlib ) +target_sources( cvmix_objects PRIVATE + shared/cvmix_kinds_and_types.F90 + shared/cvmix_background.F90 + shared/cvmix_convection.F90 + shared/cvmix_ddiff.F90 + shared/cvmix_kpp.F90 + shared/cvmix_math.F90 + shared/cvmix_put_get.F90 + shared/cvmix_shear.F90 + shared/cvmix_tidal.F90 + shared/cvmix_utils.F90 +) + +#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cvmix_version.F90.in ${CMAKE_CURRENT_BINARY_DIR}/cvmix_version.F90) + +# CVMix driver dependencies +if(CVMIX_BUILD_DRIVER) + + add_library(cvmix_io STATIC .) + set_property( TARGET cvmix_io PROPERTY FOLDER driver ) + target_sources( cvmix_io PRIVATE + cvmix_io.F90 + ) +# target_link_libraries(cvmix_io PRIVATE cvmix_static PUBLIC netcdff ) + target_link_libraries(cvmix_io PRIVATE cvmix_static PUBLIC $ENV{NetCDF_LIBRARIES} ) + + add_library(cvmix_drivers STATIC .) + set_property( TARGET cvmix_drivers PROPERTY FOLDER driver ) + target_sources( cvmix_drivers PRIVATE + drivers/cvmix_bgrnd_BL.F90 + drivers/cvmix_ddiff_drv.F90 + drivers/cvmix_kpp_drv.F90 + drivers/cvmix_shear_drv.F90 + drivers/cvmix_tidal_Simmons.F90 + ) + target_link_libraries( cvmix_drivers PRIVATE cvmix_io ) + +endif() diff --git a/src/dummy.F90 b/src/dummy.F90 new file mode 100644 index 000000000..3ddf711b8 --- /dev/null +++ b/src/dummy.F90 @@ -0,0 +1,5 @@ +! This file is needed to compile the driver program using VisualStudio. +! This is a known issue when building static/dynamic libraries based on +! object library. +! VisualStudio requires an explicit listed Fortran file to make the +! libraries - even if it is empty.