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

[Driver] Use llvm-ar by default on Unix and copy it over into the build directory #62800

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

finagolfin
Copy link
Member

@finagolfin finagolfin commented Jan 1, 2023

Now that llvm-ar is installed by default in the toolchain, #62510, and a recent SPM change requires there to be an archiver in the toolchain/PATH, swiftlang/swift-package-manager#5761, use that bundled llvm-ar for all Unix platforms, which requires copying it over into the build directory too before building the corelibs.

I noticed that we now install the LLVM and compiler tools to toolchain-linux-x86_64/ before the corelibs are built, but we don't use that yet to build the corelibs in build-script-impl, only for SPM and onwards. I considered switching over to using that installed toolchain to build the corelibs, but since that's a larger change that might fail elsewhere and because it would require simple builds to always --install-swift too, I chose this simpler route of copying over the freshly-built llvm-ar.

Alternately, we could install llvm-ar in the linux CI by making sure that Ubuntu package is always installed, but I figured this copying is easier for now.

Note that the system ar is still passed into CMAKE_AR, so the corelibs will keep using that for the non-Swift static libs on the linux CI, but at least this will allow changing the Swift compiler's default archiver name for Unix.

@finagolfin
Copy link
Member Author

@egorzhdan, would you run the CI on this?

@egorzhdan
Copy link
Contributor

@swift-ci please smoke test

@egorzhdan egorzhdan requested a review from compnerd January 3, 2023 16:11
Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

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

I'm still not convinced that this is really the right thing to do. ar is the system archiver. I think that we should continue to defer to that if/when possible. It is also possible that the ar installed on the system is new enough to support LTO via plugins. I think that defaulting AR to llvm-ar is reasonable if you are building on Termux as a host, but even when targeting android, I think that the system archiver should be preferred.

@finagolfin
Copy link
Member Author

finagolfin commented Jan 3, 2023

I'm still not convinced that this is really the right thing to do.

While this pull is not strictly required because of your SPM change, I think it's a good idea to remove that external dependency.

ar is the system archiver. I think that we should continue to defer to that if/when possible.

I mean, we already ship our own clang.

It is also possible that the ar installed on the system is new enough to support LTO via plugins.

I'm unsure what this refers to as I don't use LTO, but since llvm-ar is already the default for LTO, this pull changes nothing regarding LTO.

I think that defaulting AR to llvm-ar is reasonable if you are building on Termux as a host, but even when targeting android, I think that the system archiver should be preferred.

On the contrary, I think that if we can remove this external dependency on the system archiver for one we supply, we should. The long-standing escape hatch of supplying your own archiver with AR=/usr/bin/ar swift build still remains.

There is no "right" answer here: it's a question of priorities. @gottesmm, would you like to chime in?

@finagolfin
Copy link
Member Author

I can't make head nor tails of this Windows CI error: your LLVM directory on the Windows CI doesn't have llvm-ar?

CMake Error at utils/CMakeLists.txt:21 (file):
  file COPY cannot find "T:/llvm/bin/llvm-ar": File exists.

@compnerd
Copy link
Member

compnerd commented Jan 3, 2023

The correct spelling is llvm-ar.exe.

@finagolfin
Copy link
Member Author

The correct spelling is llvm-ar.exe

Thanks, I will just remove that copy for non-Unix platforms.

Since the linux CI passed, it appears this approach does work, unlike last time I tried but didn't copy over llvm-ar into the build directory too.

