Environment variable docs maintenance
[gromacs.git] / cmake / gmxFindFlagsForSource.cmake
blob0efa4f4281de141b7ec9cdb124f37574e16242df
2 # This file is part of the GROMACS molecular simulation package.
4 # Copyright (c) 2013,2014,2016,2017, by the GROMACS development team, led by
5 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 # and including many others, as listed in the AUTHORS file in the
7 # top-level source directory and at http://www.gromacs.org.
9 # GROMACS is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public License
11 # as published by the Free Software Foundation; either version 2.1
12 # of the License, or (at your option) any later version.
14 # GROMACS is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # Lesser General Public License for more details.
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with GROMACS; if not, see
21 # http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24 # If you want to redistribute modifications to GROMACS, please
25 # consider that scientific software is very special. Version
26 # control is crucial - bugs must be traceable. We will be happy to
27 # consider code for inclusion in the official distribution, but
28 # derived work must not be called official GROMACS. Details are found
29 # in the README & COPYING files - if they are missing, get the
30 # official version at http://www.gromacs.org.
32 # To help us fund GROMACS development, we humbly ask that you cite
33 # the research papers on the package. Check out http://www.gromacs.org.
35 # Helper function to call the correct language version of the CMake
36 # check_*_compiler_flag function.
37 function(gmx_check_compiler_flag FLAGS LANGUAGE RESULT_VARIABLE)
38     if (LANGUAGE STREQUAL "C")
39         check_c_compiler_flag("${FLAGS}" ${RESULT_VARIABLE})
40     elseif (LANGUAGE STREQUAL "CXX")
41         check_cxx_compiler_flag("${FLAGS}" ${RESULT_VARIABLE})
42     else()
43         message(FATAL_ERROR "Language '${LANGUAGE}' is not supported by gmx_check_compiler_flag")
44     endif()
45 endfunction()
47 # Helper function to call the correct language version of the CMake
48 # check_*_source_compiles function.
49 function(gmx_check_source_compiles_with_flags SOURCE FLAGS LANGUAGE RESULT_VARIABLE)
50    set(CMAKE_REQUIRED_FLAGS "${FLAGS}")
51    if (LANGUAGE STREQUAL "C")
52        check_c_source_compiles("${SOURCE}" ${RESULT_VARIABLE})
53    elseif (LANGUAGE STREQUAL "CXX")
54        check_cxx_source_compiles("${SOURCE}" ${RESULT_VARIABLE})
55    else()
56        message(FATAL_ERROR "Language '${LANGUAGE}' is not supported by gmx_check_source_compiles_with_flags")
57    endif()
58 endfunction()
60 # Helper routine to find flag (from a list) to compile a specific source (in C or C++).
61 # RESULT_VARIABLE           Name of variable to set in the parent scope to true if
62 #                           we have found a flag that works (which could be "")
63 # SOURCE                    Source code to test
64 # LANGUAGE                  Specifies the language as "C" or "CXX"
65 # TOOLCHAIN_FLAGS_VARIABLE  Name of a variable that contains any flags already known
66 #                           to be needed by the toolchain (unchanged)
67 # NEW_FLAGS_VARIABLE        The first working flag will be set to this variable.
68 # Args 6 through N          Multiple strings with compiler flags to test
70 # If gmx_check_compiler_flag() finds a working compiler flag, but the project in
71 # gmx_check_source_compiles_with_flags() fails to build source code that needs,
72 # the flag, this function sets SUGGEST_BINUTILS_UPDATE in the parent scope to
73 # suggest that the calling code tell the user about this issue if needed.
74 FUNCTION(GMX_FIND_FLAG_FOR_SOURCE RESULT_VARIABLE SOURCE LANGUAGE TOOLCHAIN_FLAGS_VARIABLE NEW_FLAGS_VARIABLE)
75     # Insert a blank element last in the list (ie. try without any flags too)
76     # This must come last, since some compilers (Intel) might try to emulate
77     # emulate AVX instructions with SSE4.1 otherwise.
78     foreach(_testflag ${ARGN} "")
79         # make valid variable names from the flag string: replace all non-alphanumerical chars
80         string(REGEX REPLACE "[^a-zA-Z0-9]+" "_" FLAG_ACCEPTED_VARIABLE "${LANGUAGE}_${_testflag}_FLAG_ACCEPTED")
81         string(REGEX REPLACE "[^a-zA-Z0-9]+" "_" COMPILE_WORKS_VARIABLE "${LANGUAGE}_${_testflag}_COMPILE_WORKS")
83         # Check that the flag itself is fine, and that it does not generate warnings either, but don't
84         # confuse the user by saying an empty flag was "accepted"
85         if("${_testflag}" STREQUAL "")
86             set(${FLAG_ACCEPTED_VARIABLE} 1)
87             # Give the empty flag variable a better name since we cannot control the CMake status messages
88             set(COMPILE_WORKS_VARIABLE "${LANGUAGE}_COMPILE_WORKS_WITHOUT_SPECIAL_FLAGS")
89         else()
90             gmx_check_compiler_flag("${${TOOLCHAIN_FLAGS_VARIABLE}} ${_testflag}" "${LANGUAGE}" ${FLAG_ACCEPTED_VARIABLE})
91         endif()
93         if(${FLAG_ACCEPTED_VARIABLE})
94             IF(DEFINED ${COMPILE_WORKS_VARIABLE})
95                 # This is a subsequent call to CMake, don't spam the status line
96                 set(RUN_QUIETLY TRUE)
97             endif()
98             # Check that we can really compile source with the full
99             # toolchain (this does not catch compiler warnings).
100             gmx_check_source_compiles_with_flags("${SOURCE}" "${${TOOLCHAIN_FLAGS_VARIABLE}} ${_testflag}" "${LANGUAGE}" ${COMPILE_WORKS_VARIABLE})
102             if(NOT ${COMPILE_WORKS_VARIABLE})
103                 if (NOT RUN_QUIETLY)
104                     if("${_testflag}" STREQUAL "")
105                         message(STATUS "Could not find any flag to build test source (this could be due to either the compiler or binutils)")
106                     else()
107                         message(STATUS "Flag was accepted, but it did not build test source (this could be due to either the compiler or binutils)")
108                         set(SUGGEST_BINUTILS_UPDATE 1 PARENT_SCOPE)
109                     endif()
110                 endif()
111             endif()
112             if (${FLAG_ACCEPTED_VARIABLE} AND ${COMPILE_WORKS_VARIABLE})
113                 set(${RESULT_VARIABLE} 1 PARENT_SCOPE)
114                 set(${NEW_FLAGS_VARIABLE} "${_testflag}" PARENT_SCOPE)
115                 break()
116             endif()
117         endif()
118     endforeach()
119     # If no flag has been found, then leaving ${RESULT_VARIABLE} unset
120     # will be interpreted by CMake as false.
121 ENDFUNCTION()
123 # Helper routine to find a flag (from a list) that will compile a specific source (in both C and C++).
124 # C_RESULT_VARIABLE             Names a variable that will be set true if a way
125 #                               to compile the source as C was found
126 # CXX_RESULT_VARIABLE           Names a variable that will be set true if a way
127 #                               to compile the source as C++ was found
128 # SOURCE                        Source code to test
129 # TOOLCHAIN_C_FLAGS_VARIABLE    As input, names a variable that contains flags needed
130 #                               by the C toolchain.
131 # TOOLCHAIN_CXX_FLAGS_VARIABLE  As input, names a variable that contains flags needed
132 #                               by the C++ toolchain.
133 # NEW_C_FLAGS_VARIABLE          The first working C flag will be set to this variable
134 # NEW_CXX_FLAGS_VARIABLE        The first working C++ flag will be set to this variable
135 # Args 8 through N              Multiple strings with compiler flags to test
137 # If a compile flag is found, but the project in check_c/cxx_source_compiles
138 # fails to build, sets SUGGEST_BINUTILS_UPDATE in parent scope to suggest
139 # that the calling code tell the user about this issue if needed.
140 macro(gmx_find_flags C_RESULT_VARIABLE CXX_RESULT_VARIABLE SOURCE TOOLCHAIN_C_FLAGS_VARIABLE TOOLCHAIN_CXX_FLAGS_VARIABLE C_FLAGS_VARIABLE CXX_FLAGS_VARIABLE)
141     gmx_find_flag_for_source(${C_RESULT_VARIABLE} "${SOURCE}" "C" ${TOOLCHAIN_C_FLAGS_VARIABLE} ${C_FLAGS_VARIABLE} ${ARGN})
142     gmx_find_flag_for_source(${CXX_RESULT_VARIABLE} "${SOURCE}" "CXX" ${TOOLCHAIN_CXX_FLAGS_VARIABLE} ${CXX_FLAGS_VARIABLE} ${ARGN})
143 endmacro()