-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Make CONFIG_USERSPACE=y and CONFIG_CMAKE_LINKER_GENERATOR=y work together #85241
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
Make CONFIG_USERSPACE=y and CONFIG_CMAKE_LINKER_GENERATOR=y work together #85241
Conversation
d248306 to
368d77e
Compare
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.
License and copyright.
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 copyright is somewhat unclear, since most of this is either refactorings (direct copy from othe rfiles) or, heavily based on the corresponding .ld files (which in turn does not have that info)
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.
Do not resolve the conversation if a resolution is still pending. It's actually up the commenter to resolve the comments as per the guidelines.
368d77e to
088b51b
Compare
pdgendt
left a comment
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.
License headers need to be accompanied with a copyright notice, I think.
I was afraid of that... The thing is that the files I am adding are either based on ld-skeletons or directly copy-pasted from linker.cmake, and there are missing copyright tags on many of these sources. So it is "hard" to add a fair copyright notice. There are also many files (e.g. among include/linker/common/*.ld) that have license tag but not copyright. |
dcb3723 to
c8ee809
Compare
c8ee809 to
fd14acd
Compare
tejlmand
left a comment
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 for this, a lot of great work.
First round of review comments ready, though I haven't been through everything in details so I might notice more things later.
I also want to carry out some testing on this.
So far mostly minor observations, where the only main concern found is the use of get_property() which means code becomes CMake configure time process order dependent and thereby prevents application code to customize / extend the linker script generated.
cmake/modules/extensions.cmake
Outdated
| # You can have mulitple PASS <name> (in which the section will | ||
| # be active in all of the phases) or you can have multiple | ||
| # PASS NOT <name> in which case the section will be active in | ||
| # passes other than any of the <name>. |
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.
because I've read the implementation later, then this becomes unclear.
If just reading this description, then multiple PASS <name> could mean this is allowed:
PASS foo PASS bar PASS baz, similar with PASS NOT <name>, however this is not the implementation, which seems to allow multipl <name> or NOT <name>, like this foo bar baz or NOT foo NOT bar NOT baz.
I think we should just allow the forms:
PASS <name> ..., examplePASS foo bar baz.PASS NOT <name> ..., examplePASS NOT foo bar baz.
as there seems to be no reason for the redundant NOT.
That will also simplify the implementation check as you only need to check for NOT at the first index in the list.
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.
Absolutely! I changed to follow your proposal.
As I used it I repeated the PASS NOT foo like so:
zephyr_linker_section(...
PASS NOT foo
PASS NOT bar)
cmake/modules/extensions.cmake
Outdated
| # Internal helper that checks if we have consistent PASS arguments. | ||
| # If the first element is NOT, check that all even elements are NOT, otherwise | ||
| # check that no element is NOT | ||
| macro(zephyr_linker_check_pass_param function_name SECTION_PASS) |
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.
function_name is unused, but I guess this whole check can be removed / simplified if following the proposal in the function description.
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 left the function and removed the parameter. Maybe it is too ambitious to do these checks ?
cmake/linker/xt-ld/target.cmake
Outdated
| # This should probably do something like: | ||
| # set(cmake_linker_script_settings ${PROJECT_BINARY_DIR}/include/generated/ld_script_settings_${linker_pass_define}.cmake) | ||
| # zephyr_linker_generate_linker_settings_file(FILE ${cmake_linker_script_settings}) | ||
| # And pass the file to the generator | ||
|
|
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 think a github enhancement issue proposing to switch to zephyr_linker_generate_linker_settings_file() would be better.
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.
Ill do that instead
cmake/modules/extensions.cmake
Outdated
| endfunction() | ||
|
|
||
| # Usage: | ||
| # zephyr_linker_generate_linker_settings_file([FILE <name>] [STRING <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.
I guess you had one intention when initially creating this function and then later made adjustments to support more use-cases, and during that process didn't take a second look at the function name.
Saving file in the function name is perhaps not optimal when it's possible to get the function to return content in a variable.
Similar with generate, as the string output is actually not generating anything.
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.
Yep, I removed the string thing.
cmake/modules/extensions.cmake
Outdated
| # Usage: | ||
| # zephyr_linker_generate_linker_settings_file([FILE <name>] [STRING <string>]) | ||
| # | ||
| # Add the content generated so far by the zephyr_linker_* functions to a file |
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.
generated so far is not correct.
When using file(GENERATE ...) then content is not written until CMake generator time, which again means that settings AFTER zephyr_linker_generate_linker_settings_file() is also taken into consideration.
For example
zephyr_linker_generate_linker_settings_file(FILE foo.txt)
zephyr_linker_symbol(SYMBOL __foo EXPR "(@__bar@)")
will actually handle the late zephyr_linker_symbol() call also and thus allowing applications to adjust or create symbols and sections as they like.
This is the reason generator expression are used.
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.
Well spotted! And fixed.
| # can't warn here because we can't check for what is relevant in this pass | ||
| # message(WARNING "Missing definition for ${match}") | ||
| endif() | ||
| message("Replacing ${match} with ${value}") |
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 could imagine this would result in a lot of general message output which the user has no idea what is about or what to use with it.
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.
True! I guarded this on CMAKE_VERBOSE_MAKEFILE
e574dae to
d86f703
Compare
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.
Take a look at the comment here: #85241 (comment)
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 will, i will. Take it easy ;)
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 will, i will. Take it easy ;)
I wasn't trying to push you, just wanted to put a direct pointer to the related comment for this file, because sometimes when number of review comments grow large then new comments to older discussions are overlooked, so trying to be helpful 🙂
| elseif(${INC_FILE} MATCHES "^.*\.cmake$") | ||
| include(${INC_FILE}) | ||
| elseif(${INC_FILE} MATCHES "^.*\.h$") | ||
| list(APPEND PREPROCESSOR_FILES ${INC_FILE}) |
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.
this is hiding what filetypes is actually supported, perhaps it's better to be explicit here:
zephyr/cmake/modules/extensions.cmake
Lines 5314 to 5317 in d86f703
| # KCONFIG : Include Kconfig via import_kconfig | |
| # | |
| function(zephyr_linker_include_generated) | |
| set(options "KCONFIG") |
So that the developers wanting to use zephyr_linker_include_generated() can actually see directly that Kconfig, c-headers, and cmake files are supported.
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 (by replacing the FILE tag with KCONFIG, HEADER or CMAKE)
CMakeLists.txt
Outdated
| # The linker generator also needs sections.h to be able to access e.g. _APP_SMEM_SECTION_NAME | ||
| # for linkerscripts that do not support c-preprocessing. | ||
| zephyr_linker_include_generated(FILE ${ZEPHYR_BASE}/include/zephyr/linker/sections.h) |
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.
not to be changed in this PR.
I consider that perhaps it's better to have developers being able to describe the content of sections.h in CMake or a template file which CMake can use, and from there generate header files, CMake files, and whatever else is needed by the build system.
CMake is better at generating header files than reading them 😉
Thoughts ?
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 agree 100%. It would be a lot cleaner if the sections names and such coul be deifned together with the other linker stuff in cmake, rather than the other way around.
|
Going from the current state of this PR there is a "big" question left, how to handle MPU_ALIGN(region_size). I deferred that to an RFC: #86563, hoping for some more attention from interested parties. Edit: there is an implementation in bjorniuppsala/iar-zephyr-fixes@953b7bb |
3260fd4 to
8f6de57
Compare
tejlmand
left a comment
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 for the update. Looks good and close to +1 .
Some minor observations, mainly related to the zephyr_linker_check_pass_param().
A function which we may even be able to replace with a very simple list() commadn and if() check.
Feel free to reply to observations.
cmake/modules/extensions.cmake
Outdated
| list(FIND SECTION_PASS "NOT" NOT_AT) | ||
| if(NOT("${NOT_AT}" STREQUAL "-1")) |
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.
can be simplified:
| list(FIND SECTION_PASS "NOT" NOT_AT) | |
| if(NOT("${NOT_AT}" STREQUAL "-1")) | |
| if("NOT" IN_LIST SECTION_PASS) |
cmake/modules/extensions.cmake
Outdated
| if(NOT SECTION_PASS) | ||
| message(FATAL_ERROR "At least one pass name required") |
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.
Usually in CMake it's acceptable to not provide a value when specifying an argument.
For example, like this:
zephyr_linker_include_generated(... PASS)
Reason for that is that it allows to simply do something like this:
zephyr_linker_include_generated(... PASS ${SOME_VAR})
without having to worry about whether SOME_VAR is defined or not.
With the proposed check, then you force callers into doing:
if(DEFINED SOME_VAR)
zephyr_linker_include_generated(... PASS ${SOME_VAR})
else()
zephyr_linker_include_generated(...)
endif()
So unless there are specific reasons why values must be given, then I propose to skip this check.
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 agree with the cmake-tradition/ease of use argument, but I think allowing an empty list of PASSes (due to undefined/empty arguments) might be inviting surprising results.
Logically this should mean that the section (or whatever) would not be included in any pass, which goes against the whole meaning of having the call. Making it mean the section is in all passes (as if it had no PASS parameter) is even more surprising.
E.g. for userspace there parts that are only enabled in a single pass. If those thing were to be included in all passes due to a case like you describe here the build will likely end up with duplicate definitions, silently wasted space, "or worse" :)
The risk of silently wasting space is key I think.
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.
Those are fair points, and if checking for values to PASS argument is a conscious choice, then I approve the decision.
But please make this restriction clear in the description of the function.
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.
In the end I think we'll stick with your proposal. PASS means not active anywhere. This should be "safe" from a waste perspective...
cmake/modules/extensions.cmake
Outdated
| endfunction() | ||
|
|
||
| # Usage: | ||
| # zephyr_linker_generate_linker_settings_file([FILE <name>]) |
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.
You are not checking for GEN_FILE before calling file(GENERATE ...) below, which I guess means FILE argument is now mandatory.
| # zephyr_linker_generate_linker_settings_file([FILE <name>]) | |
| # zephyr_linker_generate_linker_settings_file(FILE <name>) |
tejlmand
left a comment
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.
LGTM, no blocking comments.
But please take a look at this comment: #85241 (comment)
Make it possible to have multiple PASS parameters to zephyr_linker_section() and zephyr_linker_section_configure() sections (oring them) OR to have multiple PASS NOT p options (in which case the sections applies in neither of the passes) Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
Add MIN_SIZE and MAX_SIZE options to zephyr_linker_section() and zephyr_linker_section_configure(). This allows padding (for MIN_SIZE) and link-time checking (for MAX_SIZE) of sections (and parts of sections). Clarify comments for zephyr_linker_section_configure Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
Implement the MIN_SIZE and MAX_SIZE options for the ld linker file generator Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
Move creation of the generator arguments file from each target.cmake into a function (zephyr_linker_generate_linker_settings_file). Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
Add methods for the linker-script generator to pick up information from previus linkerpasses: * zephyr_linker_include_generated(FILE f.cmake [PASS X] [KCONFIG]) cmake-includes f.cmake in the relevant PASSes. This allows scripts to generate any content (e.g. sections or section configs) as if it was generated by the main cmake machiery. This is intended to cover the case of ld-script snippets generated by e.g. gen_app_partitions.py It can also parse KCconfig files to capture @CONFIG_FOO@ variables * @foo[,undef:v]@ in an value or expression in the zephyr_linker_* inputs. This looks for a defintion of FOO (se below), and uses its value if found. If FOO is not defined, the whole @@ thing is left untouched, unless ,undef: is used, in which case v is used instead. * zephyr_linker_include_generated(FILE f.h [PASS x]) greps for f.h for #define FOO value to be accessed as @foo@ * zephyr_linker_include_var(VAR FOO VALUE V) allows the main cmake-script to set a @foo@ variable. Note that the #define support is VERY basic, and does not use a proper pre-processor. It works for the current use of files generated by e.g. gen_kobject_placeholders.py but is not a general solution. Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
Tweak gen_app_partitions.py to be able to generate cmake linker generator output as well as ld-script fragments. Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
All in all this makes cmake linker generator able to work for at least
most of the kernel tests and samples, on cortex m4.
Make the cmake linker generator have a file-structure more similar to
the ld-skeletons.
Add or edit groups, sections and logic to make the generator reflect
what the ld-skeletons do, esp. for kobjects and APP_SMEM, nonint and
some other details are also effected.
Use the new zephyr_linker_include_generated() and
zephyr_linker_include_var() functions to to handle
${DEVICE_API_LINKER_SECTIONS_CMAKE}, the kobject-prebuilt-*.h files and
APP_SMEM partition. Essentially the output from gen_app_partitions.py,
gen_kobject_placeholders.py.
Add ALIGN_WITH_INPUT on sections being put into DATA_REGION. This makes
the init layout work for ld.
This leverages the updates in gen_app_partitions.py to generate its
output as cmake linker generator sections too, and puts them into a
group defined in linker.cmake
Setup generator variables for alignment of APP_SMEM. Note that this does
not yet handle MPU_ALIGN which depends on the size of the section...
Fix broken k_object_assignment iterable section
Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
It seems as if ld_script.cmake hasnt handled zephyr_linker_section_configure( ALIGN ...) due to a typo in a variable name, Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
For CONFIG_USERSPACE the input from gen_app_partitions.py there is a need to be able to specify input files as well as input sections patterns for zephyr_linker_section_configure(). This is used for app partitions from libraries (which generate input patterns like foo.a:*(.data*)). This adds documentation to zephyr_linker_section_configure() to clarify what INPUT allows, and also adds some parsing tricks to ld_script.cmake to properly add the file patterns when they are missing. Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
8f6de57 to
cbe9308
Compare
|
I would appreciate input or approvals. |
RobinKastberg
left a comment
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.
LGTM
|
With CONFIG_CMAKE_LINKER_GENERATOR=y test/kernel/threads/tls is still broken due to missing alignment of _t{data,bss}_size. Given that we lack MPU_ALIGN anyways, I'll work on a followup as a separate PR. |
This makes the CMake linker generator work with CONFIG_USERSPACE=y
It uses the features added in #84635 to make e.g. controlling which passes include what easier (the same changes are incorporated in this PR too).
I have added ways to funnel inputs from e.g. gen_kobject_placeholders.py and gen_app_partitions.py into the linker generator, in the ld-skeletons this is handled by using the the c preprocessor. I have tried to create general and reusable ways of gathering information from the intermediate linking passes easy and natural. Look at the "Functions for input from prev linker pass" commit for details.
I have split cmake/linker_script/arm/linker.cmake into multiple files to reflect how the ld-skeletons are structured.
There are few zephyr_linker_*() calls that have been changed and added to mirror what the ld-skeletons are doing for userspace. Despite this there are a fair number of differences and missing sections for linker generator, that are not related to userspace that remains to be fixed until it is a complete replacement for the skeletons.
This is currently only tested on gcc for cortex_m4, although I think the changes to make other cortex cores and toolchains working should not be too hard. The aim is to provide IAR toolchain support for CONFIG_USERSPACE, once the actual iar toolchain support is in.
Edit:
Note that the changes I propose here does not quite create a fully working solution. There are a number of further changes needed.
Most prominent may be proper handling of MPU_ALIGN(region_size) for sections defined by the cmake linker generator (see #86563), as is you have to use large enough values for e.g. CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE or CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE to get proper alignment).
In the end this effort aims to provide CONFIG_USERSPACE support for the IAR toolchain