Skip to content

Commit 09a5f46

Browse files
committed
cmake: Delay computation of linker paths until needed
With inclusion of the optimization flag into the multilib selection process, we cannot compute the compiler library path when the compiler's target.cmake is processed as OPTIMIZATION_FLAG is not computed until much later. Instead, add a function (compiler_file_path) which can be used to locate the appropriate crtbegin.o and crtend.o files. Delay computation of lib_include_dir and rt_library until after all compiler flags have been computed by adding compiler_set_linker_properties and calling that just before toolchain_linker_finalize is invoked. Place default implementations of both of these functions in a new file, cmake/compiler/target_template.cmake, where we assume the compiler works like gcc or clang and handlers the --print-file-name and --print-libgcc-file-name options. Compilers needing alternate implementations can override these functions in their target.cmake files. Signed-off-by: Keith Packard <[email protected]>
1 parent d0d5ad2 commit 09a5f46

File tree

9 files changed

+92
-60
lines changed

9 files changed

+92
-60
lines changed

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -2326,6 +2326,9 @@ add_subdirectory_ifdef(
23262326
cmake/makefile_exports
23272327
)
23282328

2329+
# Ask the compiler to set the lib_include_dir and rt_library properties
2330+
compiler_set_linker_properties()
2331+
23292332
toolchain_linker_finalize()
23302333

23312334
# export build information

cmake/compiler/clang/target.cmake

-15
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,6 @@ if(NOT "${ARCH}" STREQUAL "posix")
100100
endif()
101101
endif()
102102

103-
# This libgcc code is partially duplicated in compiler/*/target.cmake
104-
execute_process(
105-
COMMAND ${CMAKE_C_COMPILER} ${clang_target_flag} ${TOOLCHAIN_C_FLAGS}
106-
--print-libgcc-file-name
107-
OUTPUT_VARIABLE RTLIB_FILE_NAME
108-
OUTPUT_STRIP_TRAILING_WHITESPACE
109-
)
110-
111-
get_filename_component(RTLIB_DIR ${RTLIB_FILE_NAME} DIRECTORY)
112-
get_filename_component(RTLIB_NAME_WITH_PREFIX ${RTLIB_FILE_NAME} NAME_WLE)
113-
string(REPLACE lib "" RTLIB_NAME ${RTLIB_NAME_WITH_PREFIX})
114-
115-
set_property(TARGET linker PROPERTY lib_include_dir "-L${RTLIB_DIR}")
116-
set_property(TARGET linker PROPERTY rt_library "-l${RTLIB_NAME}")
117-
118103
list(APPEND CMAKE_REQUIRED_FLAGS -nostartfiles -nostdlib ${isystem_include_flags})
119104
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
120105

cmake/compiler/gcc/target.cmake

-15
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,6 @@ if(SYSROOT_DIR)
9696
set(LIBC_LIBRARY_DIR "\"${SYSROOT_DIR}\"/lib/${NEWLIB_DIR}")
9797
endif()
9898

99-
# This libgcc code is partially duplicated in compiler/*/target.cmake
100-
execute_process(
101-
COMMAND ${CMAKE_C_COMPILER} ${TOOLCHAIN_C_FLAGS} --print-libgcc-file-name
102-
OUTPUT_VARIABLE LIBGCC_FILE_NAME
103-
OUTPUT_STRIP_TRAILING_WHITESPACE
104-
)
105-
106-
assert_exists(LIBGCC_FILE_NAME)
107-
108-
get_filename_component(LIBGCC_DIR ${LIBGCC_FILE_NAME} DIRECTORY)
109-
110-
assert_exists(LIBGCC_DIR)
111-
112-
set_linker_property(PROPERTY lib_include_dir "-L\"${LIBGCC_DIR}\"")
113-
11499
# For CMake to be able to test if a compiler flag is supported by the
115100
# toolchain we need to give CMake the necessary flags to compile and
116101
# link a dummy C file.

cmake/compiler/icx/target.cmake

-15
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,6 @@ else()
4545
list(APPEND TOOLCHAIN_C_FLAGS "-m32")
4646
endif()
4747

