Skip to content

[project/cmake] add auto linker selection based on availability #4013

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

Merged
merged 4 commits into from
Apr 8, 2025

Conversation

xmkg
Copy link
Member

@xmkg xmkg commented Mar 27, 2025

mold and lld are usually several magnitudes faster compared to the default linker of the toolchains. This PR adds the configure_linker CMake function to automatically configure which linker to use based on availability of the "mold" and "lld" in the environment. The function is no-op below CMake 3.29 since the current implementation depends on a rather recent CMake variable, CMAKE_LINKER_TYPE.

The user can disable the auto linker selection by explicitly specifying the CMAKE_LINKER_TYPE at configure step, i.e.,:

cmake -DCMAKE_LINKER_TYPE=DEFAULT -S . -B build

The configure_linker is intended to be only run in non-CI environments. The is_running_in_ci determines whether the project is being built in a CI environment.

MULTI-1912

@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch 3 times, most recently from 9c0a18a to eac1517 Compare March 27, 2025 22:47
@xmkg
Copy link
Member Author

xmkg commented Mar 28, 2025

A crude test to demonstrate the link speed difference.

Test steps:

  • Build the project from scratch to a clean build folder
  • Remove only the build/bin/multipass_tests (one of the usual suspects that has looong linking time)
  • Trigger build again, nearly all of the time will be spent on linking since all object files are ready

-- Results --

Baseline: Default linker (GNU ld)
12.42 seconds

> cmake -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_LINKER_TYPE=DEFAULT -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -S . -B build
> cmake --build build/ --parallel 32
> rm build/bin/multipass_tests 
> time cmake --build build/ --parallel 32 --target multipass_tests
[0/2] Re-checking globbed directories...
[1/1] Linking CXX executable bin/multipass_tests

[0/2] Re-checking globbed directories...
[1/1] Linking CXX executable bin/multipass_tests

real    0m12,426s
user    0m8,445s
sys     0m3,980s

Contender 1: mold
1.1 seconds (11.29x faster than the baseline, 1.22x faster than lld)

> cmake -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_LINKER_TYPE=MOLD -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -S . -B build
> cmake --build build/ --parallel 32
> rm build/bin/multipass_tests 
> time cmake --build build/ --parallel 32 --target multipass_tests
[0/2] Re-checking globbed directories...
[1/1] Linking CXX executable bin/multipass_tests

real    0m1,105s
user    0m0,100s
sys     0m0,028s

Contender 2: lld
1.35 seconds (9.2x faster than the baseline)

> cmake -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_LINKER_TYPE=LLD -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -S . -B build
> cmake --build build/ --parallel 32
> rm build/bin/multipass_tests 
> time cmake --build build/ --parallel 32 --target multipass_tests
[0/2] Re-checking globbed directories...
[1/1] Linking CXX executable bin/multipass_tests

real    0m1,351s
user    0m4,301s
sys     0m2,776s

Conclusion:
Without a doubt, "mold" and "lld" blow the "ld" out of the water.

@ricab
Copy link
Collaborator

ricab commented Mar 28, 2025

Not a review, but this is a great idea! It should speed up iterating a lot without affecting our confidence on what we ship. 👍

@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch from cd58db3 to ea312ca Compare March 28, 2025 22:05
Copy link

codecov bot commented Mar 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.34%. Comparing base (7cb6b2b) to head (afab3c7).
Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4013   +/-   ##
=======================================
  Coverage   89.34%   89.34%           
=======================================
  Files         260      260           
  Lines       14738    14738           
=======================================
  Hits        13167    13167           
  Misses       1571     1571           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@andrei-toterman
Copy link
Contributor

andrei-toterman commented Apr 4, 2025

Hmm, I see that Linux CI runs log Running in CI environment? FALSE. Perhaps the env var you're looking for is not seen inside the snapcraft LXD container?

@xmkg
Copy link
Member Author

xmkg commented Apr 7, 2025

Hmm, I see that Linux CI runs log Running in CI environment? FALSE. Perhaps the env var you're looking for is not seen inside the snapcraft LXD container?