file(COPY ${LLVM_RUNTIME_OUTPUT_INTDIR}/bin/llvm-ar
DESTINATION "${SWIFT_RUNTIME_OUTPUT_INTDIR}"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
Copy link
Member

Choose a reason for hiding this comment

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

This really should be done outside of the CMake in the build-script python logic. The way that we handle this on Windows is by using the LLVM distribution functionality.

Copy link
Member Author

Choose a reason for hiding this comment

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

Any particular reason you think this should be in Python instead? I could see someone porting the toolchain to a new platform only by using CMake without build-script, as I did natively on Android initially, and this being in CMake would keep that working for new Unix platforms.

As for Windows, I simply disabled this copy on OS X and Windows in the latest version of this pull.

@finagolfin
Copy link
Member Author

Rebased and added a fix for the Windows CI.

@finagolfin
Copy link
Member Author

@compnerd, this should pass the Windows CI now.

@keith
Copy link
Member

keith commented Jan 4, 2023

@swift-ci please smoke test

@finagolfin
Copy link
Member Author

@finagolfin
Copy link
Member Author

@CodaFi, any input on this change of the default archiver name on Unix platforms?

@finagolfin
Copy link
Member Author

@troughton, you added this Driver option in #25202, any feedback on this consolidation?

@finagolfin
Copy link
Member Author

@0xTim, maybe you'd like to chime in since this affects building for linux on the server.

@0xTim
Copy link
Member

0xTim commented Feb 12, 2023

@buttaface What's the TL;DR for end users writing and compiling code? From my understanding of this is doesn't really affect anything?

@finagolfin
Copy link
Member Author

@0xTim, it shouldn't, as all it's doing is changing the default archiver used for static libraries on Unix platforms like linux from the ar that comes in the binutils system package to the llvm-ar that ships in our toolchain.

Ever since SPM made it mandatory that such a librarian archiver be installed before it builds anything last year (with 5.7, it's not mandatory and will simply fail when building static libraries if it doesn't find ar, but that changes with 5.8), I think it's best that it be one that ships in our toolchain, that's all.

@finagolfin
Copy link
Member Author

Ping @ktoso, what do you think about getting this change in?

@finagolfin
Copy link
Member Author

@edymtt, would you give your opinion on this archiver shift?

@edymtt
Copy link
Contributor

edymtt commented Jun 9, 2023

I am currently busy with other priorities, and as a result I don't plan to be able to look into this any time soon.

(And in case I'm able to return to this, I'm not sure if I would be able to do a proper review, since I don't have much experience with the Linux/Unix aspects of the build)

@finagolfin
Copy link
Member Author

Ping @tomerd, please let me know what you think.

@finagolfin
Copy link
Member Author

@al45tair, just need someone to decide on this: you have linux experience, wdyt?

@al45tair
Copy link
Contributor

Interestingly I'm actually deliberately using llvm-ar and llvm-ranlib in something I'm working on at the moment, because I'm cross-compiling and when you do that lots of things start looking for <triple>-ar and <triple>-ranlib (perfectly understandable as the object file format might be different), but in my specific case it's always ELF and I don't really want to install a GNU cross toolchain.

One thing I'm not entirely clear on here is what happens if the triple says to use a specific object format. It isn't obvious to me what llvm-ar does about e.g. COFF object files (whereas it's entirely apparent with the traditional GNU tools what will happen if your triple is powerpc-unknown-coff or similar, because things will explicitly use powerpc-unknown-coff-ar and so on instead).

There's also the somewhat orthogonal issue of the exact format of archive files. I'd assume that llvm-ar is going to default to whatever suits the system linker, which might not be the linker you're going to be using in a cross configuration. If you were also proposing to use lld as the linker in all cases, maybe that wouldn't be such an issue (in that we'd then have the same "what about the triple" question, but the answer is likely the same for all three as they're all part of LLVM).

@finagolfin
Copy link
Member Author

One thing I'm not entirely clear on here is what happens if the triple says to use a specific object format. It isn't obvious to me what llvm-ar does about e.g. COFF object files

I don't know the details, but my understanding is that the LLVM tools are fairly cross-platform. If llvm-ar doesn't work for some cross-compilation target, you can always supply your own with AR=/usr/bin/ar swift build.

Note that what this pull proposes is to change the default archiver that the Swift compiler uses for native compilation on Unix platforms: cross-compilation is a hairier situation that sometimes requires that AR override.

There's also the somewhat orthogonal issue of the exact format of archive files. I'd assume that llvm-ar is going to default to whatever suits the system linker, which might not be the linker you're going to be using in a cross configuration. If you were also proposing to use lld as the linker in all cases, maybe that wouldn't be such an issue

I'm unaware of differences in the archive format output produced by llvm-ar versus binutils ar for ELF. My understanding is that the format is simple and well-supported by both, correct me if I'm wrong.

@finagolfin
Copy link
Member Author

finagolfin commented Jan 9, 2024

@al45tair, what do you think about finally getting this in now? We have four months of solid experience with swiftlang/swift-package-manager#6829 switching the default for Unix on trunk and 5.10 to llvm-ar without any problems: I think we can take this last step and switch this archiver invoked by the compiler itself to llvm-ar.

@finagolfin
Copy link
Member Author

@bnbarham, would you run the CI and review?

@finagolfin
Copy link
Member Author

Ping @al45tair, wdyt?

@al45tair
Copy link
Contributor

@swift-ci Please smoke test

@al45tair
Copy link
Contributor

@finagolfin I'll need to discuss this with some other folks, but I'm broadly in favour of using llvm-ar and lld on non-Darwin platforms by default. Swift package manager having already made that change does help with that argument.

@finagolfin
Copy link
Member Author

@al45tair, any update? Would be good to get these two driver pulls in before the 6.0 branch.

@al45tair
Copy link
Contributor

Nothing yet, sorry. There are some things going on behind the scenes that have a bearing on decisions like this one — I don't know that we'll be able to get this in before the Swift 6 branch, and I still have some reservations (as does @compnerd, who I have spoken to briefly about this).

@finagolfin
Copy link
Member Author

@al45tair, anything new? I think we should get these two Driver pulls in before the branch, as SwiftPM switching most builds over to llvm-ar six months ago and that change now being released with 5.10 shows it works well, while switching this compiler default will align those remaining few compiler-only invocations with SwiftPM.

@finagolfin
Copy link
Member Author

@al45tair, any result from those discussions?

@finagolfin
Copy link
Member Author

@al45tair, this keeps getting delayed. We have evidence that SwiftPM works well with this llvm-ar archiver, with the 5.10 release switching its default Unix archiver over in March and no complaints: what is the holdup on switching over the compiler too?

I realize this is a small consistency issue and most Swift devs simply use SwiftPM and thus llvm-ar already, but I don't understand the trepidation for this last remaining change to get SwiftPM and the standalone Swift compiler consistent in their default archiver.

@al45tair
Copy link
Contributor

al45tair commented Jun 4, 2024

@al45tair, this keeps getting delayed. We have evidence that SwiftPM works well with this llvm-ar archiver, with the 5.10 release switching its default Unix archiver over in March and no complaints: what is the holdup on switching over the compiler too?

I realize this is a small consistency issue and most Swift devs simply use SwiftPM and thus llvm-ar already, but I don't understand the trepidation for this last remaining change to get SwiftPM and the standalone Swift compiler consistent in their default archiver.

Originally the hold-up was that we were setting up the Platform Steering Group but hadn't yet announced it, and this is definitely the kind of thing PSG is supposed to look into. Subsequently the hold-up is that I've been busy working on something other than this, and it's me that is supposed to be looking at whether it's really OK to use llvm-ar. It can't be "the default for UNIX" as a whole, because it is definitely not compatible with every UNIX archive file (it doesn't work with Darwin archives or the Darwin linker, for instance, in spite of what the documentation says — which I know because I tried it not long before I first saw this PR). It's likely fine for anything that is using lld as the linker, since both are part of the LLVM project and so pretty much have to work together, and my guess is that it's probably OK in a general sense on Linux, but I want to actually go and take the time to confirm that.

Note also that SwiftPM often doesn't bother making static archives anyway — unless it's a product in your Package.swift — and will instead just link object files in most cases, so it might not be quite as thoroughly battle tested as you'd think.

This is very much on my list of things to do, and towards the top of it at that. Next week, as I'm sure you're aware, is WWDC, which has been keeping me busy but I expect to have more time once that's over with.

@finagolfin
Copy link
Member Author

It can't be "the default for UNIX" as a whole, because it is definitely not compatible with every UNIX archive file (it doesn't work with Darwin archives or the Darwin linker, for instance, in spite of what the documentation says — which I know because I tried it not long before I first saw this PR).

By that, I and the Swift code refer to non-Darwin, non-Windows platforms, for which my SwiftPM pull made llvm-ar the default last year. This pull makes it the default archiver for a subset of even that.

my guess is that it's probably OK in a general sense on Linux, but I want to actually go and take the time to confirm that.

Great, I welcome further testing. 😄

Note also that SwiftPM often doesn't bother making static archives anyway — unless it's a product in your Package.swift — and will instead just link object files in most cases, so it might not be quite as thoroughly battle tested as you'd think.

I know it's an uncommon build product config, with a few packages simply commenting it out.

This is very much on my list of things to do, and towards the top of it at that.

OK, thanks for the update. I just didn't understand the repeated delays for this small pull, now I do.

@finagolfin
Copy link
Member Author

@al45tair, rebased this pull, would be good to get this in before the upcoming 6.1 branch.

@finagolfin
Copy link
Member Author

@swift-ci please smoke test

@finagolfin
Copy link
Member Author

@swift-ci please smoke test linux

1 similar comment
@finagolfin
Copy link
Member Author

@swift-ci please smoke test linux

@finagolfin
Copy link
Member Author

@al45tair, we're coming on the two-year anniversary of my submitting this pull, 🥲 would be good to finally get it merged in the coming months. I've rebased it and made sure it passes the CI.

…ld directory

Now that llvm-ar is installed by default in the toolchain, swiftlang#62510, and a recent
SPM change requires there to be an archiver in the toolchain/PATH,
swiftlang/swift-package-manager#5761, use that bundled llvm-ar for all Unix
platforms, which requires copying it over into the build directory too before
building the corelibs.
@finagolfin
Copy link
Member Author

@swift-ci test

@finagolfin
Copy link
Member Author

@swift-ci smoke test macos

@finagolfin
Copy link
Member Author

swiftlang/swift-driver#1822
@swift-ci build toolchain windows

@finagolfin finagolfin dismissed compnerd’s stale review March 16, 2025 17:47

Explained why it's in CMake for non-Darwin Unix platforms and no longer applies to Windows for more than a year

@finagolfin
Copy link
Member Author

@al45tair, rebased and passed all CI again, can we go ahead and get this and the equivalent swift-driver pull in now? The main SwiftPM switch to llvm-ar in swiftlang/swift-package-manager#6829 has been used for more than a year and a half with no reported problems, along with clang doing the same years prior. This simply gets the Swift compiler to match those two in standalone invocations, admittedly a minority usecase but keeps everything consistent.

@finagolfin
Copy link
Member Author

swiftlang/swift-tools-support-core#500
@swift-ci please build toolchain Amazon Linux 2

@finagolfin
Copy link
Member Author

swiftlang/swift-tools-support-core#500
@swift-ci please build toolchain Amazon Linux 2

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.

7 participants