Skip to content

Commit 40a2ffd

Browse files
tejlmandnashif
authored andcommitted
armclang: support for armclang compiler and armlink linker
This is the initial support for the armclang compiler together with the armlink linker. Introduced in this commit: - armclang compiler support - armlink linker support - armlink scatter file generator for scatter loading - dual pass linker script generation Signed-off-by: Torsten Rasmussen <[email protected]>
1 parent 4de0d55 commit 40a2ffd

File tree

7 files changed

+525
-0
lines changed

7 files changed

+525
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# First step is to inherit all properties from gcc, as clang is compatible with most flags.
2+
include(${ZEPHYR_BASE}/cmake/compiler/clang/compiler_flags.cmake)
3+
4+
# Required ASM flags when using armclang, this should be handled by CMake, but
5+
# fails because of: https://gitlab.kitware.com/cmake/cmake/-/issues/19963
6+
set_property(TARGET asm APPEND PROPERTY required "--target=${triple}")
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
# Configures CMake for using ccac
4+
5+
find_program(CMAKE_C_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME}/bin NO_DEFAULT_PATH)
6+
7+
set(triple arm-arm-none-eabi)
8+
9+
set(CMAKE_DTS_PREPROCESSOR
10+
${CMAKE_C_COMPILER}
11+
"--target=${triple}"
12+
# -march=armv6-m is added to silence the warnings:
13+
# 'armv4t' and 'arm7tdmi' is unsupported.
14+
# We only do preprocessing so the actual arch is not important.
15+
"-march=armv6-m"
16+
)
17+
18+
set(CMAKE_C_COMPILER_TARGET ${triple})
19+
set(CMAKE_ASM_COMPILER_TARGET ${triple})
20+
set(CMAKE_CXX_COMPILER_TARGET ${triple})
21+
22+
if(CMAKE_C_COMPILER STREQUAL CMAKE_C_COMPILER-NOTFOUND)
23+
message(FATAL_ERROR "Zephyr was unable to find the armclang compiler")
24+
endif()
25+
26+
execute_process(
27+
COMMAND ${CMAKE_C_COMPILER} --version
28+
RESULT_VARIABLE ret
29+
OUTPUT_QUIET
30+
ERROR_QUIET
31+
)
32+
33+
if(ret)
34+
message(FATAL_ERROR "Executing the below command failed. "
35+
"Are permissions set correctly? '${CMAKE_C_COMPILER} --version' "
36+
"And is the license setup correctly ?"
37+
)
38+
endif()
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# find the compilers for C, CPP, assembly
2+
find_program(CMAKE_C_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
3+
find_program(CMAKE_CXX_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
4+
find_program(CMAKE_ASM_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
5+
6+
# The CMAKE_REQUIRED_FLAGS variable is used by check_c_compiler_flag()
7+
# (and other commands which end up calling check_c_source_compiles())
8+
# to add additional compiler flags used during checking. These flags
9+
# are unused during "real" builds of Zephyr source files linked into
10+
# the final executable.
11+
#
12+
include(${ZEPHYR_BASE}/cmake/gcc-m-cpu.cmake)
13+
set(CMAKE_SYSTEM_PROCESSOR ${GCC_M_CPU})
14+
15+
list(APPEND TOOLCHAIN_C_FLAGS
16+
-fshort-enums
17+
)
18+
19+
if(CONFIG_ARM64)
20+
list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU})
21+
22+
list(APPEND TOOLCHAIN_C_FLAGS -mabi=lp64)
23+
list(APPEND TOOLCHAIN_LD_FLAGS -mabi=lp64)
24+
else()
25+
list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU})
26+
27+
if(CONFIG_COMPILER_ISA_THUMB2)
28+
list(APPEND TOOLCHAIN_C_FLAGS -mthumb)
29+
endif()
30+
31+
list(APPEND TOOLCHAIN_C_FLAGS -mabi=aapcs)
32+
33+
# Defines a mapping from GCC_M_CPU to FPU
34+
35+
if(CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION)
36+
set(PRECISION_TOKEN)
37+
else()
38+
set(PRECISION_TOKEN sp-)
39+
endif()
40+
41+
set(FPU_FOR_cortex-m4 fpv4-${PRECISION_TOKEN}d16)
42+
set(FPU_FOR_cortex-m7 fpv5-${PRECISION_TOKEN}d16)
43+
set(FPU_FOR_cortex-m33 fpv5-${PRECISION_TOKEN}d16)
44+
45+
if(CONFIG_FPU)
46+
list(APPEND TOOLCHAIN_C_FLAGS -mfpu=${FPU_FOR_${GCC_M_CPU}})
47+
if (CONFIG_FP_SOFTABI)
48+
list(APPEND TOOLCHAIN_C_FLAGS -mfloat-abi=softfp)
49+
elseif(CONFIG_FP_HARDABI)
50+
list(APPEND TOOLCHAIN_C_FLAGS -mfloat-abi=hard)
51+
endif()
52+
endif()
53+
endif()
54+
55+
foreach(file_name include/stddef.h)
56+
execute_process(
57+
COMMAND ${CMAKE_C_COMPILER} --print-file-name=${file_name}
58+
OUTPUT_VARIABLE _OUTPUT
59+
)
60+
get_filename_component(_OUTPUT "${_OUTPUT}" DIRECTORY)
61+
string(REGEX REPLACE "\n" "" _OUTPUT ${_OUTPUT})
62+
63+
list(APPEND NOSTDINC ${_OUTPUT})
64+
endforeach()
65+
66+
foreach(isystem_include_dir ${NOSTDINC})
67+
list(APPEND isystem_include_flags -isystem ${isystem_include_dir})
68+
endforeach()
69+
70+
set(CMAKE_REQUIRED_FLAGS -nostartfiles -nostdlib ${isystem_include_flags})
71+
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
72+
73+
# Load toolchain_cc-family macros
74+
75+
macro(toolchain_cc_nostdinc)
76+
if(NOT "${ARCH}" STREQUAL "posix")
77+
zephyr_compile_options( -nostdinc)
78+
endif()
79+
endmacro()
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
cmake_minimum_required(VERSION 3.17)
2+
3+
set(SORT_TYPE_NAME Lexical)
4+
5+
#
6+
# String functions - start
7+
#
8+
9+
function(system_to_string)
10+
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
11+
12+
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
13+
get_property(regions GLOBAL PROPERTY ${STRING_OBJECT}_REGIONS)
14+
get_property(format GLOBAL PROPERTY ${STRING_OBJECT}_FORMAT)
15+
16+
foreach(region ${regions})
17+
get_property(empty GLOBAL PROPERTY ${region}_EMPTY)
18+
if(NOT empty)
19+
to_string(OBJECT ${region} STRING ${STRING_STRING})
20+
endif()
21+
endforeach()
22+
23+
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
24+
endfunction()
25+
26+
function(group_to_string)
27+
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
28+
29+
get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
30+
if(${type} STREQUAL REGION)
31+
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
32+
get_property(address GLOBAL PROPERTY ${STRING_OBJECT}_ADDRESS)
33+
get_property(size GLOBAL PROPERTY ${STRING_OBJECT}_SIZE)
34+
set(${STRING_STRING} "${${STRING_STRING}}\n${name} ${address} NOCOMPRESS ${size}\n{\n")
35+
endif()
36+
37+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED)
38+
foreach(section ${sections})
39+
to_string(OBJECT ${section} STRING ${STRING_STRING})
40+
endforeach()
41+
42+
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS)
43+
foreach(group ${groups})
44+
to_string(OBJECT ${group} STRING ${STRING_STRING})
45+
endforeach()
46+
47+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS)
48+
foreach(section ${sections})
49+
to_string(OBJECT ${section} STRING ${STRING_STRING})
50+
endforeach()
51+
52+
get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM)
53+
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
54+
list(REMOVE_ITEM regions ${STRING_OBJECT})
55+
foreach(region ${regions})
56+
get_property(vma GLOBAL PROPERTY ${region}_NAME)
57+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED)
58+
foreach(section ${sections})
59+
to_string(OBJECT ${section} STRING ${STRING_STRING})
60+
endforeach()
61+
62+
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS)
63+
foreach(group ${groups})
64+
to_string(OBJECT ${group} STRING ${STRING_STRING})
65+
endforeach()
66+
67+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS)
68+
foreach(section ${sections})
69+
to_string(OBJECT ${section} STRING ${STRING_STRING})
70+
endforeach()
71+
endforeach()
72+
73+
get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS)
74+
foreach(symbol ${symbols})
75+
to_string(OBJECT ${symbol} STRING ${STRING_STRING})
76+
endforeach()
77+
78+
if(${type} STREQUAL REGION)
79+
set(${STRING_STRING} "${${STRING_STRING}}\n}\n")
80+
endif()
81+
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
82+
endfunction()
83+
84+
85+
function(section_to_string)
86+
cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN})
87+
88+
get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME)
89+
get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS)
90+
get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE)
91+
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN)
92+
get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN)
93+
get_property(endalign GLOBAL PROPERTY ${STRING_SECTION}_ENDALIGN)
94+
get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA)
95+
get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA)
96+
get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT)
97+
get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT)
98+
99+
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
100+
string(REPLACE "." "_" name_clean "${name_clean}")
101+
102+
set(TEMP " ${name_clean}")
103+
if(DEFINED address)
104+
set(TEMP "${TEMP} ${address}")
105+
else()
106+
set(TEMP "${TEMP} +0")
107+
endif()
108+
109+
if(noinit)
110+
# Currently we simply uses offset +0, but we must support offset defined
111+
# externally.
112+
set(TEMP "${TEMP} UNINIT")
113+
endif()
114+
115+
if(subalign)
116+
# Currently we simply uses offset +0, but we must support offset defined
117+
# externally.
118+
set(TEMP "${TEMP} ALIGN ${subalign}")
119+
endif()
120+
121+
if(NOT noinput)
122+
set(TEMP "${TEMP}\n {")
123+
124+
if("${type}" STREQUAL NOLOAD)
125+
set(TEMP "${TEMP}\n *.o(${name}*)")
126+
set(TEMP "${TEMP}\n *.o(${name}*.*)")
127+
elseif(VMA_FLAGS)
128+
# ToDo: Proper names as provided by armclang
129+
# set(TEMP "${TEMP}\n *.o(${SEC_NAME}*, +${VMA_FLAGS})")
130+
# set(TEMP "${TEMP}\n *.o(${SEC_NAME}*.*, +${VMA_FLAGS})")
131+
set(TEMP "${TEMP}\n *.o(${name}*)")
132+
set(TEMP "${TEMP}\n *.o(${name}*.*)")
133+
else()
134+
set(TEMP "${TEMP}\n *.o(${name}*)")
135+
set(TEMP "${TEMP}\n *.o(${name}*.*)")
136+
endif()
137+
else()
138+
set(empty TRUE)
139+
endif()
140+
141+
get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
142+
foreach(idx ${indicies})
143+
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN)
144+
get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY)
145+
get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST)
146+
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP)
147+
get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT)
148+
get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS)
149+
get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT)
150+
get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_OFFSET)
151+
if(DEFINED offset)
152+
set(section_close TRUE)
153+
math(EXPR offset_dec "${offset} + 0")
154+
if(empty)
155+
set(TEMP "${TEMP} EMPTY 0x0\n {")
156+
set(empty FALSE)
157+
endif()
158+
set(last_index ${offset_dec})
159+
if(sort)
160+
set(sorttype "SORTTYPE ${SORT_TYPE_${sort}}")
161+
endif()
162+
set(TEMP "${TEMP}\n }")
163+
set(TEMP "${TEMP}\n ${name_clean}_${offset_dec} (ImageBase(${name_clean}) + ${offset}) ${sorttype}\n {")
164+
elseif(sort)
165+
set(section_close TRUE)
166+
if(empty)
167+
set(TEMP "${TEMP} EMPTY 0x0\n {")
168+
set(empty FALSE)
169+
endif()
170+
set(last_index ${idx})
171+
set(TEMP "${TEMP}\n }")
172+
set(TEMP "${TEMP}\n ${name_clean}_${idx} +0 SORTTYPE ${SORT_TYPE_${sort}}\n {")
173+
endif()
174+
175+
if(empty)
176+
set(TEMP "${TEMP}\n {")
177+
set(empty FALSE)
178+
endif()
179+
180+
foreach(setting ${input})
181+
#set(SETTINGS ${SETTINGS_INPUT})
182+
183+
# # ToDo: The code below had en error in original implementation, causing
184+
# # settings not to be applied
185+
# # Verify behaviour and activate if working as intended.
186+
# if(align)
187+
# set(setting "${setting}, OVERALIGN ${align}")
188+
# endif()
189+
190+
#if(SETTINGS_KEEP)
191+
# armlink has --keep=<section_id>, but is there an scatter equivalant ?
192+
#endif()
193+
194+
if(first)
195+
set(setting "${setting}, +First")
196+
set(first "")
197+
endif()
198+
199+
set(TEMP "${TEMP}\n *.o(${setting})")
200+
endforeach()
201+
202+
if(any)
203+
if(NOT flags)
204+
message(FATAL_ERROR ".ANY requires flags to be set.")
205+
endif()
206+
string(REPLACE ";" " " flags "${flags}")
207+
208+
set(TEMP "${TEMP}\n .ANY (${flags})")
209+
endif()
210+
endforeach()
211+
212+
if(section_close OR DEFINED endalign)
213+
set(section_close)
214+
set(TEMP "${TEMP}\n }")
215+
216+
if(DEFINED endalign)
217+
if(DEFINED last_index)
218+
set(align_expr "AlignExpr(ImageLimit(${name_clean}_${last_index}), ${endalign}) FIXED")
219+
else()
220+
set(align_expr "AlignExpr(ImageLimit(${name_clean}), ${endalign}) FIXED")
221+
endif()
222+
else()
223+
set(align_expr "+0")
224+
endif()
225+
226+
set(TEMP "${TEMP}\n ${name_clean}_end ${align_expr} EMPTY 0x0\n {")
227+
set(last_index)
228+
endif()
229+
230+
set(TEMP "${TEMP}")
231+
# ToDo: add patterns here.
232+
233+
set(TEMP "${TEMP}\n }")
234+
235+
set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE)
236+
endfunction()
237+
238+
function(symbol_to_string)
239+
cmake_parse_arguments(STRING "" "SYMBOL;STRING" "" ${ARGN})
240+
241+
get_property(name GLOBAL PROPERTY ${STRING_SYMBOL}_NAME)
242+
get_property(expr GLOBAL PROPERTY ${STRING_SYMBOL}_EXPR)
243+
get_property(size GLOBAL PROPERTY ${STRING_SYMBOL}_SIZE)
244+
get_property(symbol GLOBAL PROPERTY ${STRING_SYMBOL}_SYMBOL)
245+
get_property(subalign GLOBAL PROPERTY ${STRING_SYMBOL}_SUBALIGN)
246+
247+
string(REPLACE "\\" "" expr "${expr}")
248+
string(REGEX MATCHALL "%([^%]*)%" match_res ${expr})
249+
250+
foreach(match ${match_res})
251+
string(REPLACE "%" "" match ${match})
252+
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match})
253+
string(REPLACE "%${match}%" "ImageBase(${symbol_val})" expr ${expr})
254+
endforeach()
255+
256+
if(DEFINED subalign)
257+
set(subalign "ALIGN ${subalign}")
258+
endif()
259+
260+
if(NOT DEFINED size)
261+
set(size "0x0")
262+
endif()
263+
264+
set(${STRING_STRING}
265+
"${${STRING_STRING}}\n ${symbol} ${expr} ${subalign} ${size} { }\n"
266+
PARENT_SCOPE
267+
)
268+
endfunction()
269+
270+
include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake)

0 commit comments

Comments
 (0)