blob: b1884be20471cfa75feedb767d629df8faedd446 [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 Szing3d495672022-10-12 12:58:21 +000062# libc - get compiler specific configuration from GCC
63add_library(c STATIC IMPORTED)
64# We need "freestandig" mode. Ask the compile to do the needed configurations.
65include(${TS_ROOT}/tools/cmake/compiler/GCC.cmake)
66compiler_set_freestanding(TARGET c)
67
Gyorgy Szing51f45d22021-12-08 00:44:18 +000068if (NOT NEWLIB_LIBC_PATH)
69 # Determine the number of processes to run while running parallel builds.
70 # Pass -DPROCESSOR_COUNT=<n> to cmake to override.
71 if(NOT DEFINED PROCESSOR_COUNT)
72 include(ProcessorCount)
73 ProcessorCount(PROCESSOR_COUNT)
74 set(PROCESSOR_COUNT ${PROCESSOR_COUNT}
75 CACHE STRING "Number of cores to use for parallel builds.")
76 endif()
77
78 # See if the source is available locally
79 find_file(NEWLIB_HEADER_FILE
80 NAMES newlib.h
81 PATHS ${NEWLIB_SOURCE_DIR}
82 PATH_SUFFIXES "newlib/libc/include"
83 NO_DEFAULT_PATH
84 )
85 set(NEWLIB_HEADER_FILE ${NEWLIB_HEADER_FILE})
86 unset(NEWLIB_HEADER_FILE CACHE)
87
88 # Source not found, fetch it.
89 if (NOT NEWLIB_HEADER_FILE)
90 include(FetchContent)
91
92 # Checking git
93 find_program(GIT_COMMAND "git")
94 if (NOT GIT_COMMAND)
95 message(FATAL_ERROR "Please install git")
96 endif()
97
Gyorgy Szingb202de32022-09-15 21:37:17 +020098 # List patch files.
99 file(GLOB _patch_files LIST_DIRECTORIES false "${CMAKE_CURRENT_LIST_DIR}/[0-9]*-[!0-9]*.patch")
100 # Sort items in natural order to ensure patches are amended in the right order.
101 list(SORT _patch_files COMPARE NATURAL)
102 # Convert the list to a string of concatenated quoted list items.
103 string(REPLACE ";" "\" \"" _patch_files "${_patch_files}")
104 set(_patch_files "\"${_patch_files}\"")
Gyorgy Szing3d495672022-10-12 12:58:21 +0000105 # Create a shell script patching newlib with the files listed above
Gyorgy Szingb202de32022-09-15 21:37:17 +0200106 string(APPEND _patch_script "#!/bin/sh\n"
107 " ${GIT_COMMAND} stash\n"
108 " ${GIT_COMMAND} branch ts-bf-am\n"
109 " ${GIT_COMMAND} am ${_patch_files}\n"
110 " ${GIT_COMMAND} reset ts-bf-am\n"
111 " ${GIT_COMMAND} branch -D ts-bf-am\n"
112 )
113 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/patch-newlib "${_patch_script}")
114
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000115 # Fetching newlib
116 FetchContent_Declare(
117 newlib
118 SOURCE_DIR ${NEWLIB_SOURCE_DIR}
119 GIT_REPOSITORY ${NEWLIB_URL}
120 GIT_TAG ${NEWLIB_REFSPEC}
Julian Halla628af32022-04-01 10:08:18 +0100121 GIT_SHALLOW FALSE
Gyorgy Szingb202de32022-09-15 21:37:17 +0200122 PATCH_COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/patch-newlib
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000123 )
124
125 # FetchContent_GetProperties exports newlib_SOURCE_DIR and newlib_BINARY_DIR variables
126 FetchContent_GetProperties(newlib)
127 # FetchContent_Populate will fail if the source directory is removed since it will try to
128 # do an "update" and not a "populate" action. As a workaround, remove the subbuild directory.
129 # Note: this fix assumes, the default subbuild location is used.
130 file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-subbuild")
131
132 if(NOT newlib_POPULATED)
133 message(STATUS "Fetching newlib")
134 FetchContent_Populate(newlib)
135 endif()
136 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_SOURCE_DIR})
137 endif()
138
Gyorgy Szing3d495672022-10-12 12:58:21 +0000139 # Get NEWLIB_EXTRA_PARAMS value from environment
140 set(NEWLIB_EXTRA_PARAMS $ENV{NEWLIB_EXTRA_PARAMS} CACHE STRING "")
141
Gyorgy Szingb202de32022-09-15 21:37:17 +0200142 # Split a newlib extra build parameter into a list of parameters
Gyorgy Szing3d495672022-10-12 12:58:21 +0000143 set(_extra_params ${NEWLIB_EXTRA_PARAMS})
144 separate_arguments(_extra_params)
145
146 # Transfer libgcc specific settings to newlib, and set position independent compilation
147 string(REPLACE ";" " -I" _more_cflags_target "${LIBGCC_INCLUDE_DIRS}" )
148 set(_more_cflags_target "-fpic -I${_more_cflags_target}")
149
150 # Get external extra flags for target from environment.
151 set(NEWLIB_CFLAGS_TARGET $ENV{NEWLIB_CFLAGS_TARGET} CACHE STRING "")
152
153 # Merge our CFLAGS with external CFLAGS
154 if (NOT "${NEWLIB_CFLAGS_TARGET}" STREQUAL "")
155 # Add a space separator if external value is not empty
156 string(APPEND NEWLIB_CFLAGS_TARGET " ")
157 endif()
158 # Concatenate, and override CACHE value
159 set(NEWLIB_CFLAGS_TARGET "${NEWLIB_CFLAGS_TARGET}${_more_cflags_target}" CACHE STRING "" FORCE)
160
161 # Get extra external CFLAGS for host from environment
162 set(NEWLIB_CFLAGS $ENV{NEWLIB_CFLAGS} CACHE STRING "")
Gyorgy Szingb202de32022-09-15 21:37:17 +0200163
Gyorgy Szingc7341112022-09-15 15:13:35 +0200164 # Newlib is keeping build artifacts in the source directory. If the source is pre-fetched,
165 # intermediate files of previoud build migth be still present.
166 # Run distclean to avoid build errors due to reconfiguration.
167 execute_process(COMMAND
168 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH}
169 make -j${PROCESSOR_COUNT} distclean
170 WORKING_DIRECTORY
171 ${NEWLIB_SOURCE_DIR}
172 RESULT_VARIABLE _newlib_error
173 )
174 #ignore error as distclean-host is failing.
175 #if (_newlib_error)
176 # message(FATAL_ERROR "\"distclean\" step of newlib failed with ${_newlib_error}.")
177 #endif()
178
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000179 # Newlib configure step
180 # CC env var must be unset otherwise configure will assume the cross compiler is the host
181 # compiler.
182 # The configure options are set to minimize code size and memory usage.
183 execute_process(COMMAND
184 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} ./configure
185 --target=${COMPILER_PREFIX}
Gyorgy Szingb202de32022-09-15 21:37:17 +0200186 --host=${COMPILER_PREFIX}
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000187 --prefix=${NEWLIB_INSTALL_DIR}
188 --enable-newlib-nano-formatted-io
189 --enable-newlib-nano-malloc
190 --enable-lite-exit
191 --enable-newlib-reent-small
192 --enable-newlib-global-atexit
193 --disable-multilib
Gyorgy Szing3d495672022-10-12 12:58:21 +0000194 ${_extra_params}
195 CFLAGS_FOR_TARGET=${NEWLIB_CFLAGS_TARGET}
196 CFLAGS=${NEWLIB_CFLAGS}
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000197 LDFLAGS_FOR_TARGET=-fpie
198 WORKING_DIRECTORY
199 ${NEWLIB_SOURCE_DIR}
200 RESULT_VARIABLE _newlib_error
201 )
202
203 if (_newlib_error)
204 message(FATAL_ERROR "Configuration step of newlib failed with ${_newlib_error}.")
205 endif()
206
207 # Newlib build step
208 execute_process(COMMAND
209 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH}
210 make -j${PROCESSOR_COUNT}
211 WORKING_DIRECTORY
212 ${NEWLIB_SOURCE_DIR}
213 RESULT_VARIABLE _newlib_error
214 )
215
216 if (_newlib_error)
217 message(FATAL_ERROR "Build step of newlib failed with ${_newlib_error}.")
218 endif()
219
220 # Newlib install step
221 execute_process(COMMAND
222 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} make install
223 WORKING_DIRECTORY
224 ${NEWLIB_SOURCE_DIR}
225 RESULT_VARIABLE _newlib_error
226 )
227
228 if (_newlib_error)
229 message(FATAL_ERROR "Install step of newlib failed with ${_newlib_error}.")
230 endif()
231
232 set(NEWLIB_LIBC_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libc.a")
233 set(NEWLIB_LIBNOSYS_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libnosys.a")
Imre Kisdd154112021-10-08 11:21:14 +0200234endif()
235
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000236set_property(DIRECTORY ${CMAKE_SOURCE_DIR}
237 APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_LIBC_PATH})
Imre Kisdd154112021-10-08 11:21:14 +0200238
Gyorgy Szing3d495672022-10-12 12:58:21 +0000239# libc - continue configuration
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000240set_property(TARGET c PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBC_PATH}")
Mark Dykese9db8172022-07-21 14:10:00 -0500241target_compile_definitions(c INTERFACE ENABLE_CDEFSH_FIX)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000242set_property(TARGET c PROPERTY
243 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing309e9712022-02-24 18:35:28 +0100244
245# Make standard library available in the build system.
246add_library(stdlib::c ALIAS c)
Imre Kisdd154112021-10-08 11:21:14 +0200247
248# libnosys
249add_library(nosys STATIC IMPORTED)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000250set_property(TARGET nosys PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBNOSYS_PATH}")
251set_property(TARGET nosys PROPERTY
252 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Mark Dykese9db8172022-07-21 14:10:00 -0500253compiler_set_freestanding(TARGET nosys)
Gyorgy Szing693877e2021-12-12 02:51:10 +0100254target_link_libraries(c INTERFACE nosys)