From 7b0abaac318b080d9d9044a2665541b840087c89 Mon Sep 17 00:00:00 2001
From: Johan Stridkvist <battletwixx@gmail.com>
Date: Mon, 13 May 2019 15:05:47 +0200
Subject: ARMClang: Add support for Clang-based ARM compiler

Fixes: #18215
---
 Help/release/dev/armclang.rst                     |  4 ++
 Help/variable/CMAKE_LANG_COMPILER_ID.rst          |  1 +
 Modules/CMakeCompilerIdDetection.cmake            |  1 +
 Modules/CMakeDetermineASMCompiler.cmake           |  4 ++
 Modules/CMakeDetermineCCompiler.cmake             |  3 +
 Modules/CMakeDetermineCXXCompiler.cmake           |  3 +
 Modules/CMakeDetermineCompilerId.cmake            |  1 +
 Modules/Compiler/ARMCC-ASM.cmake                  |  2 +-
 Modules/Compiler/ARMClang-ASM.cmake               |  9 +++
 Modules/Compiler/ARMClang-C-FeatureTests.cmake    |  1 +
 Modules/Compiler/ARMClang-C.cmake                 | 15 +++++
 Modules/Compiler/ARMClang-CXX-FeatureTests.cmake  |  1 +
 Modules/Compiler/ARMClang-CXX.cmake               |  3 +
 Modules/Compiler/ARMClang-DetermineCompiler.cmake | 10 ++++
 Modules/Compiler/ARMClang.cmake                   | 69 +++++++++++++++++++++++
 15 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 Help/release/dev/armclang.rst
 create mode 100644 Modules/Compiler/ARMClang-ASM.cmake
 create mode 100644 Modules/Compiler/ARMClang-C-FeatureTests.cmake
 create mode 100644 Modules/Compiler/ARMClang-C.cmake
 create mode 100644 Modules/Compiler/ARMClang-CXX-FeatureTests.cmake
 create mode 100644 Modules/Compiler/ARMClang-CXX.cmake
 create mode 100644 Modules/Compiler/ARMClang-DetermineCompiler.cmake
 create mode 100644 Modules/Compiler/ARMClang.cmake

diff --git a/Help/release/dev/armclang.rst b/Help/release/dev/armclang.rst
new file mode 100644
index 0000000..da82032
--- /dev/null
+++ b/Help/release/dev/armclang.rst
@@ -0,0 +1,4 @@
+armclang
+--------
+
+* Support for the Clang-based ARM compiler was added with compiler id ``ARMClang``.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
index 2bb3979..16d97ee 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
@@ -12,6 +12,7 @@ include:
   ADSP = Analog VisualDSP++ (analog.com)
   AppleClang = Apple Clang (apple.com)
   ARMCC = ARM Compiler (arm.com)
+  ARMClang = ARM Compiler based on Clang (arm.com)
   Bruce = Bruce C Compiler
   CCur = Concurrent Fortran (ccur.com)
   Clang = LLVM Clang (clang.llvm.org)
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index ed288f5..bb573b7 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -76,6 +76,7 @@ function(compiler_id_detection outvar lang)
       SCO
       ARMCC
       AppleClang
+      ARMClang
       Clang
       GNU
       MSVC
diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake
index eabb8b5..fb005ff 100644
--- a/Modules/CMakeDetermineASMCompiler.cmake
+++ b/Modules/CMakeDetermineASMCompiler.cmake
@@ -66,6 +66,10 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
   set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_AppleClang "--version")
   set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_AppleClang "(Apple LLVM version)")
 
+  list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS ARMClang )
+  set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMClang "--version")
+  set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMClang "armclang")
+
   list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS HP )
   set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_HP "-V")
   set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_HP "HP C")
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index 3ec534f..495d7e8 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -82,6 +82,9 @@ else()
 
     # Try compiling K&R-compatible code (needed by Bruce C Compiler).
     "-D__CLASSIC_C__"
+
+    # ARMClang need target options
+    "--target=arm-arm-none-eabi -mcpu=cortex-m3"
     )
 endif()
 
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index 68cb9fe..afcd956 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -77,6 +77,9 @@ else()
     # IAR does not detect language automatically
     "--c++"
     "--ec++"
