blob: d061d11fbc6d8d8b8d1b554f11fa576feb7c0cb5 [file] [log] [blame]
Gyorgy Szing49091802020-11-24 00:33:09 +01001#-------------------------------------------------------------------------------
2# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8#[===[.rst:
9Compiler abstraction for GCC
10----------------------------
11
12.. cmake:variable:: CROSS_COMPILE
13
14 A ';' separated GCC prefix triplets to use when searching for the cross-compiler.
15 (i.e. ``aarch64-none-elf;aarch64-elf``).
16 The variable can be set on the command line with ``-DCROSS_COMPILE=<value>`` or in the
17 environment. If both is specified, command line takes precedence.
18
19#]===]
20
21include_guard(DIRECTORY)
22
23if(NOT CROSS_COMPILE AND NOT DEFINED ENV{CROSS_COMPILE})
24 message(FATAL_ERROR "'CROSS_COMPILE' is not defined. Set if to the gcc pferix triplet, ie. cmake <..>-DCROSS_COMPILE=aarch64-elf-")
25endif()
26
27set(CROSS_COMPILE $ENV{CROSS_COMPILE} CACHE STRING "Prefix of the cross-compiler commands")
28
29#Generate a list of tool names to look for. Store the result in CMAKE_<lang>_COMPILER.
30function(gcc_find_tool NAME LANG)
31 string(REGEX REPLACE "([^;]+);" "\\1${NAME};\\1${NAME}.exe;" _gcc_names "${CROSS_COMPILE};")
32 find_program(_cross_compile_gcc NAMES ${_gcc_names} REQUIRED)
33 if (NOT _cross_compile_gcc)
34 string(REPLACE ";" " " _msg "${_gcc_names}")
35 message(FATAL_ERROR "Failed to find ${NAME} with the names: ${_msg}")
36 endif()
37 set(CMAKE_${LANG}_COMPILER ${_cross_compile_gcc} CACHE STRING "${LANG} compiler executable.")
38endfunction()
39
40gcc_find_tool(gcc C)
41gcc_find_tool(g++ CXX)
42
43#Official solution to disable compiler checks
44set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
45
46#By default when INTERFACE_INCUDES of libraryes linked to an exe are treated
47#as system includes. gcc-arm-8.2-2019.01-i686-mingw32-aarch64-elf (gcc 8.2.1) will
48#set C linkage o these files, which will result in compilation errors for C++ projects.
49#This setting fixes that.
50set(CMAKE_NO_SYSTEM_FROM_IMPORTED True)
51
52#[===[.rst:
53.. cmake:command:: compiler_preprocess_file
54
55 .. code-block:: cmake
56
57 compiler_preprocess_file(SRC file.c DST file_pp.c)
58 compiler_preprocess_file(SRC file.c DST file_pp.c
59 DEFINES USE_LIB INCLUDES include/lib)
60
61 Run the preprocessor on a file and save the output to another file. Optionally
62 provide defines and include paths to the preprocessor.
63
64 Inputs:
65
66 ``SRC``
67 Name of the source file to preprocess.
68
69 ``DST``
70 Where to write the preprocessed output.
71
72 ``DEFINES`` (multi, optional)
73 Definitions for the preprocessor.
74
75 ``INCLUDES`` (multi, optional)
76 Include paths for the preprocessor.
77
78#]===]
79function(compiler_preprocess_file)
80 set(_OPTIONS_ARGS)
81 set(_ONE_VALUE_ARGS SRC DST)
82 set(_MULTI_VALUE_ARGS DEFINES INCLUDES)
83 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
84
85 check_args(compiler_preprocess_file SRC DST)
86
87 set(_flags "")
88 if(_MY_PARAMS_DEFINES)
89 list(TRANSFORM _MY_PARAMS_DEFINES PREPEND -D)
90 list(APPEND _flags ${_MY_PARAMS_DEFINES})
91 endif()
92 if(_MY_PARAMS_INCLUDES)
93 list(TRANSFORM _MY_PARAMS_INCLUDES PREPEND -I)
94 list(APPEND _flags ${_MY_PARAMS_INCLUDES})
95 endif()
96
97 add_custom_command(
98 DEPENDS ${_MY_PARAMS_SRC} OUTPUT ${_MY_PARAMS_DST}
99 COMMAND ${CMAKE_C_COMPILER} -E -P -x assembler-with-cpp ${_flags}
100 ${_MY_PARAMS_SRC} -o ${_MY_PARAMS_DST}
101 )
102endfunction()
103
104#[===[.rst:
105.. cmake:command:: compiler_set_linker_script
106
107 .. code-block:: cmake
108
109 compiler_set_linker_script(TARGET foo FILE foo.ld.S)
110 compiler_set_linker_script(TARGET foo FILE foo.ld.S DEF USE_LIB INC include/lib)
111
112 Set linker script for a target. The function adds an LDFLAG using the
113 toolchain specific syntax to the TARGET_linker_script group, which is applied
114 onto the target by the caller function. FILE will be preprocessed, optionally
115 defines and/or includes can be provided using DEF/INC arguments.
116
117 Inputs:
118
119 ``TARGET``
120 Name of the target.
121
122 ``FILE``
123 Linker script file for the target.
124
125 ``DEF`` (multi, optional)
126 Defines for the linker script preprocessor.
127
128 ``INC`` (multi, optional)
129 Include paths for the linker script preprocessor.
130
131#]===]
132function(compiler_set_linker_script)
133 set(_OPTIONS_ARGS)
134 set(_ONE_VALUE_ARGS TARGET FILE)
135 set(_MULTI_VALUE_ARGS DEF INC)
136 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
137
138 check_args(compiler_set_linker_script TARGET FILE)
139
140 get_filename_component(_src "${_MY_PARAMS_FILE}" ABSOLUTE)
141 get_filename_component(_src_ext "${_MY_PARAMS_FILE}" EXT)
142 set(_dst "${CMAKE_BINARY_DIR}/${_MY_PARAMS_TARGET}.ld")
143
144 if(NOT ("${_src_ext}" STREQUAL ".ld" OR "${_src_ext}" STREQUAL ".ld.S"))
145 message(WARNING "compiler_set_linker_script(): extension mismatch '${_src}'")
146 endif()
147
148 compiler_preprocess_file(
149 SRC ${_src}
150 DST ${_dst}
151 DEFINES ${_MY_PARAMS_DEF} __LINKER__
152 INCLUDES ${_MY_PARAMS_INC}
153 )
154
155 add_custom_target("${_MY_PARAMS_TARGET}_ld" DEPENDS "${_dst}")
156 add_dependencies("${_MY_PARAMS_TARGET}" "${_MY_PARAMS_TARGET}_ld")
157
158 group_add(NAME "${_MY_PARAMS_TARGET}_linker_script" TYPE CONFIG KEY "LINK_DEPENDS" VAL "${_dst}")
159 group_add(NAME "${_MY_PARAMS_TARGET}_linker_script" TYPE LDFLAG KEY "-Wl,--script" VAL "${_dst}")
160endfunction()
161
162#[===[.rst:
163.. cmake:command:: compiler_generate_binary_output
164
165 .. code-block:: cmake
166
167 compiler_generate_binary_output(TARGET <name> RES <var>)
168
169 Generate binary output for the target. The function converts the output
170 executable into bin file using toolchain specific syntax.
171
172 Inputs:
173
174 ``TARGET``
175 Name of the target.
176
177 Outputs:
178
179 ``RES``
180 Full patch to output file.
181
182#]===]
183function(compiler_generate_binary_output)
184 set(options)
185 set(oneValueArgs TARGET)
186 set(multiValueArgs)
187 cmake_parse_arguments(MY "${options}" "${oneValueArgs}"
188 "${multiValueArgs}" ${ARGN} )
189 add_custom_command(
190 TARGET ${MY_TARGET} POST_BUILD
191 COMMAND ${CMAKE_OBJCOPY} -O binary
192 $<TARGET_FILE:${MY_TARGET}>
193 $<TARGET_FILE_DIR:${MY_TARGET}>/${MY_TARGET}.bin)
194 if (MY_RES)
195 set(${MY_RES} $<TARGET_FILE_DIR:${MY_TARGET}>/${MY_TARGET}.bin PARENT_SCOPE)
196 endif()
197
198endfunction()
199
200#[===[.rst:
201.. cmake:command:: compiler_generate_stripped_elf
202
203 .. code-block:: cmake
204
205 compiler_generate_stripped_elf(TARGET foo NAME foo.stripped.elf RES var)
206
207 Strip all symbols that are not needed for relocation processing and return the location
208 of the result.
209
210 Inputs:
211
212 ``TARGET``
213 Name of the target.
214
215 ``NAME``
216 Name of output file
217
218 Outputs:
219
220 ``RES``
221 Name of variable to store the full path of the stripped executable.
222
223#]===]
224
225function(compiler_generate_stripped_elf)
226 set(options)
227 set(oneValueArgs TARGET NAME RES)
228 set(multiValueArgs)
229 cmake_parse_arguments(MY "${options}" "${oneValueArgs}"
230 "${multiValueArgs}" ${ARGN} )
231
232 add_custom_command(
233 TARGET ${MY_TARGET} POST_BUILD
234 COMMAND ${CMAKE_OBJCOPY} --strip-unneeded
235 $<TARGET_FILE:${MY_TARGET}>
236 $<TARGET_FILE_DIR:${MY_TARGET}>/${MY_NAME})
237 if (MY_RES)
238 set(${MY_RES} $<TARGET_FILE_DIR:${MY_TARGET}>/${MY_NAME} PARENT_SCOPE)
239 endif()
240endfunction()