Yes, that's the case. I opted to set the CMAKE_LINKER_TYPE in snapcraft.yaml instead of forwarding the environment variables. This kinda eliminates the point of having the check, but the code needs to ensure that the same type of linker is used for all CI jobs. What do you think? Should we forward the environment variable instead? That's a reasonable approach, too.

@andrei-toterman
Copy link
Contributor

It's not a big deal, but I think it is a bit confusing that the CI logs report that the build was not running in CI. So if it isn't too difficult to fix, I'd like that. IMO, if forwarding the env var to snapcraft would not introduce any other issue, I think that approach would be more consistent.

@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch from ea312ca to 6a334df Compare April 7, 2025 10:50
@xmkg
Copy link
Member Author

xmkg commented Apr 7, 2025

I think that approach would be more consistent.

Yeah, at least we can ditch the CI patchfile changes. Updated the branch, let's see if it works.

@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch 6 times, most recently from 0b72efa to 2737db8 Compare April 7, 2025 13:08
`mold` and `lld` are usually several magnitudes faster compared to
the default linker of the toolchains. This PR adds the configure_linker
CMake function to automatically configure which linker to use based on
availability of the "mold" and "lld" in the environment. The function
is no-op below CMake 3.29 since the current implementation depends on
a rather recent CMake variable, CMAKE_LINKER_TYPE.

The user can disable the auto linker selection by explicitly specifying
the CMAKE_LINKER_TYPE at configure step, i.e.,:

cmake -DCMAKE_LINKER_TYPE=DEFAULT -S . -B build

The `configure_linker` is intended to be only run in non-CI environments.
The `is_running_in_ci` determines whether the project is being built
in a CI environment.

Signed-off-by: Mustafa Kemal Gilor <[email protected]>
@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch from 847de09 to 2e345f7 Compare April 7, 2025 13:22
@xmkg
Copy link
Member Author

xmkg commented Apr 7, 2025

It's not a big deal, but I think it is a bit confusing that the CI logs report that the build was not running in CI. So if it isn't too difficult to fix, I'd like that. IMO, if forwarding the env var to snapcraft would not introduce any other issue, I think that approach would be more consistent.

Done, the CI is now injecting the GITHUB_ACTIONS environment variable to build-environment. Also noticed that some of the previously injected variables are not using correct "is-set" tests, fixed them too.

By default, the host's environment variables are not being forwarded
to the snap build environment. Since the detection of CI environment
relies on presence of GITHUB_ACTIONS environment variable, forward
it.

Signed-off-by: Mustafa Kemal Gilor <[email protected]>
@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch from 2e345f7 to b2df790 Compare April 7, 2025 13:29
@ricab
Copy link
Collaborator

ricab commented Apr 7, 2025

Not an actual review, but I just want to add a couple of remarks

  • First, this is a great idea, thanks a lot!
  • Second, should we add a very brief line to our build instructions?

@xmkg
Copy link
Member Author

xmkg commented Apr 8, 2025

  • Second, should we add a very brief line to our build instructions?

Done!

xmkg added 2 commits April 8, 2025 10:25
some of the variables are not expanded by mistake, which results
in tests always being true regardless of the variable contents.

Signed-off-by: Mustafa Kemal Gilor <[email protected]>
@xmkg xmkg force-pushed the enhancement/use-mold-or-lld-linker-in-dev-env branch from 244efb6 to afab3c7 Compare April 8, 2025 07:26
Copy link
Contributor

@andrei-toterman andrei-toterman left a comment

Choose a reason for hiding this comment

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

Great, thanks!

@xmkg
Copy link
Member Author

xmkg commented Apr 8, 2025

@levkropp It's ready for a secondary review, lemme know if it looks good to you :)

Copy link
Contributor

@levkropp levkropp left a comment

Choose a reason for hiding this comment

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

Great work on this @xmkg ! I have tested building and I am seeing the speedup :)

[0/2] Re-checking globbed directories...
[1/2] Linking CXX executable bin/multipass_tests

real    0m1.019s
user    0m0.048s
sys     0m0.028s

@xmkg xmkg added this pull request to the merge queue Apr 8, 2025
Merged via the queue into main with commit 261158c Apr 8, 2025
15 checks passed
@xmkg xmkg deleted the enhancement/use-mold-or-lld-linker-in-dev-env branch April 8, 2025 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants