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