fix(cmake): pass an absolute picolibc specs path to ccache < 4.12

ccache before 4.12 opens a relative -specs= name from the working
directory and misses the file. When the C launcher is an older
ccache, quote the compiler's canonical path as one option.

Closes https://github.com/espressif/esp-idf/issues/19266
This commit is contained in:
Alexey Lapshin
2026-10-21 14:32:56 +08:00
committed by BOT
parent 8a14310b58
commit 364c779a11
2 changed files with 61 additions and 2 deletions
+4 -2
View File
@@ -11,12 +11,14 @@ if(CONFIG_IDF_TOOLCHAIN_GCC)
idf_toolchain_remove_flags(COMPILE_OPTIONS "-mdisable-hardware-atomics")
endif()
idf_toolchain_remove_flags(COMPILE_OPTIONS "-specs=picolibc.specs")
# Match the bare name and a previously added absolute path (optional quotes).
idf_toolchain_remove_flags(COMPILE_OPTIONS "-specs=.*picolibc.specs")
idf_toolchain_remove_flags(COMPILE_OPTIONS "-D__STDC_WANT_LIB_EXT1__=0")
# TODO GCC-495:remove
idf_toolchain_remove_flags(COMPILE_OPTIONS "-D__PICOLIBC_ERRNO_FUNCTION=__errno")
if(CONFIG_LIBC_PICOLIBC)
idf_toolchain_add_flags(COMPILE_OPTIONS "-specs=picolibc.specs")
__idf_gcc_specs_option(picolibc_specs_option picolibc.specs)
idf_toolchain_add_flags(COMPILE_OPTIONS "${picolibc_specs_option}")
# TODO GCC-495:remove
idf_toolchain_add_flags(COMPILE_OPTIONS "-D__PICOLIBC_ERRNO_FUNCTION=__errno")
if(CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY)
+57
View File
@@ -165,6 +165,63 @@ function(idf_toolchain_remove_flags)
_process_toolchain_flag_options()
endfunction()
# __idf_gcc_specs_option(output_var specs_name)
#
# @brief Return one -specs= compile option.
#
# ccache < 4.12 opens a relative -specs= name from the working directory and
# fails. If CMAKE_C_COMPILER_LAUNCHER contains such a ccache, return the
# compiler's canonical path as one quoted option:
#
# "-specs=/absolute/path"
#
# Otherwise return:
#
# -specs=<specs_name>
function(__idf_gcc_specs_option output_var specs_name)
# Bare name unless an old ccache forces an absolute path below.
set(${output_var} "-specs=${specs_name}" PARENT_SCOPE)
set(_ccache_bin "")
foreach(_launcher IN LISTS CMAKE_C_COMPILER_LAUNCHER)
if(_launcher MATCHES "ccache")
set(_ccache_bin "${_launcher}")
break()
endif()
endforeach()
if(NOT _ccache_bin)
return()
endif()
execute_process(
COMMAND "${_ccache_bin}" --version
OUTPUT_VARIABLE _ccache_version_output
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _ccache_version_result)
if(NOT _ccache_version_result EQUAL 0)
return()
endif()
if(NOT _ccache_version_output MATCHES "ccache version ([0-9.]+)")
return()
endif()
if(NOT CMAKE_MATCH_1 VERSION_LESS "4.12")
return()
endif()
execute_process(
COMMAND "${CMAKE_C_COMPILER}" -print-file-name=${specs_name}
OUTPUT_VARIABLE _specs_path
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _specs_result)
if(NOT _specs_result EQUAL 0 OR NOT IS_ABSOLUTE "${_specs_path}")
return()
endif()
file(REAL_PATH "${_specs_path}" _specs_path)
# Quotes keep "-specs=/path with spaces" one response-file token.
set(${output_var} "\"-specs=${_specs_path}\"" PARENT_SCOPE)
endfunction()
# Workaround: Re-run CMake compiler ABI detection after ABI flags are set.
#
# Problem: CMake performs compiler checks at an early stage during