1#-------------------------------------------------------------------------------
2# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8set(CMAKE_SYSTEM_NAME Generic)
9
10find_program(CMAKE_C_COMPILER ${CROSS_COMPILE}-gcc)
11find_program(CMAKE_CXX_COMPILER ${CROSS_COMPILE}-g++)
12
13if(CMAKE_C_COMPILER STREQUAL "CMAKE_C_COMPILER-NOTFOUND")
14    message(FATAL_ERROR "Could not find compiler: '${CROSS_COMPILE}-gcc'")
15endif()
16
17set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
18
19set(LINKER_VENEER_OUTPUT_FLAG -Wl,--cmse-implib,--out-implib=)
20set(COMPILER_CMSE_FLAG -mcmse)
21
22# This variable name is a bit of a misnomer. The file it is set to is included
23# at a particular step in the compiler initialisation. It is used here to
24# configure the extensions for object files. Despite the name, it also works
25# with the Ninja generator.
26set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_LIST_DIR}/cmake/set_extensions.cmake)
27
28macro(tfm_toolchain_reset_compiler_flags)
29    set_property(DIRECTORY PROPERTY COMPILE_OPTIONS "")
30
31    if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0.0)
32        add_compile_options(
33            -fmacro-prefix-map=${TFM_TEST_REPO_PATH}=TFM_TEST_REPO_PATH
34        )
35    endif()
36
37    add_compile_options(
38        --specs=nano.specs
39        -Wall
40        -Wno-format
41        -Wno-return-type
42        -Wno-unused-but-set-variable
43        -c
44        -fdata-sections
45        -ffunction-sections
46        -fno-builtin
47        -fshort-enums
48        -funsigned-char
49        -mthumb
50        -nostdlib
51        -std=c99
52        # Force DWARF version 4 for zephyr as pyelftools does not support version 5 at present
53        -gdwarf-4
54        $<$<OR:$<BOOL:${TFM_DEBUG_SYMBOLS}>,$<BOOL:${TFM_CODE_COVERAGE}>>:-g>
55    )
56endmacro()
57
58if(CONFIG_TFM_MEMORY_USAGE_QUIET)
59    set(MEMORY_USAGE_FLAG "")
60else()
61    set(MEMORY_USAGE_FLAG LINKER:--print-memory-usage)
62endif()
63
64macro(tfm_toolchain_reset_linker_flags)
65    set_property(DIRECTORY PROPERTY LINK_OPTIONS "")
66
67    add_link_options(
68        --entry=Reset_Handler
69        --specs=nano.specs
70        LINKER:-check-sections
71        LINKER:-fatal-warnings
72        LINKER:--gc-sections
73        LINKER:--no-wchar-size-warning
74        ${MEMORY_USAGE_FLAG}
75    )
76endmacro()
77
78macro(tfm_toolchain_set_processor_arch)
79    if (DEFINED TFM_SYSTEM_PROCESSOR)
80        if(TFM_SYSTEM_PROCESSOR MATCHES "cortex-m85")
81            # GNUARM does not support the -mcpu=cortex-m85 flag yet
82            # TODO: Remove this exception when the cortex-m85 support comes out.
83            message(WARNING "Cortex-m85 is not supported by GCC. Falling back to -march usage.")
84        else()
85            set(CMAKE_SYSTEM_PROCESSOR ${TFM_SYSTEM_PROCESSOR})
86
87            if (DEFINED TFM_SYSTEM_DSP)
88                if (NOT TFM_SYSTEM_DSP)
89                    string(APPEND CMAKE_SYSTEM_PROCESSOR "+nodsp")
90                endif()
91            endif()
92            # GCC specifies that '+nofp' is available on following M-profile cpus: 'cortex-m4',
93            # 'cortex-m7', 'cortex-m33', 'cortex-m35p' and 'cortex-m55'.
94            # Build fails if other M-profile cpu, such as 'cortex-m23', is added with '+nofp'.
95            # Explicitly list those cpu to align with GCC description.
96            if(GCC_VERSION VERSION_GREATER_EQUAL "8.0.0")
97                if(NOT CONFIG_TFM_ENABLE_FP AND
98                   (TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m4"
99                    OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m7"
100                    OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m33"
101                    OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m35p"
102                    OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m55"))
103                        string(APPEND CMAKE_SYSTEM_PROCESSOR "+nofp")
104                endif()
105            endif()
106
107            if(TFM_SYSTEM_ARCHITECTURE STREQUAL "armv8.1-m.main")
108                if(NOT CONFIG_TFM_ENABLE_MVE)
109                    string(APPEND CMAKE_SYSTEM_PROCESSOR "+nomve")
110                endif()
111                if(NOT CONFIG_TFM_ENABLE_MVE_FP)
112                    string(APPEND CMAKE_SYSTEM_PROCESSOR "+nomve.fp")
113                endif()
114            endif()
115        endif()
116
117    endif()
118
119    # CMAKE_SYSTEM_ARCH variable is not a built-in CMAKE variable. It is used to
120    # set the compile and link flags when TFM_SYSTEM_PROCESSOR is not specified.
121    # The variable name is choosen to align with the ARMCLANG toolchain file.
122    set(CMAKE_SYSTEM_ARCH         ${TFM_SYSTEM_ARCHITECTURE})
123
124    if(TFM_SYSTEM_ARCHITECTURE STREQUAL "armv8.1-m.main")
125        if(CONFIG_TFM_ENABLE_MVE)
126            string(APPEND CMAKE_SYSTEM_ARCH "+mve")
127        endif()
128        if(CONFIG_TFM_ENABLE_MVE_FP)
129            string(APPEND CMAKE_SYSTEM_ARCH "+mve.fp")
130        endif()
131    endif()
132
133    if (DEFINED TFM_SYSTEM_DSP)
134        # +nodsp modifier is only supported from GCC version 8.
135        if(GCC_VERSION VERSION_GREATER_EQUAL "8.0.0")
136            # armv8.1-m.main arch does not have +nodsp option
137            if ((NOT TFM_SYSTEM_ARCHITECTURE STREQUAL "armv8.1-m.main") AND
138                NOT TFM_SYSTEM_DSP)
139                string(APPEND CMAKE_SYSTEM_ARCH "+nodsp")
140            endif()
141        endif()
142    endif()
143
144    if(GCC_VERSION VERSION_GREATER_EQUAL "8.0.0")
145        if(CONFIG_TFM_ENABLE_FP)
146            string(APPEND CMAKE_SYSTEM_ARCH "+fp")
147        endif()
148    endif()
149
150endmacro()
151
152macro(tfm_toolchain_reload_compiler)
153    # CMAKE_C_COMPILER_VERSION is not guaranteed to be defined.
154    EXECUTE_PROCESS( COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION )
155
156    tfm_toolchain_set_processor_arch()
157    tfm_toolchain_reset_compiler_flags()
158    tfm_toolchain_reset_linker_flags()
159
160    if (GCC_VERSION VERSION_LESS 7.3.1)
161        message(FATAL_ERROR "Please use newer GNU Arm compiler version starting from 7.3.1.")
162    endif()
163
164    if (GCC_VERSION VERSION_EQUAL 10.2.1)
165        message(FATAL_ERROR "GNU Arm compiler version 10-2020-q4-major has an issue in CMSE support."
166                            " Select other GNU Arm compiler versions instead."
167                            " See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99157 for the issue detail.")
168    endif()
169
170    unset(CMAKE_C_FLAGS_INIT)
171    unset(CMAKE_ASM_FLAGS_INIT)
172
173    if (CMAKE_SYSTEM_PROCESSOR)
174        set(CMAKE_C_FLAGS_INIT "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
175        set(CMAKE_ASM_FLAGS_INIT "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
176        set(CMAKE_C_LINK_FLAGS "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
177        set(CMAKE_ASM_LINK_FLAGS "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
178    else()
179        set(CMAKE_C_FLAGS_INIT "-march=${CMAKE_SYSTEM_ARCH}")
180        set(CMAKE_ASM_FLAGS_INIT "-march=${CMAKE_SYSTEM_ARCH}")
181        set(CMAKE_C_LINK_FLAGS "-march=${CMAKE_SYSTEM_ARCH}")
182        set(CMAKE_ASM_LINK_FLAGS "-march=${CMAKE_SYSTEM_ARCH}")
183    endif()
184
185    set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS_INIT})
186    set(CMAKE_ASM_FLAGS ${CMAKE_ASM_FLAGS_INIT})
187
188    set(BL2_COMPILER_CP_FLAG -mfloat-abi=soft)
189
190    if (CONFIG_TFM_FLOAT_ABI STREQUAL "hard")
191        set(COMPILER_CP_FLAG -mfloat-abi=hard)
192        set(LINKER_CP_OPTION -mfloat-abi=hard)
193        if (CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE_FP)
194            set(COMPILER_CP_FLAG -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
195            set(LINKER_CP_OPTION -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
196        endif()
197    else()
198        set(COMPILER_CP_FLAG -mfloat-abi=soft)
199        set(LINKER_CP_OPTION -mfloat-abi=soft)
200    endif()
201
202    # For GNU Arm Embedded Toolchain doesn't emit __ARM_ARCH_8_1M_MAIN__, adding this macro manually.
203    add_compile_definitions($<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv8.1-m.main>:__ARM_ARCH_8_1M_MAIN__>)
204
205    # CMAKE_BUILD_TYPE=MinSizeRel default parameter is -Os.
206    # In ARMCLANG we redefined this variable to use -Oz level, but GCC still using -Os!
207    # GCC 11 not supports -Oz level, version 12 will.
208    # When this option will be available in GNUARM, set -Oz flag for both toolchains.
209endmacro()
210
211# Configure environment for the compiler setup run by cmake at the first
212# `project` call in <tfm_root>/CMakeLists.txt. After this mandatory setup is
213# done, all further compiler setup is done via tfm_toolchain_reload_compiler()
214tfm_toolchain_reload_compiler()
215
216macro(target_add_scatter_file target)
217    target_link_options(${target}
218        PRIVATE
219        -T $<TARGET_OBJECTS:${target}_scatter>
220    )
221
222    add_library(${target}_scatter OBJECT)
223    foreach(scatter_file ${ARGN})
224        target_sources(${target}_scatter
225            PRIVATE
226                ${scatter_file}
227        )
228        # Cmake cannot use generator expressions in the
229        # set_source_file_properties command, so instead we just parse the regex
230        # for the filename and set the property on all files, regardless of if
231        # the generator expression would evaluate to true or not.
232        string(REGEX REPLACE ".*>:(.*)>$" "\\1" SCATTER_FILE_PATH "${scatter_file}")
233        set_source_files_properties(${SCATTER_FILE_PATH}
234            PROPERTIES
235            LANGUAGE C
236            KEEP_EXTENSION True # Don't use .o extension for the preprocessed file
237        )
238    endforeach()
239
240    add_dependencies(${target}
241        ${target}_scatter
242    )
243
244    set_target_properties(${target} PROPERTIES LINK_DEPENDS $<TARGET_OBJECTS:${target}_scatter>)
245
246    target_link_libraries(${target}_scatter
247        platform_region_defs
248        psa_interface
249        tfm_partition_defs
250    )
251
252    target_compile_options(${target}_scatter
253        PRIVATE
254            -E
255            -P
256            -xc
257    )
258endmacro()
259
260macro(add_convert_to_bin_target target)
261    get_target_property(bin_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
262
263    add_custom_target(${target}_bin
264        SOURCES ${bin_dir}/${target}.bin
265    )
266    add_custom_command(OUTPUT ${bin_dir}/${target}.bin
267        DEPENDS ${target}
268        COMMAND ${CMAKE_OBJCOPY}
269            -O binary $<TARGET_FILE:${target}>
270            ${bin_dir}/${target}.bin
271    )
272
273    add_custom_target(${target}_elf
274        SOURCES ${bin_dir}/${target}.elf
275    )
276    add_custom_command(OUTPUT ${bin_dir}/${target}.elf
277        DEPENDS ${target}
278        COMMAND ${CMAKE_OBJCOPY}
279            -O elf32-littlearm $<TARGET_FILE:${target}>
280            ${bin_dir}/${target}.elf
281    )
282
283    add_custom_target(${target}_hex
284        SOURCES ${bin_dir}/${target}.hex
285    )
286    add_custom_command(OUTPUT ${bin_dir}/${target}.hex
287        DEPENDS ${target}
288        COMMAND ${CMAKE_OBJCOPY}
289            -O ihex $<TARGET_FILE:${target}>
290            ${bin_dir}/${target}.hex
291    )
292
293    add_custom_target(${target}_binaries
294        ALL
295        DEPENDS ${target}_bin
296        DEPENDS ${target}_elf
297        DEPENDS ${target}_hex
298    )
299endmacro()
300
301macro(target_share_symbols target symbol_name_file)
302    get_target_property(TARGET_TYPE ${target} TYPE)
303    if (NOT TARGET_TYPE STREQUAL "EXECUTABLE")
304        message(FATAL_ERROR "${target} is not an executable. Symbols cannot be shared from libraries.")
305    endif()
306
307    FILE(STRINGS ${symbol_name_file} KEEP_SYMBOL_LIST
308        LENGTH_MINIMUM 1
309    )
310
311
312    list(TRANSFORM KEEP_SYMBOL_LIST PREPEND  --keep-symbol=)
313    # strip all the symbols except those proveded as arguments
314    add_custom_command(
315        TARGET ${target}
316        POST_BUILD
317        COMMAND ${CROSS_COMPILE}-objcopy
318        ARGS $<TARGET_FILE:${target}> --wildcard ${KEEP_SYMBOL_LIST} --strip-all $<TARGET_FILE_DIR:${target}>/${target}_shared_symbols.axf
319    )
320endmacro()
321
322macro(target_link_shared_code target)
323    foreach(symbol_provider ${ARGN})
324        if (TARGET ${symbol_provider})
325            get_target_property(SYMBOL_PROVIDER_TYPE ${symbol_provider} TYPE)
326            if (NOT SYMBOL_PROVIDER_TYPE STREQUAL "EXECUTABLE")
327                message(FATAL_ERROR "${symbol_provider} is not an executable. Symbols cannot be shared from libraries.")
328            endif()
329        endif()
330
331        add_dependencies(${target} ${symbol_provider})
332        target_link_options(${target} PRIVATE LINKER:-R$<TARGET_FILE_DIR:${symbol_provider}>/${symbol_provider}_shared_symbols.axf)
333    endforeach()
334endmacro()
335
336macro(target_strip_symbols target)
337    set(SYMBOL_LIST "${ARGN}")
338    list(TRANSFORM SYMBOL_LIST PREPEND  --strip-symbol=)
339
340    add_custom_command(
341        TARGET ${target}
342        POST_BUILD
343        COMMAND ${CROSS_COMPILE}-objcopy
344        ARGS $<TARGET_FILE:${target}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${target}>
345    )
346endmacro()
347
348macro(target_strip_symbols_from_dependency target dependency)
349    set(SYMBOL_LIST "${ARGN}")
350    list(TRANSFORM SYMBOL_LIST PREPEND  --strip-symbol=)
351
352    add_custom_command(
353        TARGET ${target}
354        PRE_LINK
355        COMMAND ${CROSS_COMPILE}-objcopy
356        ARGS $<TARGET_FILE:${dependency}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${dependency}>
357    )
358endmacro()
359
360macro(target_weaken_symbols target)
361    set(SYMBOL_LIST "${ARGN}")
362    list(TRANSFORM SYMBOL_LIST PREPEND  --weaken-symbol=)
363
364    add_custom_command(
365        TARGET ${target}
366        POST_BUILD
367        COMMAND ${CROSS_COMPILE}-objcopy
368        ARGS $<TARGET_FILE:${target}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${target}>
369    )
370endmacro()
371
372macro(target_weaken_symbols_from_dependency target dependency)
373    set(SYMBOL_LIST "${ARGN}")
374    list(TRANSFORM SYMBOL_LIST PREPEND  --weaken-symbol=)
375
376    add_custom_command(
377        TARGET ${target}
378        PRE_LINK
379        COMMAND ${CROSS_COMPILE}-objcopy
380        ARGS $<TARGET_FILE:${dependency}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${dependency}>
381    )
382endmacro()
383