Languages: Add support for Objective-C

Add entries in Modules and Modules/Platform to support
Objective-C compiler determination and identification.
Add Modules to check Objective-C compiler flags, source
compilations, program checks, etc...

Use OBJC as the designator of the language, eg:

project(foo OBJC)

Add various tests for Objective-C language features.  Add
tests to preserve C++ handling of .m and .mm files when
OBJC is not a configured language.

Co-Authored-By: Cristian Adam <cristian.adam@gmail.com>
This commit is contained in:
Steve Wilson
2019-09-13 18:11:15 +01:00
committed by Cristian Adam
parent 8c568722d7
commit 80f120a85f
39 changed files with 1248 additions and 8 deletions

View File

@@ -1,7 +1,7 @@
enable_language
---------------
Enable a language (CXX/C/Fortran/etc)
Enable a language (CXX/C/OBJC/Fortran/etc)
.. code-block:: cmake
@@ -10,7 +10,7 @@ Enable a language (CXX/C/Fortran/etc)
Enables support for the named language in CMake. This is
the same as the :command:`project` command but does not create any of the extra
variables that are created by the project command. Example languages
are ``CXX``, ``C``, ``CUDA``, ``Fortran``, and ``ASM``.
are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``Fortran``, and ``ASM``.
If enabling ``ASM``, enable it last so that CMake can check whether
compilers for other languages like ``C`` work for assembly too.

View File

@@ -87,7 +87,8 @@ The options are:
Can also be specified without ``LANGUAGES`` keyword per the first, short signature.
Selects which programming languages are needed to build the project.
Supported languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``, ``Fortran``, and ``ASM``.
Supported languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``, ``OBJC`` (i.e. Objective-C),
``Fortran``, and ``ASM``.
By default ``C`` and ``CXX`` are enabled if no language options are given.
Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
to skip enabling any languages.

View File

@@ -130,6 +130,11 @@ Variable Queries
``1`` if the CMake's compiler id of the CUDA compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<OBJC_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Objective-C compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Fortran compiler matches any one
@@ -413,6 +418,9 @@ Variable Queries
``$<CUDA_COMPILER_VERSION>``
The version of the CUDA compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<OBJC_COMPILER_VERSION>``
The version of the OBJC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<Fortran_COMPILER_VERSION>``
The version of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.

View File

@@ -36,6 +36,9 @@ These modules are loaded using the :command:`include` command.
/module/CheckIncludeFiles
/module/CheckLanguage
/module/CheckLibraryExists
/module/CheckOBJCCompilerFlag
/module/CheckOBJCSourceCompiles
/module/CheckOBJCSourceRuns
/module/CheckPIESupported
/module/CheckPrototypeDefinition
/module/CheckStructHasMember

View File

@@ -0,0 +1 @@
.. cmake-module:: ../../Modules/CheckOBJCCompilerFlag.cmake

View File

@@ -0,0 +1 @@
.. cmake-module:: ../../Modules/CheckOBJCSourceCompiles.cmake

View File

@@ -0,0 +1 @@
.. cmake-module:: ../../Modules/CheckOBJCSourceRuns.cmake

View File

@@ -42,8 +42,17 @@ if(CMAKE_COMPILER_IS_MINGW)
set(MINGW 1)
endif()
set(CMAKE_CXX_COMPILER_ID_RUN 1)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
foreach (lang OBJC)
if (CMAKE_${lang}_COMPILER_ID_RUN)
foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
endforeach()
endif()
endforeach()
set(CMAKE_CXX_LINKER_PREFERENCE 30)
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)

View File

