Skip to content
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

Add -lc -lgcc from picolibc toolchain library after module libraries #51949

Merged
merged 2 commits into from
Apr 17, 2023

Conversation

keith-packard
Copy link
Collaborator

@keith-packard keith-packard commented Nov 3, 2022

Hacks like

# Make sure C library, in case of newlib, is linked after OpenThread libraries
# (to prevent linker errors)
if(CONFIG_NEWLIB_LIBC)
target_link_libraries(ot-config INTERFACE -lc)
endif()

shouldn't be required -- instead, the C library should be added to the end of the link command, rather than some place in the middle. Create a special set of link libraries which are to be added after the rest of the system and then use that for picolibc.

Copy link
Member

@stephanosio stephanosio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me, but @tejlmand might have a better idea on how to handle this more generically.

@keith-packard
Copy link
Collaborator Author

This looks reasonable to me, but @tejlmand might have a better idea on how to handle this more generically.

sounds good. I'm no cmake expert and welcome advice from others more skilled in this area.

Copy link
Collaborator

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for raising this.

This should clearly be cleaned up.

No immediate changes requested, but I just need a little time to carefully think this through.

Regarding the picolibc changes, those requires a toolchain with pre-built picolibc, but if I try to build with Zephyr SDK 0.15.1 and -DCONFIG_PICOLIBC_USE_MODULE=n then I get following error:

arm-zephyr-eabi-gcc: fatal error: cannot read spec file 'picolibc.specs': No such file or directory
compilation terminated.

@keith-packard which toolchain build are you using that is shipped with pre-built picolibc library to verify this code path ?

Comment on lines 113 to 117
function(zephyr_late_link_libraries)
set_property(TARGET zephyr_interface APPEND PROPERTY LATE_LINK_LIBRARIES ${ARGV})
endfunction()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bit unsure on this.

It's one of those functions which solves an immediate problem but once it's available people will start to use it in various places, thus it has a high built-in risk of being used wrongly if people randomly starts to use this function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this function is definitely easy to abuse. I wonder if zephyr_link_libraries should just check for system libraries (-lc -lgcc et al) and do something internally with them?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the option to handle -lc and -lgcc (if applicable) internally.

Alternatively, if the toolchain interface were to have some abstraction / function to just name it's late link libraries, then it would be slightly more adaptable.

@@ -13,7 +13,7 @@ if(NOT CONFIG_PICOLIBC_USE_MODULE)

zephyr_compile_options(--specs=picolibc.specs)
zephyr_compile_definitions(_POSIX_C_SOURCE=200809)
zephyr_link_libraries(-T/dev/null --specs=picolibc.specs c -lgcc)
zephyr_late_link_libraries(-T/dev/null --specs=picolibc.specs c -lgcc)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be one of those situation where link_libraries() is actually acceptable to use.
https://cmake.org/cmake/help/latest/command/link_libraries.html

as we actually want to ensure -lc and -lgcc are linked last.
But using link_libraries() at this location will not work, cause it needs to be on a higher level.

Moving this to higher level would require some changes to how library infrastructure is sourced in the build system.
Some libc impl also creates a library which must be linked, whereas this purely set flags.

@keith-packard
Copy link
Collaborator Author

@keith-packard which toolchain build are you using that is shipped with pre-built picolibc library to verify this code path ?

@stephanosio helped create https://github.com/zephyrproject-rtos/sdk-ng/tree/topic-picolibc which builds the toolchain using patches that enable picolibc. There are complete toolchains available from each successful run, like https://github.com/zephyrproject-rtos/sdk-ng/actions/runs/3331003572

@stephanosio
Copy link
Member

FYI, there is Zephyr SDK 0.16.0-beta1 with picolibc available now for testing.

@stephanosio
Copy link
Member

@tejlmand Do you have any updates on this?

@stephanosio
Copy link
Member

@tejlmand ping

@keith-packard
Copy link
Collaborator Author

Maybe use a different name for zephyr_late_link_libraries? Something that reflects the lower-level nature of the libraries in question? zephyr_system_link_libraries? zephyr_toolchain_link_libraries?

@keith-packard
Copy link
Collaborator Author

I've renamed the function to zephyr_libc_link_libraries to try and make it clear where this is intended to be used. Perhaps this is better? Alternate suggestions welcome.

This function allows subsystems to define libraries which get added to the
link command after all other libraries and modules. It's useful when using
a toolchain library, like libc or libgcc, as those can get added when
processing the 'lib' directory, before any module libraries and hence might
not get used to resolve symbols from modules.

Signed-off-by: Keith Packard <[email protected]>
When using the toolchain C library, that must be added to the link command
after all other libraries and modules in the system to resolve undefined
symbols.

Signed-off-by: Keith Packard <[email protected]>
Copy link
Collaborator

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, as this seems to be improvement over current solution, but as it doesn't solve the issue fully I will create a follow up enhancement issue.

Comment on lines +598 to +599
get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBRARIES)
zephyr_link_libraries(${LIBC_LINK_LIBRARIES})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in most cases this will work, but technically we are not guaranteed that there will not be added extra link libraries to the Zephyr interface library.

If the app adds extra libraries to explicitly be linked, then those might a appear later, or even some Zephyr libs could have extra libs.
However, as this still seems to ba an improvement, this comment is mostly in order for future references.

Will create followup enhancement issue.

@carlescufi carlescufi merged commit b5caccb into zephyrproject-rtos:main Apr 17, 2023
@tejlmand
Copy link
Collaborator

Approved, as this seems to be improvement over current solution, but as it doesn't solve the issue fully I will create a follow up enhancement issue.

Enhancement issue: #56924

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Build System area: C Library C Standard Library area: picolibc Picolibc C Standard Library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants