blob: 05bc93ec1df514d46683f290a15e703430156f73 [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
13# Compile TS specific newlib porting files.
14target_sources(${TGT} PRIVATE
15 "${CMAKE_CURRENT_LIST_DIR}/newlib_init.c"
16 "${CMAKE_CURRENT_LIST_DIR}/newlib_sp_assert.c"
17 "${CMAKE_CURRENT_LIST_DIR}/newlib_sp_heap.c"
18)
19
Gyorgy Szing51f45d22021-12-08 00:44:18 +000020# Fetch newlib from external repository
21set(NEWLIB_URL "https://sourceware.org/git/newlib-cygwin.git"
22 CACHE STRING "newlib repository URL")
23set(NEWLIB_REFSPEC "newlib-4.1.0"
24 CACHE STRING "newlib git refspec")
25set(NEWLIB_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-src"
26 CACHE PATH "newlib source-code location")
27set(NEWLIB_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/newlib_install"
28 CACHE PATH "newlib installation directory")
Imre Kisdd154112021-10-08 11:21:14 +020029
Gyorgy Szing693877e2021-12-12 02:51:10 +010030# Extracting compiler prefix without the trailing hyphen from the C compiler name
Imre Kisdd154112021-10-08 11:21:14 +020031get_filename_component(COMPILER_PATH ${CMAKE_C_COMPILER} DIRECTORY)
32get_filename_component(COMPILER_NAME ${CMAKE_C_COMPILER} NAME)
Imre Kis2b7ef372022-01-04 12:36:12 +010033string(REGEX REPLACE "(.*)-[^-]+$" "\\1" COMPILER_PREFIX ${COMPILER_NAME})
Imre Kisdd154112021-10-08 11:21:14 +020034
Gyorgy Szing51f45d22021-12-08 00:44:18 +000035find_library(NEWLIB_LIBC_PATH
36 NAMES libc.a c.a libc.lib c.lib
37 PATHS ${NEWLIB_INSTALL_DIR}
38 PATH_SUFFIXES "${COMPILER_PREFIX}/lib"
39 DOC "Location of newlib::libc library."
40 NO_DEFAULT_PATH
Imre Kisdd154112021-10-08 11:21:14 +020041)
Gyorgy Szing51f45d22021-12-08 00:44:18 +000042set(NEWLIB_LIBC_PATH ${NEWLIB_LIBC_PATH})
43unset(NEWLIB_LIBC_PATH CACHE)
Imre Kisdd154112021-10-08 11:21:14 +020044
Gyorgy Szing51f45d22021-12-08 00:44:18 +000045find_library(NEWLIB_LIBNOSYS_PATH
46 NAMES libnosys.a nosys.a nosys.lib nosys.lib
47 PATHS ${NEWLIB_INSTALL_DIR}
48 PATH_SUFFIXES "${COMPILER_PREFIX}/lib"
49 DOC "Location of newlib::libnosys library."
50 NO_DEFAULT_PATH
51)
Gyorgy Szingf7a91e72022-02-09 11:59:07 +010052set(NEWLIB_LIBNOSYS_PATH ${NEWLIB_LIBNOSYS_PATH})
Gyorgy Szing51f45d22021-12-08 00:44:18 +000053unset(NEWLIB_LIBNOSYS_PATH CACHE)
54
Gyorgy Szing69a10c32022-03-02 21:10:20 +000055# -noxxx options require explicitly specifying GCC specific library on the
Gyorgy Szing309e9712022-02-24 18:35:28 +010056# linker command line.
Gyorgy Szing69a10c32022-03-02 21:10:20 +000057# Use LIBGCC_PATH to manually override the search process below.
58if (NOT DEFINED LIBGCC_PATH)
59 include(${TS_ROOT}/tools/cmake/compiler/GCC.cmake)
60 gcc_get_lib_location(LIBRARY_NAME "libgcc.a" RES _TMP_VAR)
61
62 if (NOT _TMP_VAR)
63 message(FATAL_ERROR "Location of libgcc.a can not be determined. Please set LIBGCC_PATH on the command line.")
64 endif()
65 set(LIBGCC_PATH ${_TMP_VAR} CACHE PATH "location of libgcc.a")
66 unset(_TMP_VAR)
67endif()
68
69if(NOT EXISTS "${LIBGCC_PATH}" OR IS_DIRECTORY "${LIBGCC_PATH}")
70 message(FATAL_ERROR "LIBGCC_PATH \"${LIBGCC_PATH}\" must be the full path of a library file."
71 " Either set LIBGCC_PATH on the command line, or fix the value if already set.")
72endif()
73message(STATUS "libgcc.a is used from ${LIBGCC_PATH}")
74
Gyorgy Szing309e9712022-02-24 18:35:28 +010075# Moreover the GCC specific header file include directory is also required.
Gyorgy Szing69a10c32022-03-02 21:10:20 +000076# Specify LIBGCC_INCLUDE_DIRS in the command line to manually override the libgcc relative location below.
77if(NOT DEFINED LIBGCC_INCLUDE_DIRS)
78 get_filename_component(_TMP_VAR "${LIBGCC_PATH}" DIRECTORY)
79 set(LIBGCC_INCLUDE_DIRS
80 "${_TMP_VAR}/include"
81 "${_TMP_VAR}/include-fixed" CACHE STRING "GCC specific include PATHs")
82 unset(_TMP_VAR)
83endif()
84
Gyorgy Szing309e9712022-02-24 18:35:28 +010085# There is no way to stop cmake from filtering out built in compiler include paths
86# from compiler command line (see https://gitlab.kitware.com/cmake/cmake/-/issues/19227)
87# As a workaround copy headers to build directory and set include path to the new
88# location.
Gyorgy Szing69a10c32022-03-02 21:10:20 +000089foreach(_dir IN LISTS LIBGCC_INCLUDE_DIRS)
90 if(NOT IS_DIRECTORY "${_dir}")
91 message(FATAL_ERROR "GCC specific include PATH \"${_dir}\" does not exist. Try setting LIBGCC_INCLUDE_DIRS"
92 " on the command line.")
93 endif()
94 file(COPY "${_dir}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gcc-include")
95 get_filename_component(_TMP_VAR "${_dir}" NAME)
96 list(APPEND _gcc_include_dirs "${CMAKE_CURRENT_BINARY_DIR}/gcc-include/${_TMP_VAR}")
97 message(STATUS "Using compiler specific include path \"${_dir}\" mirrored to"
98 " \"${CMAKE_CURRENT_BINARY_DIR}/gcc-include/${_TMP_VAR}\".")
99endforeach()
Gyorgy Szing309e9712022-02-24 18:35:28 +0100100unset(_TMP_VAR)
101
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000102if (NOT NEWLIB_LIBC_PATH)
103 # Determine the number of processes to run while running parallel builds.
104 # Pass -DPROCESSOR_COUNT=<n> to cmake to override.
105 if(NOT DEFINED PROCESSOR_COUNT)
106 include(ProcessorCount)
107 ProcessorCount(PROCESSOR_COUNT)
108 set(PROCESSOR_COUNT ${PROCESSOR_COUNT}
109 CACHE STRING "Number of cores to use for parallel builds.")
110 endif()
111
112 # See if the source is available locally
113 find_file(NEWLIB_HEADER_FILE
114 NAMES newlib.h
115 PATHS ${NEWLIB_SOURCE_DIR}
116 PATH_SUFFIXES "newlib/libc/include"
117 NO_DEFAULT_PATH
118 )
119 set(NEWLIB_HEADER_FILE ${NEWLIB_HEADER_FILE})
120 unset(NEWLIB_HEADER_FILE CACHE)
121
122 # Source not found, fetch it.
123 if (NOT NEWLIB_HEADER_FILE)
124 include(FetchContent)
125
126 # Checking git
127 find_program(GIT_COMMAND "git")
128 if (NOT GIT_COMMAND)
129 message(FATAL_ERROR "Please install git")
130 endif()
131
132 # Fetching newlib
133 FetchContent_Declare(
134 newlib
135 SOURCE_DIR ${NEWLIB_SOURCE_DIR}
136 GIT_REPOSITORY ${NEWLIB_URL}
137 GIT_TAG ${NEWLIB_REFSPEC}
138 GIT_SHALLOW TRUE
139 PATCH_COMMAND git stash
140 COMMAND ${GIT_COMMAND} am ${CMAKE_CURRENT_LIST_DIR}/0001-Allow-aarch64-linux-gcc-to-compile-bare-metal-lib.patch
141 COMMAND ${GIT_COMMAND} reset HEAD~1
142 )
143
144 # FetchContent_GetProperties exports newlib_SOURCE_DIR and newlib_BINARY_DIR variables
145 FetchContent_GetProperties(newlib)
146 # FetchContent_Populate will fail if the source directory is removed since it will try to
147 # do an "update" and not a "populate" action. As a workaround, remove the subbuild directory.
148 # Note: this fix assumes, the default subbuild location is used.
149 file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-subbuild")
150
151 if(NOT newlib_POPULATED)
152 message(STATUS "Fetching newlib")
153 FetchContent_Populate(newlib)
154 endif()
155 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_SOURCE_DIR})
156 endif()
157
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000158 string(REPLACE ";" " -isystem " CFLAGS_FOR_TARGET "${_gcc_include_dirs}")
Gyorgy Szing309e9712022-02-24 18:35:28 +0100159 set(CFLAGS_FOR_TARGET "-isystem ${CFLAGS_FOR_TARGET} -fpic")
160
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000161 # Newlib configure step
162 # CC env var must be unset otherwise configure will assume the cross compiler is the host
163 # compiler.
164 # The configure options are set to minimize code size and memory usage.
165 execute_process(COMMAND
166 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} ./configure
167 --target=${COMPILER_PREFIX}
168 --prefix=${NEWLIB_INSTALL_DIR}
169 --enable-newlib-nano-formatted-io
170 --enable-newlib-nano-malloc
171 --enable-lite-exit
172 --enable-newlib-reent-small
173 --enable-newlib-global-atexit
174 --disable-multilib
Gyorgy Szing309e9712022-02-24 18:35:28 +0100175 CFLAGS_FOR_TARGET=${CFLAGS_FOR_TARGET}
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000176 LDFLAGS_FOR_TARGET=-fpie
177 WORKING_DIRECTORY
178 ${NEWLIB_SOURCE_DIR}
179 RESULT_VARIABLE _newlib_error
180 )
181
182 if (_newlib_error)
183 message(FATAL_ERROR "Configuration step of newlib failed with ${_newlib_error}.")
184 endif()
185
186 # Newlib build step
187 execute_process(COMMAND
188 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH}
189 make -j${PROCESSOR_COUNT}
190 WORKING_DIRECTORY
191 ${NEWLIB_SOURCE_DIR}
192 RESULT_VARIABLE _newlib_error
193 )
194
195 if (_newlib_error)
196 message(FATAL_ERROR "Build step of newlib failed with ${_newlib_error}.")
197 endif()
198
199 # Newlib install step
200 execute_process(COMMAND
201 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} make install
202 WORKING_DIRECTORY
203 ${NEWLIB_SOURCE_DIR}
204 RESULT_VARIABLE _newlib_error
205 )
206
207 if (_newlib_error)
208 message(FATAL_ERROR "Install step of newlib failed with ${_newlib_error}.")
209 endif()
210
211 set(NEWLIB_LIBC_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libc.a")
212 set(NEWLIB_LIBNOSYS_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libnosys.a")
Imre Kisdd154112021-10-08 11:21:14 +0200213endif()
214
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000215set_property(DIRECTORY ${CMAKE_SOURCE_DIR}
216 APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_LIBC_PATH})
Imre Kisdd154112021-10-08 11:21:14 +0200217
218# libc
219add_library(c STATIC IMPORTED)
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000220link_libraries(c INTERFACE ${LIBGCC_PATH})
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000221set_property(TARGET c PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBC_PATH}")
222set_property(TARGET c PROPERTY
223 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100224target_compile_options(c INTERFACE -nostdinc)
225target_link_options(c INTERFACE -nostartfiles -nodefaultlibs)
Gyorgy Szing69a10c32022-03-02 21:10:20 +0000226target_include_directories(c SYSTEM INTERFACE ${_gcc_include_dirs})
Gyorgy Szing309e9712022-02-24 18:35:28 +0100227
228# Make standard library available in the build system.
229add_library(stdlib::c ALIAS c)
Imre Kisdd154112021-10-08 11:21:14 +0200230
231# libnosys
232add_library(nosys STATIC IMPORTED)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000233set_property(TARGET nosys PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBNOSYS_PATH}")
234set_property(TARGET nosys PROPERTY
235 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100236target_compile_options(nosys INTERFACE -nostdinc)
237target_link_options(nosys INTERFACE -nostartfiles -nodefaultlibs)
238target_link_libraries(c INTERFACE nosys)