@@ -0,0 +1,189 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# determine the compiler to use for Objective-C programs
# NOTE, a generator may set CMAKE_OBJC_COMPILER before
# loading this file to force a compiler.
# use environment variable OBJC first if defined by user, next use
# the cmake variable CMAKE_GENERATOR_OBJC which can be defined by a generator
# as a default compiler
#
# Sets the following variables:
# CMAKE_OBJC_COMPILER
# CMAKE_AR
# CMAKE_RANLIB
# CMAKE_COMPILER_IS_GNUOBJC
# CMAKE_COMPILER_IS_CLANGOBJC
#
# If not already set before, it also sets
# _CMAKE_TOOLCHAIN_PREFIX
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
# Load system-specific compiler preferences for this language.
include(Platform/${CMAKE_SYSTEM_NAME}-Determine-OBJC OPTIONAL)
include(Platform/${CMAKE_SYSTEM_NAME}-OBJC OPTIONAL)
if(NOT CMAKE_OBJC_COMPILER_NAMES)
set(CMAKE_OBJC_COMPILER_NAMES clang)
endif()
if("${CMAKE_GENERATOR}" MATCHES "Xcode")
set(CMAKE_OBJC_COMPILER_XCODE_TYPE sourcecode.c.objc)
else()
if(NOT CMAKE_OBJC_COMPILER)
set(CMAKE_OBJC_COMPILER_INIT NOTFOUND)
# prefer the environment variable OBJC
if($ENV{OBJC} MATCHES ".+")
get_filename_component(CMAKE_OBJC_COMPILER_INIT $ENV{OBJC} PROGRAM PROGRAM_ARGS CMAKE_OBJC_FLAGS_ENV_INIT)
if(CMAKE_OBJC_FLAGS_ENV_INIT)
set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_FLAGS_ENV_INIT}" CACHE STRING "First argument to Objective-C compiler")
endif()
if(NOT EXISTS ${CMAKE_OBJC_COMPILER_INIT})
message(FATAL_ERROR "Could not find compiler set in environment variable OBJC:\n$ENV{OBJC}.")
endif()
endif()
# next try prefer the compiler specified by the generator
if(CMAKE_GENERATOR_OBJC)
if(NOT CMAKE_OBJC_COMPILER_INIT)
set(CMAKE_OBJC_COMPILER_INIT ${CMAKE_GENERATOR_OBJC})
endif()
endif()
# finally list compilers to try
if(NOT CMAKE_OBJC_COMPILER_INIT)
set(CMAKE_OBJC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang)
endif()
_cmake_find_compiler(OBJC)
else()
# we only get here if CMAKE_OBJC_COMPILER was specified using -D or a pre-made CMakeCache.txt
# (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
# if CMAKE_OBJC_COMPILER is a list of length 2, use the first item as
# CMAKE_OBJC_COMPILER and the 2nd one as CMAKE_OBJC_COMPILER_ARG1
list(LENGTH CMAKE_OBJC_COMPILER _CMAKE_OBJC_COMPILER_LIST_LENGTH)
if("${_CMAKE_OBJC_COMPILER_LIST_LENGTH}" EQUAL 2)
list(GET CMAKE_OBJC_COMPILER 1 CMAKE_OBJC_COMPILER_ARG1)
list(GET CMAKE_OBJC_COMPILER 0 CMAKE_OBJC_COMPILER)
endif()
# if a compiler was specified by the user but without path,
# now try to find it with the full path
# if it is found, force it into the cache,
# if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
# if the C compiler already had a path, reuse it for searching the CXX compiler
get_filename_component(_CMAKE_USER_OBJC_COMPILER_PATH "${CMAKE_OBJC_COMPILER}" PATH)
if(NOT _CMAKE_USER_OBJC_COMPILER_PATH)
find_program(CMAKE_OBJC_COMPILER_WITH_PATH NAMES ${CMAKE_OBJC_COMPILER})
if(CMAKE_OBJC_COMPILER_WITH_PATH)
set(CMAKE_OBJC_COMPILER ${CMAKE_OBJC_COMPILER_WITH_PATH} CACHE STRING "Objective-C compiler" FORCE)
endif()
unset(CMAKE_OBJC_COMPILER_WITH_PATH CACHE)
endif()
endif()
mark_as_advanced(CMAKE_OBJC_COMPILER)
# Each entry in this list is a set of extra flags to try
# adding to the compile line to see if it helps produce
# a valid identification file.
set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS_FIRST)
set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS
# Try compiling to an object file only.
"-c"
)
endif()
# Build a small source file to identify the compiler.
if(NOT CMAKE_OBJC_COMPILER_ID_RUN)
set(CMAKE_OBJC_COMPILER_ID_RUN 1)
# Try to identify the compiler.
set(CMAKE_OBJC_COMPILER_ID)
file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT)
# Match the link line from xcodebuild output of the form
# Ld ...
# ...
# /path/to/cc ...CompilerIdOBJC/...
# to extract the compiler front-end for the language.
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)/)?CompilerIdOBJC[ \t\n\\\"]")
set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_INDEX 2)
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
CMAKE_DETERMINE_COMPILER_ID(OBJC OBJCCFLAGS CMakeOBJCCompilerId.m)
# Set old compiler and platform id variables.
if(CMAKE_OBJC_COMPILER_ID STREQUAL "GNU")
set(CMAKE_COMPILER_IS_GNUOBJC 1)
endif()
if(CMAKE_OBJC_COMPILER_ID STREQUAL "Clang")
set(CMAKE_COMPILER_IS_CLANGOBJC 1)
endif()
endif()
if (NOT _CMAKE_TOOLCHAIN_LOCATION)
get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJC_COMPILER}" PATH)
endif ()
# If we have a gcc cross compiler, they have usually some prefix, like
# e.g. powerpc-linux-gcc, arm-elf-gcc or i586-mingw32msvc-gcc, optionally
# with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2).
# The other tools of the toolchain usually have the same prefix
# NAME_WE cannot be used since then this test will fail for names like
# "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
# "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX)
if(CMAKE_OBJC_COMPILER_ID MATCHES "GNU|Clang|QCC")
get_filename_component(COMPILER_BASENAME "${CMAKE_OBJC_COMPILER}" NAME)
if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
elseif(CMAKE_OBJC_COMPILER_ID MATCHES "Clang")
if(CMAKE_OBJC_COMPILER_TARGET)
set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJC_COMPILER_TARGET}-)
endif()
elseif(COMPILER_BASENAME MATCHES "qcc(\\.exe)?$")
if(CMAKE_OBJC_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)?")
set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
endif()
endif ()
# if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils
# but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.)
if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$")
set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
endif ()
endif()
endif ()
set(_CMAKE_PROCESSING_LANGUAGE "OBJC")
include(CMakeFindBinUtils)
include(Compiler/${CMAKE_OBJC_COMPILER_ID}-FindBinUtils OPTIONAL)
unset(_CMAKE_PROCESSING_LANGUAGE)
if(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID)
set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID
"set(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJC_COMPILER_ARCHITECTURE_ID})")
else()
set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID "")
endif()
if(CMAKE_OBJC_XCODE_ARCHS)
set(SET_CMAKE_XCODE_ARCHS
"set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJC_XCODE_ARCHS}\")")
endif()
# configure variables set in this file for fast reload later on
configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
@ONLY
)
set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")

View File

