Browse Source

Merge topic 'compiler_flags'

f76c20da63 Toolchain: Test compiler initial settings
db486da265 Toolchain: Update documentation for initial compiler flags
deec2f587c Toolchain: Take CMAKE_<lang>_FLAGS_INIT into account during compiler detection
ca899af3e2 Toolchain: Handle repeated invocations of CMake with -DCMAKE_C_COMPILER
12ba89e142 Toolchain: Make `/path/comp;-argn' behave the same as 'comp;-argn'
6f1af899db Toolchain: Capture all arguments from CMAKE_<LANG>_COMPILER
ec1d3bc0b6 cmake: avoid exception when printing "changed variables" message

Acked-by: Kitware Robot <[email protected]>
Merge-request: !4136
Brad King 5 years ago
parent
commit
4daf76e10a
35 changed files with 235 additions and 39 deletions
  1. 8 0
      Help/envvar/ASM_DIALECT.rst
  2. 8 0
      Help/envvar/CC.rst
  3. 1 1
      Help/envvar/CSFLAGS.rst
  4. 8 0
      Help/envvar/CUDACXX.rst
  5. 8 0
      Help/envvar/CXX.rst
  6. 8 0
      Help/envvar/FC.rst
  7. 8 0
      Help/envvar/RC.rst
  8. 8 0
      Help/envvar/SWIFTC.rst
  9. 9 0
      Help/release/dev/compiler_flags.rst
  10. 25 0
      Help/variable/CMAKE_LANG_COMPILER.rst
  11. 1 1
      Modules/CMakeDetermineASMCompiler.cmake
  12. 1 1
      Modules/CMakeDetermineCCompiler.cmake
  13. 1 1
      Modules/CMakeDetermineCUDACompiler.cmake
  14. 1 1
      Modules/CMakeDetermineCXXCompiler.cmake
  15. 12 8
      Modules/CMakeDetermineCompiler.cmake
  16. 3 1
      Modules/CMakeDetermineCompilerId.cmake
  17. 1 1
      Modules/CMakeDetermineFortranCompiler.cmake
  18. 1 1
      Modules/CMakeDetermineJavaCompiler.cmake
  19. 6 9
      Modules/CMakeDetermineOBJCCompiler.cmake
  20. 6 9
      Modules/CMakeDetermineOBJCXXCompiler.cmake
  21. 1 1
      Modules/CMakeDetermineRCCompiler.cmake
  22. 1 1
      Modules/CMakeDetermineSwiftCompiler.cmake
  23. 8 0
      Source/cmGlobalGenerator.cxx
  24. 1 1
      Source/cmRulePlaceholderExpander.cxx
  25. 7 2
      Source/cmake.cxx
  26. 1 0
      Tests/RunCMake/CMakeLists.txt
  27. 3 0
      Tests/RunCMake/CompilerArgs/C.cmake
  28. 3 0
      Tests/RunCMake/CompilerArgs/CMakeLists.txt
  29. 3 0
      Tests/RunCMake/CompilerArgs/CXX.cmake
  30. 2 0
      Tests/RunCMake/CompilerArgs/FindCCompiler.cmake
  31. 2 0
      Tests/RunCMake/CompilerArgs/FindCXXCompiler.cmake
  32. 58 0
      Tests/RunCMake/CompilerArgs/RunCMakeTest.cmake
  33. 10 0
      Tests/RunCMake/CompilerArgs/main.c
  34. 10 0
      Tests/RunCMake/CompilerArgs/main.cxx
  35. 1 0
      Tests/RunCMake/CompilerArgs/toolchain.cmake.in

+ 8 - 0
Help/envvar/ASM_DIALECT.rst

@@ -14,3 +14,11 @@ in the cache as
 :variable:`CMAKE_ASM<DIALECT>_COMPILER <CMAKE_<LANG>_COMPILER>`. For subsequent
 configuration runs, the environment variable will be ignored in favor of
 :variable:`CMAKE_ASM<DIALECT>_COMPILER <CMAKE_<LANG>_COMPILER>`.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export ASM="custom-compiler --arg1 --arg2"

+ 8 - 0
Help/envvar/CC.rst

@@ -11,3 +11,11 @@ value for ``CC`` is stored in the cache as
 :variable:`CMAKE_C_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration run
 (including the first), the environment variable will be ignored if the
 :variable:`CMAKE_C_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export CC="custom-compiler --arg1 --arg2"

+ 1 - 1
Help/envvar/CSFLAGS.rst

@@ -5,7 +5,7 @@ CSFLAGS
 
 .. include:: ENV_VAR.txt
 
-Preferred executable for compiling ``CSharp`` language files. Will only be
+Default compilation flags to be used when compiling ``CSharp`` files. Will only be
 used by CMake on the first configuration to determine ``CSharp`` default
 compilation flags, after which the value for ``CSFLAGS`` is stored in the cache
 as :variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration

+ 8 - 0
Help/envvar/CUDACXX.rst

@@ -11,3 +11,11 @@ value for ``CUDA`` is stored in the cache as
 :variable:`CMAKE_CUDA_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration
 run (including the first), the environment variable will be ignored if the
 :variable:`CMAKE_CUDA_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export CUDACXX="custom-compiler --arg1 --arg2"

+ 8 - 0
Help/envvar/CXX.rst

@@ -11,3 +11,11 @@ value for ``CXX`` is stored in the cache as
 :variable:`CMAKE_CXX_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration
 run (including the first), the environment variable will be ignored if the
 :variable:`CMAKE_CXX_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export CXX="custom-compiler --arg1 --arg2"

+ 8 - 0
Help/envvar/FC.rst

@@ -12,3 +12,11 @@ which the value for ``Fortran`` is stored in the cache as
 configuration run (including the first), the environment variable will be
 ignored if the :variable:`CMAKE_Fortran_COMPILER <CMAKE_<LANG>_COMPILER>`
 variable is defined.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export FC="custom-compiler --arg1 --arg2"

+ 8 - 0
Help/envvar/RC.rst

@@ -11,3 +11,11 @@ value for ``RC`` is stored in the cache as
 :variable:`CMAKE_RC_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration run
 (including the first), the environment variable will be ignored if the
 :variable:`CMAKE_RC_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export RC="custom-compiler --arg1 --arg2"

+ 8 - 0
Help/envvar/SWIFTC.rst

@@ -11,3 +11,11 @@ value for ``SWIFTC`` is stored in the cache as
 :variable:`CMAKE_Swift_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration run
 (including the first), the environment variable will be ignored if the
 :variable:`CMAKE_Swift_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included;
+  they can not be changed.
+
+.. code-block:: console
+
+  $ export SWIFTC="custom-compiler --arg1 --arg2"

+ 9 - 0
Help/release/dev/compiler_flags.rst

@@ -0,0 +1,9 @@
+compiler_flags
+-----------------
+
+* The :variable:`CMAKE_<LANG>_COMPILER` variable may now be used to
+  store "mandatory" compiler flags like the :envvar:`CC` and other environment variables.
+
+* The :variable:`CMAKE_<LANG>_FLAGS_INIT` variable will now be considered during
+  the compiler indentification check if other sources like :variable:`CMAKE_<LANG>_FLAGS`
+  or :envvar:`CFLAGS` are not set.

+ 25 - 0
Help/variable/CMAKE_LANG_COMPILER.rst

@@ -5,3 +5,28 @@ The full path to the compiler for ``LANG``.
 
 This is the command that will be used as the ``<LANG>`` compiler.  Once
 set, you can not change this variable.
+
+Usage
+^^^^^
+
+This variable can be set by the user during the first time a build tree is configured.
+
+If a non-full path value is supplied then CMake will resolve the full path of
+the compiler.
+
+The variable could be set in a user supplied toolchain file or via `-D` on the command line.
+
+.. note::
+  Options that are required to make the compiler work correctly can be included
+  as items in a list; they can not be changed.
+
+.. code-block:: cmake
+
+  #set within user supplied toolchain file
+  set(CMAKE_C_COMPILER /full/path/to/qcc --arg1 --arg2)
+
+or
+
+.. code-block:: console
+
+  $ cmake ... -DCMAKE_C_COMPILER='qcc;--arg1;--arg2'

+ 1 - 1
Modules/CMakeDetermineASMCompiler.cmake

@@ -11,7 +11,7 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER)
   if(NOT $ENV{ASM${ASM_DIALECT}} STREQUAL "")
     get_filename_component(CMAKE_ASM${ASM_DIALECT}_COMPILER_INIT $ENV{ASM${ASM_DIALECT}} PROGRAM PROGRAM_ARGS CMAKE_ASM${ASM_DIALECT}_FLAGS_ENV_INIT)
     if(CMAKE_ASM${ASM_DIALECT}_FLAGS_ENV_INIT)
-      set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARG1 "${CMAKE_ASM${ASM_DIALECT}_FLAGS_ENV_INIT}" CACHE STRING "First argument to ASM${ASM_DIALECT} compiler")
+      set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARG1 "${CMAKE_ASM${ASM_DIALECT}_FLAGS_ENV_INIT}" CACHE STRING "Arguments to ASM${ASM_DIALECT} compiler")
     endif()
     if(NOT EXISTS ${CMAKE_ASM${ASM_DIALECT}_COMPILER_INIT})
       message(FATAL_ERROR "Could not find compiler set in environment variable ASM${ASM_DIALECT}:\n$ENV{ASM${ASM_DIALECT}}.")

+ 1 - 1
Modules/CMakeDetermineCCompiler.cmake

@@ -43,7 +43,7 @@ else()
     if(NOT $ENV{CC} STREQUAL "")
       get_filename_component(CMAKE_C_COMPILER_INIT $ENV{CC} PROGRAM PROGRAM_ARGS CMAKE_C_FLAGS_ENV_INIT)
       if(CMAKE_C_FLAGS_ENV_INIT)
-        set(CMAKE_C_COMPILER_ARG1 "${CMAKE_C_FLAGS_ENV_INIT}" CACHE STRING "First argument to C compiler")
+        set(CMAKE_C_COMPILER_ARG1 "${CMAKE_C_FLAGS_ENV_INIT}" CACHE STRING "Arguments to C compiler")
       endif()
       if(NOT EXISTS ${CMAKE_C_COMPILER_INIT})
         message(FATAL_ERROR "Could not find compiler set in environment variable CC:\n$ENV{CC}.")

+ 1 - 1
Modules/CMakeDetermineCUDACompiler.cmake

@@ -19,7 +19,7 @@ else()
       if(NOT $ENV{CUDACXX} STREQUAL "")
         get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
         if(CMAKE_CUDA_FLAGS_ENV_INIT)
-          set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
+          set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CXX compiler")
         endif()
         if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
           message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")

+ 1 - 1
Modules/CMakeDetermineCXXCompiler.cmake

@@ -42,7 +42,7 @@ else()
     if(NOT $ENV{CXX} STREQUAL "")
       get_filename_component(CMAKE_CXX_COMPILER_INIT $ENV{CXX} PROGRAM PROGRAM_ARGS CMAKE_CXX_FLAGS_ENV_INIT)
       if(CMAKE_CXX_FLAGS_ENV_INIT)
-        set(CMAKE_CXX_COMPILER_ARG1 "${CMAKE_CXX_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
+        set(CMAKE_CXX_COMPILER_ARG1 "${CMAKE_CXX_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CXX compiler")
       endif()
       if(NOT EXISTS ${CMAKE_CXX_COMPILER_INIT})
         message(FATAL_ERROR "Could not find compiler set in environment variable CXX:\n$ENV{CXX}.\n${CMAKE_CXX_COMPILER_INIT}")

+ 12 - 8
Modules/CMakeDetermineCompiler.cmake

@@ -107,16 +107,14 @@ macro(_cmake_find_compiler_path lang)
   if(CMAKE_${lang}_COMPILER)
     # we only get here if CMAKE_${lang}_COMPILER was specified using -D or a pre-made CMakeCache.txt
     # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
-    # if CMAKE_${lang}_COMPILER is a list of length 2, use the first item as
-    # CMAKE_${lang}_COMPILER and the 2nd one as CMAKE_${lang}_COMPILER_ARG1
-    list(LENGTH CMAKE_${lang}_COMPILER _CMAKE_${lang}_COMPILER_LIST_LENGTH)
-    if("${_CMAKE_${lang}_COMPILER_LIST_LENGTH}" EQUAL 2)
-      list(GET CMAKE_${lang}_COMPILER 1 CMAKE_${lang}_COMPILER_ARG1)
-      list(GET CMAKE_${lang}_COMPILER 0 CMAKE_${lang}_COMPILER)
-    endif()
-    unset(_CMAKE_${lang}_COMPILER_LIST_LENGTH)
+    # if CMAKE_${lang}_COMPILER is a list, use the first item as
+    # CMAKE_${lang}_COMPILER and the rest as CMAKE_${lang}_COMPILER_ARG1
+    set(CMAKE_${lang}_COMPILER_ARG1 "${CMAKE_${lang}_COMPILER}")
+    list(POP_FRONT CMAKE_${lang}_COMPILER_ARG1 CMAKE_${lang}_COMPILER)
+    list(JOIN CMAKE_${lang}_COMPILER_ARG1 " " CMAKE_${lang}_COMPILER_ARG1)
 
     # find the compiler in the PATH if necessary
+    # if compiler (and arguments) comes from cache then synchronize cache with updated CMAKE_<LANG>_COMPILER
     get_filename_component(_CMAKE_USER_${lang}_COMPILER_PATH "${CMAKE_${lang}_COMPILER}" PATH)
     if(NOT _CMAKE_USER_${lang}_COMPILER_PATH)
       find_program(CMAKE_${lang}_COMPILER_WITH_PATH NAMES ${CMAKE_${lang}_COMPILER})
@@ -129,6 +127,12 @@ macro(_cmake_find_compiler_path lang)
         unset(_CMAKE_${lang}_COMPILER_CACHED)
       endif()
       unset(CMAKE_${lang}_COMPILER_WITH_PATH CACHE)
+    elseif (EXISTS ${CMAKE_${lang}_COMPILER})
+      get_property(_CMAKE_${lang}_COMPILER_CACHED CACHE CMAKE_${lang}_COMPILER PROPERTY TYPE)
+      if(_CMAKE_${lang}_COMPILER_CACHED)
+        set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER}" CACHE STRING "${lang} compiler" FORCE)
+      endif()
+      unset(_CMAKE_${lang}_COMPILER_CACHED)
     endif()
   endif()
 endmacro()

+ 3 - 1
Modules/CMakeDetermineCompilerId.cmake

@@ -14,8 +14,10 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
   # Make sure user-specified compiler flags are used.
   if(CMAKE_${lang}_FLAGS)
     set(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS})
-  else()
+  elseif(DEFINED ENV{${flagvar}})
     set(CMAKE_${lang}_COMPILER_ID_FLAGS $ENV{${flagvar}})
+  else(CMAKE_${lang}_FLAGS_INIT)
+    set(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS_INIT})
   endif()
   string(REPLACE " " ";" CMAKE_${lang}_COMPILER_ID_FLAGS_LIST "${CMAKE_${lang}_COMPILER_ID_FLAGS}")
 

+ 1 - 1
Modules/CMakeDetermineFortranCompiler.cmake

@@ -26,7 +26,7 @@ else()
     if(NOT $ENV{FC} STREQUAL "")
       get_filename_component(CMAKE_Fortran_COMPILER_INIT $ENV{FC} PROGRAM PROGRAM_ARGS CMAKE_Fortran_FLAGS_ENV_INIT)
       if(CMAKE_Fortran_FLAGS_ENV_INIT)
-        set(CMAKE_Fortran_COMPILER_ARG1 "${CMAKE_Fortran_FLAGS_ENV_INIT}" CACHE STRING "First argument to Fortran compiler")
+        set(CMAKE_Fortran_COMPILER_ARG1 "${CMAKE_Fortran_FLAGS_ENV_INIT}" CACHE STRING "Arguments to Fortran compiler")
       endif()
       if(EXISTS ${CMAKE_Fortran_COMPILER_INIT})
       else()

+ 1 - 1
Modules/CMakeDetermineJavaCompiler.cmake

@@ -11,7 +11,7 @@ if(NOT CMAKE_Java_COMPILER)
   if(NOT $ENV{JAVA_COMPILER} STREQUAL "")
     get_filename_component(CMAKE_Java_COMPILER_INIT $ENV{JAVA_COMPILER} PROGRAM PROGRAM_ARGS CMAKE_Java_FLAGS_ENV_INIT)
     if(CMAKE_Java_FLAGS_ENV_INIT)
-      set(CMAKE_Java_COMPILER_ARG1 "${CMAKE_Java_FLAGS_ENV_INIT}" CACHE STRING "First argument to Java compiler")
+      set(CMAKE_Java_COMPILER_ARG1 "${CMAKE_Java_FLAGS_ENV_INIT}" CACHE STRING "Arguments to Java compiler")
     endif()
     if(NOT EXISTS ${CMAKE_Java_COMPILER_INIT})
       message(SEND_ERROR "Could not find compiler set in environment variable JAVA_COMPILER:\n$ENV{JAVA_COMPILER}.")

+ 6 - 9
Modules/CMakeDetermineOBJCCompiler.cmake

@@ -39,7 +39,7 @@ else()
       if($ENV{${var}} MATCHES ".+")
         get_filename_component(CMAKE_OBJC_COMPILER_INIT $ENV{${var}} 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")
+          set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_FLAGS_ENV_INIT}" CACHE STRING "Arguments to Objective-C compiler")
         endif()
         if(NOT EXISTS ${CMAKE_OBJC_COMPILER_INIT})
           message(FATAL_ERROR "Could not find compiler set in environment variable ${var}:\n  $ENV{${var}}")
@@ -65,14 +65,11 @@ else()
   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 CMAKE_OBJC_COMPILER is a list, use the first item as
+    # CMAKE_OBJC_COMPILER and the rest as CMAKE_OBJC_COMPILER_ARG1
+    set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_COMPILER}")
+    list(POP_FRONT CMAKE_OBJC_COMPILER_ARG1 CMAKE_OBJC_COMPILER)
+    list(JOIN CMAKE_OBJC_COMPILER_ARG1 " " CMAKE_OBJC_COMPILER_ARG1)
 
     # if a compiler was specified by the user but without path,
     # now try to find it with the full path

+ 6 - 9
Modules/CMakeDetermineOBJCXXCompiler.cmake

@@ -41,7 +41,7 @@ else()
       if($ENV{${var}} MATCHES ".+")
         get_filename_component(CMAKE_OBJCXX_COMPILER_INIT $ENV{${var}} 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")
+          set(CMAKE_OBJCXX_COMPILER_ARG1 "${CMAKE_OBJCXX_FLAGS_ENV_INIT}" CACHE STRING "Arguments to Objective-C++ compiler")
         endif()
         if(NOT EXISTS ${CMAKE_OBJCXX_COMPILER_INIT})
           message(FATAL_ERROR "Could not find compiler set in environment variable ${var}:\n  $ENV{${var}}")
@@ -67,14 +67,11 @@ else()
   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 CMAKE_OBJCXX_COMPILER is a list, use the first item as
+    # CMAKE_OBJCXX_COMPILER and the rest as CMAKE_OBJCXX_COMPILER_ARG1
+    set(CMAKE_OBJCXX_COMPILER_ARG1 "${CMAKE_OBJCXX_COMPILER}")
+    list(POP_FRONT CMAKE_OBJCXX_COMPILER_ARG1 CMAKE_OBJCXX_COMPILER)
+    list(JOIN CMAKE_OBJCXX_COMPILER_ARG1 " " CMAKE_OBJCXX_COMPILER_ARG1)
 
     # if a compiler was specified by the user but without path,
     # now try to find it with the full path

+ 1 - 1
Modules/CMakeDetermineRCCompiler.cmake

@@ -13,7 +13,7 @@ if(NOT CMAKE_RC_COMPILER)
   if(NOT $ENV{RC} STREQUAL "")
     get_filename_component(CMAKE_RC_COMPILER_INIT $ENV{RC} PROGRAM PROGRAM_ARGS CMAKE_RC_FLAGS_ENV_INIT)
     if(CMAKE_RC_FLAGS_ENV_INIT)
-      set(CMAKE_RC_COMPILER_ARG1 "${CMAKE_RC_FLAGS_ENV_INIT}" CACHE STRING "First argument to RC compiler")
+      set(CMAKE_RC_COMPILER_ARG1 "${CMAKE_RC_FLAGS_ENV_INIT}" CACHE STRING "Arguments to RC compiler")
     endif()
     if(EXISTS ${CMAKE_RC_COMPILER_INIT})
     else()

+ 1 - 1
Modules/CMakeDetermineSwiftCompiler.cmake

@@ -27,7 +27,7 @@ elseif("${CMAKE_GENERATOR}" MATCHES "^Ninja")
         PROGRAM_ARGS CMAKE_Swift_FLAGS_ENV_INIT)
       if(CMAKE_Swift_FLAGS_ENV_INIT)
         set(CMAKE_Swift_COMPILER_ARG1 "${CMAKE_Swift_FLAGS_ENV_INIT}" CACHE
-          STRING "First argument to the Swift compiler")
+          STRING "Arguments to the Swift compiler")
       endif()
       if(NOT EXISTS ${CMAKE_Swift_COMPILER_INIT})
         message(FATAL_ERROR "Could not find compiler set in environment variable SWIFTC\n$ENV{SWIFTC}.\n${CMAKE_Swift_COMPILER_INIT}")

+ 8 - 0
Source/cmGlobalGenerator.cxx

@@ -235,6 +235,14 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
   }
   cmProp cname =
     this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
+
+  // Split compiler from arguments
+  std::vector<std::string> cnameArgVec;
+  if (cname && !cname->empty()) {
+    cmExpandList(*cname, cnameArgVec);
+    cname = &cnameArgVec.front();
+  }
+
   std::string changeVars;
   if (cname && !optional) {
     std::string cnameString;

+ 1 - 1
Source/cmRulePlaceholderExpander.cxx

@@ -261,7 +261,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
       this->VariableMappings["CMAKE_" + compIt->second +
                              "_COMPILE_OPTIONS_SYSROOT"];
 
-    // if there is a required first argument to the compiler add it
+    // if there are required arguments to the compiler add it
     // to the compiler string
     if (!compilerArg1.empty()) {
       ret += " ";

+ 7 - 2
Source/cmake.cxx

@@ -1390,8 +1390,13 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
     save.key = *i;
     warning << *i << "= ";
     i++;
-    save.value = *i;
-    warning << *i << "\n";
+    if (i != argsSplit.end()) {
+      save.value = *i;
+      warning << *i << "\n";
+    } else {
+      warning << "\n";
+      i -= 1;
+    }
     cmProp existingValue = this->State->GetCacheEntryValue(save.key);
     if (existingValue) {
       save.type = this->State->GetCacheEntryType(save.key);

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -626,6 +626,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
   set_property(TEST RunCMake.CompilerLauncher APPEND
     PROPERTY LABELS "CUDA")
   add_RunCMake_test(ctest_labels_for_subprojects)
+  add_RunCMake_test(CompilerArgs)
 endif()
 
 set(cpack_tests

+ 3 - 0
Tests/RunCMake/CompilerArgs/C.cmake

@@ -0,0 +1,3 @@
+enable_language(C)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.c)

+ 3 - 0
Tests/RunCMake/CompilerArgs/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.2)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 3 - 0
Tests/RunCMake/CompilerArgs/CXX.cmake

@@ -0,0 +1,3 @@
+enable_language(CXX)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.cxx)

+ 2 - 0
Tests/RunCMake/CompilerArgs/FindCCompiler.cmake

@@ -0,0 +1,2 @@
+enable_language(C)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/C_comp.cmake" "set(temp_CMAKE_C_COMPILER \"${CMAKE_C_COMPILER}\")\n")

+ 2 - 0
Tests/RunCMake/CompilerArgs/FindCXXCompiler.cmake

@@ -0,0 +1,2 @@
+enable_language(CXX)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CXX_comp.cmake" "set(temp_CMAKE_CXX_COMPILER \"${CMAKE_CXX_COMPILER}\")\n")

+ 58 - 0
Tests/RunCMake/CompilerArgs/RunCMakeTest.cmake

@@ -0,0 +1,58 @@
+include(RunCMake)
+
+function(find_compiler lang)
+  # Detect the compiler in use in the current environment.
+  run_cmake(Find${lang}Compiler)
+  # Use the detected compiler
+  include(${RunCMake_BINARY_DIR}/Find${lang}Compiler-build/${lang}_comp.cmake)
+  if(NOT temp_CMAKE_${lang}_COMPILER)
+    message(FATAL_ERROR "FindCompiler provided no compiler!")
+  endif()
+  # Create a toolchain file
+  set(__test_compiler_var CMAKE_${lang}_COMPILER)
+  set(__test_compiler "${temp_CMAKE_${lang}_COMPILER}")
+  configure_file(${RunCMake_SOURCE_DIR}/toolchain.cmake.in
+      ${RunCMake_BINARY_DIR}/Find${lang}Compiler-build/toolchain_${lang}_comp.cmake @ONLY)
+endfunction()
+
+function(run_compiler_env lang)
+  # Use the correct compiler
+  include(${RunCMake_BINARY_DIR}/Find${lang}Compiler-build/${lang}_comp.cmake)
+
+  # Use a single build tree for tests without cleaning.
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-env-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+  # Set the compiler
+  if(lang STREQUAL "C")
+    set(ENV{CC} "'${temp_CMAKE_${lang}_COMPILER}' -DFOO1 -DFOO2")
+  else()
+    set(ENV{${lang}} "'${temp_CMAKE_${lang}_COMPILER}' -DFOO1 -DFOO2")
+  endif()
+
+  run_cmake(${lang})
+  run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args})
+endfunction()
+
+function(run_compiler_tc lang)
+  # Use a single build tree for tests without cleaning.
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-tc-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+  set(RunCMake_TEST_OPTIONS
+      -DCMAKE_TOOLCHAIN_FILE=${RunCMake_BINARY_DIR}/Find${lang}Compiler-build/toolchain_${lang}_comp.cmake)
+  run_cmake(${lang})
+  run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args})
+endfunction()
+
+set(langs C CXX)
+
+foreach(lang ${langs})
+  find_compiler(${lang})
+  run_compiler_env(${lang})
+  run_compiler_tc(${lang})
+endforeach()

+ 10 - 0
Tests/RunCMake/CompilerArgs/main.c

@@ -0,0 +1,10 @@
+#ifndef FOO1
+#  error Missing FOO1
+#endif
+#ifndef FOO2
+#  error Missing FOO2
+#endif
+int main(void)
+{
+  return 0;
+}

+ 10 - 0
Tests/RunCMake/CompilerArgs/main.cxx

@@ -0,0 +1,10 @@
+#ifndef FOO1
+#  error Missing FOO1
+#endif
+#ifndef FOO2
+#  error Missing FOO2
+#endif
+int main()
+{
+  return 0;
+}

+ 1 - 0
Tests/RunCMake/CompilerArgs/toolchain.cmake.in

@@ -0,0 +1 @@
+set(@__test_compiler_var@ "@__test_compiler@" -DFOO1 -DFOO2)