blob: fff5e2a3a74ae4c7370b4aa8ebf308390cf14efa [file] [log] [blame]
Imre Kisdd154112021-10-08 11:21:14 +02001#-------------------------------------------------------------------------------
Gyorgy Szing51f45d22021-12-08 00:44:18 +00002# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
Imre Kisdd154112021-10-08 11:21:14 +02003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
Gyorgy Szing51f45d22021-12-08 00:44:18 +00008# Add newlib specific porting files to the project.
Gyorgy Szing693877e2021-12-12 02:51:10 +01009if (NOT DEFINED TGT)
10 message(FATAL_ERROR "mandatory parameter TGT is not defined.")
11endif()
12
Imre Kis217192d2021-12-17 14:04:43 +010013# Adding libc interface
14add_components(TARGET ${TGT}
15 BASE_DIR ${TS_ROOT}
16 COMPONENTS
17 components/common/libc
18)
19
Gyorgy Szing693877e2021-12-12 02:51:10 +010020# Compile TS specific newlib porting files.
21target_sources(${TGT} PRIVATE
22 "${CMAKE_CURRENT_LIST_DIR}/newlib_init.c"
23 "${CMAKE_CURRENT_LIST_DIR}/newlib_sp_assert.c"
24 "${CMAKE_CURRENT_LIST_DIR}/newlib_sp_heap.c"
25)
26
Gyorgy Szing51f45d22021-12-08 00:44:18 +000027# Fetch newlib from external repository
28set(NEWLIB_URL "https://sourceware.org/git/newlib-cygwin.git"
29 CACHE STRING "newlib repository URL")
30set(NEWLIB_REFSPEC "newlib-4.1.0"
31 CACHE STRING "newlib git refspec")
32set(NEWLIB_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-src"
33 CACHE PATH "newlib source-code location")
34set(NEWLIB_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/newlib_install"
35 CACHE PATH "newlib installation directory")
Imre Kisdd154112021-10-08 11:21:14 +020036
Gyorgy Szing693877e2021-12-12 02:51:10 +010037# Extracting compiler prefix without the trailing hyphen from the C compiler name
Imre Kisdd154112021-10-08 11:21:14 +020038get_filename_component(COMPILER_PATH ${CMAKE_C_COMPILER} DIRECTORY)
39get_filename_component(COMPILER_NAME ${CMAKE_C_COMPILER} NAME)
Imre Kis2b7ef372022-01-04 12:36:12 +010040string(REGEX REPLACE "(.*)-[^-]+$" "\\1" COMPILER_PREFIX ${COMPILER_NAME})
Imre Kisdd154112021-10-08 11:21:14 +020041
Gyorgy Szing51f45d22021-12-08 00:44:18 +000042find_library(NEWLIB_LIBC_PATH
43 NAMES libc.a c.a libc.lib c.lib
44 PATHS ${NEWLIB_INSTALL_DIR}
45 PATH_SUFFIXES "${COMPILER_PREFIX}/lib"
46 DOC "Location of newlib::libc library."
47 NO_DEFAULT_PATH
Imre Kisdd154112021-10-08 11:21:14 +020048)
Gyorgy Szing51f45d22021-12-08 00:44:18 +000049set(NEWLIB_LIBC_PATH ${NEWLIB_LIBC_PATH})
50unset(NEWLIB_LIBC_PATH CACHE)
Imre Kisdd154112021-10-08 11:21:14 +020051
Gyorgy Szing51f45d22021-12-08 00:44:18 +000052find_library(NEWLIB_LIBNOSYS_PATH
53 NAMES libnosys.a nosys.a nosys.lib nosys.lib
54 PATHS ${NEWLIB_INSTALL_DIR}
55 PATH_SUFFIXES "${COMPILER_PREFIX}/lib"
56 DOC "Location of newlib::libnosys library."
57 NO_DEFAULT_PATH
58)
Gyorgy Szingf7a91e72022-02-09 11:59:07 +010059set(NEWLIB_LIBNOSYS_PATH ${NEWLIB_LIBNOSYS_PATH})
Gyorgy Szing51f45d22021-12-08 00:44:18 +000060unset(NEWLIB_LIBNOSYS_PATH CACHE)
61
Gyorgy Szing69a10c32022-03-02 21:10:20 +000062# -noxxx options require explicitly specifying GCC specific library on the
Gyorgy Szing309e9712022-02-24 18:35:28 +010063# linker command line.
Gyorgy Szing69a10c32022-03-02 21:10:20 +000064# Use LIBGCC_PATH to manually override the search process below.
65if (NOT DEFINED LIBGCC_PATH)
66 include(${TS_ROOT}/tools/cmake/compiler/GCC.cmake)
67 gcc_get_lib_location(LIBRARY_NAME "libgcc.a" RES _TMP_VAR)
68
69 if (NOT _TMP_VAR)
70 message(FATAL_ERROR "Location of libgcc.a can not be determined. Please set LIBGCC_PATH on the command line.")
71 endif()
72 set(LIBGCC_PATH ${_TMP_VAR} CACHE PATH "location of libgcc.a")
73 unset(_TMP_VAR)
74endif()
75
76if(NOT EXISTS "${LIBGCC_PATH}" OR IS_DIRECTORY "${LIBGCC_PATH}")
77 message(FATAL_ERROR "LIBGCC_PATH \"${LIBGCC_PATH}\" must be the full path of a library file."
78 " Either set LIBGCC_PATH on the command line, or fix the value if already set.")
79endif()
80message(STATUS "libgcc.a is used from ${LIBGCC_PATH}")
81
Gyorgy Szing309e9712022-02-24 18:35:28 +010082# Moreover the GCC specific header file include directory is also required.
Gyorgy Szing69a10c32022-03-02 21:10:20 +000083# Specify LIBGCC_INCLUDE_DIRS in the command line to manually override the libgcc relative location below.
84if(NOT DEFINED LIBGCC_INCLUDE_DIRS)
85 get_filename_component(_TMP_VAR "${LIBGCC_PATH}" DIRECTORY)
86 set(LIBGCC_INCLUDE_DIRS
87 "${_TMP_VAR}/include"
88 "${_TMP_VAR}/include-fixed" CACHE STRING "GCC specific include PATHs")
89 unset(_TMP_VAR)
90endif()
91
Gyorgy Szing309e9712022-02-24 18:35:28 +010092# There is no way to stop cmake from filtering out built in compiler include paths
93# from compiler command line (see https://gitlab.kitware.com/cmake/cmake/-/issues/19227)
94# As a workaround copy headers to build directory and set include path to the new
95# location.
Gyorgy Szing69a10c32022-03-02 21:10:20 +000096foreach(_dir IN LISTS LIBGCC_INCLUDE_DIRS)
97 if(NOT IS_DIRECTORY "${_dir}")
98 message(FATAL_ERROR "GCC specific include PATH \"${_dir}\" does not exist. Try setting LIBGCC_INCLUDE_DIRS"
99 " on the command line.")
100 endif()
101 file(COPY "${_dir}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gcc-include")
102 get_filename_component(_TMP_VAR "${_dir}" NAME)
103 list(APPEND _gcc_include_dirs "${CMAKE_CURRENT_BINARY_DIR}/gcc-include/${_TMP_VAR}")
104 message(STATUS "Using compiler specific include path \"${_dir}\" mirrored to"
105 " \"${CMAKE_CURRENT_BINARY_DIR}/gcc-include/${_TMP_VAR}\".")
106endforeach()
Gyorgy Szing309e9712022-02-24 18:35:28 +0100107unset(_TMP_VAR)
108
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000109if (NOT NEWLIB_LIBC_PATH)
110 # Determine the number of processes to run while running parallel builds.
111 # Pass -DPROCESSOR_COUNT=<n> to cmake to override.
112 if(NOT DEFINED PROCESSOR_COUNT)
113 include(ProcessorCount)
114 ProcessorCount(PROCESSOR_COUNT)
115 set(PROCESSOR_COUNT ${PROCESSOR_COUNT}
116 CACHE STRING "Number of cores to use for parallel builds.")
117 endif()
118
119 # See if the source is available locally
120 find_file(NEWLIB_HEADER_FILE
121 NAMES newlib.h
122 PATHS ${NEWLIB_SOURCE_DIR}
123 PATH_SUFFIXES "newlib/libc/include"
124 NO_DEFAULT_PATH
125 )
126 set(NEWLIB_HEADER_FILE ${NEWLIB_HEADER_FILE})
127 unset(NEWLIB_HEADER_FILE CACHE)
128
129 # Source not found, fetch it.
130 if (NOT NEWLIB_HEADER_FILE)
131 include(FetchContent)
132
133 # Checking git
134 find_program(GIT_COMMAND "git")
135 if (NOT GIT_COMMAND)
136 message(FATAL_ERROR "Please install git")
137 endif()
138
139 # Fetching newlib
140 FetchContent_Declare(
141 newlib
142 SOURCE_DIR ${NEWLIB_SOURCE_DIR}
143 GIT_REPOSITORY ${NEWLIB_URL}
144 GIT_TAG ${NEWLIB_REFSPEC}
Julian Halla628af32022-04-01 10:08:18 +0100145 GIT_SHALLOW FALSE
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000146 PATCH_COMMAND git stash
147 COMMAND ${GIT_COMMAND} am ${CMAKE_CURRENT_LIST_DIR}/0001-Allow-aarch64-linux-gcc-to-compile-bare-metal-lib.patch
148 COMMAND ${GIT_COMMAND} reset HEAD~1
149 )
150
151 # FetchContent_GetProperties exports newlib_SOURCE_DIR and newlib_BINARY_DIR variables
152 FetchContent_GetProperties(newlib)
153 # FetchContent_Populate will fail if the source directory is removed since it will try to
154 # do an "update" and not a "populate" action. As a workaround, remove the subbuild directory.
155 # Note: this fix assumes, the default subbuild location is used.
156 file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-subbuild")
157
158 if(NOT newlib_POPULATED)
159 message(STATUS "Fetching newlib")
160 FetchContent_Populate(newlib)
161 endif()
162 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_SOURCE_DIR})
163 endif()
164
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000165 string(REPLACE ";" " -isystem " CFLAGS_FOR_TARGET "${_gcc_include_dirs}")
Gyorgy Szing309e9712022-02-24 18:35:28 +0100166 set(CFLAGS_FOR_TARGET "-isystem ${CFLAGS_FOR_TARGET} -fpic")
167
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000168 # Newlib configure step
169 # CC env var must be unset otherwise configure will assume the cross compiler is the host
170 # compiler.
171 # The configure options are set to minimize code size and memory usage.
172 execute_process(COMMAND
173 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} ./configure
174 --target=${COMPILER_PREFIX}
175 --prefix=${NEWLIB_INSTALL_DIR}
176 --enable-newlib-nano-formatted-io
177 --enable-newlib-nano-malloc
178 --enable-lite-exit
179 --enable-newlib-reent-small
180 --enable-newlib-global-atexit
181 --disable-multilib
Gyorgy Szing309e9712022-02-24 18:35:28 +0100182 CFLAGS_FOR_TARGET=${CFLAGS_FOR_TARGET}
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000183 LDFLAGS_FOR_TARGET=-fpie
184 WORKING_DIRECTORY
185 ${NEWLIB_SOURCE_DIR}
186 RESULT_VARIABLE _newlib_error
187 )
188
189 if (_newlib_error)
190 message(FATAL_ERROR "Configuration step of newlib failed with ${_newlib_error}.")
191 endif()
192
193 # Newlib build step
194 execute_process(COMMAND
195 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH}
196 make -j${PROCESSOR_COUNT}
197 WORKING_DIRECTORY
198 ${NEWLIB_SOURCE_DIR}
199 RESULT_VARIABLE _newlib_error
200 )
201
202 if (_newlib_error)
203 message(FATAL_ERROR "Build step of newlib failed with ${_newlib_error}.")
204 endif()
205
206 # Newlib install step
207 execute_process(COMMAND
208 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} make install
209 WORKING_DIRECTORY
210 ${NEWLIB_SOURCE_DIR}
211 RESULT_VARIABLE _newlib_error
212 )
213
214 if (_newlib_error)
215 message(FATAL_ERROR "Install step of newlib failed with ${_newlib_error}.")
216 endif()
217
218 set(NEWLIB_LIBC_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libc.a")
219 set(NEWLIB_LIBNOSYS_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libnosys.a")
Imre Kisdd154112021-10-08 11:21:14 +0200220endif()
221
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000222set_property(DIRECTORY ${CMAKE_SOURCE_DIR}
223 APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_LIBC_PATH})
Imre Kisdd154112021-10-08 11:21:14 +0200224
225# libc
226add_library(c STATIC IMPORTED)
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000227link_libraries(c INTERFACE ${LIBGCC_PATH})
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000228set_property(TARGET c PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBC_PATH}")
229set_property(TARGET c PROPERTY
230 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100231target_compile_options(c INTERFACE -nostdinc)
Gyorgy Szing8fad9bc2021-12-12 03:56:41 +0100232target_compile_definitions(c INTERFACE ENABLE_CDEFSH_FIX)
Gyorgy Szing693877e2021-12-12 02:51:10 +0100233target_link_options(c INTERFACE -nostartfiles -nodefaultlibs)
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000234target_include_directories(c SYSTEM INTERFACE ${_gcc_include_dirs})
Gyorgy Szing309e9712022-02-24 18:35:28 +0100235
236# Make standard library available in the build system.
237add_library(stdlib::c ALIAS c)
Imre Kisdd154112021-10-08 11:21:14 +0200238
239# libnosys
240add_library(nosys STATIC IMPORTED)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000241set_property(TARGET nosys PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBNOSYS_PATH}")
242set_property(TARGET nosys PROPERTY
243 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100244target_compile_options(nosys INTERFACE -nostdinc)
245target_link_options(nosys INTERFACE -nostartfiles -nodefaultlibs)
246target_link_libraries(c INTERFACE nosys)