@@ -0,0 +1,69 @@
set(CMAKE_OBJC_COMPILER "@CMAKE_OBJC_COMPILER@")
set(CMAKE_OBJC_COMPILER_ARG1 "@CMAKE_OBJC_COMPILER_ARG1@")
set(CMAKE_OBJC_COMPILER_ID "@CMAKE_OBJC_COMPILER_ID@")
set(CMAKE_OBJC_COMPILER_VERSION "@CMAKE_OBJC_COMPILER_VERSION@")
set(CMAKE_OBJC_COMPILER_VERSION_INTERNAL "@CMAKE_OBJC_COMPILER_VERSION_INTERNAL@")
set(CMAKE_OBJC_COMPILER_WRAPPER "@CMAKE_OBJC_COMPILER_WRAPPER@")
set(CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT@")
set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@")
set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@")
set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@")
set(CMAKE_OBJC11_COMPILE_FEATURES "@CMAKE_OBJC11_COMPILE_FEATURES@")
set(CMAKE_OBJC_PLATFORM_ID "@CMAKE_OBJC_PLATFORM_ID@")
set(CMAKE_OBJC_SIMULATE_ID "@CMAKE_OBJC_SIMULATE_ID@")
set(CMAKE_OBJC_COMPILER_FRONTEND_VARIANT "@CMAKE_OBJC_COMPILER_FRONTEND_VARIANT@")
set(CMAKE_OBJC_SIMULATE_VERSION "@CMAKE_OBJC_SIMULATE_VERSION@")
@_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID@
@SET_CMAKE_XCODE_ARCHS@
set(CMAKE_AR "@CMAKE_AR@")
set(CMAKE_OBJC_COMPILER_AR "@CMAKE_OBJC_COMPILER_AR@")
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_OBJC_COMPILER_RANLIB "@CMAKE_OBJC_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_COMPILER_IS_GNUOBJC @CMAKE_COMPILER_IS_GNUOBJC@)
set(CMAKE_OBJC_COMPILER_LOADED 1)
set(CMAKE_OBJC_COMPILER_WORKS @CMAKE_OBJC_COMPILER_WORKS@)
set(CMAKE_OBJC_ABI_COMPILED @CMAKE_OBJC_ABI_COMPILED@)
set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")
set(CMAKE_OBJC_COMPILER_ID_RUN 1)
set(CMAKE_OBJC_SOURCE_FILE_EXTENSIONS m)
set(CMAKE_OBJC_IGNORE_EXTENSIONS h;H;o;O)
set(CMAKE_OBJC_LINKER_PREFERENCE 5)
foreach (lang C CXX OBJCXX)
foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
if (CMAKE_${lang}_COMPILER_ID_RUN)
list(REMOVE_ITEM CMAKE_${lang}_SOURCE_FILE_EXTENSIONS ${extension})
endif()
endforeach()
endforeach()
# Save compiler ABI information.
set(CMAKE_OBJC_SIZEOF_DATA_PTR "@CMAKE_OBJC_SIZEOF_DATA_PTR@")
set(CMAKE_OBJC_COMPILER_ABI "@CMAKE_OBJC_COMPILER_ABI@")
set(CMAKE_OBJC_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
if(CMAKE_OBJC_SIZEOF_DATA_PTR)
set(CMAKE_SIZEOF_VOID_P "${CMAKE_OBJC_SIZEOF_DATA_PTR}")
endif()
if(CMAKE_OBJC_COMPILER_ABI)
set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_OBJC_COMPILER_ABI}")
endif()
if(CMAKE_OBJC_LIBRARY_ARCHITECTURE)
set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
endif()
@CMAKE_OBJC_COMPILER_CUSTOM_CODE@
@CMAKE_OBJC_SYSROOT_FLAG_CODE@
@CMAKE_OBJC_OSX_DEPLOYMENT_TARGET_FLAG_CODE@
set(CMAKE_OBJC_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_INCLUDE_DIRECTORIES@")
set(CMAKE_OBJC_IMPLICIT_LINK_LIBRARIES "@CMAKE_OBJC_IMPLICIT_LINK_LIBRARIES@")
set(CMAKE_OBJC_IMPLICIT_LINK_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_LINK_DIRECTORIES@")
set(CMAKE_OBJC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")

View File

@@ -0,0 +1,20 @@
#ifdef __cplusplus
# error "A C++ compiler has been selected for Objective-C."
#endif
/*--------------------------------------------------------------------------*/
#include "CMakeCompilerABI.h"
/*--------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int require = 0;
require += info_sizeof_dptr[argc];
#if defined(ABI_ID)
require += info_abi[argc];
#endif
(void)argv;
return require;
}

View File

@@ -0,0 +1,63 @@
#ifdef __cplusplus
# error "An Objective-C++ compiler has been selected for Objective-C."
#endif
@CMAKE_OBJC_COMPILER_ID_CONTENT@
/* Construct the string literal in pieces to prevent the source from
getting matched. Store it in a pointer rather than an array
because some compilers will just produce instructions to fill the
array rather than assigning a pointer to a static array. */
char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
#ifdef SIMULATE_ID
char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
#endif
#ifdef __QNXNTO__
char const* qnxnto = "INFO" ":" "qnxnto[]";
#endif
@CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT@
@CMAKE_OBJC_COMPILER_ID_ERROR_FOR_TEST@
#if !defined(__STDC__)
# if (defined(_MSC_VER) && !defined(__clang__)) \
|| (defined(__ibmxl__) || defined(__IBMC__))
# define C_DIALECT "90"
# else
# define C_DIALECT
# endif
#elif __STDC_VERSION__ >= 201000L
# define C_DIALECT "11"
#elif __STDC_VERSION__ >= 199901L
# define C_DIALECT "99"
#else
# define C_DIALECT "90"
#endif
const char* info_language_dialect_default =
"INFO" ":" "dialect_default[" C_DIALECT "]";
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[])
{
int require = 0;
require += info_compiler[argc];
require += info_platform[argc];
require += info_arch[argc];
#ifdef COMPILER_VERSION_MAJOR
require += info_version[argc];
#endif
#ifdef COMPILER_VERSION_INTERNAL
require += info_version_internal[argc];
#endif
#ifdef SIMULATE_ID
require += info_simulate[argc];
#endif
#ifdef SIMULATE_VERSION_MAJOR
require += info_simulate_version[argc];
#endif
require += info_language_dialect_default[argc];
(void)argv;
return require;
}

View File

@@ -0,0 +1,188 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# This file sets the basic flags for the Objective-C language in CMake.
# It also loads the available platform file for the system-compiler
# if it exists.
# It also loads a system - compiler - processor (or target hardware)
# specific file, which is mainly useful for crosscompiling and embedded systems.
include(CMakeLanguageInformation)
# some compilers use different extensions (e.g. sdcc uses .rel)
# so set the extension here first so it can be overridden by the compiler specific file
set(CMAKE_OBJC_OUTPUT_EXTENSION .o)
if(NOT CMAKE_INCLUDE_FLAG_OBJC)
set(CMAKE_INCLUDE_FLAG_OBJC ${CMAKE_INCLUDE_FLAG_C})
endif()
set(_INCLUDED_FILE 0)
# Load compiler-specific information.
if(CMAKE_OBJC_COMPILER_ID)
include(Compiler/${CMAKE_OBJC_COMPILER_ID}-OBJC OPTIONAL)
endif()
set(CMAKE_BASE_NAME)
get_filename_component(CMAKE_BASE_NAME "${CMAKE_OBJC_COMPILER}" NAME_WE)
if(CMAKE_COMPILER_IS_GNUOBJC)
set(CMAKE_BASE_NAME gcc)
endif()
# load a hardware specific file, mostly useful for embedded compilers
if(CMAKE_SYSTEM_PROCESSOR)
if(CMAKE_OBJC_COMPILER_ID)
include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJC_COMPILER_ID}-OBJC-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif ()
endif()
# load the system- and compiler specific files
if(CMAKE_OBJC_COMPILER_ID)
include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJC_COMPILER_ID}-OBJC
OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}
OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif ()
# load any compiler-wrapper specific information
if (CMAKE_OBJC_COMPILER_WRAPPER)
__cmake_include_compiler_wrapper(OBJC)
endif ()
# We specify the compiler information in the system file for some
# platforms, but this language may not have been enabled when the file
# was first included. Include it again to get the language info.
# Remove this when all compiler info is removed from system files.
if (NOT _INCLUDED_FILE)
include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)
endif ()
if(CMAKE_OBJC_SIZEOF_DATA_PTR)
foreach(f ${CMAKE_OBJC_ABI_FILES})
include(${f})
endforeach()
unset(CMAKE_OBJC_ABI_FILES)
endif()
# This should be included before the _INIT variables are
# used to initialize the cache. Since the rule variables
# have if blocks on them, users can still define them here.
# But, it should still be after the platform file so changes can
# be made to those values.
if(CMAKE_USER_MAKE_RULES_OVERRIDE)
# Save the full path of the file so try_compile can use it.
include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
endif()
if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC)
# Save the full path of the file so try_compile can use it.
include(${CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC} RESULT_VARIABLE _override)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC "${_override}")
endif()
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
# copy the values from the LIBRARY variables
if(NOT CMAKE_MODULE_EXISTS)
set(CMAKE_SHARED_MODULE_OBJC_FLAGS ${CMAKE_SHARED_LIBRARY_OBJC_FLAGS})
set(CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS})
endif()
set(CMAKE_OBJC_FLAGS_INIT "$ENV{OBJCFLAGS} ${CMAKE_OBJC_FLAGS_INIT}")
cmake_initialize_per_config_variable(CMAKE_OBJC_FLAGS "Flags used by the Objective-C compiler")
if(CMAKE_OBJC_STANDARD_LIBRARIES_INIT)
set(CMAKE_OBJC_STANDARD_LIBRARIES "${CMAKE_OBJC_STANDARD_LIBRARIES_INIT}"
CACHE STRING "Libraries linked by default with all Objective-C applications.")
mark_as_advanced(CMAKE_OBJC_STANDARD_LIBRARIES)
endif()
include(CMakeCommonLanguageInclude)
# now define the following rule variables
# CMAKE_OBJC_CREATE_SHARED_LIBRARY
# CMAKE_OBJC_CREATE_SHARED_MODULE
# CMAKE_OBJC_COMPILE_OBJECT
# CMAKE_OBJC_LINK_EXECUTABLE
# variables supplied by the generator at use time
# <TARGET>
# <TARGET_BASE> the target without the suffix
# <OBJECTS>
# <OBJECT>
# <LINK_LIBRARIES>
# <FLAGS>
# <LINK_FLAGS>
# Objective-C compiler information
# <CMAKE_OBJC_COMPILER>
# <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS>
# <CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS>
# <CMAKE_OBJC_LINK_FLAGS>
# Static library tools
# <CMAKE_AR>
# <CMAKE_RANLIB>
# create an Objective-C shared library
if(NOT CMAKE_OBJC_CREATE_SHARED_LIBRARY)
set(CMAKE_OBJC_CREATE_SHARED_LIBRARY
"<CMAKE_OBJC_COMPILER> <CMAKE_SHARED_LIBRARY_OBJC_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
endif()
# create an Objective-C shared module just copy the shared library rule
if(NOT CMAKE_OBJC_CREATE_SHARED_MODULE)
set(CMAKE_OBJC_CREATE_SHARED_MODULE ${CMAKE_OBJC_CREATE_SHARED_LIBRARY})
endif()
# Create an static archive incrementally for large object file counts.
# If CMAKE_OBJC_CREATE_STATIC_LIBRARY is set it will override these.
if(NOT DEFINED CMAKE_OBJC_ARCHIVE_CREATE)
set(CMAKE_OBJC_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
endif()
if(NOT DEFINED CMAKE_OBJC_ARCHIVE_APPEND)
set(CMAKE_OBJC_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
endif()
if(NOT DEFINED CMAKE_OBJC_ARCHIVE_FINISH)
set(CMAKE_OBJC_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
endif()
# compile an Objective-C file into an object file
if(NOT CMAKE_OBJC_COMPILE_OBJECT)
set(CMAKE_OBJC_COMPILE_OBJECT
"<CMAKE_OBJC_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
endif()
if(NOT CMAKE_OBJC_LINK_EXECUTABLE)
set(CMAKE_OBJC_LINK_EXECUTABLE
"<CMAKE_OBJC_COMPILER> <FLAGS> <CMAKE_OBJC_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()
if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG)
set(CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG})
endif()
if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG_SEP)
set(CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG_SEP})
endif()
if(NOT CMAKE_EXECUTABLE_RPATH_LINK_OBJC_FLAG)
set(CMAKE_EXECUTABLE_RPATH_LINK_OBJC_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJC_FLAG})
endif()
set(CMAKE_OBJC_INFORMATION_LOADED 1)

View File

@@ -0,0 +1,94 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
if(CMAKE_OBJC_COMPILER_FORCED)
# The compiler configuration was forced by the user.
# Assume the user has configured all compiler information.
set(CMAKE_OBJC_COMPILER_WORKS TRUE)
return()
endif()
include(CMakeTestCompilerCommon)
# work around enforced code signing and / or missing exectuable target type
set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE)
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE})
endif()
# Remove any cached result from an older CMake version.
# We now store this in CMakeCCompiler.cmake.
unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
# determine that that selected Objective-C compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
if(NOT CMAKE_OBJC_COMPILER_WORKS)
PrintTestCompilerStatus("OBJC" "")
__TestCompiler_setTryCompileTargetType()
file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
"#ifdef __cplusplus\n"
"# error \"The CMAKE_OBJC_COMPILER is set to a C++ compiler\"\n"
"#endif\n"
"#ifndef __OBJC__\n"
"# error \"The CMAKE_OBJC_COMPILER is not an Objective-C compiler\"\n"
"#endif\n"
"int main(int argc, char* argv[])\n"
"{ (void)argv; return argc-1;}\n")
try_compile(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT)
# Move result from cache to normal variable.
set(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_OBJC_COMPILER_WORKS})
unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
set(OBJC_TEST_WAS_RUN 1)
__TestCompiler_restoreTryCompileTargetType()
endif()
if(NOT CMAKE_OBJC_COMPILER_WORKS)
PrintTestCompilerStatus("OBJC" " -- broken")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the Objective-C compiler works failed with "
"the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n")
string(REPLACE "\n" "\n " _output "${__CMAKE_OBJC_COMPILER_OUTPUT}")
message(FATAL_ERROR "The Objective-C compiler\n \"${CMAKE_OBJC_COMPILER}\"\n"
"is not able to compile a simple test program.\nIt fails "
"with the following output:\n ${_output}\n\n"
"CMake will not be able to correctly generate this project.")
else()
if(OBJC_TEST_WAS_RUN)
PrintTestCompilerStatus("OBJC" " -- works")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if the Objective-C compiler works passed with "
"the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n")
endif()
# Try to identify the ABI and configure it into CMakeOBJCCompiler.cmake
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
CMAKE_DETERMINE_COMPILER_ABI(OBJC ${CMAKE_ROOT}/Modules/CMakeOBJCCompilerABI.m)
# Try to identify the compiler features
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
CMAKE_DETERMINE_COMPILE_FEATURES(OBJC)
# Re-configure to save learned information.
configure_file(
${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
@ONLY
)
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake)
if(CMAKE_OBJC_SIZEOF_DATA_PTR)
foreach(f ${CMAKE_OBJC_ABI_FILES})
include(${f})
endforeach()
unset(CMAKE_OBJC_ABI_FILES)
endif()
endif()
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE})
unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE)
unset(__CMAKE_OBJC_COMPILER_OUTPUT)

