-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Zephyr toolchain / linking improvements #78320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zephyr toolchain / linking improvements #78320
Conversation
west.yml
Outdated
@@ -315,7 +315,8 @@ manifest: | |||
- debug | |||
- name: picolibc | |||
path: modules/lib/picolibc | |||
revision: 764ef4e401a8f4c6a86ab723533841f072885a5b | |||
revision: b9fae840f916881cd0e36b6d9883300a3da7a52a | |||
# revision: pull/<no>/head |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
6cda54c
to
bc7c49a
Compare
The following west manifest projects have been modified in this Pull Request:
Note: This message is automatically posted and updated by the Manifest GitHub Action. |
@evgeniy-paltsev / @abrodkin can you please verify the changes with arc mwdt ? |
bc7c49a
to
cfe7a16
Compare
It doesn't look like this solves the problem of placing libc/minimal and libc/common inside the whole-archive set of libs (as in #65434)? Should we try to make that work in this series or do you think that can be done after this lands? |
Sure, I've started the verification so, I'll update about the results when they are ready. Thanks for the mentioning! |
I has the same problem with the tricore llvm toolchain. Will test this pr. |
cfe7a16
to
2eba348
Compare
@keith-packard thanks for directing my attention to that PR. But I think that the strategy used in this PR will be beneficial for #65434, so let me take a look and see if I can cover #65434 or as minimum facilitate the work you have done in #65434 |
@keith-packard @stephanosio could you take another look? |
Looks ok to me. zephyrproject-rtos/zephyr-lang-rust#9 needs to be merged before this can be merged. |
The Zephyr PR zephyrproject-rtos/zephyr#78320 clean up and improves link handling in Zephyr. One improvement is the deterministic and correct link location of runtime and C library linking at the end of link arguments to ensure all libraries are able to use standard functions. However the librustapp.a library created by the cargo tool also contains runtime functions. It would in most cases be considered correct that a library, such as librustapp.a, which provides functions are linked first so that those functions provided as part of rust toolchain takes precedence over the runtime library provided by the C / C++ toolchain. However on the riscv32 / riscv64 architecture the rust prebuilt libraries makes use of relocation types in the clzsi2 object which are unknown to the ld linker in use. Thus linking librustapp.a first, for example like `librustapp.a -lgcc` results in the following warning (and thus CI failures): > <path>/ld.bfd: <path>/librustapp.a(45c91108d938afe8-clzdi2.o): > unsupported relocation type 0x3d Therefore we ensure that the runtime library is linked first, for example `-lgcc librustapp.a`. Signed-off-by: Torsten Rasmussen <[email protected]>
Merged @tejlmand |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The picolibc changes look reasonable to me.
Update zephyr-lang-rust module to include commit for linking the runtime library before the librustapp.a. Signed-off-by: Torsten Rasmussen <[email protected]>
2e7d667
to
3b8e621
Compare
# This is needed because when linking with newlib on aarch64, then libgcc has a | ||
# link dependency to libc (strchr), but libc also has dependencies to libgcc. | ||
# Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv | ||
set_property(TARGET linker APPEND PROPERTY link_order_library "math;c;rt;c") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be reasonable to use --start-group -lc -lgcc --end-group
instead of listing libc twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I think that it's good to make it visible that there are indeed circular dependencies, and that we can see the number of loops.
--start/end-group
are useful when you really start to have complex circular dependencies, but it easily turn into cargo-cult which no one dares to cleanup, and in future easily ends in a bunch of libs inside those flags.
As side-note, from the ld manual:
--start-group archives --end-group
...
Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.
set_linker_property(NO_CREATE TARGET linker PROPERTY c_library "-lc") | ||
# Default per standard, will be populated by clang/target.cmake based on clang output. | ||
set_linker_property(NO_CREATE TARGET linker PROPERTY rt_library "") | ||
set_linker_property(TARGET linker PROPERTY c++_library "-lc++;-lc++abi") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this mention math_library
somehow? Either noting that it's not needed or setting to the empty string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
II don't think so.
The lib names are not fixed in that sense, a linker implementation can define extra libraries to always link in, as described here:
zephyr/cmake/linker/linker_libraries_template.cmake
Lines 9 to 10 in 3b8e621
# It is also possible to define extra libraries of the form `<name>_library`, and then include | |
# Fixed library search path can be defined in the `lib_include_dir` property if needed. |
I will be working on a docset to describe the whole toolchain infrastructure and how to implement support for a custom one.
And there the math lib could be a good candidate to show.
@@ -139,3 +139,7 @@ set_compiler_property(PROPERTY warning_shadow_variables) | |||
# Compiler flags to avoid recognizing built-in functions | |||
set_compiler_property(PROPERTY no_builtin) | |||
set_compiler_property(PROPERTY no_builtin_malloc) | |||
|
|||
# Compiler flag for defining specs. Used only by gcc, other compilers may keep |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we eventually plan on supporting clang's --config
using this same mechanism?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of that, and some clang/LLVM releases, like LLVM for Arm, does provide dedicated configs for this, but i'm unsure how well established / standardized this principle is, so for a start it's kept a bit independent in cmake/compiler/clang/target.cmake
.
and also because it's needed for the existing compile check functionality.
endif() | ||
|
||
if(CONFIG_PICOLIBC) | ||
file(GLOB_RECURSE picolibc_cfg ${LLVM_TOOLCHAIN_PATH}/picolibc.cfg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe share the --specs mechanism somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see other answer related to this. But good to have in mind for further improvements 👍
@tejlmand This change is breaking building with cadence xtensa toolchains:
|
Follow-up: zephyrproject-rtos#78320 Create linker_libraries.cmake for the Cadence Xtensa xt-ld linker to ensure correct linking of runtime and C libraries as well as correct link order. Signed-off-by: Torsten Rasmussen <[email protected]>
Follow-up: #78320 Create linker_libraries.cmake for the Cadence Xtensa xt-ld linker to ensure correct linking of runtime and C libraries as well as correct link order. Signed-off-by: Torsten Rasmussen <[email protected]>
-L${PROJECT_BINARY_DIR} | ||
${TOOLCHAIN_LIBS} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now -lhal
is missing when using xt-xcc
and compilation fails with undefined xthal_window_spill
(xthal_window_spill
is provided by the xt-xcc
toolchain in libhal.a
)
If I restore this specific line then xt-xcc
compilation succeeds again.
I wonder why was this ${TOOLCHAIN_LIBS}
line removed from SOME target.cmake
files by commit 2e3873a but as of today's commit 27456ed it is still present in the following files? This seems inconsistent.
cmake/compiler/icx/target.cmake
cmake/linker/arcmwdt/target.cmake
cmake/linker/xt-ld/target.cmake
Indeed, if I remove ${TOOLCHAIN_LIBS}
from cmake/linker/xt-ld/target.cmake
then xt-clang
fails with the same error.
cc: @kv2019i , @andyross, @cujomalainey, @dcpleung
FYI:
cmake/compiler/xcc/target.cmake:list(APPEND TOOLCHAIN_LIBS
cmake/compiler/xcc/target.cmake- gcc
cmake/compiler/xcc/target.cmake- hal
cmake/compiler/xcc/target.cmake- )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an oversight.
I initially wanted to still allow for the old use of TOOLCHAIN_LIBS
for toolchains I didn't have available, but later changes related to picolibc has actually resulted in the situation that all toolchains must be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @tejlmand !
actually resulted in the situation that all toolchains must be updated.
While @dcpleung is removing the obsolete TOOLCHAIN_LIBS for Xtensa in #79731, as of today I see it still present in the main branch for cmake/compiler/icx/target.cmake
and cmake/linker/arcmwdt/target.cmake
. I think it would be good to file a bug and use git blame
to warn the owners of these files that TOOLCHAIN_LIBS does not work anymore in case they still try and fail to use it downstream somehow. Something I did not mention before: it took me HOURS to debug this Xtensa compilation failure and find that it was down to this TOOLCHAIN_LIBS variable. Funny enough, git grep hal
does not work very well! It would be nice to avoid others' a similar... effort.
In case these toolchains have no owner left, then it is a great opportunity to notice that and delete them entirely.
There is also a mysterious TOOLCHAIN_LIBS_OBJECTS
in cmake/linker/armlink/target.cmake
... My 2 cents.
This is a series of linking improvements in Zephyr.
First part is moving linking of C and runtime libraries out away from
zephyr_link_libraries()
.Using
zephyr_link_libraries()
is vulnerable to link dependency and link ordering, which has been discussed multiple times in the past.It has also resulted in CMake construct like this:
zephyr_link_libraries(-lc)
/zephyr_link_libraries(-lgcc)
and thus making it harder to support non-gcc toolchains / libraries. This again has resulted in constructs likeif(${ZEPHYR_TOOLCHAIN_VARIANT}) ...)
. All of this should be handled by Zephyr's toolchain infrastructure and normal CMake library creation should not need to know anything about C or runtime libraries, nor the toolchain in use.By moving C / runtime library linking into the toolchain infrastructure and specify C / runtime libraries using CMake linker rules instead of
zephyr_link_libraries()
then we avoid CMake reordering the libraries, and CMake deduplication, and we ensure they are always linked at correct location.To still allow Zephyr CMake code full flexibility and the use of Kconfig to select the libraries to use, then standard library selection has been moved to CMake linker properties, which provides a given set of defaults depending on the toolchain in use.
But the default can later be adjusted, based on other criteria.
This set of improvements allows for better LLVM support, especially when using LLVM with picolibc built-in support, but also when building picolibc as a module.
With this PR it is now possible to use LLVM for Arm for cross-compilation using both built-in Picolibc support as well as picolibc as module. LLVM for Arm with newlib is also supported.
LLVM for Arm:
https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/
In environment, set:
To build Zephyr Hello world for an Arm target, such as nrf52840dk, using build-in picolibc support and lld with compiler rt, use:
Using picolibc as module:
Using newlib as pre-built (remember to also install
LLVM-ET-Arm-newlib-overlay-18.1.3.tar.xz
):As part of the LLVM improvement, then support for LLVM with C++ has also been improved, which means it's now possible to build the simply C++ hello world:
although some warnings are currently seen.