├── CHANGELOG.md ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake └── Modules │ ├── FindOpenMP_Fortran.cmake │ ├── SetCompileFlag.cmake │ ├── SetFortranFlags.cmake │ ├── SetParallelizationLibrary.cmake │ └── SetUpLAPACK.cmake ├── distclean.cmake └── src ├── bar ├── CMakeLists.txt └── bar.f90 └── foo ├── CMakeLists.txt ├── constants.f90 └── foo.f90 /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | [1.0.0] - 2013-01-16 2 | --- 3 | 4 | - Inital template 5 | 6 | 7 | [1.0.0]: https://github.com/SethMMorton/cmake_fortran_template/releases/tag/1.0.0 8 | 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake project file for FOO 2 | 3 | ################################################## 4 | # Define the project and the depencies that it has 5 | ################################################## 6 | 7 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5) 8 | PROJECT(FOO Fortran) 9 | 10 | # Set the FOO version 11 | SET(VERSION 1.2.3) 12 | 13 | # Add our local modlues to the module path 14 | SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/") 15 | 16 | # Uncomment if it is required that Fortran 90 is supported 17 | #IF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) 18 | # MESSAGE(FATAL_ERROR "Fortran compiler does not support F90") 19 | #ENDIF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) 20 | 21 | # Set some options the user may choose 22 | # Uncomment the below if you want the user to choose a parallelization library 23 | #OPTION(USE_MPI "Use the MPI library for parallelization" OFF) 24 | #OPTION(USE_OPENMP "Use OpenMP for parallelization" OFF) 25 | 26 | # This INCLUDE statement executes code that sets the compile flags for DEBUG, 27 | # RELEASE, and TESTING. You should review this file and make sure the flags 28 | # are to your liking. 29 | INCLUDE(${CMAKE_MODULE_PATH}/SetFortranFlags.cmake) 30 | # Locate and set parallelization libraries. There are some CMake peculiarities 31 | # taken care of here, such as the fact that the FindOpenMP routine doesn't know 32 | # about Fortran. 33 | #INCLUDE(${CMAKE_MODULE_PATH}/SetParallelizationLibrary.cmake) 34 | # Setup the LAPACK libraries. This also takes care of peculiarities, such as 35 | # the fact the searching for MKL requires a C compiler, and that the results 36 | # are not stored in the cache. 37 | #INCLUDE(${CMAKE_MODULE_PATH}/SetUpLAPACK.cmake) 38 | 39 | # There is an error in CMAKE with this flag for pgf90. Unset it 40 | GET_FILENAME_COMPONENT(FCNAME ${CMAKE_Fortran_COMPILER} NAME) 41 | IF(FCNAME STREQUAL "pgf90") 42 | UNSET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS) 43 | ENDIF(FCNAME STREQUAL "pgf90") 44 | 45 | ############################################################ 46 | # Define the actual files and folders that make up the build 47 | ############################################################ 48 | 49 | # Define the executable name 50 | SET(FOOEXE foo) 51 | 52 | # Define the library name 53 | SET(BARLIB bar) 54 | 55 | # Define some directories 56 | SET(SRC ${CMAKE_SOURCE_DIR}/src) 57 | SET(LIB ${CMAKE_SOURCE_DIR}/lib) 58 | SET(BIN ${CMAKE_SOURCE_DIR}/bin) 59 | SET(SRCFOO ${SRC}/foo) 60 | SET(SRCBAR ${SRC}/bar) 61 | 62 | # Have the .mod files placed in the lib folder 63 | SET(CMAKE_Fortran_MODULE_DIRECTORY ${LIB}) 64 | 65 | # The source for the BAR library and have it placed in the lib folder 66 | ADD_SUBDIRECTORY(${SRCBAR} ${LIB}) 67 | 68 | # The source for the FOO binary and have it placed in the bin folder 69 | ADD_SUBDIRECTORY(${SRCFOO} ${BIN}) 70 | 71 | # Add a distclean target to the Makefile 72 | ADD_CUSTOM_TARGET(distclean 73 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/distclean.cmake 74 | ) 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Seth M. Morton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **NOTE** I no longer actively code in Fortran, nor use nor do I any longer actively use CMake. However, I do not want this repository to become a dead resource. If you have found that information in this template is out-of-date, or if there are better ways to approach 2 | solving these problems, *please* make a pull request. 3 | 4 | # CMake Fortran Template # 5 | 6 | I have found there is a dirth of information about how to create Fortran projects with CMake on the web. For this reason, I have created a template project for Fortran using CMake as the build system. 7 | 8 | ## The directory structure ## 9 | 10 | CMakeLists.txt 11 | README.md 12 | bin/ 13 | cmake/ 14 | Modules/ 15 | FindOpenMP_Fortran.cmake 16 | SetCompileFlag.cmake 17 | SetFortranFlags.cmake 18 | SetParallelizationLibrary.cmake 19 | SetUpLAPACK.cmake 20 | distclean.cmake 21 | lib/ 22 | src/ 23 | foo/ 24 | CMakeLists.txt 25 | foo.f90 26 | constants.f90 27 | bar/ 28 | CMakeLists.txt 29 | bar.f90 30 | 31 | ### CMakeLists.txt ### 32 | 33 | This file contains all the boilerplate that you will need to set up your program. Pretty much all you will need to edit in this file is the name of the project/program and uncomment any lines pertaining to options you may need. 34 | 35 | ### distclean.cmake ### 36 | 37 | This is a CMake script that will remove all files and folder that are created after running `make`. You can run this code in one of two ways: 38 | 39 | * Execute `cmake -P distclean.cmake`. (The `-P` option to `cmake` will execute a CMake script) 40 | * Execute `make distclean` after your Makefile has been generated. 41 | 42 | You shouldn't need to edit this file. 43 | 44 | ### cmake/Modules/ ### 45 | 46 | This directory contains CMake scripts that aid in configuring the build system. 47 | 48 | ###### FindOpenMP_Fortran.cmake ###### 49 | 50 | The `FindOpenMP.cmake` file that comes with CMake does not have support for Fortran compilers. This file finds the correct OpenMP flags for many Fortran compilers. 51 | 52 | ###### SetCompileFlag.cmake ###### 53 | 54 | This file defines a function that will test a set of compiler flags to see which one works and adds that flag to a list of compiler flags. This is used to set compile flags when you don't know which compiler will be used. 55 | 56 | ###### SetFortranFlags.cmake ###### 57 | 58 | This file uses the function from `SetCompilerFlag.cmake` to set the DEBUG, TESTING, and RELEASE compile flags for your build. You might want to inspect this file and edit the flags to your liking. 59 | 60 | ###### SetParallelizationLibrary.cmake ###### 61 | 62 | This file takes care of locating OpenMP or MPI as well as issues with switching between the two. 63 | 64 | ###### SetUpLAPACK.cmake ###### 65 | 66 | This file takes care of some oddities with CMake related to setting up LAPACK, such as the fact that the LAPACK variables are not saved to the cache, and that finding MKL requires a C compiler. 67 | 68 | ### src/ ### 69 | 70 | This directory contains the source for your project. In this project example, there is a library (in `bar/`) and the executable itself (in `foo/`). Each of these subdirectories contains a `CMakeLists.txt`. 71 | 72 | ###### bar/CMakeLists.txt ###### 73 | 74 | All that is contained in this file is a list of the source files for the library bar and a statement that these sources should be compiled to a library. You will need to edit the source list (and the `STATIC` modifier to `SHARED` if you want a shared library instead of static.). 75 | 76 | ###### foo/CMakeLists.txt ###### 77 | 78 | This file contains the sources for the foo executable. It also specifies that this executable must link to the bar library. You will need to edit the source list (and whether or not there are libraries to link to). There is commented code related to parallelization and LAPACK that you may uncomment if required. 79 | 80 | ### bin/ and lib/ ### 81 | 82 | These folders are created after running `make`. Any libraries created end up in `lib/`, as well as compiled Fortran `.mod` files. The executable will end up in `bin/`. 83 | 84 | ## Configuring the build ## 85 | 86 | It is usually preferred that you do an out-of-source build. To do this, create a `build/` directory at the top level of your project and build there. 87 | 88 | $ mkdir build 89 | $ cd build 90 | $ cmake .. 91 | $ make 92 | 93 | When you do this, temporary CMake files will not be created in your `src/` directory. 94 | 95 | As written, this template will allow you to specify one of three different sets of compiler flags. The default is RELEASE. You can change this using to TESTING or DEBUG using 96 | 97 | $ cmake .. -DCMAKE_BUILD_TYPE=DEBUG 98 | 99 | or 100 | 101 | $ cmake .. -DCMAKE_BUILD_TYPE=TESTING 102 | 103 | There are also options you may uncomment to add support for OpenMP or MPI. To use these, use 104 | 105 | $ cmake .. -DUSE_OPENMP=ON 106 | 107 | or 108 | 109 | $ cmake .. -DUSE_MPI=ON 110 | 111 | Of course, you can also edit the template so that OpenMP or MPI is always used. 112 | 113 | ## History ## 114 | 115 | Please see the [CHANGELOG.md](https://github.com/SethMMorton/cmake_fortran_template/blob/master/CHANGELOG.md) in this repository for how this template has changed over time. 116 | -------------------------------------------------------------------------------- /cmake/Modules/FindOpenMP_Fortran.cmake: -------------------------------------------------------------------------------- 1 | # - Finds OpenMP support 2 | # This module can be used to detect OpenMP support in a compiler. 3 | # If the compiler supports OpenMP, the flags required to compile with 4 | # openmp support are set. 5 | # 6 | # This module was modified from the standard FindOpenMP module to find Fortran 7 | # flags. 8 | # 9 | # The following variables are set: 10 | # OpenMP_Fortran_FLAGS - flags to add to the Fortran compiler for OpenMP 11 | # support. In general, you must use these at both 12 | # compile- and link-time. 13 | # OMP_NUM_PROCS - the max number of processors available to OpenMP 14 | 15 | #============================================================================= 16 | # Copyright 2009 Kitware, Inc. 17 | # Copyright 2008-2009 André Rigland Brodtkorb 18 | # 19 | # Distributed under the OSI-approved BSD License (the "License"); 20 | # see accompanying file Copyright.txt for details. 21 | # 22 | # This software is distributed WITHOUT ANY WARRANTY; without even the 23 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 24 | # See the License for more information. 25 | #============================================================================= 26 | # (To distribute this file outside of CMake, substitute the full 27 | # License text for the above reference.) 28 | 29 | INCLUDE (${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) 30 | 31 | SET (OpenMP_Fortran_FLAG_CANDIDATES 32 | #Microsoft Visual Studio 33 | "/openmp" 34 | #Intel windows 35 | "/Qopenmp" 36 | #Intel 37 | "-openmp" 38 | #Gnu 39 | "-fopenmp" 40 | #Empty, if compiler automatically accepts openmp 41 | " " 42 | #Sun 43 | "-xopenmp" 44 | #HP 45 | "+Oopenmp" 46 | #IBM XL C/c++ 47 | "-qsmp" 48 | #Portland Group 49 | "-mp" 50 | ) 51 | 52 | IF (DEFINED OpenMP_Fortran_FLAGS) 53 | SET (OpenMP_Fortran_FLAG_CANDIDATES) 54 | ENDIF (DEFINED OpenMP_Fortran_FLAGS) 55 | 56 | # check fortran compiler. also determine number of processors 57 | FOREACH (FLAG ${OpenMP_Fortran_FLAG_CANDIDATES}) 58 | SET (SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") 59 | SET (CMAKE_REQUIRED_FLAGS "${FLAG}") 60 | UNSET (OpenMP_FLAG_DETECTED CACHE) 61 | MESSAGE (STATUS "Try OpenMP Fortran flag = [${FLAG}]") 62 | FILE (WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranOpenMP.f90" 63 | " 64 | program TestOpenMP 65 | use omp_lib 66 | write(*,'(I2)',ADVANCE='NO') omp_get_num_procs() 67 | end program TestOpenMP 68 | ") 69 | SET (MACRO_CHECK_FUNCTION_DEFINITIONS 70 | "-DOpenMP_FLAG_DETECTED ${CMAKE_REQUIRED_FLAGS}") 71 | TRY_RUN (OpenMP_RUN_FAILED OpenMP_FLAG_DETECTED ${CMAKE_BINARY_DIR} 72 | ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranOpenMP.f90 73 | COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} 74 | CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} 75 | COMPILE_OUTPUT_VARIABLE OUTPUT 76 | RUN_OUTPUT_VARIABLE OMP_NUM_PROCS_INTERNAL) 77 | IF (OpenMP_FLAG_DETECTED) 78 | FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 79 | "Determining if the Fortran compiler supports OpenMP passed with " 80 | "the following output:\n${OUTPUT}\n\n") 81 | SET (OpenMP_FLAG_DETECTED 1) 82 | IF (OpenMP_RUN_FAILED) 83 | MESSAGE (FATAL_ERROR "OpenMP found, but test code did not run") 84 | ENDIF (OpenMP_RUN_FAILED) 85 | SET (OMP_NUM_PROCS ${OMP_NUM_PROCS_INTERNAL} CACHE 86 | STRING "Number of processors OpenMP may use" FORCE) 87 | SET (OpenMP_Fortran_FLAGS_INTERNAL "${FLAG}") 88 | BREAK () 89 | ELSE () 90 | FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 91 | "Determining if the Fortran compiler supports OpenMP failed with " 92 | "the following output:\n${OUTPUT}\n\n") 93 | SET (OpenMP_FLAG_DETECTED 0) 94 | ENDIF (OpenMP_FLAG_DETECTED) 95 | ENDFOREACH (FLAG ${OpenMP_Fortran_FLAG_CANDIDATES}) 96 | 97 | SET (OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_INTERNAL}" 98 | CACHE STRING "Fortran compiler flags for OpenMP parallization") 99 | 100 | # handle the standard arguments for FIND_PACKAGE 101 | FIND_PACKAGE_HANDLE_STANDARD_ARGS (OpenMP_Fortran DEFAULT_MSG 102 | OpenMP_Fortran_FLAGS) 103 | 104 | MARK_AS_ADVANCED(OpenMP_Fortran_FLAGS) 105 | -------------------------------------------------------------------------------- /cmake/Modules/SetCompileFlag.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Given a list of flags, this function will try each, one at a time, 3 | # and choose the first flag that works. If no flags work, then nothing 4 | # will be set, unless the REQUIRED key is given, in which case an error 5 | # will be given. 6 | # 7 | # Call is: 8 | # SET_COMPILE_FLAG(FLAGVAR FLAGVAL (Fortran|C|CXX) flag1 flag2...) 9 | # 10 | # For example, if you have the flag CMAKE_C_FLAGS and you want to add 11 | # warnings and want to fail if this is not possible, you might call this 12 | # function in this manner: 13 | # SET_COMPILE_FLAGS(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" C REQUIRED 14 | # "-Wall" # GNU 15 | # "-warn all" # Intel 16 | # ) 17 | # The optin "-Wall" will be checked first, and if it works, will be 18 | # appended to the CMAKE_C_FLAGS variable. If it doesn't work, then 19 | # "-warn all" will be tried. If this doesn't work then checking will 20 | # terminate because REQUIRED was given. 21 | # 22 | # The reasong that the variable must be given twice (first as the name then 23 | # as the value in quotes) is because of the way CMAKE handles the passing 24 | # of variables in functions; it is difficult to extract a variable's 25 | # contents and assign new values to it from within a function. 26 | ############################################################################# 27 | 28 | INCLUDE(${CMAKE_ROOT}/Modules/CheckCCompilerFlag.cmake) 29 | INCLUDE(${CMAKE_ROOT}/Modules/CheckCXXCompilerFlag.cmake) 30 | 31 | FUNCTION(SET_COMPILE_FLAG FLAGVAR FLAGVAL LANG) 32 | 33 | # Do some up front setup if Fortran 34 | IF(LANG STREQUAL "Fortran") 35 | # Create a list of error messages from compilers 36 | SET(FAIL_REGEX 37 | "ignoring unknown option" # Intel 38 | "invalid argument" # Intel 39 | "unrecognized .*option" # GNU 40 | "[Uu]nknown switch" # Portland Group 41 | "ignoring unknown option" # MSVC 42 | "warning D9002" # MSVC, any lang 43 | "[Uu]nknown option" # HP 44 | "[Ww]arning: [Oo]ption" # SunPro 45 | "command option .* is not recognized" # XL 46 | ) 47 | ENDIF(LANG STREQUAL "Fortran") 48 | 49 | # Make a variable holding the flags. Filter out REQUIRED if it is there 50 | SET(FLAG_REQUIRED FALSE) 51 | SET(FLAG_FOUND FALSE) 52 | UNSET(FLAGLIST) 53 | FOREACH (var ${ARGN}) 54 | STRING(TOUPPER "${var}" UP) 55 | IF(UP STREQUAL "REQUIRED") 56 | SET(FLAG_REQUIRED TRUE) 57 | ELSE() 58 | SET(FLAGLIST ${FLAGLIST} "${var}") 59 | ENDIF(UP STREQUAL "REQUIRED") 60 | ENDFOREACH (var ${ARGN}) 61 | 62 | # Now, loop over each flag 63 | FOREACH(flag ${FLAGLIST}) 64 | 65 | UNSET(FLAG_WORKS) 66 | # Check the flag for the given language 67 | IF(LANG STREQUAL "C") 68 | CHECK_C_COMPILER_FLAG("${flag}" FLAG_WORKS) 69 | ELSEIF(LANG STREQUAL "CXX") 70 | CHECK_CXX_COMPILER_FLAG("${flag}" FLAG_WORKS) 71 | ELSEIF(LANG STREQUAL "Fortran") 72 | # There is no nice function to do this for FORTRAN, so we must manually 73 | # create a test program and check if it compiles with a given flag. 74 | SET(TESTFILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}") 75 | SET(TESTFILE "${TESTFILE}/CMakeTmp/testFortranFlags.f90") 76 | FILE(WRITE "${TESTFILE}" 77 | " 78 | program dummyprog 79 | i = 5 80 | end program dummyprog 81 | ") 82 | TRY_COMPILE(FLAG_WORKS ${CMAKE_BINARY_DIR} ${TESTFILE} 83 | COMPILE_DEFINITIONS "${flag}" OUTPUT_VARIABLE OUTPUT) 84 | 85 | # Check that the output message doesn't match any errors 86 | FOREACH(rx ${FAIL_REGEX}) 87 | IF("${OUTPUT}" MATCHES "${rx}") 88 | SET(FLAG_WORKS FALSE) 89 | ENDIF("${OUTPUT}" MATCHES "${rx}") 90 | ENDFOREACH(rx ${FAIL_REGEX}) 91 | 92 | ELSE() 93 | MESSAGE(FATAL_ERROR "Unknown language in SET_COMPILE_FLAGS: ${LANG}") 94 | ENDIF(LANG STREQUAL "C") 95 | 96 | # If this worked, use these flags, otherwise use other flags 97 | IF(FLAG_WORKS) 98 | # Append this flag to the end of the list that already exists 99 | SET(${FLAGVAR} "${FLAGVAL} ${flag}" CACHE STRING 100 | "Set the ${FLAGVAR} flags" FORCE) 101 | SET(FLAG_FOUND TRUE) 102 | BREAK() # We found something that works, so exit 103 | ENDIF(FLAG_WORKS) 104 | 105 | ENDFOREACH(flag ${FLAGLIST}) 106 | 107 | # Raise an error if no flag was found 108 | IF(FLAG_REQUIRED AND NOT FLAG_FOUND) 109 | MESSAGE(FATAL_ERROR "No compile flags were found") 110 | ENDIF(FLAG_REQUIRED AND NOT FLAG_FOUND) 111 | 112 | ENDFUNCTION() 113 | -------------------------------------------------------------------------------- /cmake/Modules/SetFortranFlags.cmake: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | # Determine and set the Fortran compiler flags we want 3 | ###################################################### 4 | 5 | #################################################################### 6 | # Make sure that the default build type is RELEASE if not specified. 7 | #################################################################### 8 | INCLUDE(${CMAKE_MODULE_PATH}/SetCompileFlag.cmake) 9 | 10 | # Make sure the build type is uppercase 11 | STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT) 12 | 13 | IF(BT STREQUAL "RELEASE") 14 | SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING 15 | "Choose the type of build, options are DEBUG, RELEASE, or TESTING." 16 | FORCE) 17 | ELSEIF(BT STREQUAL "DEBUG") 18 | SET (CMAKE_BUILD_TYPE DEBUG CACHE STRING 19 | "Choose the type of build, options are DEBUG, RELEASE, or TESTING." 20 | FORCE) 21 | ELSEIF(BT STREQUAL "TESTING") 22 | SET (CMAKE_BUILD_TYPE TESTING CACHE STRING 23 | "Choose the type of build, options are DEBUG, RELEASE, or TESTING." 24 | FORCE) 25 | ELSEIF(NOT BT) 26 | SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING 27 | "Choose the type of build, options are DEBUG, RELEASE, or TESTING." 28 | FORCE) 29 | MESSAGE(STATUS "CMAKE_BUILD_TYPE not given, defaulting to RELEASE") 30 | ELSE() 31 | MESSAGE(FATAL_ERROR "CMAKE_BUILD_TYPE not valid, choices are DEBUG, RELEASE, or TESTING") 32 | ENDIF(BT STREQUAL "RELEASE") 33 | 34 | ######################################################### 35 | # If the compiler flags have already been set, return now 36 | ######################################################### 37 | 38 | IF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fortran_FLAGS_DEBUG) 39 | RETURN () 40 | ENDIF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fortran_FLAGS_DEBUG) 41 | 42 | ######################################################################## 43 | # Determine the appropriate flags for this compiler for each build type. 44 | # For each option type, a list of possible flags is given that work 45 | # for various compilers. The first flag that works is chosen. 46 | # If none of the flags work, nothing is added (unless the REQUIRED 47 | # flag is given in the call). This way unknown compiles are supported. 48 | ####################################################################### 49 | 50 | ##################### 51 | ### GENERAL FLAGS ### 52 | ##################### 53 | 54 | # Don't add underscores in symbols for C-compatability 55 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" 56 | Fortran "-fno-underscoring") 57 | 58 | # There is some bug where -march=native doesn't work on Mac 59 | IF(APPLE) 60 | SET(GNUNATIVE "-mtune=native") 61 | ELSE() 62 | SET(GNUNATIVE "-march=native") 63 | ENDIF() 64 | # Optimize for the host's architecture 65 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" 66 | Fortran "-xHost" # Intel 67 | "/QxHost" # Intel Windows 68 | ${GNUNATIVE} # GNU 69 | "-ta=host" # Portland Group 70 | ) 71 | 72 | ################### 73 | ### DEBUG FLAGS ### 74 | ################### 75 | 76 | # NOTE: debugging symbols (-g or /debug:full) are already on by default 77 | 78 | # Disable optimizations 79 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" 80 | Fortran REQUIRED "-O0" # All compilers not on Windows 81 | "/Od" # Intel Windows 82 | ) 83 | 84 | # Turn on all warnings 85 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" 86 | Fortran "-warn all" # Intel 87 | "/warn:all" # Intel Windows 88 | "-Wall" # GNU 89 | # Portland Group (on by default) 90 | ) 91 | 92 | # Traceback 93 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" 94 | Fortran "-traceback" # Intel/Portland Group 95 | "/traceback" # Intel Windows 96 | "-fbacktrace" # GNU (gfortran) 97 | "-ftrace=full" # GNU (g95) 98 | ) 99 | 100 | # Check array bounds 101 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" 102 | Fortran "-check bounds" # Intel 103 | "/check:bounds" # Intel Windows 104 | "-fcheck=bounds" # GNU (New style) 105 | "-fbounds-check" # GNU (Old style) 106 | "-Mbounds" # Portland Group 107 | ) 108 | 109 | ##################### 110 | ### TESTING FLAGS ### 111 | ##################### 112 | 113 | # Optimizations 114 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_TESTING}" 115 | Fortran REQUIRED "-O2" # All compilers not on Windows 116 | "/O2" # Intel Windows 117 | ) 118 | 119 | ##################### 120 | ### RELEASE FLAGS ### 121 | ##################### 122 | 123 | # NOTE: agressive optimizations (-O3) are already turned on by default 124 | 125 | # Unroll loops 126 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" 127 | Fortran "-funroll-loops" # GNU 128 | "-unroll" # Intel 129 | "/unroll" # Intel Windows 130 | "-Munroll" # Portland Group 131 | ) 132 | 133 | # Inline functions 134 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" 135 | Fortran "-inline" # Intel 136 | "/Qinline" # Intel Windows 137 | "-finline-functions" # GNU 138 | "-Minline" # Portland Group 139 | ) 140 | 141 | # Interprocedural (link-time) optimizations 142 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" 143 | Fortran "-ipo" # Intel 144 | "/Qipo" # Intel Windows 145 | "-flto" # GNU 146 | "-Mipa" # Portland Group 147 | ) 148 | 149 | # Single-file optimizations 150 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" 151 | Fortran "-ip" # Intel 152 | "/Qip" # Intel Windows 153 | ) 154 | 155 | # Vectorize code 156 | SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" 157 | Fortran "-vec-report0" # Intel 158 | "/Qvec-report0" # Intel Windows 159 | "-Mvect" # Portland Group 160 | ) 161 | -------------------------------------------------------------------------------- /cmake/Modules/SetParallelizationLibrary.cmake: -------------------------------------------------------------------------------- 1 | # Turns on either OpenMP or MPI 2 | # If both are requested, the other is disabled 3 | # When one is turned on, the other is turned off 4 | # If both are off, we explicitly disable them just in case 5 | 6 | IF (USE_OPENMP AND USE_MPI) 7 | MESSAGE (FATAL_ERROR "Cannot use both OpenMP and MPI") 8 | ELSEIF (USE_OPENMP) 9 | # Find OpenMP 10 | IF (NOT OpenMP_Fortran_FLAGS) 11 | FIND_PACKAGE (OpenMP_Fortran) 12 | IF (NOT OpenMP_Fortran_FLAGS) 13 | MESSAGE (FATAL_ERROR "Fortran compiler does not support OpenMP") 14 | ENDIF (NOT OpenMP_Fortran_FLAGS) 15 | ENDIF (NOT OpenMP_Fortran_FLAGS) 16 | # Turn of MPI 17 | UNSET (MPI_FOUND CACHE) 18 | UNSET (MPI_COMPILER CACHE) 19 | UNSET (MPI_LIBRARY CACHE) 20 | ELSEIF (USE_MPI) 21 | # Find MPI 22 | IF (NOT MPI_Fortran_FOUND) 23 | FIND_PACKAGE (MPI REQUIRED) 24 | ENDIF (NOT MPI_Fortran_FOUND) 25 | # Turn off OpenMP 26 | SET (OMP_NUM_PROCS 0 CACHE 27 | STRING "Number of processors OpenMP may use" FORCE) 28 | UNSET (OpenMP_C_FLAGS CACHE) 29 | UNSET (GOMP_Fortran_LINK_FLAGS CACHE) 30 | ELSE () 31 | # Turn off both OpenMP and MPI 32 | SET (OMP_NUM_PROCS 0 CACHE 33 | STRING "Number of processors OpenMP may use" FORCE) 34 | UNSET (OpenMP_Fortran_FLAGS CACHE) 35 | UNSET (GOMP_Fortran_LINK_FLAGS CACHE) 36 | UNSET (MPI_FOUND CACHE) 37 | UNSET (MPI_COMPILER CACHE) 38 | UNSET (MPI_LIBRARY CACHE) 39 | ENDIF (USE_OPENMP AND USE_MPI) 40 | -------------------------------------------------------------------------------- /cmake/Modules/SetUpLAPACK.cmake: -------------------------------------------------------------------------------- 1 | # Find LAPACK (finds BLAS also) if not already found 2 | IF(NOT LAPACK_FOUND) 3 | ENABLE_LANGUAGE(C) # Some libraries need a C compiler to find 4 | FIND_PACKAGE(LAPACK REQUIRED) 5 | # Remember that LAPACK (and BLAS) was found. For some reason the 6 | # FindLAPACK routine doesn't place these into the CACHE. 7 | SET(BLAS_FOUND TRUE CACHE INTERNAL "BLAS was found" FORCE) 8 | SET(LAPACK_FOUND TRUE CACHE INTERNAL "LAPACK was found" FORCE) 9 | SET(BLAS_LIBRARIES ${BLAS_LIBRARIES} CACHE INTERNAL "BLAS LIBS" FORCE) 10 | SET(LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE INTERNAL "LAPACK LIBS" FORCE) 11 | ENDIF(NOT LAPACK_FOUND) 12 | -------------------------------------------------------------------------------- /distclean.cmake: -------------------------------------------------------------------------------- 1 | # This CMake script will delete build directories and files to bring the 2 | # package back to it's distribution state 3 | 4 | # We want to start from the top of the source dir, so if we are in build 5 | # we want to start one directory up 6 | GET_FILENAME_COMPONENT(BASEDIR ${CMAKE_SOURCE_DIR} NAME) 7 | IF(${BASEDIR} STREQUAL "build") 8 | SET(TOPDIR "${CMAKE_SOURCE_DIR}/..") 9 | ELSE() 10 | SET(TOPDIR "${CMAKE_SOURCE_DIR}") 11 | ENDIF() 12 | 13 | MACRO(GET_PARENT_DIRECTORIES search_string return_list grandparents) 14 | FILE(GLOB_RECURSE new_list ${search_string}) 15 | SET(dir_list "") 16 | FOREACH(file_path ${new_list}) 17 | GET_FILENAME_COMPONENT(dir_path ${file_path} PATH) 18 | # Remove an extra directory component to return grandparent 19 | IF(${grandparents}) 20 | # Tack on a fake extension to trick CMake into removing a second 21 | # path component 22 | SET(dir_path "${dir_path}.tmp") 23 | GET_FILENAME_COMPONENT(dir_path ${dir_path} PATH) 24 | ENDIF(${grandparents}) 25 | SET(dir_list ${dir_list} ${dir_path}) 26 | ENDFOREACH() 27 | LIST(REMOVE_DUPLICATES dir_list) 28 | SET(${return_list} ${dir_list}) 29 | ENDMACRO() 30 | 31 | # Find directories and files that we will want to remove 32 | FILE(GLOB_RECURSE CMAKECACHE "${TOPDIR}/*CMakeCache.txt") 33 | FILE(GLOB_RECURSE CMAKEINSTALL "${TOPDIR}/*cmake_install.cmake" 34 | "${TOPDIR}/*install_manifest.txt") 35 | FILE(GLOB_RECURSE MAKEFILE "${TOPDIR}/*Makefile") 36 | FILE(GLOB_RECURSE CMAKETESTFILES "${TOPDIR}/*CTestTestfile.cmake") 37 | SET(TOPDIRECTORIES "${TOPDIR}/lib" 38 | "${TOPDIR}/test" 39 | "${TOPDIR}/bin" 40 | ) 41 | 42 | # CMake has trouble finding directories recursively, so locate these 43 | # files and then save the parent directory of the files 44 | GET_PARENT_DIRECTORIES(Makefile.cmake CMAKEFILES 0) 45 | GET_PARENT_DIRECTORIES(LastTest.log CMAKETESTING 1) 46 | 47 | # Place these files and directories into a list 48 | SET(DEL ${TOPDIRECTORIES} 49 | ${CMAKECACHE} 50 | ${CMAKEINSTALL} 51 | ${MAKEFILE} 52 | ${CMAKEFILES} 53 | ${CMAKETESTING} 54 | ${CMAKETESTFILES} 55 | ) 56 | 57 | # If we are not in the build dir, delete that as well 58 | IF(NOT (${BASEDIR} STREQUAL "build")) 59 | FILE(GLOB BUILD "${TOPDIR}/build") 60 | SET(DEL ${DEL} ${BUILD}) 61 | ENDIF() 62 | 63 | # Loop over the directories and delete each one 64 | FOREACH(D ${DEL}) 65 | IF(EXISTS ${D}) 66 | FILE(REMOVE_RECURSE ${D}) 67 | ENDIF() 68 | ENDFOREACH() 69 | -------------------------------------------------------------------------------- /src/bar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # bar library 2 | SET(BAR_src ${SRCBAR}/bar.f90) 3 | ADD_LIBRARY(${BARLIB} STATIC ${BAR_src}) 4 | -------------------------------------------------------------------------------- /src/bar/bar.f90: -------------------------------------------------------------------------------- 1 | Subroutine bar(a, b) 2 | 3 | ! Performs the bar action 4 | 5 | Implicit None 6 | 7 | Integer, Intent(In) :: a 8 | Integer, Intent(Out) :: b 9 | 10 | b = a + 100 - 7 11 | 12 | End Subroutine bar 13 | -------------------------------------------------------------------------------- /src/foo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ######################################## 2 | # Set up how to compile the source files 3 | ######################################## 4 | 5 | # Add the source files 6 | SET(FOO_src ${SRCFOO}/foo.f90 7 | ${SRCFOO}/constants.f90 8 | ) 9 | 10 | # Define the executable in terms of the source files 11 | ADD_EXECUTABLE(${FOOEXE} ${FOO_src}) 12 | 13 | ##################################################### 14 | # Add the needed libraries and special compiler flags 15 | ##################################################### 16 | 17 | # This links foo to the bar library 18 | TARGET_LINK_LIBRARIES(${FOOEXE} ${BARLIB}) 19 | 20 | # Uncomment if you need to link to BLAS and LAPACK 21 | #TARGET_LINK_LIBRARIES(${FOOEXE} ${BLAS_LIBRARIES} 22 | # ${LAPACK_LIBRARIES} 23 | # ${CMAKE_THREAD_LIBS_INIT}) 24 | 25 | # Uncomment if you have parallization 26 | #IF(USE_OPENMP) 27 | # SET_TARGET_PROPERTIES(${FOOEXE} PROPERTIES 28 | # COMPILE_FLAGS "${OpenMP_Fortran_FLAGS}" 29 | # LINK_FLAGS "${OpenMP_Fortran_FLAGS}") 30 | #ELSEIF(USE_MPI) 31 | # SET_TARGET_PROPERTIES(${FOOEXE} PROPERTIES 32 | # COMPILE_FLAGS "${MPI_Fortran_COMPILE_FLAGS}" 33 | # LINK_FLAGS "${MPI_Fortran_LINK_FLAGS}") 34 | # INCLUDE_DIRECTORIES(${MPI_Fortran_INCLUDE_PATH}) 35 | # TARGET_LINK_LIBRARIES(${FOOEXE} ${MPI_Fortran_LIBRARIES}) 36 | #ENDIF(USE_OPENMP) 37 | 38 | ##################################### 39 | # Tell how to install this executable 40 | ##################################### 41 | 42 | IF(WIN32) 43 | SET(CMAKE_INSTALL_PREFIX "C:\\Program Files") 44 | ELSE() 45 | SET(CMAKE_INSTALL_PREFIX /usr/local) 46 | ENDIF(WIN32) 47 | INSTALL(TARGETS ${FOOEXE} RUNTIME DESTINATION bin) 48 | -------------------------------------------------------------------------------- /src/foo/constants.f90: -------------------------------------------------------------------------------- 1 | Module constants 2 | 3 | Implicit None 4 | 5 | ! Handles 6 | Integer, Parameter :: stdin = 5 7 | Integer, Parameter :: stdout = 6 8 | Integer, Parameter :: stderr = 0 9 | 10 | ! Precision 11 | Integer, Parameter :: KINDR = KIND(0d0) 12 | 13 | Real(KINDR), Parameter :: ZERO = 0.0e0_KINDR 14 | Real(KINDR), Parameter :: ONE = 1.0e0_KINDR 15 | Real(KINDR), Parameter :: TWO = 2.0e0_KINDR 16 | Real(KINDR), Parameter :: THREE = 3.0e0_KINDR 17 | Real(KINDR), Parameter :: FOUR = 4.0e0_KINDR 18 | Real(KINDR), Parameter :: FIVE = 5.0e0_KINDR 19 | Real(KINDR), Parameter :: SIX = 6.0e0_KINDR 20 | Real(KINDR), Parameter :: SEVEN = 7.0e0_KINDR 21 | Real(KINDR), Parameter :: EIGHT = 8.0e0_KINDR 22 | Real(KINDR), Parameter :: NINE = 9.0e0_KINDR 23 | Real(KINDR), Parameter :: TEN = 10.0e0_KINDR 24 | Real(KINDR), Parameter :: ELEVEN = 11.0e0_KINDR 25 | Real(KINDR), Parameter :: TWELVE = 12.0e0_KINDR 26 | Real(KINDR), Parameter :: THIRTEEN = 13.0e0_KINDR 27 | Real(KINDR), Parameter :: FOURTEEN = 14.0e0_KINDR 28 | Real(KINDR), Parameter :: FIFTEEN = 15.0e0_KINDR 29 | Real(KINDR), Parameter :: SIXTEEN = 16.0e0_KINDR 30 | Real(KINDR), Parameter :: SEVENTEEN = 17.0e0_KINDR 31 | Real(KINDR), Parameter :: EIGHTEEN = 18.0e0_KINDR 32 | Real(KINDR), Parameter :: NINETEEN = 19.0e0_KINDR 33 | Real(KINDR), Parameter :: TWENTY = 20.0e0_KINDR 34 | Real(KINDR), Parameter :: TWENTYTWO = 22.0e0_KINDR 35 | Real(KINDR), Parameter :: TWENTYFOUR = 24.0e0_KINDR 36 | Real(KINDR), Parameter :: THIRTYTWO = 32.0e0_KINDR 37 | Real(KINDR), Parameter :: THIRTYSIX = 36.0e0_KINDR 38 | Real(KINDR), Parameter :: FORTYEIGHT = 48.0e0_KINDR 39 | Real(KINDR), Parameter :: SEVENTYTWO = 72.0e0_KINDR 40 | Real(KINDR), Parameter :: HUNDRED = 1.0e2_KINDR 41 | Real(KINDR), Parameter :: FOURTH = 0.25e0_KINDR 42 | Real(KINDR), Parameter :: HALF = 0.5e0_KINDR 43 | Real(KINDR), Parameter :: THREEFOURTH = 0.75e0_KINDR 44 | Real(KINDR), Parameter :: THIRD = 1.0e0_KINDR / 3.0e0_KINDR 45 | Real(KINDR), Parameter :: TWOTHIRD = 2.0e0_KINDR / 3.0e0_KINDR 46 | Real(KINDR), Parameter :: SIXTH = 1.0e0_KINDR / 6.0e0_KINDR 47 | Real(KINDR), Parameter :: THREESECOND = 3.0e0_KINDR / 2.0e0_KINDR 48 | Real(KINDR), Parameter :: FOURTHIRD = 4.0e0_KINDR / 3.0e0_KINDR 49 | 50 | Real(KINDR), Parameter :: PI = 3.14159265358979323846_KINDR 51 | Real(KINDR), Parameter :: SQRTPI = 1.7724538509055159_KINDR 52 | Real(KINDR), Parameter :: TWOINVPI = TWO / PI 53 | Real(KINDR), Parameter :: SQRTTWOINVPI = 0.79788456080286541_KINDR 54 | Real(KINDR), Parameter :: TWOINVSQRTPI = TWO / SQRTPI 55 | 56 | Complex(KINDR), Parameter :: I_C = CMPLX(ZERO, ONE, KINDR) 57 | Complex(KINDR), Parameter :: ZERO_C = CMPLX(ZERO, ZERO, KINDR) 58 | Complex(KINDR), Parameter :: ONE_C = CMPLX(ONE, ZERO, KINDR) 59 | Complex(KINDR), Parameter :: TWO_C = CMPLX(TWO, ZERO, KINDR) 60 | Complex(KINDR), Parameter :: THREE_C = CMPLX(THREE, ZERO, KINDR) 61 | Complex(KINDR), Parameter :: FOUR_C = CMPLX(FOUR, ZERO, KINDR) 62 | Complex(KINDR), Parameter :: FIVE_C = CMPLX(FIVE, ZERO, KINDR) 63 | Complex(KINDR), Parameter :: SIX_C = CMPLX(SIX, ZERO, KINDR) 64 | Complex(KINDR), Parameter :: HALF_C = CMPLX(HALF, ZERO, KINDR) 65 | Complex(KINDR), Parameter :: HUNDRED_C = CMPLX(HUNDRED, ZERO, KINDR) 66 | 67 | End Module constants 68 | -------------------------------------------------------------------------------- /src/foo/foo.f90: -------------------------------------------------------------------------------- 1 | Program foo 2 | 3 | ! FOO!!! This is the best foo implementatiton ever! 4 | 5 | use constants 6 | 7 | Implicit None 8 | 9 | Real(KINDR) :: r 10 | Integer :: i 11 | 12 | write(stdout,*) "Hello, world!" 13 | r = FIVE 14 | write(stdout,*) r 15 | call bar (5, i) 16 | write(stdout,*) i 17 | 18 | End Program foo 19 | --------------------------------------------------------------------------------