View File

@@ -0,0 +1,64 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
CheckOBJCCompilerFlag
---------------------
Check whether the Objective-C compiler supports a given flag.
.. command:: check_objc_compiler_flag
.. code-block:: cmake
check_objc_compiler_flag(<flag> <var>)
Check that the ``<flag>`` is accepted by the compiler without
a diagnostic. Stores the result in an internal cache entry
named ``<var>``.
This command temporarily sets the ``CMAKE_REQUIRED_DEFINITIONS`` variable
and calls the ``check_objc_source_compiles`` macro from the
:module:`CheckOBJCSourceCompiles` module. See documentation of that
module for a listing of variables that can otherwise modify the build.
A positive result from this check indicates only that the compiler did not
issue a diagnostic message when given the flag. Whether the flag has any
effect or even a specific one is beyond the scope of this module.
.. note::
Since the :command:`try_compile` command forwards flags from variables
like :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
in such variables may cause a false negative for this check.
#]=======================================================================]
include_guard(GLOBAL)
include(CheckOBJCSourceCompiles)
include(CMakeCheckCompilerFlagCommonPatterns)
macro (CHECK_OBJC_COMPILER_FLAG _FLAG _RESULT)
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
# Normalize locale during test compilation.
set(_CheckOBJCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
set(_CheckOBJCCompilerFlag_SAVED_${v} "$ENV{${v}}")
set(ENV{${v}} OBJC)
endforeach()
CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
CHECK_OBJC_SOURCE_COMPILES("#ifndef __OBJC__\n# error \"Not an Objective-C compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
# Some compilers do not fail with a bad flag
FAIL_REGEX "command line option .* is valid for .* but not for Objective-C" # GNU
FAIL_REGEX "argument unused during compilation: .*" # Clang
${_CheckOBJCCompilerFlag_COMMON_PATTERNS}
)
foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
set(ENV{${v}} ${_CheckOBJCCompilerFlag_SAVED_${v}})
unset(_CheckOBJCCompilerFlag_SAVED_${v})
endforeach()
unset(_CheckOBJCCompilerFlag_LOCALE_VARS)
unset(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
endmacro ()

View File

@@ -0,0 +1,145 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
CheckOBJCSourceCompiles
-----------------------
Check if given Objective-C source compiles and links into an executable.
.. command:: check_objc_source_compiles
.. code-block:: cmake
check_objc_source_compiles(<code> <resultVar>
[FAIL_REGEX <regex1> [<regex2>...]])
Check that the source supplied in ``<code>`` can be compiled as a Objectie-C source
file and linked as an executable (so it must contain at least a ``main()``
function). The result will be stored in the internal cache variable specified
by ``<resultVar>``, with a boolean true value for success and boolean false
for failure. If ``FAIL_REGEX`` is provided, then failure is determined by
checking if anything in the output matches any of the specified regular
expressions.
The underlying check is performed by the :command:`try_compile` command. The
compile and link commands can be influenced by setting any of the following
variables prior to calling ``check_objc_source_compiles()``:
``CMAKE_REQUIRED_FLAGS``
Additional flags to pass to the compiler. Note that the contents of
:variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
configuration-specific variable are automatically added to the compiler
command before the contents of ``CMAKE_REQUIRED_FLAGS``.
``CMAKE_REQUIRED_DEFINITIONS``
A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
``<resultVar>`` will also be added automatically.
``CMAKE_REQUIRED_INCLUDES``
A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler. These will be the only header search paths used by
``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_compile` for further details).
``CMAKE_REQUIRED_LIBRARIES``
A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. These can be the name of system libraries or they can be
:ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for
further details).
``CMAKE_REQUIRED_QUIET``
If this variable evaluates to a boolean true value, all status messages
associated with the check will be suppressed.
The check is only performed once, with the result cached in the variable
named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
value rather than performing the check again, even if the ``<code>`` changes.
In order to force the check to be re-evaluated, the variable named by
``<resultVar>`` must be manually removed from the cache.
#]=======================================================================]
include_guard(GLOBAL)
macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR)
if(NOT DEFINED "${VAR}")
set(_FAIL_REGEX)
set(_key)
foreach(arg ${ARGN})
if("${arg}" MATCHES "^(FAIL_REGEX)$")
set(_key "${arg}")
elseif(_key)
list(APPEND _${_key} "${arg}")
else()
message(FATAL_ERROR "Unknown argument:\n ${arg}\n")
endif()
endforeach()
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LINK_OPTIONS)
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS
LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
else()
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS)
endif()
if(CMAKE_REQUIRED_LIBRARIES)
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES
LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
else()
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES)
endif()
if(CMAKE_REQUIRED_INCLUDES)
set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
else()
set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES)
endif()
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m"
"${SOURCE}\n")
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VAR}")
endif()
try_compile(${VAR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS}
${CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
foreach(_regex ${_FAIL_REGEX})
if("${OUTPUT}" MATCHES "${_regex}")
set(${VAR} 0)
endif()
endforeach()
if(${VAR})
set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VAR} - Success")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
else()
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VAR} - Failed")
endif()
set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing Objective-C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
endif()
endif()
endmacro()

View File

@@ -0,0 +1,145 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
CheckOBJCSourceRuns
-------------------
Check if given Objective-C source compiles and links into an executable and can
subsequently be run.
.. command:: check_objc_source_runs
.. code-block:: cmake
check_objc_source_runs(<code> <resultVar>)
Check that the source supplied in ``<code>`` can be compiled as a Objective-C source
file, linked as an executable and then run. The ``<code>`` must contain at
least a ``main()`` function. If the ``<code>`` could be built and run
successfully, the internal cache variable specified by ``<resultVar>`` will
be set to 1, otherwise it will be set to an value that evaluates to boolean
false (e.g. an empty string or an error message).
The underlying check is performed by the :command:`try_run` command. The
compile and link commands can be influenced by setting any of the following
variables prior to calling ``check_objc_source_runs()``:
``CMAKE_REQUIRED_FLAGS``
Additional flags to pass to the compiler. Note that the contents of
:variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
configuration-specific variable are automatically added to the compiler
command before the contents of ``CMAKE_REQUIRED_FLAGS``.
``CMAKE_REQUIRED_DEFINITIONS``
A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
``<resultVar>`` will also be added automatically.
``CMAKE_REQUIRED_INCLUDES``
A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler. These will be the only header search paths used by
``try_run()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_run` for further details).
``CMAKE_REQUIRED_LIBRARIES``
A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. These can be the name of system libraries or they can be
:ref:`Imported Targets <Imported Targets>` (see :command:`try_run` for
further details).
``CMAKE_REQUIRED_QUIET``
If this variable evaluates to a boolean true value, all status messages
associated with the check will be suppressed.
The check is only performed once, with the result cached in the variable
named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
value rather than performing the check again, even if the ``<code>`` changes.
In order to force the check to be re-evaluated, the variable named by
``<resultVar>`` must be manually removed from the cache.
#]=======================================================================]
include_guard(GLOBAL)
macro(CHECK_OBJC_SOURCE_RUNS SOURCE VAR)
if(NOT DEFINED "${VAR}")
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LINK_OPTIONS)
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS
LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
else()
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS)
endif()
if(CMAKE_REQUIRED_LIBRARIES)
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES
LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
else()
set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES)
endif()
if(CMAKE_REQUIRED_INCLUDES)
set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
else()
set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES)
endif()
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m"
"${SOURCE}\n")
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VAR}")
endif()
try_run(${VAR}_EXITCODE ${VAR}_COMPILED
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS}
${CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
-DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
"${CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES}"
COMPILE_OUTPUT_VARIABLE OUTPUT
RUN_OUTPUT_VARIABLE RUN_OUTPUT)
# if it did not compile make the return value fail code of 1
if(NOT ${VAR}_COMPILED)
set(${VAR}_EXITCODE 1)
endif()
# if the return value was 0 then it worked
if("${${VAR}_EXITCODE}" EQUAL 0)
set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VAR} - Success")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n"
"${OUTPUT}\n"
"...and run output:\n"
"${RUN_OUTPUT}\n"
"Return value: ${${VAR}}\n"
"Source file was:\n${SOURCE}\n")
else()
if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN")
set(${VAR} "${${VAR}_EXITCODE}")
else()
set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
endif()
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VAR} - Failed")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing Objective-C SOURCE FILE Test ${VAR} failed with the following compile output:\n"
"${OUTPUT}\n"
"...and run output:\n"
"${RUN_OUTPUT}\n"
"Return value: ${${VAR}_EXITCODE}\n"
"Source file was:\n${SOURCE}\n")
endif()
endif()
endmacro()

