-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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 LTO support in CMake build system. #17027
base: master
Are you sure you want to change the base?
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.
LGTM, I've added some non-required comments/asks inline.
However, LTO should be disabled by default.
CMakeLists.txt
Outdated
# Handling of LTO/IPO | ||
# | ||
|
||
option(DISABLE_LTO "Disable use of LTO when building. Defaults to being enabled if supported." FALSE) |
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.
As a general tip, I prefer using ENABLE_XXX
instead of DISABLE_XXX
, because this avoids double negation in the code, eg. NOT DISABLE_XXX
.
I was under the impression that we wanted it by default, at least for release builds, because we had determined that it was a significant performance improvement for our code (hence why we had it by default in the old build system). |
Correct. However, LTO is quite heavy on build times. We can either add this CMake option explicitly whenever we call cmake (ie. on release jobs), or add a check to see if the CMAKE_BUILD_TYPE is Debug. |
OK, so the goal then is to just allow for fast debug builds. That’s doable without much issue. |
Rebased to pick up the latest changes in the master branch. |
@vkalintiris I initially switched things to |
Rebased to resolve merge conflicts. |
Rebased to pick up fixes for CI in master. |
Rebased to resolve merge conflicts. |
8169c6a
to
f5199ff
Compare
Rebased to pick up latest changes in master branch. |
This comment was marked as resolved.
This comment was marked as resolved.
My own testing with with no external components vendored, I suspect that’s what’s different here. I’ll need to look deeper into this. I can 100% confirm though that enabling both LTO (with |
Based on further investigation and discussion with @ilyam8:
|
Internally, CMake calls LTO ‘Interprocedural Optimization’, and it provides functionality for checking for support for this as well as enabling it by default for targets. This leverages that support to auto-detect LTO and enable it if it’s supported.
Using `ENABLE_LTO` leads to a possibility for confusion among users, as it does behave in the most intuitive manner. Instead of ensuring that LTO is used (and thus behaving like every other `ENABLE_*` option we have), it allows the usage LTO if it’s supported. Thus a build with `-DENABLE_LTO=True` may not actually be built with LTO. By instead using `DISABLE_LTO`, the behavior matches up directly with how most people are likely to interpret the meaning, because a build with `-DDISABLE_LTO=True` will _never_ have LTO flags added to the compiler/linker flags.
On pretty much all RPM platforms, the RPM build process itself will correctly add the required compiler flags when building, so we don’t actually need to auto-detect LTO support in CMake here. Additionally, on at least some RPM platforms, CMake’s auto-detection for LTO support actually breaks the build when used.
On at least some systems, `-fdata-sections` combined with LTO reliably causes failures at link time with our code. The final binary size on systems where the combination _works_ differs by no more than a few KiB on average (tested on 64-bit x86 on Ubuntu 22.04, Debian 12, Fedora 39, and Rocky Linux 9), so we’re not actually getting almost any benefit out of using both with things as they are now, but LTO gives us a meaasurable performance improvement that per-function and per-data sections do not.
Rebased to resolve merge conflicts and pick up the latest changes in the master branch. |
Summary
Internally, CMake calls LTO ‘Interprocedural Optimization’, abbreviated as ‘IPO’, and it provides functionality for checking for support for this as well as enabling it by default for targets. This leverages that support to auto-detect LTO and enable it if it’s supported.
Also includes a new option (DISABLE_LTO) to explicitly disable LTO without checking for support for it.
Test Plan
Preliminary testing consists of just verifying that CI passes on this PR.
Further testing requires manually confirming the compiler flags used on a variety of platforms to ensure that LTO is enabled correctly.