Ryan Prichard | f6283ab | 2022-01-13 17:30:19 -0800 | [diff] [blame] | 1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| 2 | # file Copyright.txt or https://cmake.org/licensing for details. |
| 3 | |
| 4 | |
| 5 | # determine the compiler to use for C programs |
| 6 | # NOTE, a generator may set CMAKE_C_COMPILER before |
| 7 | # loading this file to force a compiler. |
| 8 | # use environment variable CC first if defined by user, next use |
| 9 | # the cmake variable CMAKE_GENERATOR_CC which can be defined by a generator |
| 10 | # as a default compiler |
| 11 | # If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used |
| 12 | # as prefix for the tools (e.g. arm-elf-gcc, arm-elf-ar etc.). This works |
| 13 | # currently with the GNU crosscompilers. |
| 14 | # |
| 15 | # Sets the following variables: |
| 16 | # CMAKE_C_COMPILER |
| 17 | # CMAKE_AR |
| 18 | # CMAKE_RANLIB |
| 19 | # CMAKE_COMPILER_IS_GNUCC |
| 20 | # |
| 21 | # If not already set before, it also sets |
| 22 | # _CMAKE_TOOLCHAIN_PREFIX |
| 23 | |
| 24 | include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) |
| 25 | |
| 26 | # Load system-specific compiler preferences for this language. |
| 27 | include(Platform/${CMAKE_SYSTEM_NAME}-Determine-C OPTIONAL) |
| 28 | include(Platform/${CMAKE_SYSTEM_NAME}-C OPTIONAL) |
| 29 | if(NOT CMAKE_C_COMPILER_NAMES) |
| 30 | set(CMAKE_C_COMPILER_NAMES cc) |
| 31 | endif() |
| 32 | |
| 33 | if(${CMAKE_GENERATOR} MATCHES "Visual Studio") |
| 34 | elseif("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") |
| 35 | elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") |
| 36 | set(CMAKE_C_COMPILER_XCODE_TYPE sourcecode.c.c) |
| 37 | _cmake_find_compiler_path(C) |
| 38 | else() |
| 39 | if(NOT CMAKE_C_COMPILER) |
| 40 | set(CMAKE_C_COMPILER_INIT NOTFOUND) |
| 41 | |
| 42 | # prefer the environment variable CC |
| 43 | if(NOT $ENV{CC} STREQUAL "") |
| 44 | get_filename_component(CMAKE_C_COMPILER_INIT $ENV{CC} PROGRAM PROGRAM_ARGS CMAKE_C_FLAGS_ENV_INIT) |
| 45 | if(CMAKE_C_FLAGS_ENV_INIT) |
| 46 | set(CMAKE_C_COMPILER_ARG1 "${CMAKE_C_FLAGS_ENV_INIT}" CACHE STRING "Arguments to C compiler") |
| 47 | endif() |
| 48 | if(NOT EXISTS ${CMAKE_C_COMPILER_INIT}) |
| 49 | message(FATAL_ERROR "Could not find compiler set in environment variable CC:\n$ENV{CC}.") |
| 50 | endif() |
| 51 | endif() |
| 52 | |
| 53 | # next try prefer the compiler specified by the generator |
| 54 | if(CMAKE_GENERATOR_CC) |
| 55 | if(NOT CMAKE_C_COMPILER_INIT) |
| 56 | set(CMAKE_C_COMPILER_INIT ${CMAKE_GENERATOR_CC}) |
| 57 | endif() |
| 58 | endif() |
| 59 | |
| 60 | # finally list compilers to try |
| 61 | if(NOT CMAKE_C_COMPILER_INIT) |
| 62 | set(CMAKE_C_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc cl bcc xlc icx clang) |
| 63 | endif() |
| 64 | |
| 65 | _cmake_find_compiler(C) |
| 66 | |
| 67 | else() |
| 68 | _cmake_find_compiler_path(C) |
| 69 | endif() |
| 70 | mark_as_advanced(CMAKE_C_COMPILER) |
| 71 | |
| 72 | # Each entry in this list is a set of extra flags to try |
| 73 | # adding to the compile line to see if it helps produce |
| 74 | # a valid identification file. |
| 75 | set(CMAKE_C_COMPILER_ID_TEST_FLAGS_FIRST) |
| 76 | set(CMAKE_C_COMPILER_ID_TEST_FLAGS |
| 77 | # Try compiling to an object file only. |
| 78 | "-c" |
| 79 | |
| 80 | # Try enabling ANSI mode on HP. |
| 81 | "-Aa" |
| 82 | |
| 83 | # Try compiling K&R-compatible code (needed by Bruce C Compiler). |
| 84 | "-D__CLASSIC_C__" |
| 85 | |
| 86 | # ARMClang need target options |
| 87 | "--target=arm-arm-none-eabi -mcpu=cortex-m3" |
| 88 | |
| 89 | # MSVC needs at least one include directory for __has_include to function, |
| 90 | # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags. |
| 91 | # Also avoid linking so this works with no LIB env var. |
| 92 | "-c -I__does_not_exist__" |
| 93 | ) |
| 94 | endif() |
| 95 | if(CMAKE_C_COMPILER_TARGET) |
| 96 | set(CMAKE_C_COMPILER_ID_TEST_FLAGS_FIRST "-c --target=${CMAKE_C_COMPILER_TARGET}") |
| 97 | endif() |
| 98 | # Build a small source file to identify the compiler. |
| 99 | if(NOT CMAKE_C_COMPILER_ID_RUN) |
| 100 | set(CMAKE_C_COMPILER_ID_RUN 1) |
| 101 | |
| 102 | # Try to identify the compiler. |
| 103 | set(CMAKE_C_COMPILER_ID) |
| 104 | set(CMAKE_C_PLATFORM_ID) |
| 105 | file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in |
| 106 | CMAKE_C_COMPILER_ID_PLATFORM_CONTENT) |
| 107 | |
| 108 | # The IAR compiler produces weird output. |
| 109 | # See https://gitlab.kitware.com/cmake/cmake/-/issues/10176#note_153591 |
| 110 | list(APPEND CMAKE_C_COMPILER_ID_VENDORS IAR) |
| 111 | set(CMAKE_C_COMPILER_ID_VENDOR_FLAGS_IAR ) |
| 112 | set(CMAKE_C_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler") |
| 113 | |
| 114 | # Match the link line from xcodebuild output of the form |
| 115 | # Ld ... |
| 116 | # ... |
| 117 | # /path/to/cc ...CompilerIdC/... |
| 118 | # to extract the compiler front-end for the language. |
| 119 | set(CMAKE_C_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdC/(\\./)?(CompilerIdC.(framework|xctest|build/[^ \t\r\n]+)/)?CompilerIdC[ \t\n\\\"]") |
| 120 | set(CMAKE_C_COMPILER_ID_TOOL_MATCH_INDEX 2) |
| 121 | |
| 122 | include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) |
| 123 | CMAKE_DETERMINE_COMPILER_ID(C CFLAGS CMakeCCompilerId.c) |
| 124 | |
| 125 | _cmake_find_compiler_sysroot(C) |
| 126 | |
| 127 | # Set old compiler and platform id variables. |
| 128 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") |
| 129 | set(CMAKE_COMPILER_IS_GNUCC 1) |
| 130 | endif() |
| 131 | else() |
| 132 | if(NOT DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT) |
| 133 | # Some toolchain files set our internal CMAKE_C_COMPILER_ID_RUN |
| 134 | # variable but are not aware of CMAKE_C_COMPILER_FRONTEND_VARIANT. |
| 135 | # They pre-date our support for the GNU-like variant targeting the |
| 136 | # MSVC ABI so we do not consider that here. |
| 137 | if(CMAKE_C_COMPILER_ID STREQUAL "Clang" |
| 138 | OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xIntelLLVM") |
| 139 | if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") |
| 140 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "MSVC") |
| 141 | else() |
| 142 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") |
| 143 | endif() |
| 144 | else() |
| 145 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") |
| 146 | endif() |
| 147 | endif() |
| 148 | endif() |
| 149 | |
| 150 | if (NOT _CMAKE_TOOLCHAIN_LOCATION) |
| 151 | get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH) |
| 152 | endif () |
| 153 | |
| 154 | # If we have a gcc cross compiler, they have usually some prefix, like |
| 155 | # e.g. powerpc-linux-gcc, arm-elf-gcc or i586-mingw32msvc-gcc, optionally |
| 156 | # with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2). |
| 157 | # The other tools of the toolchain usually have the same prefix |
| 158 | # NAME_WE cannot be used since then this test will fail for names like |
| 159 | # "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be |
| 160 | # "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-" |
| 161 | if (NOT _CMAKE_TOOLCHAIN_PREFIX) |
| 162 | |
| 163 | if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|QCC") |
| 164 | get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME) |
| 165 | if (COMPILER_BASENAME MATCHES "^(.+-)?(clang|g?cc)(-cl)?(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$") |
| 166 | set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) |
| 167 | set(_CMAKE_TOOLCHAIN_SUFFIX ${CMAKE_MATCH_4}) |
| 168 | set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_6}) |
| 169 | elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") |
| 170 | if(CMAKE_C_COMPILER_TARGET) |
| 171 | set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_C_COMPILER_TARGET}-) |
| 172 | endif() |
| 173 | elseif(COMPILER_BASENAME MATCHES "qcc(\\.exe)?$") |
| 174 | if(CMAKE_C_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)?") |
| 175 | set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-) |
| 176 | endif() |
| 177 | endif () |
| 178 | |
| 179 | # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils |
| 180 | # but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.) |
| 181 | if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$") |
| 182 | set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) |
| 183 | endif () |
| 184 | elseif(CMAKE_C_COMPILER_ID MATCHES "TI") |
| 185 | # TI compilers are named e.g. cl6x, cl470 or armcl.exe |
| 186 | get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME) |
| 187 | if (COMPILER_BASENAME MATCHES "^(.+)?cl([^.]+)?(\\.exe)?$") |
| 188 | set(_CMAKE_TOOLCHAIN_PREFIX "${CMAKE_MATCH_1}") |
| 189 | set(_CMAKE_TOOLCHAIN_SUFFIX "${CMAKE_MATCH_2}") |
| 190 | endif () |
| 191 | endif() |
| 192 | |
| 193 | endif () |
| 194 | |
| 195 | set(_CMAKE_PROCESSING_LANGUAGE "C") |
| 196 | include(CMakeFindBinUtils) |
| 197 | include(Compiler/${CMAKE_C_COMPILER_ID}-FindBinUtils OPTIONAL) |
| 198 | unset(_CMAKE_PROCESSING_LANGUAGE) |
| 199 | |
| 200 | if(CMAKE_C_COMPILER_SYSROOT) |
| 201 | string(CONCAT _SET_CMAKE_C_COMPILER_SYSROOT |
| 202 | "set(CMAKE_C_COMPILER_SYSROOT \"${CMAKE_C_COMPILER_SYSROOT}\")\n" |
| 203 | "set(CMAKE_COMPILER_SYSROOT \"${CMAKE_C_COMPILER_SYSROOT}\")") |
| 204 | else() |
| 205 | set(_SET_CMAKE_C_COMPILER_SYSROOT "") |
| 206 | endif() |
| 207 | |
| 208 | if(CMAKE_C_COMPILER_ARCHITECTURE_ID) |
| 209 | set(_SET_CMAKE_C_COMPILER_ARCHITECTURE_ID |
| 210 | "set(CMAKE_C_COMPILER_ARCHITECTURE_ID ${CMAKE_C_COMPILER_ARCHITECTURE_ID})") |
| 211 | else() |
| 212 | set(_SET_CMAKE_C_COMPILER_ARCHITECTURE_ID "") |
| 213 | endif() |
| 214 | |
| 215 | if(MSVC_C_ARCHITECTURE_ID) |
| 216 | set(SET_MSVC_C_ARCHITECTURE_ID |
| 217 | "set(MSVC_C_ARCHITECTURE_ID ${MSVC_C_ARCHITECTURE_ID})") |
| 218 | endif() |
| 219 | |
| 220 | if(CMAKE_C_XCODE_ARCHS) |
| 221 | set(SET_CMAKE_XCODE_ARCHS |
| 222 | "set(CMAKE_XCODE_ARCHS \"${CMAKE_C_XCODE_ARCHS}\")") |
| 223 | endif() |
| 224 | |
| 225 | # configure variables set in this file for fast reload later on |
| 226 | configure_file(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in |
| 227 | ${CMAKE_PLATFORM_INFO_DIR}/CMakeCCompiler.cmake |
| 228 | @ONLY |
| 229 | ) |
| 230 | set(CMAKE_C_COMPILER_ENV_VAR "CC") |