View File

@@ -0,0 +1,17 @@
include(Compiler/Clang-OBJC)
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0)
set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
set(CMAKE_OBJC90_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_OBJC99_STANDARD_COMPILE_OPTION "-std=c99")
set(CMAKE_OBJC99_EXTENSION_COMPILE_OPTION "-std=gnu99")
set(CMAKE_OBJC99_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_OBJC11_STANDARD_COMPILE_OPTION "-std=c11")
set(CMAKE_OBJC11_EXTENSION_COMPILE_OPTION "-std=gnu11")
set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
endif()
__compiler_check_default_language_standard(OBJC 4.0 99)

View File

@@ -0,0 +1,18 @@
include(Compiler/Clang)
__compiler_clang(OBJC)
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4)
set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
set(CMAKE_OBJC90_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_OBJC99_STANDARD_COMPILE_OPTION "-std=c99")
set(CMAKE_OBJC99_EXTENSION_COMPILE_OPTION "-std=gnu99")
set(CMAKE_OBJC99_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_OBJC11_STANDARD_COMPILE_OPTION "-std=c11")
set(CMAKE_OBJC11_EXTENSION_COMPILE_OPTION "-std=gnu11")
set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
endif()
__compiler_check_default_language_standard(OBJC 3.4 99 3.6 11)

