diff options
author | Brad King <brad.king@kitware.com> | 2019-09-30 14:24:55 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2019-09-30 14:25:19 (GMT) |
commit | 9b03baee308d78db119554def6e34fd9db9683ac (patch) | |
tree | b02b7066410e92956bf1a11401ac923be1f9a855 | |
parent | b24e501bc289956867b6104aac9d07afb75c906e (diff) | |
parent | dd0f304613b1661754d9cccf5829087a8bb19a12 (diff) | |
download | CMake-9b03baee308d78db119554def6e34fd9db9683ac.zip CMake-9b03baee308d78db119554def6e34fd9db9683ac.tar.gz CMake-9b03baee308d78db119554def6e34fd9db9683ac.tar.bz2 |
Merge topic 'objective-c-cxx'
dd0f304613 Objective C/C++: Add compiler standard detection
b515af782b Help: Add release note for Objective-C/C++ language support
9e66397c28 Languages: Add support for Objective-C++
80f120a85f Languages: Add support for Objective-C
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3811
72 files changed, 2787 insertions, 81 deletions
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst index fb49b44..fdc44f2 100644 --- a/Help/command/enable_language.rst +++ b/Help/command/enable_language.rst @@ -1,7 +1,6 @@ enable_language --------------- - -Enable a language (CXX/C/Fortran/etc) +Enable a language (CXX/C/OBJC/OBJCXX/Fortran/etc) .. code-block:: cmake @@ -10,7 +9,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``, ``OBJCXX``, ``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. diff --git a/Help/command/project.rst b/Help/command/project.rst index baf18be..3951456 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -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), ``OBJCXX``, ``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. diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index c0449fb..6e7f9b5 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -130,6 +130,16 @@ 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. +``$<OBJCXX_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 @@ -144,6 +154,12 @@ Variable Queries ``$<CUDA_COMPILER_VERSION:version>`` ``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. +``$<OBJC_COMPILER_VERSION:version>`` + ``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``. + See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. +``$<OBJCXX_COMPILER_VERSION:version>`` + ``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``. + See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. ``$<Fortran_COMPILER_VERSION:version>`` ``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. @@ -401,6 +417,12 @@ Variable Queries ``$<CUDA_COMPILER_ID>`` The CMake's compiler id of the CUDA compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. +``$<OBJC_COMPILER_ID>`` + The CMake's compiler id of the OBJC compiler used. + See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. +``$<OBJCXX_COMPILER_ID>`` + The CMake's compiler id of the OBJCXX compiler used. + See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. ``$<Fortran_COMPILER_ID>`` The CMake's compiler id of the Fortran compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. @@ -413,6 +435,12 @@ 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. +``$<OBJCXX_COMPILER_VERSION>`` + The version of the OBJCXX 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. diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index fc4bfdc..c60dc40 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -36,6 +36,12 @@ These modules are loaded using the :command:`include` command. /module/CheckIncludeFiles /module/CheckLanguage /module/CheckLibraryExists + /module/CheckOBJCCompilerFlag + /module/CheckOBJCSourceCompiles + /module/CheckOBJCSourceRuns + /module/CheckOBJCXXCompilerFlag + /module/CheckOBJCXXSourceCompiles + /module/CheckOBJCXXSourceRuns /module/CheckPIESupported /module/CheckPrototypeDefinition /module/CheckStructHasMember diff --git a/Help/module/CheckOBJCCompilerFlag.rst b/Help/module/CheckOBJCCompilerFlag.rst new file mode 100644 index 0000000..e4bd6fd --- /dev/null +++ b/Help/module/CheckOBJCCompilerFlag.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckOBJCCompilerFlag.cmake diff --git a/Help/module/CheckOBJCSourceCompiles.rst b/Help/module/CheckOBJCSourceCompiles.rst new file mode 100644 index 0000000..d4a1484 --- /dev/null +++ b/Help/module/CheckOBJCSourceCompiles.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckOBJCSourceCompiles.cmake diff --git a/Help/module/CheckOBJCSourceRuns.rst b/Help/module/CheckOBJCSourceRuns.rst new file mode 100644 index 0000000..c72f0db --- /dev/null +++ b/Help/module/CheckOBJCSourceRuns.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckOBJCSourceRuns.cmake diff --git a/Help/module/CheckOBJCXXCompilerFlag.rst b/Help/module/CheckOBJCXXCompilerFlag.rst new file mode 100644 index 0000000..1518a48 --- /dev/null +++ b/Help/module/CheckOBJCXXCompilerFlag.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckOBJCXXCompilerFlag.cmake diff --git a/Help/module/CheckOBJCXXSourceCompiles.rst b/Help/module/CheckOBJCXXSourceCompiles.rst new file mode 100644 index 0000000..a1c8ae9 --- /dev/null +++ b/Help/module/CheckOBJCXXSourceCompiles.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckOBJCXXSourceCompiles.cmake diff --git a/Help/module/CheckOBJCXXSourceRuns.rst b/Help/module/CheckOBJCXXSourceRuns.rst new file mode 100644 index 0000000..5198e1b --- /dev/null +++ b/Help/module/CheckOBJCXXSourceRuns.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckOBJCXXSourceRuns.cmake diff --git a/Help/release/dev/objective-c-cxx.rst b/Help/release/dev/objective-c-cxx.rst new file mode 100644 index 0000000..218af4e --- /dev/null +++ b/Help/release/dev/objective-c-cxx.rst @@ -0,0 +1,9 @@ +Objective C/C++ +--------------- + +* CMake learned to support the Objective C (``OBJC``) and Objective C++ + (``OBJCXX``) languages. They may be enabled via the :command:`project` + and :command:`enable_language` commands. When ``OBJC`` or ``OBJCXX`` + is enabled, source files with the ``.m`` or ``.mm``, respectively, + will be compiled as Objective C or C++. Otherwise they will be treated + as plain C++ sources as they were before. diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index e7f0e70..ef65021 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -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 OBJCXX) + 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) diff --git a/Modules/CMakeDetermineOBJCCompiler.cmake b/Modules/CMakeDetermineOBJCCompiler.cmake new file mode 100644 index 0000000..ad13eab --- /dev/null +++ b/Modules/CMakeDetermineOBJCCompiler.cmake @@ -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") diff --git a/Modules/CMakeDetermineOBJCXXCompiler.cmake b/Modules/CMakeDetermineOBJCXXCompiler.cmake new file mode 100644 index 0000000..60fcbb3 --- /dev/null +++ b/Modules/CMakeDetermineOBJCXXCompiler.cmake @@ -0,0 +1,197 @@ +# 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_OBJCXX_COMPILER before +# loading this file to force a compiler. +# use environment variable OBJCXX first if defined by user, next use +# the cmake variable CMAKE_GENERATOR_OBJCXX which can be defined by a generator +# as a default compiler +# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used +# as prefix for the tools (e.g. arm-elf-g++, arm-elf-ar etc.) +# +# Sets the following variables: +# CMAKE_OBJCXX_COMPILER +# CMAKE_COMPILER_IS_GNUOBJCXX +# CMAKE_COMPILER_IS_CLANGOBJCXX +# CMAKE_AR +# CMAKE_RANLIB +# +# 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-OBJCXX OPTIONAL) +include(Platform/${CMAKE_SYSTEM_NAME}-OBJCXX OPTIONAL) +if(NOT CMAKE_OBJCXX_COMPILER_NAMES) + set(CMAKE_OBJCXX_COMPILER_NAMES clang++) +endif() + +if("${CMAKE_GENERATOR}" MATCHES "Xcode") + set(CMAKE_OBJCXX_COMPILER_XCODE_TYPE sourcecode.cpp.objcpp) +else() + if(NOT CMAKE_OBJCXX_COMPILER) + set(CMAKE_OBJCXX_COMPILER_INIT NOTFOUND) + + # prefer the environment variable OBJCXX + if($ENV{OBJCXX} MATCHES ".+") + get_filename_component(CMAKE_OBJCXX_COMPILER_INIT $ENV{OBJCXX} PROGRAM PROGRAM_ARGS CMAKE_OBJCXX_FLAGS_ENV_INIT) + if(CMAKE_OBJCXX_FLAGS_ENV_INIT) + set(CMAKE_OBJCXX_COMPILER_ARG1 "${CMAKE_OBJCXX_FLAGS_ENV_INIT}" CACHE STRING "First argument to Objective-C++ compiler") + endif() + if(NOT EXISTS ${CMAKE_OBJCXX_COMPILER_INIT}) + message(FATAL_ERROR "Could not find compiler set in environment variable OBJCXX:\n$ENV{OBJCXX}.\n${CMAKE_OBJCXX_COMPILER_INIT}") + endif() + endif() + + # next prefer the generator specified compiler + if(CMAKE_GENERATOR_OBJCXX) + if(NOT CMAKE_OBJCXX_COMPILER_INIT) + set(CMAKE_OBJCXX_COMPILER_INIT ${CMAKE_GENERATOR_OBJCXX}) + endif() + endif() + + # finally list compilers to try + if(NOT CMAKE_OBJCXX_COMPILER_INIT) + set(CMAKE_OBJCXX_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ clang++) + endif() + + _cmake_find_compiler(OBJCXX) + + else() + # we only get here if CMAKE_OBJCXX_COMPILER was specified using -D or a pre-made CMakeCache.txt + # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE + # if CMAKE_OBJCXX_COMPILER is a list of length 2, use the first item as + # CMAKE_OBJCXX_COMPILER and the 2nd one as CMAKE_OBJCXX_COMPILER_ARG1 + + list(LENGTH CMAKE_OBJCXX_COMPILER _CMAKE_OBJCXX_COMPILER_LIST_LENGTH) + if("${_CMAKE_OBJCXX_COMPILER_LIST_LENGTH}" EQUAL 2) + list(GET CMAKE_OBJCXX_COMPILER 1 CMAKE_OBJCXX_COMPILER_ARG1) + list(GET CMAKE_OBJCXX_COMPILER 0 CMAKE_OBJCXX_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_OBJCXX_COMPILER_PATH "${CMAKE_OBJCXX_COMPILER}" PATH) + if(NOT _CMAKE_USER_OBJCXX_COMPILER_PATH) + find_program(CMAKE_OBJCXX_COMPILER_WITH_PATH NAMES ${CMAKE_OBJCXX_COMPILER}) + if(CMAKE_OBJCXX_COMPILER_WITH_PATH) + set(CMAKE_OBJCXX_COMPILER ${CMAKE_OBJCXX_COMPILER_WITH_PATH} CACHE STRING "Objective-C++ compiler" FORCE) + endif() + unset(CMAKE_OBJCXX_COMPILER_WITH_PATH CACHE) + endif() + + endif() + mark_as_advanced(CMAKE_OBJCXX_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_OBJCXX_COMPILER_ID_TEST_FLAGS_FIRST) + set(CMAKE_OBJCXX_COMPILER_ID_TEST_FLAGS + # Try compiling to an object file only. + "-c" + + # ARMClang need target options + "--target=arm-arm-none-eabi -mcpu=cortex-m3" + ) +endif() + +# Build a small source file to identify the compiler. +if(NOT CMAKE_OBJCXX_COMPILER_ID_RUN) + set(CMAKE_OBJCXX_COMPILER_ID_RUN 1) + + # Try to identify the compiler. + set(CMAKE_OBJCXX_COMPILER_ID) + file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in + CMAKE_OBJCXX_COMPILER_ID_PLATFORM_CONTENT) + + # Match the link line from xcodebuild output of the form + # Ld ... + # ... + # /path/to/cc ...CompilerIdOBJCXX/... + # to extract the compiler front-end for the language. + set(CMAKE_OBJCXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdOBJCXX/(\\./)?(CompilerIdOBJCXX.(framework|xctest)/)?CompilerIdOBJCXX[ \t\n\\\"]") + set(CMAKE_OBJCXX_COMPILER_ID_TOOL_MATCH_INDEX 2) + + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + CMAKE_DETERMINE_COMPILER_ID(OBJCXX OBJCXXFLAGS CMakeOBJCXXCompilerId.mm) + + # Set old compiler and platform id variables. + if(CMAKE_OBJCXX_COMPILER_ID MATCHES "GNU") + set(CMAKE_COMPILER_IS_GNUOBJCXX 1) + endif() + if(CMAKE_OBJCXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_COMPILER_IS_CLANGOBJCXX 1) + endif() +endif() + +if (NOT _CMAKE_TOOLCHAIN_LOCATION) + get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJCXX_COMPILER}" PATH) +endif () + +# if we have a g++ cross compiler, they have usually some prefix, like +# e.g. powerpc-linux-g++, arm-elf-g++ or i586-mingw32msvc-g++ , 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_OBJCXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC") + get_filename_component(COMPILER_BASENAME "${CMAKE_OBJCXX_COMPILER}" NAME) + if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$") + set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) + set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5}) + elseif("${CMAKE_OBJCXX_COMPILER_ID}" MATCHES "Clang") + if(CMAKE_OBJCXX_COMPILER_TARGET) + set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJCXX_COMPILER_TARGET}-) + endif() + elseif(COMPILER_BASENAME MATCHES "QCC(\\.exe)?$") + if(CMAKE_OBJCXX_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 "OBJCXX") +include(CMakeFindBinUtils) +include(Compiler/${CMAKE_OBJCXX_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) + +if(CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID) + set(_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID + "set(CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID})") +else() + set(_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID "") +endif() + +if(CMAKE_OBJCXX_XCODE_ARCHS) + set(SET_CMAKE_XCODE_ARCHS + "set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJCXX_XCODE_ARCHS}\")") +endif() + +# configure all variables set in this file +configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCXXCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake + @ONLY + ) + +set(CMAKE_OBJCXX_COMPILER_ENV_VAR "OBJCXX") diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in new file mode 100644 index 0000000..1555517 --- /dev/null +++ b/Modules/CMakeOBJCCompiler.cmake.in @@ -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@") diff --git a/Modules/CMakeOBJCCompilerABI.m b/Modules/CMakeOBJCCompilerABI.m new file mode 100644 index 0000000..8fa8511 --- /dev/null +++ b/Modules/CMakeOBJCCompilerABI.m @@ -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; +} diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in new file mode 100644 index 0000000..2b8aa30 --- /dev/null +++ b/Modules/CMakeOBJCCompilerId.m.in @@ -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; +} diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake new file mode 100644 index 0000000..2baad4a --- /dev/null +++ b/Modules/CMakeOBJCInformation.cmake @@ -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) diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in new file mode 100644 index 0000000..b6452c4 --- /dev/null +++ b/Modules/CMakeOBJCXXCompiler.cmake.in @@ -0,0 +1,79 @@ +set(CMAKE_OBJCXX_COMPILER "@CMAKE_OBJCXX_COMPILER@") +set(CMAKE_OBJCXX_COMPILER_ARG1 "@CMAKE_OBJCXX_COMPILER_ARG1@") +set(CMAKE_OBJCXX_COMPILER_ID "@CMAKE_OBJCXX_COMPILER_ID@") +set(CMAKE_OBJCXX_COMPILER_VERSION "@CMAKE_OBJCXX_COMPILER_VERSION@") +set(CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL "@CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL@") +set(CMAKE_OBJCXX_COMPILER_WRAPPER "@CMAKE_OBJCXX_COMPILER_WRAPPER@") +set(CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_OBJCXX_COMPILE_FEATURES "@CMAKE_OBJCXX_COMPILE_FEATURES@") +set(CMAKE_OBJCXX98_COMPILE_FEATURES "@CMAKE_OBJCXX98_COMPILE_FEATURES@") +set(CMAKE_OBJCXX11_COMPILE_FEATURES "@CMAKE_OBJCXX11_COMPILE_FEATURES@") +set(CMAKE_OBJCXX14_COMPILE_FEATURES "@CMAKE_OBJCXX14_COMPILE_FEATURES@") +set(CMAKE_OBJCXX17_COMPILE_FEATURES "@CMAKE_OBJCXX17_COMPILE_FEATURES@") +set(CMAKE_OBJCXX20_COMPILE_FEATURES "@CMAKE_OBJCXX20_COMPILE_FEATURES@") + +set(CMAKE_OBJCXX_PLATFORM_ID "@CMAKE_OBJCXX_PLATFORM_ID@") +set(CMAKE_OBJCXX_SIMULATE_ID "@CMAKE_OBJCXX_SIMULATE_ID@") +set(CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT "@CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT@") +set(CMAKE_OBJCXX_SIMULATE_VERSION "@CMAKE_OBJCXX_SIMULATE_VERSION@") +@_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID@ +@SET_CMAKE_XCODE_ARCHS@ +set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_OBJCXX_COMPILER_AR "@CMAKE_OBJCXX_COMPILER_AR@") +set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_OBJCXX_COMPILER_RANLIB "@CMAKE_OBJCXX_COMPILER_RANLIB@") +set(CMAKE_LINKER "@CMAKE_LINKER@") +set(CMAKE_MT "@CMAKE_MT@") +set(CMAKE_COMPILER_IS_GNUOBJCXX @CMAKE_COMPILER_IS_GNUOBJCXX@) +set(CMAKE_OBJCXX_COMPILER_LOADED 1) +set(CMAKE_OBJCXX_COMPILER_WORKS @CMAKE_OBJCXX_COMPILER_WORKS@) +set(CMAKE_OBJCXX_ABI_COMPILED @CMAKE_OBJCXX_ABI_COMPILED@) + +set(CMAKE_OBJCXX_COMPILER_ENV_VAR "OBJCXX") + +set(CMAKE_OBJCXX_COMPILER_ID_RUN 1) +set(CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS M;m;mm) +set(CMAKE_OBJCXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O) + +if (CMAKE_OBJC_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() +endif() + +foreach (lang C CXX OBJC) + foreach(extension IN LISTS CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS) + if (CMAKE_${lang}_COMPILER_ID_RUN) + list(REMOVE_ITEM CMAKE_${lang}_SOURCE_FILE_EXTENSIONS ${extension}) + endif() + endforeach() +endforeach() + +set(CMAKE_OBJCXX_LINKER_PREFERENCE 25) +set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@") +set(CMAKE_OBJCXX_COMPILER_ABI "@CMAKE_OBJCXX_COMPILER_ABI@") +set(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@") + +if(CMAKE_OBJCXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_OBJCXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_OBJCXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_OBJCXX_COMPILER_ABI}") +endif() + +if(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@") +endif() + +@CMAKE_OBJCXX_COMPILER_CUSTOM_CODE@ +@CMAKE_OBJCXX_SYSROOT_FLAG_CODE@ +@CMAKE_OBJCXX_OSX_DEPLOYMENT_TARGET_FLAG_CODE@ + +set(CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES@") +set(CMAKE_OBJCXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_OBJCXX_IMPLICIT_LINK_LIBRARIES@") +set(CMAKE_OBJCXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_OBJCXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") diff --git a/Modules/CMakeOBJCXXCompilerABI.mm b/Modules/CMakeOBJCXXCompilerABI.mm new file mode 100644 index 0000000..288a58c --- /dev/null +++ b/Modules/CMakeOBJCXXCompilerABI.mm @@ -0,0 +1,20 @@ +#ifndef __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; +} diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in new file mode 100644 index 0000000..fe04de1 --- /dev/null +++ b/Modules/CMakeOBJCXXCompilerId.mm.in @@ -0,0 +1,68 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "An Objective-C compiler has been selected for Objective-C++." +#endif + +@CMAKE_OBJCXX_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_OBJCXX_COMPILER_ID_PLATFORM_CONTENT@ +@CMAKE_OBJCXX_COMPILER_ID_ERROR_FOR_TEST@ + +#if defined(_MSC_VER) && defined(_MSVC_LANG) +#define CXX_STD _MSVC_LANG +#else +#define CXX_STD __cplusplus +#endif + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[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; +} diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake new file mode 100644 index 0000000..3f55b01 --- /dev/null +++ b/Modules/CMakeOBJCXXInformation.cmake @@ -0,0 +1,273 @@ +# 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_OBJCXX_OUTPUT_EXTENSION .o) + +set(_INCLUDED_FILE 0) + +# Load compiler-specific information. +if(CMAKE_OBJCXX_COMPILER_ID) + include(Compiler/${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX OPTIONAL) +endif() + +set(CMAKE_BASE_NAME) +get_filename_component(CMAKE_BASE_NAME "${CMAKE_OBJCXX_COMPILER}" NAME_WE) +# since the gnu compiler has several names force g++ +if(CMAKE_COMPILER_IS_GNUOBJCXX) + set(CMAKE_BASE_NAME g++) +endif() + + +# load a hardware specific file, mostly useful for embedded compilers +if(CMAKE_SYSTEM_PROCESSOR) + if(CMAKE_OBJCXX_COMPILER_ID) + include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX-${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_OBJCXX_COMPILER_ID) + include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX 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_OBJCXX_COMPILER_WRAPPER) + __cmake_include_compiler_wrapper(OBJCXX) +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_OBJCXX_SIZEOF_DATA_PTR) + foreach(f ${CMAKE_OBJCXX_ABI_FILES}) + include(${f}) + endforeach() + unset(CMAKE_OBJCXX_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_OBJCXX) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX "${_override}") +endif() + + +# Create a set of shared library variable specific to Objective-C++ +# For 90% of the systems, these are the same flags as the Objective-C versions +# so if these are not set just copy the flags from the Objective-C version +if(NOT CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS) + set(CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS}) +endif() + +if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_PIC) + set(CMAKE_OBJCXX_COMPILE_OPTIONS_PIC ${CMAKE_OBJC_COMPILE_OPTIONS_PIC}) +endif() + +if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_PIE) + set(CMAKE_OBJCXX_COMPILE_OPTIONS_PIE ${CMAKE_OBJC_COMPILE_OPTIONS_PIE}) +endif() +if(NOT CMAKE_OBJCXX_LINK_OPTIONS_PIE) + set(CMAKE_OBJCXX_LINK_OPTIONS_PIE ${CMAKE_OBJC_LINK_OPTIONS_PIE}) +endif() +if(NOT CMAKE_OBJCXX_LINK_OPTIONS_NO_PIE) + set(CMAKE_OBJCXX_LINK_OPTIONS_NO_PIE ${CMAKE_OBJC_LINK_OPTIONS_NO_PIE}) +endif() + +if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_DLL) + set(CMAKE_OBJCXX_COMPILE_OPTIONS_DLL ${CMAKE_OBJC_COMPILE_OPTIONS_DLL}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS) + set(CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_OBJC_FLAGS}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_OBJCXX_FLAGS) + set(CMAKE_SHARED_LIBRARY_LINK_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_OBJC_FLAGS}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG) + set(CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP) + set(CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG_SEP}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG) + set(CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJC_FLAG}) +endif() + +if(NOT DEFINED CMAKE_EXE_EXPORTS_OBJCXX_FLAG) + set(CMAKE_EXE_EXPORTS_OBJCXX_FLAG ${CMAKE_EXE_EXPORTS_OBJC_FLAG}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_OBJCXX_FLAG) + set(CMAKE_SHARED_LIBRARY_SONAME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_OBJC_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG) + set(CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG_SEP) + set(CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP}) +endif() + +if(NOT CMAKE_EXECUTABLE_RPATH_LINK_OBJCXX_FLAG) + set(CMAKE_EXECUTABLE_RPATH_LINK_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_OBJCXX_WITH_RUNTIME_PATH) + set(CMAKE_SHARED_LIBRARY_LINK_OBJCXX_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_OBJC_WITH_RUNTIME_PATH}) +endif() + +if(NOT CMAKE_INCLUDE_FLAG_OBJCXX) + set(CMAKE_INCLUDE_FLAG_OBJCXX ${CMAKE_INCLUDE_FLAG_C}) +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_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS}) + set(CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS}) +endif() + +# repeat for modules +if(NOT CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS) + set(CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS}) +endif() + +if(NOT CMAKE_SHARED_MODULE_OBJCXX_FLAGS) + set(CMAKE_SHARED_MODULE_OBJCXX_FLAGS ${CMAKE_SHARED_MODULE_OBJC_FLAGS}) +endif() + +# Initialize OBJCXX link type selection flags from OBJC versions. +foreach(type SHARED_LIBRARY SHARED_MODULE EXE) + if(NOT CMAKE_${type}_LINK_STATIC_OBJCXX_FLAGS) + set(CMAKE_${type}_LINK_STATIC_OBJCXX_FLAGS + ${CMAKE_${type}_LINK_STATIC_OBJC_FLAGS}) + endif() + if(NOT CMAKE_${type}_LINK_DYNAMIC_OBJCXX_FLAGS) + set(CMAKE_${type}_LINK_DYNAMIC_OBJCXX_FLAGS + ${CMAKE_${type}_LINK_DYNAMIC_OBJC_FLAGS}) + endif() +endforeach() + +# add the flags to the cache based +# on the initial values computed in the platform/*.cmake files +# use _INIT variables so that this only happens the first time +# and you can set these flags in the cmake cache +set(CMAKE_OBJCXX_FLAGS_INIT "$ENV{OBJCXXFLAGS} ${CMAKE_OBJCXX_FLAGS_INIT}") + +cmake_initialize_per_config_variable(CMAKE_OBJCXX_FLAGS "Flags used by the Objective-C++ compiler") + +if(CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT) + set(CMAKE_OBJCXX_STANDARD_LIBRARIES "${CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT}" + CACHE STRING "Libraries linked by default with all Objective-C++ applications.") + mark_as_advanced(CMAKE_OBJCXX_STANDARD_LIBRARIES) +endif() + +include(CMakeCommonLanguageInclude) + +# now define the following rules: +# CMAKE_OBJCXX_CREATE_SHARED_LIBRARY +# CMAKE_OBJCXX_CREATE_SHARED_MODULE +# CMAKE_OBJCXX_COMPILE_OBJECT +# CMAKE_OBJCXX_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_OBJCXX_COMPILER> +# <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> +# <CMAKE_OBJCXX_SHARED_MODULE_CREATE_FLAGS> +# <CMAKE_OBJCXX_LINK_FLAGS> + +# Static library tools +# <CMAKE_AR> +# <CMAKE_RANLIB> + + +# create a shared Objective-C++ library +if(NOT CMAKE_OBJCXX_CREATE_SHARED_LIBRARY) + set(CMAKE_OBJCXX_CREATE_SHARED_LIBRARY + "<CMAKE_OBJCXX_COMPILER> <CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>") +endif() + +# create an Objective-C++ shared module copy the shared library rule by default +if(NOT CMAKE_OBJCXX_CREATE_SHARED_MODULE) + set(CMAKE_OBJCXX_CREATE_SHARED_MODULE ${CMAKE_OBJCXX_CREATE_SHARED_LIBRARY}) +endif() + + +# Create a static archive incrementally for large object file counts. +# If CMAKE_OBJCXX_CREATE_STATIC_LIBRARY is set it will override these. +if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_CREATE) + set(CMAKE_OBJCXX_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>") +endif() +if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_APPEND) + set(CMAKE_OBJCXX_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>") +endif() +if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_FINISH) + set(CMAKE_OBJCXX_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>") +endif() + +# compile an Objective-C++ file into an object file +if(NOT CMAKE_OBJCXX_COMPILE_OBJECT) + set(CMAKE_OBJCXX_COMPILE_OBJECT + "<CMAKE_OBJCXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>") +endif() + +if(NOT CMAKE_OBJCXX_LINK_EXECUTABLE) + set(CMAKE_OBJCXX_LINK_EXECUTABLE + "<CMAKE_OBJCXX_COMPILER> <FLAGS> <CMAKE_OBJCXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") +endif() + +mark_as_advanced( +CMAKE_VERBOSE_MAKEFILE +) + +set(CMAKE_OBJCXX_INFORMATION_LOADED 1) diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake new file mode 100644 index 0000000..0030683 --- /dev/null +++ b/Modules/CMakeTestOBJCCompiler.cmake @@ -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) diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake new file mode 100644 index 0000000..bcce2f1 --- /dev/null +++ b/Modules/CMakeTestOBJCXXCompiler.cmake @@ -0,0 +1,93 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +if(CMAKE_OBJCXX_COMPILER_FORCED) + # The compiler configuration was forced by the user. + # Assume the user has configured all compiler information. + set(CMAKE_OBJCXX_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 CMakeOBJCXXCompiler.cmake. +unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE) + +# This file is used by EnableLanguage in cmGlobalGenerator to +# determine that the 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_OBJCXX_COMPILER_WORKS) + PrintTestCompilerStatus("OBJCXX" "") + __TestCompiler_setTryCompileTargetType() + file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm + "#ifndef __cplusplus\n" + "# error \"The CMAKE_OBJCXX_COMPILER is set to a C compiler\"\n" + "#endif\n" + "#ifndef __OBJC__\n" + "# error \"The CMAKE_OBJCXX_COMPILER is not an Objective-C++ compiler\"\n" + "#endif\n" + "int main(){return 0;}\n") + try_compile(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm + OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT) + # Move result from cache to normal variable. + set(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_OBJCXX_COMPILER_WORKS}) + unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE) + set(OBJCXX_TEST_WAS_RUN 1) + __TestCompiler_restoreTryCompileTargetType() +endif() + +if(NOT CMAKE_OBJCXX_COMPILER_WORKS) + PrintTestCompilerStatus("OBJCXX" " -- 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_OBJCXX_COMPILER_OUTPUT}\n\n") + string(REPLACE "\n" "\n " _output "${__CMAKE_OBJCXX_COMPILER_OUTPUT}") + message(FATAL_ERROR "The Objective-C++ compiler\n \"${CMAKE_OBJCXX_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(OBJCXX_TEST_WAS_RUN) + PrintTestCompilerStatus("OBJCXX" " -- 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_OBJCXX_COMPILER_OUTPUT}\n\n") + endif() + + # Try to identify the ABI and configure it into CMakeOBJCXXCompiler.cmake + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) + CMAKE_DETERMINE_COMPILER_ABI(OBJCXX ${CMAKE_ROOT}/Modules/CMakeOBJCXXCompilerABI.mm) + # Try to identify the compiler features + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake) + CMAKE_DETERMINE_COMPILE_FEATURES(OBJCXX) + + # Re-configure to save learned information. + configure_file( + ${CMAKE_ROOT}/Modules/CMakeOBJCXXCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake + @ONLY + ) + include(${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake) + + if(CMAKE_OBJCXX_SIZEOF_DATA_PTR) + foreach(f ${CMAKE_OBJCXX_ABI_FILES}) + include(${f}) + endforeach() + unset(CMAKE_OBJCXX_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_OBJCXX_COMPILER_OUTPUT) diff --git a/Modules/CheckOBJCCompilerFlag.cmake b/Modules/CheckOBJCCompilerFlag.cmake new file mode 100644 index 0000000..1d975da --- /dev/null +++ b/Modules/CheckOBJCCompilerFlag.cmake @@ -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 () diff --git a/Modules/CheckOBJCSourceCompiles.cmake b/Modules/CheckOBJCSourceCompiles.cmake new file mode 100644 index 0000000..a4676ad --- /dev/null +++ b/Modules/CheckOBJCSourceCompiles.cmake @@ -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() diff --git a/Modules/CheckOBJCSourceRuns.cmake b/Modules/CheckOBJCSourceRuns.cmake new file mode 100644 index 0000000..00a1ebd --- /dev/null +++ b/Modules/CheckOBJCSourceRuns.cmake @@ -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() diff --git a/Modules/CheckOBJCXXCompilerFlag.cmake b/Modules/CheckOBJCXXCompilerFlag.cmake new file mode 100644 index 0000000..c32741b --- /dev/null +++ b/Modules/CheckOBJCXXCompilerFlag.cmake @@ -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: +CheckOBJCXXCompilerFlag +----------------------- + +Check whether the Objective-C++ compiler supports a given flag. + +.. command:: check_objcxx_compiler_flag + + .. code-block:: cmake + + check_objcxx_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_objcxx_source_compiles`` macro from the +:module:`CheckOBJCXXSourceCompiles` 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_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags + in such variables may cause a false negative for this check. +#]=======================================================================] + +include_guard(GLOBAL) +include(CheckOBJCXXSourceCompiles) +include(CMakeCheckCompilerFlagCommonPatterns) + +macro (CHECK_OBJCXX_COMPILER_FLAG _FLAG _RESULT) + set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + + # Normalize locale during test compilation. + set(_CheckOBJCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) + foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS}) + set(_CheckOBJCXXCompilerFlag_SAVED_${v} "$ENV{${v}}") + set(ENV{${v}} OBJCXX) + endforeach() + CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS) + CHECK_OBJCXX_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 + ${_CheckOBJCXXCompilerFlag_COMMON_PATTERNS} + ) + foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS}) + set(ENV{${v}} ${_CheckOBJCXXCompilerFlag_SAVED_${v}}) + unset(_CheckOBJCXXCompilerFlag_SAVED_${v}) + endforeach() + unset(_CheckOBJCXXCompilerFlag_LOCALE_VARS) + unset(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS) + + set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") +endmacro () diff --git a/Modules/CheckOBJCXXSourceCompiles.cmake b/Modules/CheckOBJCXXSourceCompiles.cmake new file mode 100644 index 0000000..4c0fdd0 --- /dev/null +++ b/Modules/CheckOBJCXXSourceCompiles.cmake @@ -0,0 +1,146 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CheckOBJCXXSourceCompiles +------------------------- + +Check if given Objective-C++ source compiles and links into an executable. + +.. command:: check_objcxx_source_compiles + + .. code-block:: cmake + + check_objcxx_source_compiles(<code> <resultVar> + [FAIL_REGEX <regex1> [<regex2>...]]) + + Check that the source supplied in ``<code>`` can be compiled as a Objective-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_objcxx_source_compiles()``: + + ``CMAKE_REQUIRED_FLAGS`` + Additional flags to pass to the compiler. Note that the contents of + :variable:`CMAKE_OBJCXX_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_OBJCXX_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_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS + LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) + else() + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS) + endif() + if(CMAKE_REQUIRED_LIBRARIES) + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES) + endif() + if(CMAKE_REQUIRED_INCLUDES) + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES) + endif() + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm" + "${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.mm + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS} + ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + "${CHECK_OBJCXX_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() diff --git a/Modules/CheckOBJCXXSourceRuns.cmake b/Modules/CheckOBJCXXSourceRuns.cmake new file mode 100644 index 0000000..a3d5923 --- /dev/null +++ b/Modules/CheckOBJCXXSourceRuns.cmake @@ -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: +CheckOBJCXXSourceRuns +--------------------- + +Check if given Objective-C++ source compiles and links into an executable and can +subsequently be run. + +.. command:: check_objcxx_source_runs + + .. code-block:: cmake + + check_objcxx_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_objcxx_source_runs()``: + + ``CMAKE_REQUIRED_FLAGS`` + Additional flags to pass to the compiler. Note that the contents of + :variable:`CMAKE_OBJCXX_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_OBJCXX_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_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS + LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) + else() + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS) + endif() + if(CMAKE_REQUIRED_LIBRARIES) + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES) + endif() + if(CMAKE_REQUIRED_INCLUDES) + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES) + endif() + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm" + "${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.mm + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS} + ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} + "${CHECK_OBJCXX_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 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 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() diff --git a/Modules/Compiler/AppleClang-OBJC.cmake b/Modules/Compiler/AppleClang-OBJC.cmake new file mode 100644 index 0000000..d1f3706 --- /dev/null +++ b/Modules/Compiler/AppleClang-OBJC.cmake @@ -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) diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake new file mode 100644 index 0000000..7c6f763 --- /dev/null +++ b/Modules/Compiler/AppleClang-OBJCXX.cmake @@ -0,0 +1,37 @@ +include(Compiler/Clang-OBJCXX) + +if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.0) + set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") + set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") +endif() + +if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1) + set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++14") + set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14") + set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON) +elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 5.1) + # AppleClang 5.0 knows this flag, but does not set a __cplusplus macro greater than 201103L + set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++1y") + set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y") + set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1) + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") +endif() + +if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 8.0) + set(CMAKE_OBJCXX11_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 10.0) + set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std=c++2a") + set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") +endif() + +__compiler_check_default_language_standard(OBJCXX 4.0 98) diff --git a/Modules/Compiler/Clang-OBJC.cmake b/Modules/Compiler/Clang-OBJC.cmake new file mode 100644 index 0000000..c61c497 --- /dev/null +++ b/Modules/Compiler/Clang-OBJC.cmake @@ -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) diff --git a/Modules/Compiler/Clang-OBJCXX.cmake b/Modules/Compiler/Clang-OBJCXX.cmake new file mode 100644 index 0000000..b01ce64 --- /dev/null +++ b/Modules/Compiler/Clang-OBJCXX.cmake @@ -0,0 +1,70 @@ +include(Compiler/Clang) +__compiler_clang(OBJCXX) + +if("x${CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") + if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 2.1) + set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") + endif() + + if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.1) + set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") + set(CMAKE_OBJCXX11_STANDARD__HAS_FULL_SUPPORT ON) + elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 2.1) + set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++0x") + set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x") + endif() + + if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.5) + set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++14") + set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14") + set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON) + elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.4) + set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++1y") + set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y") + set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON) + endif() + + set(_clang_version_std17 5.0) + + if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}") + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") + elseif (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.5) + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") + endif() + + if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}") + set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std=c++2a") + set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") + endif() + + unset(_clang_version_std17) + + __compiler_check_default_language_standard(OBJCXX 2.1 98) +elseif(CMAKE_OBJCXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.9 + AND CMAKE_OBJCXX_SIMULATE_VERSION VERSION_GREATER_EQUAL 19.0) + # This version of clang-cl and the MSVC version it simulates have + # support for -std: flags. + set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "") + set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "") + set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "") + set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "") + set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std:c++14") + set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std:c++14") + if (CMAKE_OBJCXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std:c++17") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std:c++17") + set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std:c++latest") + set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std:c++latest") + else() + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std:c++latest") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std:c++latest") + endif() + + __compiler_check_default_language_standard(OBJCXX 3.9 14) +endif() diff --git a/Modules/Compiler/GNU-OBJC.cmake b/Modules/Compiler/GNU-OBJC.cmake new file mode 100644 index 0000000..5fba801 --- /dev/null +++ b/Modules/Compiler/GNU-OBJC.cmake @@ -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() diff --git a/Modules/Compiler/GNU-OBJCXX.cmake b/Modules/Compiler/GNU-OBJCXX.cmake new file mode 100644 index 0000000..66a547e --- /dev/null +++ b/Modules/Compiler/GNU-OBJCXX.cmake @@ -0,0 +1,10 @@ +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() + +if(NOT CMAKE_OBJCXX_LINK_FLAGS) + set(CMAKE_OBCXX_LINK_FLAGS "-lstdc++") +endif() diff --git a/Modules/Platform/Apple-AppleClang-OBJC.cmake b/Modules/Platform/Apple-AppleClang-OBJC.cmake new file mode 100644 index 0000000..b78edb1 --- /dev/null +++ b/Modules/Platform/Apple-AppleClang-OBJC.cmake @@ -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() diff --git a/Modules/Platform/Apple-AppleClang-OBJCXX.cmake b/Modules/Platform/Apple-AppleClang-OBJCXX.cmake new file mode 100644 index 0000000..ed172f1 --- /dev/null +++ b/Modules/Platform/Apple-AppleClang-OBJCXX.cmake @@ -0,0 +1,6 @@ +include(Platform/Apple-Clang-OBJCXX) +if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.2) + set(CMAKE_OBJCXX_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ") +else() + unset(CMAKE_OBJCXX_SYSTEM_FRAMEWORK_SEARCH_FLAG) +endif() diff --git a/Modules/Platform/Apple-Clang-OBJC.cmake b/Modules/Platform/Apple-Clang-OBJC.cmake new file mode 100644 index 0000000..63cd846 --- /dev/null +++ b/Modules/Platform/Apple-Clang-OBJC.cmake @@ -0,0 +1,2 @@ +include(Platform/Apple-Clang) +__apple_compiler_clang(OBJC) diff --git a/Modules/Platform/Apple-Clang-OBJCXX.cmake b/Modules/Platform/Apple-Clang-OBJCXX.cmake new file mode 100644 index 0000000..28fc352 --- /dev/null +++ b/Modules/Platform/Apple-Clang-OBJCXX.cmake @@ -0,0 +1,2 @@ +include(Platform/Apple-Clang) +__apple_compiler_clang(OBJCXX) diff --git a/Modules/Platform/Apple-GNU-OBJC.cmake b/Modules/Platform/Apple-GNU-OBJC.cmake new file mode 100644 index 0000000..aa8b33f --- /dev/null +++ b/Modules/Platform/Apple-GNU-OBJC.cmake @@ -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) diff --git a/Modules/Platform/Apple-GNU-OBJCXX.cmake b/Modules/Platform/Apple-GNU-OBJCXX.cmake new file mode 100644 index 0000000..919e11d --- /dev/null +++ b/Modules/Platform/Apple-GNU-OBJCXX.cmake @@ -0,0 +1,4 @@ +include(Platform/Apple-GNU) +__apple_compiler_gnu(OBJCXX) +cmake_gnu_set_sysroot_flag(OBJCXX) +cmake_gnu_set_osx_deployment_target_flag(OBJCXX) diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 7e02814..d0bb359 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -119,10 +119,18 @@ 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> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>") + +set(CMAKE_OBJCXX_CREATE_MACOSX_FRAMEWORK + "<CMAKE_OBJCXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <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_OBJCXX_FRAMEWORK_SEARCH_FLAG -F) set(CMAKE_Fortran_FRAMEWORK_SEARCH_FLAG -F) # default to searching for frameworks first @@ -222,7 +230,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 OBJCXX) list(APPEND _CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT ${_CMAKE_OSX_SYSROOT_PATH}/usr/include) endforeach() endif() diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 641cbaf..5a35007 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -707,7 +707,8 @@ struct CompilerIdNode : public cmGeneratorExpressionNode }; static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"), - cudaCompilerIdNode("CUDA"), fortranCompilerIdNode("Fortran"); + cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"), + objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran"); struct CompilerVersionNode : public cmGeneratorExpressionNode { @@ -771,6 +772,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode static const CompilerVersionNode cCompilerVersionNode("C"), cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"), + objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"), fortranCompilerVersionNode("Fortran"); struct PlatformIdNode : public cmGeneratorExpressionNode @@ -2243,6 +2245,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "NOT", ¬Node }, { "C_COMPILER_ID", &cCompilerIdNode }, { "CXX_COMPILER_ID", &cxxCompilerIdNode }, + { "OBJC_COMPILER_ID", &objcCompilerIdNode }, + { "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode }, { "CUDA_COMPILER_ID", &cudaCompilerIdNode }, { "Fortran_COMPILER_ID", &fortranCompilerIdNode }, { "VERSION_GREATER", &versionGreaterNode }, @@ -2253,6 +2257,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "C_COMPILER_VERSION", &cCompilerVersionNode }, { "CXX_COMPILER_VERSION", &cxxCompilerVersionNode }, { "CUDA_COMPILER_VERSION", &cudaCompilerVersionNode }, + { "OBJC_COMPILER_VERSION", &objcCompilerVersionNode }, + { "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode }, { "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode }, { "PLATFORM_ID", &platformIdNode }, { "COMPILE_FEATURES", &compileFeaturesNode }, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 7af3da5..6e6ca51 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1655,7 +1655,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; @@ -1942,10 +1942,20 @@ void cmLocalGenerator::AddCompilerRequirementFlag( langStdMap["CXX"].emplace_back("11"); langStdMap["CXX"].emplace_back("98"); + langStdMap["OBJCXX"].emplace_back("20"); + langStdMap["OBJCXX"].emplace_back("17"); + langStdMap["OBJCXX"].emplace_back("14"); + langStdMap["OBJCXX"].emplace_back("11"); + langStdMap["OBJCXX"].emplace_back("98"); + langStdMap["C"].emplace_back("11"); langStdMap["C"].emplace_back("99"); langStdMap["C"].emplace_back("90"); + langStdMap["OBJC"].emplace_back("11"); + langStdMap["OBJC"].emplace_back("99"); + langStdMap["OBJC"].emplace_back("90"); + langStdMap["CUDA"].emplace_back("14"); langStdMap["CUDA"].emplace_back("11"); langStdMap["CUDA"].emplace_back("98"); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index a528fc6..264a73a 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -38,6 +38,7 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" @@ -4629,9 +4630,9 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, target->AppendProperty("COMPILE_FEATURES", feature.c_str()); - return lang == "C" - ? this->AddRequiredTargetCFeature(target, feature, error) - : this->AddRequiredTargetCxxFeature(target, feature, error); + return lang == "C" || lang == "OBJC" + ? this->AddRequiredTargetCFeature(target, feature, lang, error) + : this->AddRequiredTargetCxxFeature(target, feature, lang, error); } bool cmMakefile::CompileFeatureKnown(cmTarget const* target, @@ -4723,30 +4724,33 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target, std::string const& lang, const std::string& feature) const { - return lang == "C" ? this->HaveCStandardAvailable(target, feature) - : this->HaveCxxStandardAvailable(target, feature); + return lang == "C" || lang == "OBJC" + ? this->HaveCStandardAvailable(target, feature, lang) + : this->HaveCxxStandardAvailable(target, feature, lang); } bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, - const std::string& feature) const + const std::string& feature, + std::string const& lang) const { const char* defaultCStandard = - this->GetDefinition("CMAKE_C_STANDARD_DEFAULT"); + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (!defaultCStandard) { this->IssueMessage( MessageType::INTERNAL_ERROR, - "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler."); + cmStrCat("CMAKE_", lang, + "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler.")); // Return true so the caller does not try to lookup the default standard. return true; } if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) { - std::ostringstream e; - e << "The CMAKE_C_STANDARD_DEFAULT variable contains an " - "invalid value: \"" - << defaultCStandard << "\"."; - this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); + const std::string e = cmStrCat("The CMAKE_", lang, + "_STANDARD_DEFAULT variable contains an " + "invalid value: \"", + defaultCStandard, "\"."); + this->IssueMessage(MessageType::INTERNAL_ERROR, e); return false; } @@ -4754,19 +4758,20 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, bool needC99 = false; bool needC11 = false; - this->CheckNeededCLanguage(feature, needC90, needC99, needC11); + this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11); - const char* existingCStandard = target->GetProperty("C_STANDARD"); + const char* existingCStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); if (!existingCStandard) { existingCStandard = defaultCStandard; } if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) { - std::ostringstream e; - e << "The C_STANDARD property on target \"" << target->GetName() - << "\" contained an invalid value: \"" << existingCStandard << "\"."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCStandard, "\"."); + this->IssueMessage(MessageType::FATAL_ERROR, e); return false; } @@ -4797,7 +4802,7 @@ bool cmMakefile::IsLaterStandard(std::string const& lang, std::string const& lhs, std::string const& rhs) { - if (lang == "C") { + if (lang == "C" || lang == "OBJC") { const char* const* rhsIt = std::find_if( cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs)); @@ -4812,25 +4817,26 @@ bool cmMakefile::IsLaterStandard(std::string const& lang, } bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, - const std::string& feature) const + const std::string& feature, + std::string const& lang) const { const char* defaultCxxStandard = - this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT"); + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (!defaultCxxStandard) { this->IssueMessage( MessageType::INTERNAL_ERROR, - "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler."); + cmStrCat("CMAKE_", lang, + "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler.")); // Return true so the caller does not try to lookup the default standard. return true; } if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) { - std::ostringstream e; - e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an " - "invalid value: \"" - << defaultCxxStandard << "\"."; - this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); + const std::string e = + cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", + "invalid value: \"", defaultCxxStandard, "\"."); + this->IssueMessage(MessageType::INTERNAL_ERROR, e); return false; } @@ -4839,10 +4845,11 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, bool needCxx14 = false; bool needCxx17 = false; bool needCxx20 = false; - this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14, + this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14, needCxx17, needCxx20); - const char* existingCxxStandard = target->GetProperty("CXX_STANDARD"); + const char* existingCxxStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); if (!existingCxxStandard) { existingCxxStandard = defaultCxxStandard; } @@ -4851,10 +4858,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(existingCxxStandard)); if (existingCxxLevel == cm::cend(CXX_STANDARDS)) { - std::ostringstream e; - e << "The CXX_STANDARD property on target \"" << target->GetName() - << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCxxStandard, "\"."); + this->IssueMessage(MessageType::FATAL_ERROR, e); return false; } @@ -4872,32 +4879,33 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, } void cmMakefile::CheckNeededCxxLanguage(const std::string& feature, + std::string const& lang, bool& needCxx98, bool& needCxx11, bool& needCxx14, bool& needCxx17, bool& needCxx20) const { if (const char* propCxx98 = - this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "98_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propCxx98); needCxx98 = cmContains(props, feature); } if (const char* propCxx11 = - this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propCxx11); needCxx11 = cmContains(props, feature); } if (const char* propCxx14 = - this->GetDefinition("CMAKE_CXX14_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propCxx14); needCxx14 = cmContains(props, feature); } if (const char* propCxx17 = - this->GetDefinition("CMAKE_CXX17_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propCxx17); needCxx17 = cmContains(props, feature); } if (const char* propCxx20 = - this->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propCxx20); needCxx20 = cmContains(props, feature); } @@ -4905,6 +4913,7 @@ void cmMakefile::CheckNeededCxxLanguage(const std::string& feature, bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, const std::string& feature, + std::string const& lang, std::string* error) const { bool needCxx98 = false; @@ -4913,13 +4922,14 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, bool needCxx17 = false; bool needCxx20 = false; - this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14, + this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14, needCxx17, needCxx20); - const char* existingCxxStandard = target->GetProperty("CXX_STANDARD"); + const char* existingCxxStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); if (existingCxxStandard == nullptr) { const char* defaultCxxStandard = - this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT"); + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (defaultCxxStandard && *defaultCxxStandard) { existingCxxStandard = defaultCxxStandard; } @@ -4930,14 +4940,14 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(existingCxxStandard)); if (existingCxxLevel == cm::cend(CXX_STANDARDS)) { - std::ostringstream e; - e << "The CXX_STANDARD property on target \"" << target->GetName() - << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCxxStandard, "\"."); if (error) { - *error = e.str(); + *error = e; } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, - e.str(), this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, + this->Backtrace); } return false; } @@ -4978,7 +4988,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, // Ensure the C++ language level is high enough to support // the needed C++ features. if (!existingCxxLevel || existingCxxLevel < needCxxLevel) { - target->SetProperty("CXX_STANDARD", *needCxxLevel); + target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel); } // Ensure the CUDA language level is high enough to support @@ -4992,21 +5002,21 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, } void cmMakefile::CheckNeededCLanguage(const std::string& feature, - bool& needC90, bool& needC99, - bool& needC11) const + std::string const& lang, bool& needC90, + bool& needC99, bool& needC11) const { if (const char* propC90 = - this->GetDefinition("CMAKE_C90_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "90_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propC90); needC90 = cmContains(props, feature); } if (const char* propC99 = - this->GetDefinition("CMAKE_C99_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "99_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propC99); needC99 = cmContains(props, feature); } if (const char* propC11 = - this->GetDefinition("CMAKE_C11_COMPILE_FEATURES")) { + this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(propC11); needC11 = cmContains(props, feature); } @@ -5014,18 +5024,20 @@ void cmMakefile::CheckNeededCLanguage(const std::string& feature, bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, const std::string& feature, + std::string const& lang, std::string* error) const { bool needC90 = false; bool needC99 = false; bool needC11 = false; - this->CheckNeededCLanguage(feature, needC90, needC99, needC11); + this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11); - const char* existingCStandard = target->GetProperty("C_STANDARD"); + const char* existingCStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); if (existingCStandard == nullptr) { const char* defaultCStandard = - this->GetDefinition("CMAKE_C_STANDARD_DEFAULT"); + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (defaultCStandard && *defaultCStandard) { existingCStandard = defaultCStandard; } @@ -5033,14 +5045,14 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, if (existingCStandard) { if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) { - std::ostringstream e; - e << "The C_STANDARD property on target \"" << target->GetName() - << "\" contained an invalid value: \"" << existingCStandard << "\"."; + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCStandard, "\"."); if (error) { - *error = e.str(); + *error = e; } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, - e.str(), this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, + this->Backtrace); } return false; } @@ -5071,11 +5083,11 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, } if (setC11) { - target->SetProperty("C_STANDARD", "11"); + target->SetProperty(cmStrCat(lang, "_STANDARD"), "11"); } else if (setC99) { - target->SetProperty("C_STANDARD", "99"); + target->SetProperty(cmStrCat(lang, "_STANDARD"), "99"); } else if (setC90) { - target->SetProperty("C_STANDARD", "90"); + target->SetProperty(cmStrCat(lang, "_STANDARD"), "90"); } return true; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index bb88bed..3a17aaf 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -1146,22 +1146,28 @@ private: bool MightHaveCustomCommand(const std::string& name) const; bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature, + std::string const& lang, std::string* error = nullptr) const; bool AddRequiredTargetCxxFeature(cmTarget* target, const std::string& feature, + std::string const& lang, std::string* error = nullptr) const; - void CheckNeededCLanguage(const std::string& feature, bool& needC90, + void CheckNeededCLanguage(const std::string& feature, + std::string const& lang, bool& needC90, bool& needC99, bool& needC11) const; - void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98, + void CheckNeededCxxLanguage(const std::string& feature, + std::string const& lang, bool& needCxx98, bool& needCxx11, bool& needCxx14, bool& needCxx17, bool& needCxx20) const; bool HaveCStandardAvailable(cmTarget const* target, - const std::string& feature) const; + const std::string& feature, + std::string const& lang) const; bool HaveCxxStandardAvailable(cmTarget const* target, - const std::string& feature) const; + const std::string& feature, + std::string const& lang) const; void CheckForUnusedVariables() const; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ae77d9e..62ead60 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -332,6 +332,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("C_STANDARD"); initProp("C_STANDARD_REQUIRED"); initProp("C_EXTENSIONS"); + initProp("OBJC_STANDARD"); + initProp("OBJC_STANDARD_REQUIRED"); + initProp("OBJC_EXTENSIONS"); initProp("CXX_CLANG_TIDY"); initProp("CXX_COMPILER_LAUNCHER"); initProp("CXX_CPPLINT"); @@ -340,6 +343,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CXX_STANDARD"); initProp("CXX_STANDARD_REQUIRED"); initProp("CXX_EXTENSIONS"); + initProp("OBJCXX_STANDARD"); + initProp("OBJCXX_STANDARD_REQUIRED"); + initProp("OBJCXX_EXTENSIONS"); initProp("CUDA_STANDARD"); initProp("CUDA_STANDARD_REQUIRED"); initProp("CUDA_EXTENSIONS"); @@ -452,6 +458,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->GetType() != cmStateEnums::UTILITY) { initProp("C_VISIBILITY_PRESET"); initProp("CXX_VISIBILITY_PRESET"); + initProp("OBJC_VISIBILITY_PRESET"); + initProp("OBJCXX_VISIBILITY_PRESET"); initProp("CUDA_VISIBILITY_PRESET"); initProp("VISIBILITY_INLINES_HIDDEN"); } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index c284603..789fc0e 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2328,6 +2328,79 @@ ${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") + + add_test(Objective-CXX.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-CXX.cxx-file-extension-test ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Objective-C++/cxx-file-extension-test" + "${CMake_BINARY_DIR}/Tests/Objective-C++/cxx-file-extension-test" + --build-two-config + ${build_generator_args} + --build-project cxx-file-extension-test + --build-options ${build_options} + --test-command cxx-file-extension-test + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C++/cxx-file-extension-test") + + add_test(Objective-CXX.objcxx-file-extension-test ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Objective-C++/objcxx-file-extension-test" + "${CMake_BINARY_DIR}/Tests/Objective-C++/objcxx-file-extension-test" + --build-two-config + ${build_generator_args} + --build-project objcxx-file-extension-test + --build-options ${build_options} + --test-command objcxx-file-extension-test + ) + list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C++/objcxx-file-extension-test") + endif () endif () diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index 19f3f79..03babd2 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -30,6 +30,17 @@ 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_OBJCXX_COMPILER) + add_CMakeOnly_test(CompilerIdOBJCXX) + add_CMakeOnly_test(CheckOBJCXXCompilerFlag) +endif() + if(CMAKE_Fortran_COMPILER) add_CMakeOnly_test(CompilerIdFortran) endif() diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt index ca4becb..90aa921 100644 --- a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt +++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt @@ -5,10 +5,20 @@ include(CheckLanguage) set(langs ) set(expect_C 1) set(expect_CXX 1) + +if(APPLE) + set(expect_OBJC 1) + set(expect_OBJCXX 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 OBJCXX) +endif() + +foreach(lang ${LANGUAGES}) check_language(${lang}) if(NOT DEFINED CMAKE_${lang}_COMPILER) message(FATAL_ERROR "check_language(${lang}) did not set result") diff --git a/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt new file mode 100644 index 0000000..a9a96ee --- /dev/null +++ b/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt @@ -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 diff --git a/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt new file mode 100644 index 0000000..f83b738 --- /dev/null +++ b/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12) + +project(CheckOBJCXXCompilerFlag) + +include(CheckOBJCXXCompilerFlag) + +if(CMAKE_COMPILER_IS_GNUOBJCXX) + set(COMPILER_FLAG -fobjc-direct-dispatch) +else() + set(COMPILER_FLAG -fobjc-gc) +endif() + +CHECK_OBJCXX_COMPILER_FLAGS(${COMPILER_FLAG} HAS_COMPILER_FLAG) + +if(NOT HAS_COMPILER_FLAG) + message(SEND_ERROR "Test fail: HAS_COMPILER_FLAG: ${COMPILER_FLAG}") +endif() diff --git a/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt b/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt new file mode 100644 index 0000000..8f13787 --- /dev/null +++ b/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt @@ -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() diff --git a/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt b/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt new file mode 100644 index 0000000..8f41db0 --- /dev/null +++ b/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8.12) +project(CompilerIdOBJCXX OBJCXX) + +foreach(v + CMAKE_OBJCXX_COMPILER + CMAKE_OBJCXX_COMPILER_ID + CMAKE_OBJCXX_COMPILER_VERSION + ) + if(${v}) + message(STATUS "${v}=[${${v}}]") + else() + message(SEND_ERROR "${v} not set!") + endif() +endforeach() diff --git a/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt new file mode 100644 index 0000000..0b33875 --- /dev/null +++ b/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.15) + +project(cxx-file-extension-test CXX) + +add_executable(cxx-file-extension-test main.mm) diff --git a/Tests/Objective-C++/cxx-file-extension-test/main.mm b/Tests/Objective-C++/cxx-file-extension-test/main.mm new file mode 100644 index 0000000..1c159a9 --- /dev/null +++ b/Tests/Objective-C++/cxx-file-extension-test/main.mm @@ -0,0 +1,8 @@ +#ifndef __OBJC__ +# error "Compiler cannot compile Objective-C" +#endif + +int main() +{ + return 0; +} diff --git a/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt new file mode 100644 index 0000000..eda7bba --- /dev/null +++ b/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.15) + +project(objcxx-file-extension-test OBJCXX CXX) + +add_executable(objcxx-file-extension-test main.mm) +target_link_libraries(objcxx-file-extension-test "-framework Foundation") diff --git a/Tests/Objective-C++/objcxx-file-extension-test/main.mm b/Tests/Objective-C++/objcxx-file-extension-test/main.mm new file mode 100644 index 0000000..d4aa1bb --- /dev/null +++ b/Tests/Objective-C++/objcxx-file-extension-test/main.mm @@ -0,0 +1,14 @@ +#ifndef __OBJC__ +# error "Compiler is not an Objective-C compiler." +#endif + +#import <Foundation/Foundation.h> +#include <iostream> + +int main() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + std::cout << "Hello World" << std::endl; + [pool release]; + return 0; +} diff --git a/Tests/Objective-C++/simple-build-test/CMakeLists.txt b/Tests/Objective-C++/simple-build-test/CMakeLists.txt new file mode 100644 index 0000000..cf27683 --- /dev/null +++ b/Tests/Objective-C++/simple-build-test/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.15) + +set(CMAKE_MACOSX_RPATH OFF) + +project(simple-build-test OBJCXX) + +add_library(foo SHARED foo.mm) +target_link_libraries(foo "-framework Foundation") + +add_executable(simple-build-test main.mm) +target_link_libraries(simple-build-test "-framework Foundation" foo) diff --git a/Tests/Objective-C++/simple-build-test/foo.h b/Tests/Objective-C++/simple-build-test/foo.h new file mode 100644 index 0000000..b3fb084 --- /dev/null +++ b/Tests/Objective-C++/simple-build-test/foo.h @@ -0,0 +1,9 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject { + NSNumber* age; +} + +@property (nonatomic, retain) NSNumber* age; + +@end diff --git a/Tests/Objective-C++/simple-build-test/foo.mm b/Tests/Objective-C++/simple-build-test/foo.mm new file mode 100644 index 0000000..2d452a8 --- /dev/null +++ b/Tests/Objective-C++/simple-build-test/foo.mm @@ -0,0 +1,7 @@ +#import "foo.h" + +@implementation Foo + +@synthesize age; + +@end diff --git a/Tests/Objective-C++/simple-build-test/main.mm b/Tests/Objective-C++/simple-build-test/main.mm new file mode 100644 index 0000000..7c85551 --- /dev/null +++ b/Tests/Objective-C++/simple-build-test/main.mm @@ -0,0 +1,14 @@ +#import <Foundation/Foundation.h> +#import "foo.h" +#include <iostream> + +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]); + std::cout << [theFoo.age intValue] << std::endl; + [pool release]; + return 0; +} diff --git a/Tests/Objective-C/c-file-extension-test/CMakeLists.txt b/Tests/Objective-C/c-file-extension-test/CMakeLists.txt new file mode 100644 index 0000000..e091448 --- /dev/null +++ b/Tests/Objective-C/c-file-extension-test/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.15) + +project(c-file-extension-test C) + +add_executable(c-file-extension-test main.m) diff --git a/Tests/Objective-C/c-file-extension-test/main.m b/Tests/Objective-C/c-file-extension-test/main.m new file mode 100644 index 0000000..1c159a9 --- /dev/null +++ b/Tests/Objective-C/c-file-extension-test/main.m @@ -0,0 +1,8 @@ +#ifndef __OBJC__ +# error "Compiler cannot compile Objective-C" +#endif + +int main() +{ + return 0; +} diff --git a/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt b/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt new file mode 100644 index 0000000..27e88be --- /dev/null +++ b/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt @@ -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") diff --git a/Tests/Objective-C/objc-file-extension-test/main.m b/Tests/Objective-C/objc-file-extension-test/main.m new file mode 100644 index 0000000..2ec3917 --- /dev/null +++ b/Tests/Objective-C/objc-file-extension-test/main.m @@ -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; +} diff --git a/Tests/Objective-C/simple-build-test/CMakeLists.txt b/Tests/Objective-C/simple-build-test/CMakeLists.txt new file mode 100644 index 0000000..5ab46ac --- /dev/null +++ b/Tests/Objective-C/simple-build-test/CMakeLists.txt @@ -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) diff --git a/Tests/Objective-C/simple-build-test/foo.h b/Tests/Objective-C/simple-build-test/foo.h new file mode 100644 index 0000000..b3fb084 --- /dev/null +++ b/Tests/Objective-C/simple-build-test/foo.h @@ -0,0 +1,9 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject { + NSNumber* age; +} + +@property (nonatomic, retain) NSNumber* age; + +@end diff --git a/Tests/Objective-C/simple-build-test/foo.m b/Tests/Objective-C/simple-build-test/foo.m new file mode 100644 index 0000000..2d452a8 --- /dev/null +++ b/Tests/Objective-C/simple-build-test/foo.m @@ -0,0 +1,7 @@ +#import "foo.h" + +@implementation Foo + +@synthesize age; + +@end diff --git a/Tests/Objective-C/simple-build-test/main.m b/Tests/Objective-C/simple-build-test/main.m new file mode 100644 index 0000000..970d554 --- /dev/null +++ b/Tests/Objective-C/simple-build-test/main.m @@ -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; +} diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index 54e96a2..498e556 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -313,6 +313,60 @@ 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_OBJCXX_SOURCE_COMPILES +# CHECK_OBJC_SOURCE_RUNS and CHECK_OBJCXX_SOURCE_RUNS macros work + +if (APPLE) + enable_language(OBJC) + enable_language(OBJCXX) + + include(CheckOBJCSourceCompiles) + include(CheckOBJCXXSourceCompiles) + include(CheckOBJCSourceRuns) + include(CheckOBJCXXSourceRuns) + + 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") + + + CHECK_OBJCXX_SOURCE_COMPILES("I don't build in Objective-C++" OBJCXX_BUILD_SHOULD_FAIL) + CHECK_OBJCXX_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJCXX_BUILD_SHOULD_WORK) + + TEST_FAIL(OBJCXX_BUILD_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_COMPILES() succeeded, but should have failed") + TEST_ASSERT(SIMPLE_OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded") + + CHECK_OBJCXX_SOURCE_COMPILES("#import <Foundation/Foundation.h>\n#include <iostream>\nint main()\n{\nNSObject *foo;\nstd::cout << \"Hello\" << std::endl;\nreturn 0;\n}\n" OBJCXX_BUILD_SHOULD_WORK) + CHECK_OBJCXX_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJCXX_RUN_SHOULD_FAIL) + CHECK_OBJCXX_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJCXX_RUN_SHOULD_WORK) + CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 2;\n}\n" OBJCXX_RUN_SHOULD_FAIL) + CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 0;\n}\n" OBJCXX_RUN_SHOULD_WORK) + + TEST_ASSERT(OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded") + TEST_FAIL(SIMPLE_OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURC_RUNS() succeeds, but should have failed") + TEST_ASSERT(SIMPLE_OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded") + TEST_FAIL(OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_RUNS() succeeds, but should have failed") + TEST_ASSERT(OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded") +endif() + ####################################################################### # # also test that the check_prototype_definition macro works |