48-
49-
# This libgcc code is partially duplicated in compiler/*/target.cmake
50-
execute_process(
51-
COMMAND ${CMAKE_C_COMPILER} ${TOOLCHAIN_C_FLAGS} --print-libgcc-file-name
52-
OUTPUT_VARIABLE LIBGCC_FILE_NAME
53-
OUTPUT_STRIP_TRAILING_WHITESPACE
54-
)
55-
56-
get_filename_component(LIBGCC_DIR ${LIBGCC_FILE_NAME} DIRECTORY)
57-
58-
list(APPEND LIB_INCLUDE_DIR "-L\"${LIBGCC_DIR}\"")
59-
if(LIBGCC_DIR)
60-
list(APPEND TOOLCHAIN_LIBS gcc)
61-
endif()
62-
6348
set(CMAKE_REQUIRED_FLAGS -nostartfiles -nostdlib ${isystem_include_flags})
6449
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
6550

cmake/compiler/target_template.cmake

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# Copyright (c) 2025, Nordic Semiconductor ASA
4+
5+
# Template file for optional Zephyr compiler functions.
6+
#
7+
# This file will define optional compiler functions for toolchains that are not
8+
# defining these functions themselves.
9+
10+
if(NOT COMMAND compiler_file_path)
11+
12+
# Search for filename in default compiler library path using the
13+
# --print-file-name option which is common to gcc and clang. If the
14+
# file is not found, filepath_out will be set to an empty string.
15+
#
16+
# This won't work correctly when additional compiler flags that affect
17+
# the search path are specified using zephyr_compile_options rather than
18+
# via TOOLCHAIN_C_FLAGS or OPTIMIZATION_FLAG. We can't use those values
19+
# as they are embedded in a generator expresssion.
20+
#
21+
# Compilers needing a different implementation should provide this
22+
# function in their target.cmake file
23+
24+
function(compiler_file_path filename filepath_out)
25+
execute_process(
26+
COMMAND ${CMAKE_C_COMPILER} ${TOOLCHAIN_C_FLAGS} ${OPTIMIZATION_FLAG}
27+
--print-file-name ${filename}
28+
OUTPUT_VARIABLE filepath
29+
OUTPUT_STRIP_TRAILING_WHITESPACE
30+
)
31+
if(${filepath} STREQUAL ${filename})
32+
set(filepath "")
33+
endif()
34+
set(${filepath_out} "${filepath}" PARENT_SCOPE)
35+
endfunction()
36+
37+
endif()
38+
39+
if(NOT COMMAND compiler_set_linker_properties)
40+
41+
# Set the lib_include_dir and rt_library linker properties
42+
# by searching for the runtime library in the compiler default
43+
# library search path. If no runtime library is found, these
44+
# properties will remain unset
45+
#
46+
# Compilers needing a different implementation should provide this
47+
# function in their target.cmake file
48+
49+
function(compiler_set_linker_properties)
50+
51+
# Compute complete path to the runtime library using the
52+
# --print-libgcc-file-name compiler flag
53+
execute_process(
54+
COMMAND ${CMAKE_C_COMPILER} ${TOOLCHAIN_C_FLAGS} ${OPTIMIZATION_FLAG}
55+
--print-libgcc-file-name
56+
OUTPUT_VARIABLE library_path
57+
OUTPUT_STRIP_TRAILING_WHITESPACE
58+
)
59+
60+
# Compute the directory name and library basename (removing the .a suffix)
61+
62+
# Don't set the lib_include_dir as it is probably wrong; we don't have
63+
# many of the necessary compiler flags available at this point as they're
64+
# all hidden inside the INTERFACE_COMPILE_OPTIONS generator expression
65+
# which cannot be expanded at this time. Instead, trust that the
66+
# linker will search the correct directory using the linker flags.
67+
68+
#get_filename_component(library_dir ${library_path} DIRECTORY)
69+
#set_linker_property(PROPERTY lib_include_dir "-L${library_dir}")
70+
71+
get_filename_component(library_basename ${library_path} NAME_WLE)
72+
73+
# Remove the leading 'lib' prefix to leave a value suitable for use with
74+
# the linker -l flag
75+
string(REPLACE lib "" library_name ${library_basename})
76+
77+
set_linker_property(PROPERTY rt_library "-l${library_name}")
78+
endfunction()
79+
80+
endif()

