blob: 131eb7e8f8e28ba2c649e4a88fd88e9163f09fdc [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
Gyorgy Szingb202de32022-09-15 21:37:17 +0200139 # List patch files.
140 file(GLOB _patch_files LIST_DIRECTORIES false "${CMAKE_CURRENT_LIST_DIR}/[0-9]*-[!0-9]*.patch")
141 # Sort items in natural order to ensure patches are amended in the right order.
142 list(SORT _patch_files COMPARE NATURAL)
143 # Convert the list to a string of concatenated quoted list items.
144 string(REPLACE ";" "\" \"" _patch_files "${_patch_files}")
145 set(_patch_files "\"${_patch_files}\"")
146 # Create a shell script pathching newlib witht the files listed above
147 string(APPEND _patch_script "#!/bin/sh\n"
148 " ${GIT_COMMAND} stash\n"
149 " ${GIT_COMMAND} branch ts-bf-am\n"
150 " ${GIT_COMMAND} am ${_patch_files}\n"
151 " ${GIT_COMMAND} reset ts-bf-am\n"
152 " ${GIT_COMMAND} branch -D ts-bf-am\n"
153 )
154 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/patch-newlib "${_patch_script}")
155
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000156 # Fetching newlib
157 FetchContent_Declare(
158 newlib
159 SOURCE_DIR ${NEWLIB_SOURCE_DIR}
160 GIT_REPOSITORY ${NEWLIB_URL}
161 GIT_TAG ${NEWLIB_REFSPEC}
Julian Halla628af32022-04-01 10:08:18 +0100162 GIT_SHALLOW FALSE
Gyorgy Szingb202de32022-09-15 21:37:17 +0200163 PATCH_COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/patch-newlib
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000164 )
165
166 # FetchContent_GetProperties exports newlib_SOURCE_DIR and newlib_BINARY_DIR variables
167 FetchContent_GetProperties(newlib)
168 # FetchContent_Populate will fail if the source directory is removed since it will try to
169 # do an "update" and not a "populate" action. As a workaround, remove the subbuild directory.
170 # Note: this fix assumes, the default subbuild location is used.
171 file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-subbuild")
172
173 if(NOT newlib_POPULATED)
174 message(STATUS "Fetching newlib")
175 FetchContent_Populate(newlib)
176 endif()
177 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_SOURCE_DIR})
178 endif()
179
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000180 string(REPLACE ";" " -isystem " CFLAGS_FOR_TARGET "${_gcc_include_dirs}")
Gyorgy Szing309e9712022-02-24 18:35:28 +0100181 set(CFLAGS_FOR_TARGET "-isystem ${CFLAGS_FOR_TARGET} -fpic")
182
Gyorgy Szingb202de32022-09-15 21:37:17 +0200183 # Split a newlib extra build parameter into a list of parameters
184 set(NEWLIB_EXTRAS ${NEWLIB_EXTRA})
185 separate_arguments(NEWLIB_EXTRAS)
186
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000187 # Newlib configure step
188 # CC env var must be unset otherwise configure will assume the cross compiler is the host
189 # compiler.
190 # The configure options are set to minimize code size and memory usage.
191 execute_process(COMMAND
192 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} ./configure
193 --target=${COMPILER_PREFIX}
Gyorgy Szingb202de32022-09-15 21:37:17 +0200194 --host=${COMPILER_PREFIX}
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000195 --prefix=${NEWLIB_INSTALL_DIR}
196 --enable-newlib-nano-formatted-io
197 --enable-newlib-nano-malloc
198 --enable-lite-exit
199 --enable-newlib-reent-small
200 --enable-newlib-global-atexit
201 --disable-multilib
Gyorgy Szingb202de32022-09-15 21:37:17 +0200202 ${NEWLIB_EXTRAS}
Gyorgy Szing309e9712022-02-24 18:35:28 +0100203 CFLAGS_FOR_TARGET=${CFLAGS_FOR_TARGET}
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000204 LDFLAGS_FOR_TARGET=-fpie
205 WORKING_DIRECTORY
206 ${NEWLIB_SOURCE_DIR}
207 RESULT_VARIABLE _newlib_error
208 )
209
210 if (_newlib_error)
211 message(FATAL_ERROR "Configuration step of newlib failed with ${_newlib_error}.")
212 endif()
213
214 # Newlib build step
215 execute_process(COMMAND
216 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH}
217 make -j${PROCESSOR_COUNT}
218 WORKING_DIRECTORY
219 ${NEWLIB_SOURCE_DIR}
220 RESULT_VARIABLE _newlib_error
221 )
222
223 if (_newlib_error)
224 message(FATAL_ERROR "Build step of newlib failed with ${_newlib_error}.")
225 endif()
226
227 # Newlib install step
228 execute_process(COMMAND
229 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} make install
230 WORKING_DIRECTORY
231 ${NEWLIB_SOURCE_DIR}
232 RESULT_VARIABLE _newlib_error
233 )
234
235 if (_newlib_error)
236 message(FATAL_ERROR "Install step of newlib failed with ${_newlib_error}.")
237 endif()
238
239 set(NEWLIB_LIBC_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libc.a")
240 set(NEWLIB_LIBNOSYS_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libnosys.a")
Imre Kisdd154112021-10-08 11:21:14 +0200241endif()
242
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000243set_property(DIRECTORY ${CMAKE_SOURCE_DIR}
244 APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_LIBC_PATH})
Imre Kisdd154112021-10-08 11:21:14 +0200245
246# libc
247add_library(c STATIC IMPORTED)
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000248link_libraries(c INTERFACE ${LIBGCC_PATH})
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000249set_property(TARGET c PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBC_PATH}")
250set_property(TARGET c PROPERTY
251 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100252target_compile_options(c INTERFACE -nostdinc)
Gyorgy Szing8fad9bc2021-12-12 03:56:41 +0100253target_compile_definitions(c INTERFACE ENABLE_CDEFSH_FIX)
Gyorgy Szing693877e2021-12-12 02:51:10 +0100254target_link_options(c INTERFACE -nostartfiles -nodefaultlibs)
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000255target_include_directories(c SYSTEM INTERFACE ${_gcc_include_dirs})
Gyorgy Szing309e9712022-02-24 18:35:28 +0100256
257# Make standard library available in the build system.
258add_library(stdlib::c ALIAS c)
Imre Kisdd154112021-10-08 11:21:14 +0200259
260# libnosys
261add_library(nosys STATIC IMPORTED)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000262set_property(TARGET nosys PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBNOSYS_PATH}")
263set_property(TARGET nosys PROPERTY
264 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100265target_compile_options(nosys INTERFACE -nostdinc)
266target_link_options(nosys INTERFACE -nostartfiles -nodefaultlibs)
267target_link_libraries(c INTERFACE nosys)