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 Objective-C programs
6# NOTE, a generator may set CMAKE_OBJC_COMPILER before
7# loading this file to force a compiler.
8# use environment variable OBJC first if defined by user, next use
9# the cmake variable CMAKE_GENERATOR_OBJC which can be defined by a generator
10# as a default compiler
11#
12# Sets the following variables:
13#   CMAKE_OBJC_COMPILER
14#   CMAKE_AR
15#   CMAKE_RANLIB
16#   CMAKE_COMPILER_IS_GNUOBJC
17#   CMAKE_COMPILER_IS_CLANGOBJC
18#
19# If not already set before, it also sets
20#   _CMAKE_TOOLCHAIN_PREFIX
21
22include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
23
24# Load system-specific compiler preferences for this language.
25include(Platform/${CMAKE_SYSTEM_NAME}-Determine-OBJC OPTIONAL)
26include(Platform/${CMAKE_SYSTEM_NAME}-OBJC OPTIONAL)
27if(NOT CMAKE_OBJC_COMPILER_NAMES)
28  set(CMAKE_OBJC_COMPILER_NAMES clang)
29endif()
30
31if("${CMAKE_GENERATOR}" MATCHES "Xcode")
32  set(CMAKE_OBJC_COMPILER_XCODE_TYPE sourcecode.c.objc)
33else()
34  if(NOT CMAKE_OBJC_COMPILER)
35    set(CMAKE_OBJC_COMPILER_INIT NOTFOUND)
36
37    # prefer the environment variable OBJC or CC
38    foreach(var OBJC CC)
39      if($ENV{${var}} MATCHES ".+")
40        get_filename_component(CMAKE_OBJC_COMPILER_INIT $ENV{${var}} PROGRAM PROGRAM_ARGS CMAKE_OBJC_FLAGS_ENV_INIT)
41        if(CMAKE_OBJC_FLAGS_ENV_INIT)
42          set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_FLAGS_ENV_INIT}" CACHE STRING "Arguments to Objective-C compiler")
43        endif()
44        if(NOT EXISTS ${CMAKE_OBJC_COMPILER_INIT})
45          message(FATAL_ERROR "Could not find compiler set in environment variable ${var}:\n  $ENV{${var}}")
46        endif()
47        break()
48      endif()
49    endforeach()
50
51    # next try prefer the compiler specified by the generator
52    if(CMAKE_GENERATOR_OBJC)
53      if(NOT CMAKE_OBJC_COMPILER_INIT)
54        set(CMAKE_OBJC_COMPILER_INIT ${CMAKE_GENERATOR_OBJC})
55      endif()
56    endif()
57
58    # finally list compilers to try
59    if(NOT CMAKE_OBJC_COMPILER_INIT)
60      set(CMAKE_OBJC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang)
61    endif()
62
63    _cmake_find_compiler(OBJC)
64
65  else()
66    # we only get here if CMAKE_OBJC_COMPILER was specified using -D or a pre-made CMakeCache.txt
67    # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
68    # if CMAKE_OBJC_COMPILER is a list, use the first item as
69    # CMAKE_OBJC_COMPILER and the rest as CMAKE_OBJC_COMPILER_ARG1
70    set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_COMPILER}")
71    list(POP_FRONT CMAKE_OBJC_COMPILER_ARG1 CMAKE_OBJC_COMPILER)
72    list(JOIN CMAKE_OBJC_COMPILER_ARG1 " " CMAKE_OBJC_COMPILER_ARG1)
73
74    # if a compiler was specified by the user but without path,
75    # now try to find it with the full path
76    # if it is found, force it into the cache,
77    # if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
78    # if the C compiler already had a path, reuse it for searching the CXX compiler
79    get_filename_component(_CMAKE_USER_OBJC_COMPILER_PATH "${CMAKE_OBJC_COMPILER}" PATH)
80    if(NOT _CMAKE_USER_OBJC_COMPILER_PATH)
81      find_program(CMAKE_OBJC_COMPILER_WITH_PATH NAMES ${CMAKE_OBJC_COMPILER})
82      if(CMAKE_OBJC_COMPILER_WITH_PATH)
83        set(CMAKE_OBJC_COMPILER ${CMAKE_OBJC_COMPILER_WITH_PATH} CACHE STRING "Objective-C compiler" FORCE)
84      endif()
85      unset(CMAKE_OBJC_COMPILER_WITH_PATH CACHE)
86    endif()
87  endif()
88  mark_as_advanced(CMAKE_OBJC_COMPILER)
89
90  # Each entry in this list is a set of extra flags to try
91  # adding to the compile line to see if it helps produce
92  # a valid identification file.
93  set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS_FIRST)
94  set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS
95    # Try compiling to an object file only.
96    "-c"
97
98    )
99endif()
100
101# Build a small source file to identify the compiler.
102if(NOT CMAKE_OBJC_COMPILER_ID_RUN)
103  set(CMAKE_OBJC_COMPILER_ID_RUN 1)
104
105  # Try to identify the compiler.
106  set(CMAKE_OBJC_COMPILER_ID)
107  file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
108    CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT)
109
110  # Match the link line from xcodebuild output of the form
111  #  Ld ...
112  #      ...
113  #      /path/to/cc ...CompilerIdOBJC/...
114  # to extract the compiler front-end for the language.
115  set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdOBJC/(\\./)?(CompilerIdOBJC.(framework|xctest|build/[^ \t\r\n]+)/)?CompilerIdOBJC[ \t\n\\\"]")
116  set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_INDEX 2)
117
118  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
119  CMAKE_DETERMINE_COMPILER_ID(OBJC OBJCCFLAGS CMakeOBJCCompilerId.m)
120
121  # Set old compiler and platform id variables.
122  if(CMAKE_OBJC_COMPILER_ID STREQUAL "GNU")
123    set(CMAKE_COMPILER_IS_GNUOBJC 1)
124  endif()
125  if(CMAKE_OBJC_COMPILER_ID STREQUAL "Clang")
126    set(CMAKE_COMPILER_IS_CLANGOBJC 1)
127  endif()
128endif()
129
130if (NOT _CMAKE_TOOLCHAIN_LOCATION)
131  get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJC_COMPILER}" PATH)
132endif ()
133
134# If we have a gcc cross compiler, they have usually some prefix, like
135# e.g. powerpc-linux-gcc, arm-elf-gcc or i586-mingw32msvc-gcc, optionally
136# with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2).
137# The other tools of the toolchain usually have the same prefix
138# NAME_WE cannot be used since then this test will fail for names like
139# "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
140# "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
141if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
142
143  if(CMAKE_OBJC_COMPILER_ID MATCHES "GNU|Clang|QCC")
144    get_filename_component(COMPILER_BASENAME "${CMAKE_OBJC_COMPILER}" NAME)
145    if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
146      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
147      set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
148    elseif(CMAKE_OBJC_COMPILER_ID MATCHES "Clang")
149      if(CMAKE_OBJC_COMPILER_TARGET)
150        set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJC_COMPILER_TARGET}-)
151      endif()
152    elseif(COMPILER_BASENAME MATCHES "qcc(\\.exe)?$")
153      if(CMAKE_OBJC_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)?")
154        set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
155      endif()
156    endif ()
157
158    # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils
159    # but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.)
160    if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$")
161      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
162    endif ()
163  endif()
164
165endif ()
166
167set(_CMAKE_PROCESSING_LANGUAGE "OBJC")
168include(CMakeFindBinUtils)
169include(Compiler/${CMAKE_OBJC_COMPILER_ID}-FindBinUtils OPTIONAL)
170unset(_CMAKE_PROCESSING_LANGUAGE)
171
172if(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID)
173  set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID
174    "set(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJC_COMPILER_ARCHITECTURE_ID})")
175else()
176  set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID "")
177endif()
178
179if(CMAKE_OBJC_XCODE_ARCHS)
180  set(SET_CMAKE_XCODE_ARCHS
181    "set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJC_XCODE_ARCHS}\")")
182endif()
183
184# configure variables set in this file for fast reload later on
185configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
186  ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
187  @ONLY
188  )
189set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")
190