cmake/compiler/xcc/target.cmake

-11
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,6 @@ foreach(file_name include/stddef.h include-fixed/limits.h)
4040
list(APPEND NOSTDINC ${_OUTPUT})
4141
endforeach()
4242

43-
# This libgcc code is partially duplicated in compiler/*/target.cmake
44-
execute_process(
45-
COMMAND ${CMAKE_C_COMPILER} ${TOOLCHAIN_C_FLAGS} --print-libgcc-file-name
46-
OUTPUT_VARIABLE LIBGCC_FILE_NAME
47-
OUTPUT_STRIP_TRAILING_WHITESPACE
48-
)
49-
50-
get_filename_component(LIBGCC_DIR ${LIBGCC_FILE_NAME} DIRECTORY)
51-
52-
list(APPEND LIB_INCLUDE_DIR "-L\"${LIBGCC_DIR}\"")
53-
5443
# For CMake to be able to test if a compiler flag is supported by the
5544
# toolchain we need to give CMake the necessary flags to compile and
5645
# link a dummy C file.

cmake/linker/ld/target.cmake

+4-2
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,12 @@ macro(toolchain_linker_finalize)
159159

160160
set(cpp_link "${common_link}")
161161
if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host")
162-
if(CONFIG_CPP_EXCEPTIONS AND LIBGCC_DIR)
162+
compiler_file_path(crtbegin.o CRTBEGIN_PATH)
163+
compiler_file_path(crtend.o CRTEND_PATH)
164+
if(CONFIG_CPP_EXCEPTIONS AND CRTBEGIN_PATH AND CRTEND_PATH)
163165
# When building with C++ Exceptions, it is important that crtbegin and crtend
164166
# are linked at specific locations.
165-
set(cpp_link "<LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o ${link_libraries} ${LIBGCC_DIR}/crtend.o")
167+
set(cpp_link "<LINK_FLAGS> ${CRTBEGIN_PATH} ${link_libraries} ${CRTEND_PATH}")
166168
endif()
167169
endif()
168170
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${cpp_link}")

cmake/linker/xt-ld/target.cmake

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ find_program(CMAKE_LINKER xt-ld ${LD_SEARCH_PATH})
1111

1212
set_ifndef(LINKERFLAGPREFIX -Wl)
1313

14-
if(CONFIG_CPP_EXCEPTIONS)
14+
compiler_file_path(crtbegin.o CRTBEGIN_PATH)
15+
compiler_file_path(crtend.o CRTEND_PATH)
16+
if(CONFIG_CPP_EXCEPTIONS AND CRTBEGIN_PATH AND CRTEND_PATH)
1517
# When building with C++ Exceptions, it is important that crtbegin and crtend
1618
# are linked at specific locations.
1719
# The location is so important that we cannot let this be controlled by normal
1820
# link libraries, instead we must control the link command specifically as
1921
# part of toolchain.
2022
set(CMAKE_CXX_LINK_EXECUTABLE
21-
"<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${LIBGCC_DIR}/crtend.o")
23+
"<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${CRTBEGIN_PATH} <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${CRTEND_PATH}")
2224
endif()
2325

2426
# Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen}

cmake/modules/FindTargetTools.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ include(${ZEPHYR_BASE}/cmake/bintools/bintools_template.cmake)
106106
include(${TOOLCHAIN_ROOT}/cmake/bintools/${BINTOOLS}/target.cmake OPTIONAL)
107107

108108
include(${TOOLCHAIN_ROOT}/cmake/linker/target_template.cmake)
109+
include(${TOOLCHAIN_ROOT}/cmake/compiler/target_template.cmake)
109110

110111
set(TargetTools_FOUND TRUE)
111112
set(TARGETTOOLS_FOUND TRUE)

0 commit comments

Comments
 (0)