1if(_ARMClang_CMAKE_LOADED)
2  return()
3endif()
4
5# This file requires CMAKE_LINKER and CMAKE_AR set by CMakeFindBinUtils.cmake.
6if(NOT (DEFINED CMAKE_LINKER AND DEFINED CMAKE_AR))
7  return()
8endif()
9
10set(_ARMClang_CMAKE_LOADED TRUE)
11
12# Save the CMP0123 setting in a variable used both below and by try_compile.
13cmake_policy(GET CMP0123 CMAKE_ARMClang_CMP0123)
14
15cmake_policy(PUSH)
16cmake_policy(SET CMP0057 NEW) # if IN_LIST
17
18set(CMAKE_EXECUTABLE_SUFFIX ".elf")
19
20if (CMAKE_LINKER MATCHES "armlink")
21  set(__CMAKE_ARMClang_USING_armlink TRUE)
22  set(CMAKE_LIBRARY_PATH_FLAG "--userlibpath=")
23else()
24  set(__CMAKE_ARMClang_USING_armlink FALSE)
25endif()
26
27# get compiler supported cpu list
28function(__armclang_set_processor_list lang out_var)
29  execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" --target=${CMAKE_${lang}_COMPILER_TARGET} -mcpu=list
30    OUTPUT_VARIABLE processor_list
31    ERROR_VARIABLE processor_list)
32  string(REGEX MATCHALL "-mcpu=([^ \n]*)" processor_list "${processor_list}")
33  string(REGEX REPLACE "-mcpu=" "" processor_list "${processor_list}")
34  set(${out_var} "${processor_list}" PARENT_SCOPE)
35endfunction()
36
37# check processor is in list
38function(__armclang_check_processor processor list out_var)
39  string(TOLOWER "${processor}" processor)
40  if(processor IN_LIST list)
41    set(${out_var} TRUE PARENT_SCOPE)
42  else()
43    set(${out_var} FALSE PARENT_SCOPE)
44  endif()
45endfunction()
46
47# get compiler supported arch list
48function(__armclang_set_arch_list lang out_var)
49  execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" --target=${CMAKE_${lang}_COMPILER_TARGET} -march=list
50    OUTPUT_VARIABLE arch_list
51    ERROR_VARIABLE arch_list)
52  string(REGEX MATCHALL "-march=([^ \n]*)" arch_list "${arch_list}")
53  string(REGEX REPLACE "-march=" "" arch_list "${arch_list}")
54  set(${out_var} "${arch_list}" PARENT_SCOPE)
55endfunction()
56
57# get linker supported cpu list
58function(__armlink_set_cpu_list lang out_var)
59  if(__CMAKE_ARMClang_USING_armlink)
60    set(__linker_wrapper_flags "")
61  else()
62    set(__linker_wrapper_flags --target=${CMAKE_${lang}_COMPILER_TARGET} -Xlinker)
63  endif()
64
65  execute_process(COMMAND "${CMAKE_LINKER}" ${__linker_wrapper_flags} --cpu=list
66    OUTPUT_VARIABLE cpu_list
67    ERROR_VARIABLE cpu_list)
68  string(REGEX MATCHALL "--cpu=([^ \n]*)" cpu_list "${cpu_list}")
69  string(REGEX REPLACE "--cpu=" "" cpu_list "${cpu_list}")
70  set(${out_var} "${cpu_list}" PARENT_SCOPE)
71endfunction()
72
73macro(__compiler_armclang lang)
74  if(NOT CMAKE_${lang}_COMPILER_TARGET)
75    set(CMAKE_${lang}_COMPILER_TARGET arm-arm-none-eabi)
76  endif()
77  if(NOT CMAKE_${lang}_COMPILER_PROCESSOR_LIST)
78    __armclang_set_processor_list(${lang} CMAKE_${lang}_COMPILER_PROCESSOR_LIST)
79  endif()
80  if(NOT CMAKE_${lang}_COMPILER_ARCH_LIST)
81    __armclang_set_arch_list(${lang} CMAKE_${lang}_COMPILER_ARCH_LIST)
82  endif()
83
84  # CMAKE_SYSTEM_PROCESSOR and CMAKE_SYSTEM_ARCH are not sufficient because they provide no
85  # information of additional CPU features needed in `-mcpu=<name>[+[no]<feature>+...]`.
86  # The automatic setting of compile and link options is deprecated and projects should specify their own.
87  cmake_policy(GET CMP0123 policy_CMP0123)
88  if(NOT "x${CMAKE_ARMClang_CMP0123}x" STREQUAL "xNEWx")
89    if(NOT "x${CMAKE_ARMClang_CMP0123}x" STREQUAL "xOLDx")
90      cmake_policy(GET_WARNING CMP0123 _cmp0123_warning)
91      message(AUTHOR_WARNING
92        "${_cmp0123_warning}\n"
93        "For compatibility, CMake will automatically add cpu/arch flags based "
94        "on the CMAKE_SYSTEM_PROCESSOR and/or CMAKE_SYSTEM_ARCH variables."
95        )
96    endif()
97
98    if(NOT CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_ARCH)
99      message(FATAL_ERROR "  CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n"
100        "  Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n"
101        "  Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}")
102    else()
103      __armclang_check_processor("${CMAKE_SYSTEM_ARCH}" "${CMAKE_${lang}_COMPILER_ARCH_LIST}" _CMAKE_${lang}_CHECK_ARCH_RESULT)
104      if( _CMAKE_${lang}_CHECK_ARCH_RESULT)
105        string(APPEND CMAKE_${lang}_FLAGS_INIT " -march=${CMAKE_SYSTEM_ARCH}")
106        set(__march_flag_set TRUE)
107      endif()
108      __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
109      if(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
110        string(APPEND CMAKE_${lang}_FLAGS_INIT " -mcpu=${CMAKE_SYSTEM_PROCESSOR}")
111        set(__mcpu_flag_set TRUE)
112      endif()
113      if(NOT __march_flag_set AND NOT __mcpu_flag_set)
114        message(FATAL_ERROR "At least one of the variables CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n"
115                            "Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n"
116                            "  Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}")
117      endif()
118      unset(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
119      unset(_CMAKE_${lang}_CHECK_ARCH_RESULT)
120    endif()
121
122    #check if CMAKE_SYSTEM_PROCESSOR belongs to supported cpu list for armlink
123    __armlink_set_cpu_list( ${lang} CMAKE_LINKER_CPU_LIST)
124    list(TRANSFORM CMAKE_LINKER_CPU_LIST TOLOWER)
125    __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_LINKER_CPU_LIST}" _CMAKE_CHECK_LINK_CPU_RESULT)
126    if(_CMAKE_CHECK_LINK_CPU_RESULT)
127      string(APPEND CMAKE_${lang}_LINK_FLAGS " --cpu=${CMAKE_SYSTEM_PROCESSOR}")
128    endif()
129
130  endif()
131
132  if(__CMAKE_ARMClang_USING_armlink)
133    unset(CMAKE_${lang}_LINKER_WRAPPER_FLAG)
134    set(__CMAKE_ARMClang_USING_armlink_WRAPPER "")
135  else()
136    set(__CMAKE_ARMClang_USING_armlink_WRAPPER "-Xlinker")
137  endif()
138  set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET> ${__CMAKE_ARMClang_USING_armlink_WRAPPER} --list=<TARGET_BASE>.map")
139  set(CMAKE_${lang}_CREATE_STATIC_LIBRARY  "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>")
140  set(CMAKE_${lang}_ARCHIVE_CREATE         "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>")
141  set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "${__CMAKE_ARMClang_USING_armlink_WRAPPER} --via=")
142  set(CMAKE_${lang}_OUTPUT_EXTENSION ".o")
143  set(CMAKE_${lang}_OUTPUT_EXTENSION_REPLACE 1)
144endmacro()
145
146cmake_policy(POP)
147