+
+    # ARMClang need target options
+    "--target=arm-arm-none-eabi -mcpu=cortex-m3"
     )
 endif()
 
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 746a806..1cd919a 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -28,6 +28,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
     foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
                       ""
                       ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
+      separate_arguments(testflags UNIX_COMMAND "${testflags}")
       CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}")
       CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
       if(CMAKE_${lang}_COMPILER_ID)
diff --git a/Modules/Compiler/ARMCC-ASM.cmake b/Modules/Compiler/ARMCC-ASM.cmake
index 539d525..5819fc7 100644
--- a/Modules/Compiler/ARMCC-ASM.cmake
+++ b/Modules/Compiler/ARMCC-ASM.cmake
@@ -4,4 +4,4 @@ set(CMAKE_ASM_OUTPUT_EXTENSION ".o")
 set(CMAKE_ASM_OUTPUT_EXTENSION_REPLACE 1)
 
 set(CMAKE_ASM_COMPILE_OBJECT       "<CMAKE_ASM_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
-set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
+set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS S;s;asm;msa)
diff --git a/Modules/Compiler/ARMClang-ASM.cmake b/Modules/Compiler/ARMClang-ASM.cmake
new file mode 100644
index 0000000..ceff3e8
--- /dev/null
+++ b/Modules/Compiler/ARMClang-ASM.cmake
@@ -0,0 +1,9 @@
+include(Compiler/ARMClang)
+
+set(CMAKE_ASM_OUTPUT_EXTENSION ".o")
+set(CMAKE_ASM_OUTPUT_EXTENSION_REPLACE 1)
+
+set(CMAKE_ASM_COMPILE_OBJECT       "<CMAKE_ASM_COMPILER> <INCLUDES> <FLAGS> -c -o <OBJECT> <SOURCE>")
+set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS S;s;asm;msa)
+
+__compiler_armclang(ASM)
diff --git a/Modules/Compiler/ARMClang-C-FeatureTests.cmake b/Modules/Compiler/ARMClang-C-FeatureTests.cmake
new file mode 100644
index 0000000..ef79229
--- /dev/null
+++ b/Modules/Compiler/ARMClang-C-FeatureTests.cmake
@@ -0,0 +1 @@
+include(Compiler/Clang-C-FeatureTests)
diff --git a/Modules/Compiler/ARMClang-C.cmake b/Modules/Compiler/ARMClang-C.cmake
new file mode 100644
index 0000000..0a64a8a
--- /dev/null
+++ b/Modules/Compiler/ARMClang-C.cmake
@@ -0,0 +1,15 @@
+include(Compiler/Clang-C)
+include(Compiler/ARMClang)
+__compiler_armclang(C)
+
+set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
+set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
+
+set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
+set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
+
+set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
+set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
diff --git a/Modules/Compiler/ARMClang-CXX-FeatureTests.cmake b/Modules/Compiler/ARMClang-CXX-FeatureTests.cmake
new file mode 100644
index 0000000..e038e80
--- /dev/null
+++ b/Modules/Compiler/ARMClang-CXX-FeatureTests.cmake
@@ -0,0 +1 @@
+include(Compiler/Clang-CXX-FeatureTests)
diff --git a/Modules/Compiler/ARMClang-CXX.cmake b/Modules/Compiler/ARMClang-CXX.cmake
new file mode 100644
index 0000000..5dfb401
--- /dev/null
+++ b/Modules/Compiler/ARMClang-CXX.cmake
@@ -0,0 +1,3 @@
+include(Compiler/Clang-CXX)
+include(Compiler/ARMClang)
+__compiler_armclang(CXX)
diff --git a/Modules/Compiler/ARMClang-DetermineCompiler.cmake b/Modules/Compiler/ARMClang-DetermineCompiler.cmake
new file mode 100644
index 0000000..eb0de53
--- /dev/null
+++ b/Modules/Compiler/ARMClang-DetermineCompiler.cmake
@@ -0,0 +1,10 @@
+# ARMClang Toolchain
+set(_compiler_id_pp_test "defined(__clang__) && defined(__ARMCOMPILER_VERSION)")
+
+set(_compiler_id_version_compute "
+  # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__ARMCOMPILER_VERSION/1000000)
+  # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__ARMCOMPILER_VERSION/10000 % 100)
+  # define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__ARMCOMPILER_VERSION     % 10000)")
+
+string(APPEND _compiler_id_version_compute "
+# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__ARMCOMPILER_VERSION)")
diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake
new file mode 100644
index 0000000..5ca49df
--- /dev/null
+++ b/Modules/Compiler/ARMClang.cmake
@@ -0,0 +1,69 @@
+if(_ARMClang_CMAKE_LOADED)
+  return()
+endif()
+set(_ARMClang_CMAKE_LOADED TRUE)
+
+get_filename_component(_CMAKE_C_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH)
+get_filename_component(_CMAKE_CXX_TOOLCHAIN_LOCATION "${CMAKE_CXX_COMPILER}" PATH)
+
+set(CMAKE_EXECUTABLE_SUFFIX ".elf")
+
+find_program(CMAKE_ARMClang_LINKER armlink HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" )
+find_program(CMAKE_ARMClang_AR     armar   HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" )
+
+set(CMAKE_LINKER "${CMAKE_ARMClang_LINKER}" CACHE FILEPATH "The ARMClang linker" FORCE)
+mark_as_advanced(CMAKE_ARMClang_LINKER)
+set(CMAKE_AR "${CMAKE_ARMClang_AR}" CACHE FILEPATH "The ARMClang archiver" FORCE)
+mark_as_advanced(CMAKE_ARMClang_AR)
+
+# get compiler supported cpu list
+function(__armclang_set_processor_list lang out_var)
+  execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" --target=${CMAKE_${lang}_COMPILER_TARGET} -mcpu=list
+    OUTPUT_VARIABLE processor_list
+    ERROR_VARIABLE processor_list)
+  string(REGEX MATCHALL "-mcpu=([^ \n]*)" processor_list "${processor_list}")
+  string(REGEX REPLACE "-mcpu=" "" processor_list "${processor_list}")
+  set(${out_var} "${processor_list}" PARENT_SCOPE)
+endfunction()
+
+# check processor is in list
+function(__armclang_check_processor processor list out_var)
+  string(TOLOWER "${processor}" processor)
+  if(POLICY CMP0057)
+    cmake_policy(SET CMP0057 NEW)
+  endif()
+  if(processor IN_LIST list)
+    set(${out_var} TRUE PARENT_SCOPE)
+  else()
+    set(${out_var} FALSE PARENT_SCOPE)
+  endif()
+endfunction()
+
+macro(__compiler_armclang lang)
+  if(NOT CMAKE_${lang}_COMPILER_TARGET)
+    set(CMAKE_${lang}_COMPILER_TARGET arm-arm-none-eabi)
+  endif()
+  if(NOT CMAKE_${lang}_COMPILER_PROCESSOR_LIST)
+    __armclang_set_processor_list(${lang} CMAKE_${lang}_COMPILER_PROCESSOR_LIST)
+  endif()
+  if(NOT CMAKE_SYSTEM_PROCESSOR)
+    message(FATAL_ERROR "  CMAKE_SYSTEM_PROCESSOR must be set for ARMClang\n"
+      "  Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n")
+  else()
+    __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_RESULT)
+    if(NOT _CMAKE_${lang}_CHECK_RESULT)
+      message(FATAL_ERROR "  System processor '${CMAKE_SYSTEM_PROCESSOR}' not supported by ARMClang ${lang} compiler\n"
+        "  Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n")
+    endif()
+    unset(_CMAKE_${lang}_CHECK_RESULT)
+  endif()
+  string(APPEND CMAKE_${lang}_FLAGS_INIT "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
+  string(APPEND CMAKE_${lang}_LINK_FLAGS "--cpu=${CMAKE_SYSTEM_PROCESSOR}")
+
+  set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET> --list <TARGET_BASE>.map")
+  set(CMAKE_${lang}_CREATE_STATIC_LIBRARY  "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>")
+  set(CMAKE_${lang}_ARCHIVE_CREATE         "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>")
+  set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "--via=")
+  set(CMAKE_${lang}_OUTPUT_EXTENSION ".o")
+  set(CMAKE_${lang}_OUTPUT_EXTENSION_REPLACE 1)
+endmacro()
-- 
cgit v0.12