blob: 739794157260e2727eeb2a628082f09d0cdcc081 [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
55if (NOT NEWLIB_LIBC_PATH)
56 # Determine the number of processes to run while running parallel builds.
57 # Pass -DPROCESSOR_COUNT=<n> to cmake to override.
58 if(NOT DEFINED PROCESSOR_COUNT)
59 include(ProcessorCount)
60 ProcessorCount(PROCESSOR_COUNT)
61 set(PROCESSOR_COUNT ${PROCESSOR_COUNT}
62 CACHE STRING "Number of cores to use for parallel builds.")
63 endif()
64
65 # See if the source is available locally
66 find_file(NEWLIB_HEADER_FILE
67 NAMES newlib.h
68 PATHS ${NEWLIB_SOURCE_DIR}
69 PATH_SUFFIXES "newlib/libc/include"
70 NO_DEFAULT_PATH
71 )
72 set(NEWLIB_HEADER_FILE ${NEWLIB_HEADER_FILE})
73 unset(NEWLIB_HEADER_FILE CACHE)
74
75 # Source not found, fetch it.
76 if (NOT NEWLIB_HEADER_FILE)
77 include(FetchContent)
78
79 # Checking git
80 find_program(GIT_COMMAND "git")
81 if (NOT GIT_COMMAND)
82 message(FATAL_ERROR "Please install git")
83 endif()
84
85 # Fetching newlib
86 FetchContent_Declare(
87 newlib
88 SOURCE_DIR ${NEWLIB_SOURCE_DIR}
89 GIT_REPOSITORY ${NEWLIB_URL}
90 GIT_TAG ${NEWLIB_REFSPEC}
91 GIT_SHALLOW TRUE
92 PATCH_COMMAND git stash
93 COMMAND ${GIT_COMMAND} am ${CMAKE_CURRENT_LIST_DIR}/0001-Allow-aarch64-linux-gcc-to-compile-bare-metal-lib.patch
94 COMMAND ${GIT_COMMAND} reset HEAD~1
95 )
96
97 # FetchContent_GetProperties exports newlib_SOURCE_DIR and newlib_BINARY_DIR variables
98 FetchContent_GetProperties(newlib)
99 # FetchContent_Populate will fail if the source directory is removed since it will try to
100 # do an "update" and not a "populate" action. As a workaround, remove the subbuild directory.
101 # Note: this fix assumes, the default subbuild location is used.
102 file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/_deps/newlib-subbuild")
103
104 if(NOT newlib_POPULATED)
105 message(STATUS "Fetching newlib")
106 FetchContent_Populate(newlib)
107 endif()
108 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_SOURCE_DIR})
109 endif()
110
111 # Newlib configure step
112 # CC env var must be unset otherwise configure will assume the cross compiler is the host
113 # compiler.
114 # The configure options are set to minimize code size and memory usage.
115 execute_process(COMMAND
116 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} ./configure
117 --target=${COMPILER_PREFIX}
118 --prefix=${NEWLIB_INSTALL_DIR}
119 --enable-newlib-nano-formatted-io
120 --enable-newlib-nano-malloc
121 --enable-lite-exit
122 --enable-newlib-reent-small
123 --enable-newlib-global-atexit
124 --disable-multilib
125 CFLAGS_FOR_TARGET=-fpic
126 LDFLAGS_FOR_TARGET=-fpie
127 WORKING_DIRECTORY
128 ${NEWLIB_SOURCE_DIR}
129 RESULT_VARIABLE _newlib_error
130 )
131
132 if (_newlib_error)
133 message(FATAL_ERROR "Configuration step of newlib failed with ${_newlib_error}.")
134 endif()
135
136 # Newlib build step
137 execute_process(COMMAND
138 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH}
139 make -j${PROCESSOR_COUNT}
140 WORKING_DIRECTORY
141 ${NEWLIB_SOURCE_DIR}
142 RESULT_VARIABLE _newlib_error
143 )
144
145 if (_newlib_error)
146 message(FATAL_ERROR "Build step of newlib failed with ${_newlib_error}.")
147 endif()
148
149 # Newlib install step
150 execute_process(COMMAND
151 ${CMAKE_COMMAND} -E env --unset=CC PATH=${COMPILER_PATH}:$ENV{PATH} make install
152 WORKING_DIRECTORY
153 ${NEWLIB_SOURCE_DIR}
154 RESULT_VARIABLE _newlib_error
155 )
156
157 if (_newlib_error)
158 message(FATAL_ERROR "Install step of newlib failed with ${_newlib_error}.")
159 endif()
160
161 set(NEWLIB_LIBC_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libc.a")
162 set(NEWLIB_LIBNOSYS_PATH "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/lib/libnosys.a")
Imre Kisdd154112021-10-08 11:21:14 +0200163endif()
164
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000165set_property(DIRECTORY ${CMAKE_SOURCE_DIR}
166 APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_LIBC_PATH})
Imre Kisdd154112021-10-08 11:21:14 +0200167
168# libc
169add_library(c STATIC IMPORTED)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000170set_property(TARGET c PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBC_PATH}")
171set_property(TARGET c PROPERTY
172 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100173target_compile_options(c INTERFACE -nostdinc)
174target_link_options(c INTERFACE -nostartfiles -nodefaultlibs)
Imre Kisdd154112021-10-08 11:21:14 +0200175
176# libnosys
177add_library(nosys STATIC IMPORTED)
Gyorgy Szing51f45d22021-12-08 00:44:18 +0000178set_property(TARGET nosys PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBNOSYS_PATH}")
179set_property(TARGET nosys PROPERTY
180 INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
Gyorgy Szing693877e2021-12-12 02:51:10 +0100181target_compile_options(nosys INTERFACE -nostdinc)
182target_link_options(nosys INTERFACE -nostartfiles -nodefaultlibs)
183target_link_libraries(c INTERFACE nosys)
184
185# Make standard library available in the build system.
186add_library(stdlib::c ALIAS c)
187
188# -noxxx options above require explicitly naming GCC specific library on the
189# linker command line.
190include(${TS_ROOT}/tools/cmake/compiler/GCC.cmake)
191gcc_get_lib_location(LIBRARY_NAME "libgcc.a" RES _TMP_VAR)
192link_libraries(${_TMP_VAR})
193# Moreover the GCC specific header file include directory is also required.
194# There is no way to stop cmake from filtering out built in compiler include paths
195# from compiler command line (see https://gitlab.kitware.com/cmake/cmake/-/issues/19227)
196# As a workaround copy headers to build directory and set include path to the new
197# location.
198get_filename_component(_TMP_VAR "${_TMP_VAR}" DIRECTORY)
199file(COPY "${_TMP_VAR}/include" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gcc_include)
200file(COPY "${_TMP_VAR}/include-fixed" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gcc-include)
201include_directories("${CMAKE_CURRENT_BINARY_DIR}/gcc_include/include")
202include_directories("${CMAKE_CURRENT_BINARY_DIR}/gcc-include/include-fixed")
203unset(_TMP_VAR)