Enhance GCC compatibility of newlib integration
- Allow overriding GCC specific library location and search paths from
CMake command line.
This enables using GCC binaries which are unable to find libgcc.a.
- Enhance error handling and error messages.
Change-Id: Ie8ef9e1dd1bdece9f47595e14d3e3241b4621470
Signed-off-by: Gyorgy Szing <Gyorgy.Szing@arm.com>
diff --git a/external/newlib/newlib.cmake b/external/newlib/newlib.cmake
index f8b8887..05bc93e 100644
--- a/external/newlib/newlib.cmake
+++ b/external/newlib/newlib.cmake
@@ -52,22 +52,51 @@
set(NEWLIB_LIBNOSYS_PATH ${NEWLIB_LIBNOSYS_PATH})
unset(NEWLIB_LIBNOSYS_PATH CACHE)
-# -noxxx options require explicitly naming GCC specific library on the
+# -noxxx options require explicitly specifying GCC specific library on the
# linker command line.
-include(${TS_ROOT}/tools/cmake/compiler/GCC.cmake)
-gcc_get_lib_location(LIBRARY_NAME "libgcc.a" RES _TMP_VAR)
-set(_LIBGCC_PATH ${_TMP_VAR})
+# Use LIBGCC_PATH to manually override the search process below.
+if (NOT DEFINED LIBGCC_PATH)
+ include(${TS_ROOT}/tools/cmake/compiler/GCC.cmake)
+ gcc_get_lib_location(LIBRARY_NAME "libgcc.a" RES _TMP_VAR)
+
+ if (NOT _TMP_VAR)
+ message(FATAL_ERROR "Location of libgcc.a can not be determined. Please set LIBGCC_PATH on the command line.")
+ endif()
+ set(LIBGCC_PATH ${_TMP_VAR} CACHE PATH "location of libgcc.a")
+ unset(_TMP_VAR)
+endif()
+
+if(NOT EXISTS "${LIBGCC_PATH}" OR IS_DIRECTORY "${LIBGCC_PATH}")
+ message(FATAL_ERROR "LIBGCC_PATH \"${LIBGCC_PATH}\" must be the full path of a library file."
+ " Either set LIBGCC_PATH on the command line, or fix the value if already set.")
+endif()
+message(STATUS "libgcc.a is used from ${LIBGCC_PATH}")
+
# Moreover the GCC specific header file include directory is also required.
+# Specify LIBGCC_INCLUDE_DIRS in the command line to manually override the libgcc relative location below.
+if(NOT DEFINED LIBGCC_INCLUDE_DIRS)
+ get_filename_component(_TMP_VAR "${LIBGCC_PATH}" DIRECTORY)
+ set(LIBGCC_INCLUDE_DIRS
+ "${_TMP_VAR}/include"
+ "${_TMP_VAR}/include-fixed" CACHE STRING "GCC specific include PATHs")
+ unset(_TMP_VAR)
+endif()
+
# There is no way to stop cmake from filtering out built in compiler include paths
# from compiler command line (see https://gitlab.kitware.com/cmake/cmake/-/issues/19227)
# As a workaround copy headers to build directory and set include path to the new
# location.
-get_filename_component(_TMP_VAR "${_TMP_VAR}" DIRECTORY)
-file(COPY "${_TMP_VAR}/include" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gcc_include)
-file(COPY "${_TMP_VAR}/include-fixed" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gcc-include)
-set(_libgcc_includes
- "${CMAKE_CURRENT_BINARY_DIR}/gcc_include/include"
- "${CMAKE_CURRENT_BINARY_DIR}/gcc-include/include-fixed")
+foreach(_dir IN LISTS LIBGCC_INCLUDE_DIRS)
+ if(NOT IS_DIRECTORY "${_dir}")
+ message(FATAL_ERROR "GCC specific include PATH \"${_dir}\" does not exist. Try setting LIBGCC_INCLUDE_DIRS"
+ " on the command line.")
+ endif()
+ file(COPY "${_dir}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gcc-include")
+ get_filename_component(_TMP_VAR "${_dir}" NAME)
+ list(APPEND _gcc_include_dirs "${CMAKE_CURRENT_BINARY_DIR}/gcc-include/${_TMP_VAR}")
+ message(STATUS "Using compiler specific include path \"${_dir}\" mirrored to"
+ " \"${CMAKE_CURRENT_BINARY_DIR}/gcc-include/${_TMP_VAR}\".")
+endforeach()
unset(_TMP_VAR)
if (NOT NEWLIB_LIBC_PATH)
@@ -126,7 +155,7 @@
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NEWLIB_SOURCE_DIR})
endif()
- string(REPLACE ";" " -isystem " CFLAGS_FOR_TARGET "${_libgcc_includes}")
+ string(REPLACE ";" " -isystem " CFLAGS_FOR_TARGET "${_gcc_include_dirs}")
set(CFLAGS_FOR_TARGET "-isystem ${CFLAGS_FOR_TARGET} -fpic")
# Newlib configure step
@@ -188,14 +217,13 @@
# libc
add_library(c STATIC IMPORTED)
-target_link_libraries(c INTERFACE "${_LIBGCC_PATH}")
-unset(_LIBGCC_PATH)
+link_libraries(c INTERFACE ${LIBGCC_PATH})
set_property(TARGET c PROPERTY IMPORTED_LOCATION "${NEWLIB_LIBC_PATH}")
set_property(TARGET c PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${NEWLIB_INSTALL_DIR}/${COMPILER_PREFIX}/include")
target_compile_options(c INTERFACE -nostdinc)
target_link_options(c INTERFACE -nostartfiles -nodefaultlibs)
-target_include_directories(c SYSTEM INTERFACE ${_libgcc_includes})
+target_include_directories(c SYSTEM INTERFACE ${_gcc_include_dirs})
# Make standard library available in the build system.
add_library(stdlib::c ALIAS c)