View File

@@ -0,0 +1,6 @@
include(Compiler/GNU)
__compiler_gnu(OBJC)
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif()

View File

@@ -0,0 +1,6 @@
include(Platform/Apple-Clang-OBJC)
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.2)
set(CMAKE_OBJC_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
else()
unset(CMAKE_OBJC_SYSTEM_FRAMEWORK_SEARCH_FLAG)
endif()

View File

@@ -0,0 +1,2 @@
include(Platform/Apple-Clang)
__apple_compiler_clang(OBJC)

View File

@@ -0,0 +1,4 @@
include(Platform/Apple-GNU)
__apple_compiler_gnu(OBJC)
cmake_gnu_set_sysroot_flag(OBJC)
cmake_gnu_set_osx_deployment_target_flag(OBJC)

View File

@@ -119,10 +119,15 @@ set(CMAKE_C_CREATE_MACOSX_FRAMEWORK
set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
"<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_OBJC_CREATE_MACOSX_FRAMEWORK
"<CMAKE_OBJC_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <LINK_FLAGS> -o <TARGET> -dynamiclib -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>"
)
# Set default framework search path flag for languages known to use a
# preprocessor that may find headers in frameworks.
set(CMAKE_C_FRAMEWORK_SEARCH_FLAG -F)
set(CMAKE_CXX_FRAMEWORK_SEARCH_FLAG -F)
set(CMAKE_OBJC_FRAMEWORK_SEARCH_FLAG -F)
set(CMAKE_Fortran_FRAMEWORK_SEARCH_FLAG -F)
# default to searching for frameworks first
@@ -222,7 +227,7 @@ unset(_apps_paths)
include(Platform/UnixPaths)
if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr)
foreach(lang C CXX)
foreach(lang C CXX OBJC)
list(APPEND _CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
endforeach()
endif()

View File

@@ -1654,7 +1654,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
const char* deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
if (!archs.empty() && !lang.empty() &&
(lang[0] == 'C' || lang[0] == 'F')) {
(lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) {
for (std::string const& arch : archs) {
flags += " -arch ";
flags += arch;

View File

@@ -2328,6 +2328,43 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CFBundleTest")
ADD_TEST_MACRO(ObjC++ ObjC++)
add_test(Objective-C.simple-build-test ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/Objective-C/simple-build-test"
"${CMake_BINARY_DIR}/Tests/Objective-C/simple-build-test"
--build-two-config
${build_generator_args}
--build-project simple-build-test
--build-options ${build_options}
--test-command simple-build-test
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/simple-build-test")
add_test(Objective-C.c-file-extension-test ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/Objective-C/c-file-extension-test"
"${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test"
--build-two-config
${build_generator_args}
--build-project c-file-extension-test
--build-options ${build_options}
--test-command c-file-extension-test
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test")
add_test(Objective-C.objc-file-extension-test ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/Objective-C/objc-file-extension-test"
"${CMake_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test"
--build-two-config
${build_generator_args}
--build-project objc-file-extension-test
--build-options ${build_options}
--test-command objc-file-extension-test
)
list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test")
endif ()
endif ()

View File

@@ -30,6 +30,12 @@ add_CMakeOnly_test(CheckStructHasMember)
add_CMakeOnly_test(CompilerIdC)
add_CMakeOnly_test(CompilerIdCXX)
if(CMAKE_OBJC_COMPILER)
add_CMakeOnly_test(CompilerIdOBJC)
add_CMakeOnly_test(CheckOBJCCompilerFlag)
endif()
if(CMAKE_Fortran_COMPILER)
add_CMakeOnly_test(CompilerIdFortran)
endif()

View File

@@ -5,10 +5,19 @@ include(CheckLanguage)
set(langs )
set(expect_C 1)
set(expect_CXX 1)
if(APPLE)
set(expect_OBJC 1)
endif()
unset(expect_Fortran)
set(expect_NoSuchLanguage 0)
foreach(lang C CXX Fortran CUDA NoSuchLanguage)
set(LANGUAGES C CXX Fortran CUDA NoSuchLanguage)
if(APPLE)
list(APPEND LANGUAGES OBJC)
endif()
foreach(lang ${LANGUAGES})
check_language(${lang})
if(NOT DEFINED CMAKE_${lang}_COMPILER)
message(FATAL_ERROR "check_language(${lang}) did not set result")

View File

@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 2.8.12)
project(CheckOBJCCompilerFlag)
include(CheckOBJCCompilerFlag)
if(CMAKE_COMPILER_IS_GNUOBJC)
set(COMPILER_FLAG -fobjc-direct-dispatch)
else()
set(COMPILER_FLAG -fobjc-gc)
endif()
CHECK_OBJC_COMPILER_FLAGS(${COMPILER_FLAG} HAS_COMPILER_FLAG)
if(NOT HAS_COMPILER_FLAG)
message(SEND_ERROR "Test fail: HAS_COMPILER_FLAG: ${COMPILER_FLAG}")
endif

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.8.12)
project(CompilerIdOBJC OBJC)
foreach(v
CMAKE_OBJC_COMPILER
CMAKE_OBJC_COMPILER_ID
CMAKE_OBJC_COMPILER_VERSION
)
if(${v})
message(STATUS "${v}=[${${v}}]")
else()
message(SEND_ERROR "${v} not set!")
endif()
endforeach()

View File

@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(c-file-extension-test C)
add_executable(c-file-extension-test main.m)

View File

@@ -0,0 +1,8 @@
#ifndef __OBJC__
# error "Compiler cannot compile Objective-C"
#endif
int main()
{
return 0;
}

View File

@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.15)
project(objc-file-extension-test OBJC CXX)
add_executable(objc-file-extension-test main.m)
target_link_libraries(objc-file-extension-test "-framework Foundation")

View File

@@ -0,0 +1,12 @@
#ifndef __OBJC__
# error "Compiler is not an Objective-C compiler."
#endif
#import <Foundation/Foundation.h>
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[pool release];
return 0;
}

View File

@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.15)
set(CMAKE_MACOSX_RPATH OFF)
project(simple-build-test OBJC)
add_library(foo SHARED foo.m)
target_link_libraries(foo "-framework Foundation")
add_executable(simple-build-test main.m)
target_link_libraries(simple-build-test "-framework Foundation" foo)

View File

@@ -0,0 +1,9 @@
#import <Foundation/Foundation.h>
@interface Foo : NSObject {
NSNumber* age;
}
@property (nonatomic, retain) NSNumber* age;
@end

View File

@@ -0,0 +1,7 @@
#import "foo.h"
@implementation Foo
@synthesize age;
@end

View File

@@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import "foo.h"
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Foo *theFoo = [[Foo alloc] init];
theFoo.age = [NSNumber numberWithInt:argc];
NSLog(@"%d\n",[theFoo.age intValue]);
[pool release];
return 0;
}

View File

@@ -1,5 +1,5 @@
cmake_minimum_required (VERSION 2.6)
project(TryCompile)
project(TryCompile OBJC C CXX)
macro(TEST_ASSERT value msg)
if (NOT ${value})
@@ -313,6 +313,34 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
TEST_ASSERT(C_STRICT_PROTOTYPES "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes")
endif()
#########################################################################
#
# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJC_SOURCE_RUNS
# macros work.
include(CheckOBJCSourceCompiles)
include(CheckOBJCSourceRuns)
CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL)
CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK)
TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed")
TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation")
CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK)
CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL)
CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK)
CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL)
CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK)
TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed")
TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed")
TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
#######################################################################
#
# also test that the check_prototype_definition macro works