-
Notifications
You must be signed in to change notification settings - Fork 7.3k
cmake: Pass OPTIMIZATION_FLAG to linker too #87657
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
base: main
Are you sure you want to change the base?
cmake: Pass OPTIMIZATION_FLAG to linker too #87657
Conversation
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 cleanup.
It would be nice to get rid of -L<libgcc_dir>
, but we should ensure there are no side-effects (can't remember in which cases this happend last time I looked at this).
A couple of code observations to be addressed in addition.
89450e4
to
ca2f7c8
Compare
I've reworked the second patch so that the computation of rt_library and lib_include_dir are delayed until the compiler flags are finished. I renamed With this, the values of lib_include_dir and rt_library are both uniformly computed using --print-libgcc-file-name. As lib_include_dir is already used in the linker, that will ensure that the -L flag continues to get passed along as before, but this time it will have a value computed using the whole set of compiler flags. This refactoring let me remove a bunch of nearly identical code in the compiler target.cmake files. |
6649017
to
09a5f46
Compare
Ok, I've discovered it's actually impossible for us to compute libgcc_dir correctly in this fashion because some of the critical compiler flags are only available in the INTERFACE_COMPILE_OPTIONS property which is a generator expression, and hence cannot be evaluated during the cmake run. Things like -m32/-m64, various -mfpu flags and many flags used on arc targets will all affect the multilib path value, but are unavailable when computing the libgcc path. I'm kinda amazed this ever worked anywhere. For libgcc/compiler-rt, it's pretty simple - we can figure out what the runtime library basename is and use just that, without attempting to include the directory name. That should work as we can probably assume that any compiler install will use the same library name for all multilib configs? For crtbegin.o/crtend.o, the linker won't search along the paths for them, so we really need to compute the whole path name. And that means capturing the output of the compiler front-end with the full compiler flags evaluated at build time? |
09a5f46
to
3305ccf
Compare
I did the best I could -- elided any flags which contained generator expressions and used the rest for all of the computations. That appears to at least get the flags needed for native_sim to work. A more complete solution would involve pushing the flag computation into the actual build run, and that seems 'problematic' as we'd have to pull the result back into the build process and insert it into the compile commands. Possible with make, but I'm unsure that could even work with ninja. |
3305ccf
to
463b68c
Compare
Btw, this is blocking an updated SDK which will use the optimization flag to select between versions of the C library, and that's part of the picolibc 1.8.10 uplevel process which will pull in RX target support, so we either need this in Zephyr or we need to decide that we're not doing any of this and to go back to the previous library selection mechanism kludge fest. |
463b68c
to
e5cf768
Compare
@keith-packard thanks for the effort, it's really appreciated 👍 I've been looking at the code, and in some ways we're getting a bit back to the older hassle of toolchain integration starting to depend on specific macros / functions to be available, which was addressed with the introduction of compiler properties. However, the Also I'm not too fond of the "guessing" of which compiler flags should be used when looking up the compiler dirs / which flags will impact library selection, this should be more controlled to avoid later genex surprises. Will get back on this soon. |
Thanks.
There's a circular dependency here -- we need to ask the compiler to emit a path which is then used later on as a linker command line parameter. I don't think we can do that with generator expressions, which the current property mechanism uses extensively. That was the big blocker I found in this work.
Agreed. Spamming the compiler with as many arguments as we can gather mostly works, but it sure doesn't seem like the right plan.
Can we set a deadline in the next few weeks with a plan to use this as temporary hack until you have time to fix it for real? I'm getting worried that we're going to run out of time to deliver the desired SDK features in time for the next Zephyr release. Meanwhile, I'm adding -fsanitize=undefined support for picolibc 1.8.10 while I wait for Zephyr to be ready for that release. So at least I'm not bored? |
@tejlmand lets discuss this in toolchain WG on 14/4, @keith-packard if you can join, it would help :) |
The compiler may want to know the desired optimization level during linking, as when the compiler multilib configuration includes -Os as a selector. Do this by adding a new (optional) linker function, toolchain_linker_add_compiler_options, which maps compiler options to equivalent linker options, discarding any that aren't applicable. Linker configurations which use the compiler driver (ld, lld, and xt-ld) apply all provided compiler options. Linkers which don't provide this function fall back to an implementation which simply discards all options. Signed-off-by: Keith Packard <[email protected]>
e5cf768
to
1a75649
Compare
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. These implementations require that no generator expressions are necessary for the compiler to compute the right library paths. This mechanism is also used to take any additional compiler options and pass them to the linker using toolchain_linker_add_compiler_options. Signed-off-by: Keith Packard <[email protected]>
1a75649
to
1bb65eb
Compare
Yes, I see the issue. Following this approach I think the linker should have a property describing flags which might impact path calc, but as the actual flag usage \is config dependent we need improved Kconfig -> mapping, which I guess will be on my shoulders 😃 . For now, I made a draft to show improved linker optimization flag #89073.
but also have the ability to reference the property fetching mechanism to another target, for example to re-use compiler properties, like this:
I think this can replace: 894587f and thereby at first avoid the request for implementing
See above reply.
#89073 is a first step, will take a look and the next and hopefully have something early next week. |
The compiler may want to know the desired optimization level during linking, as when the compiler multilib configuration includes -Os as a selector.