Skip to content

Commit fd9e542

Browse files
tejlmandcarlescufi
authored andcommitted
cmake: detect sysroot for cross-compile toolchains
Fixes: #49587 Try to detect sysroot for cross-compile toolchain if not specified by the user with `-DSYSROOT_DIR=<path>`. First, the C compiler is asked if it knows its sysroot, some C compilers are able to return the sysroot, as an example: > $ arm-none-eabi-gcc -print-sysroot > <path>/bin/../arm-none-eabi > $ but majority of gcc-based C compilers seems to return empty string: > $ arm-zephyr-eabi-gcc --print-sysroot > $ in such cases, the cross-compiler target CMake file will try to discover the sysroot by searching for libc.a, starting one level up from the compiler location. If no sysroot candidate is found, a warning will be printed to the user. If a single sysroot candidate is found, this candidate will be selected. If multiply sysroot candidates are found, a warning is printed, and the first candiate in the list is selected. User may select another candidate with `-DSYSROOT_DIR=<use-this>`. Signed-off-by: Torsten Rasmussen <[email protected]>
1 parent c825d42 commit fd9e542

File tree

1 file changed

+62
-1
lines changed

1 file changed

+62
-1
lines changed
Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,64 @@
11
# SPDX-License-Identifier: Apache-2.0
22

3-
# This file intentionally left blank.
3+
if(NOT SYSROOT_DIR)
4+
# When using cross-compile, the generic toolchain will be identical to the
5+
# target toolchain, hence let's ask the compiler if it knows its own sysroot.
6+
# Some gcc based compilers do have this information built-in.
7+
execute_process(COMMAND ${CMAKE_C_COMPILER} --print-sysroot
8+
RESULT_VARIABLE return_val
9+
OUTPUT_VARIABLE reported_sysroot
10+
OUTPUT_STRIP_TRAILING_WHITESPACE
11+
)
12+
if(NOT return_val AND NOT "${reported_sysroot}" STREQUAL "")
13+
set(SYSROOT_DIR "${reported_sysroot}" CACHE INTERNAL "Sysroot reported by ${CMAKE_C_COMPILER}")
14+
else()
15+
# Let's try to lookup a sysroot.
16+
# Compiler is expected to be located in `bin/` so we go one folder up for search.
17+
cmake_path(GET CMAKE_C_COMPILER PARENT_PATH search_path)
18+
cmake_path(SET search_path NORMALIZE "${search_path}/..")
19+
file(GLOB_RECURSE libc_dirs RELATIVE ${search_path} ${search_path}/**/libc.a )
20+
21+
# Did we find any candidates ?
22+
list(LENGTH libc_dirs libc_dirs_length)
23+
if(${libc_dirs_length} GREATER 0)
24+
list(TRANSFORM libc_dirs REPLACE "libc.a$" "")
25+
list(SORT libc_dirs COMPARE NATURAL)
26+
list(GET libc_dirs 0 sysroot)
27+
set(sysroot_candidates ${sysroot})
28+
29+
foreach(dir ${libc_dirs})
30+
string(FIND "${dir}" "${sysroot}" index)
31+
if(${index} EQUAL -1)
32+
set(sysroot ${dir})
33+
list(APPEND sysroot_candidates ${sysroot})
34+
endif()
35+
endforeach()
36+
37+
# We detect the lib folders, the actual sysroot is up one level.
38+
list(TRANSFORM sysroot_candidates REPLACE "/lib[/]?$" "")
39+
40+
list(LENGTH sysroot_candidates sysroot_candidates_length)
41+
if(sysroot_candidates_length GREATER 1)
42+
list(TRANSFORM sysroot_candidates PREPEND "${search_path}")
43+
string(REPLACE ";" "\n" sysroot_candidates_str "${sysroot_candidates}")
44+
45+
message(WARNING "Multiple sysroot candidates found: ${sysroot_candidates_str}\n"
46+
"Use `-DSYSROOT_DIR=<sysroot-dir>` to select sysroot.\n"
47+
)
48+
endif()
49+
50+
# Use first candidate as sysroot.
51+
list(GET sysroot_candidates 0 chosen_sysroot)
52+
cmake_path(SET SYSROOT_DIR NORMALIZE "${search_path}/${chosen_sysroot}")
53+
endif()
54+
55+
if(SYSROOT_DIR)
56+
set(SYSROOT_DIR "${SYSROOT_DIR}" CACHE INTERNAL "Sysroot discovered")
57+
message(STATUS "Found sysroot: ${SYSROOT_DIR}")
58+
else()
59+
message(WARNING "No sysroot found, build may not work.\n"
60+
"Use `-DSYSROOT_DIR=<sysroot-dir>` to specify sysroot to use.\n"
61+
)
62+
endif()
63+
endif()
64+
endif()

0 commit comments

Comments
 (0)