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

Swift SDKs: fix toolset.linker.path not passed to -ld-path #6719

Merged
merged 5 commits into from Sep 19, 2023

Conversation

kabiroberai
Copy link
Contributor

@kabiroberai kabiroberai commented Jul 18, 2023

This PR implements support for the linker.path field in the Swift SDK toolset spec.

Depends on apple/swift#68495 and apple/swift-driver#1441.

Motivation:

This field was previously parsed but not respected.

Modifications:

Add -ld-path=\(linker.path) to the toolchain's Swift flags if a linker path override is supplied

Result:

The linker path is now respected.

var swiftCompilerFlags = destination.toolset.knownTools[.swiftCompiler]?.extraCLIOptions ?? []

if let linker = destination.toolset.knownTools[.linker]?.path {
swiftCompilerFlags += ["-use-ld=\(linker.pathString)"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

cc @compnerd could this interfere with the use-ld check that's used to infer the librarian on Windows? Specifically, this uses an absolute path rather than just the name — so maybe determineLibrarian should just look at the last path component?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Does -use-ld= support absolute paths? If so, yes, this would need to have an associated change to the testing for the librarian check for Windows. Additionally, I think that you should be using linker._nativePathString(escaped: false) here ... to ensure that we actually test with the proper path on windows, e.g. -use-ld=C:\Program Files\Swift\Toolchain\0.0.0+Asserts\usr\bin\lld-link.exe. Note the space in the path and the use of \.

Copy link
Member

Choose a reason for hiding this comment

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

If #6730 is merged _nativePathString(escaped: false) will be applied automatically in that string interpolation.

Copy link
Member

Choose a reason for hiding this comment

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

Does -use-ld= support absolute paths?

It does on macOS. As we assume we're always passing this to Clang, wouldn't Clang on Windows maintain this support for consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm it looks like passing a path to -fuse-ld is supported but not recommended: https://github.com/apple/llvm-project/blob/1604b03867ff8c0ece77a61d16e3f609e3cfcb3c/clang/lib/Driver/ToolChain.cpp#L820

The correct flag expected by the clang driver seems to be --ld-path. Will switch to that instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This raises another question though: should we attempt to derive the linker flavor based on linker.path? Or should we just pass --ld-path and allow SDK vendors to specify the flavor via extraCLIArguments if they wish?

@MaxDesiatov
Copy link
Member

@swift-ci smoke test

@kabiroberai kabiroberai changed the title Swift SDKs: Implement toolset.linker.path Swift SDKs: implement toolset.linker.path Jul 18, 2023
@MaxDesiatov MaxDesiatov requested a review from rauhul July 18, 2023 16:49
@MaxDesiatov
Copy link
Member

@swift-ci smoke test

@MaxDesiatov
Copy link
Member

@swift-ci test windows

@MaxDesiatov MaxDesiatov self-assigned this Jul 18, 2023
@MaxDesiatov MaxDesiatov changed the title Swift SDKs: implement toolset.linker.path Swift SDKs: fix toolset.linker.path not passed to -use-ld Jul 18, 2023
@MaxDesiatov
Copy link
Member

MaxDesiatov commented Jul 18, 2023

I need to test these changes with some Swift SDKs I have generated locally, and then assuming that goes well it can be merged.

Copy link
Member

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

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

Just ran end-to-end tests on my side with this change, working well. Good stuff, thanks for cleaning it up!

Copy link
Collaborator

@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.

Please account for the absolute path in the librarian checks in Windows.

@kabiroberai
Copy link
Contributor Author

@compnerd what would the appropriate API for extracting the last path component from an absolute-or-relative path be? I'm assuming we don't want to use Foundation.URL here

@MaxDesiatov
Copy link
Member

MaxDesiatov commented Jul 19, 2023

what would the appropriate API for extracting the last path component from an absolute-or-relative path be? I'm assuming we don't want to use Foundation.URL here

Note that a deserialized Toolset already uses absolute paths, so there's no need to account for relative ones. AbsolutePath.basename seems like a good fit. If that's not the case on Windows that feels like a bug to me that we should fix in a separate PR.

Although I then have another question, how exactly would you use this last path component? If Clang on Windows supports absolute paths (with spaces and all, quoted if needed), then wouldn't we prefer to always use absolute paths here and not deal with relative ones at all?

@kabiroberai
Copy link
Contributor Author

kabiroberai commented Jul 19, 2023

Note that a deserialized Toolset already uses absolute paths, so there's no need to account for relative ones.

my bad, I think my comment was a bit vague: we should be fine on L334 because we already have an AbsolutePath (I'll switch to _nativePathString there). My concern is L171, where there's a (somewhat unrelated) check for -use-ld= on Windows. Since we're now adding -use-ld with an absolute path to the compiler flags, that check no longer works consistently because it assumes the value is the linker name rather than the path. In fact the L171 check would've always had this issue (assuming clang on Windows accepts file paths for -fuse-ld) but it's just more likely to manifest now. So to fix this we need to parse the -use-ld= argument as a path and get the last component, I'm just not sure how to parse the path since it can either be absolute (C:\path\to\ld) or relative (ld).

@MaxDesiatov
Copy link
Member

It doesn't look like deriveSwiftCFlags calls determineLibrarian in its codepaths, so L171 check seems unrelated. Please make sure that's the case, and if so we just need to verify that -use-ld= works with absolute paths on Windows and that its argument is correctly quoted so that spaces in paths don't break anything.

@kabiroberai
Copy link
Contributor Author

It doesn't look like deriveSwiftCFlags calls determineLibrarian in its codepaths

The concern is the other way around: determineLibrarian takes extraSwiftFlags which are based on the output of deriveSwiftCFlags. So if deriveSwiftCFlags returned ["-use-ld=C:\path\to\lld"] then determineLibrarian wouldn't work as expected because the linker == "lld" check would fail. Something like (linker as NSString).lastPathComponent == "lld" would fix it but I don't know if that's portable.

@MaxDesiatov
Copy link
Member

MaxDesiatov commented Jul 19, 2023

The concern is the other way around: determineLibrarian takes extraSwiftFlags which are based on the output of deriveSwiftCFlags. So if deriveSwiftCFlags returned ["-use-ld=C:\path\to\lld"] then determineLibrarian wouldn't work as expected because the linker == "lld" check would fail. Something like (linker as NSString).lastPathComponent == "lld" would fix it but I don't know if that's portable.

It's likely to be "-use-ld=C:\path\to\lld.exe" having .exe extension in the real world.

@compnerd would using AbsoluteString.basenameWithoutExt be acceptable workaround or do we need a different approach here to make sure this code is cross-platform?

@kabiroberai
Copy link
Contributor Author

Switching to --ld-path should have resolved the issues with the Windows -use-ld check — I think this PR is in a good state now

MaxDesiatov pushed a commit to apple/swift-driver that referenced this pull request Sep 5, 2023
This PR introduces an `--ld-path` option, which is forwarded to the Clang linker-driver option with the same name. This change is required to support the `toolset.linker.path` option in [SE-0387](https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md). 

## See also

Upstream: apple/swift#67956.
Downstream: apple/swift-package-manager#6719.
MaxDesiatov added a commit to apple/swift that referenced this pull request Sep 5, 2023
This PR defines an `--ld-path` option for the Swift Driver, which is forwarded to the Clang linker-driver option with the same name. This change is required to support the `toolset.linker.path` option in [SE-0387](https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md).

## See Also

Downstream: apple/swift-driver#1416, apple/swift-package-manager#6719.
@MaxDesiatov
Copy link
Member

@swift-ci smoke test

@MaxDesiatov
Copy link
Member

@swift-ci test windows

Copy link
Member

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

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

Thanks, sorry about the delay. This LGTM!

@MaxDesiatov MaxDesiatov enabled auto-merge (squash) September 5, 2023 17:48
@MaxDesiatov
Copy link
Member

@swift-ci test windows

@kabiroberai
Copy link
Contributor Author

@compnerd mind taking a look at this again please? I think I've addressed the changes that you requested — it should be possible to merge this PR once you approve.

var swiftCompilerFlags = swiftSDK.toolset.knownTools[.swiftCompiler]?.extraCLIOptions ?? []

if let linker = swiftSDK.toolset.knownTools[.linker]?.path {
swiftCompilerFlags += ["--ld-path=\(linker)"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not use -use-ld=\(linker) here? I'd really rather not introduce new spellings for existing functionality.

Copy link
Member

Choose a reason for hiding this comment

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

@kabiroberai I had a chat about this offline and we landed on -ld-path, I've submitted follow up PRs for that:

apple/swift#68495
apple/swift-driver#1441

There's a still a question what happens when both options are passed as -use-ld=silly-linker -ld-path=/usr/bin/funny-linker. We also need a test to verify that, whatever behavior is when both of those options are passed, it doesn't regress.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for handling the upstream side of things! I believe -use-ld and -ld-path are (mostly) orthogonal but I see how that could regress; that test would be best suited to swift-driver right?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, tests for this are more appropriate in Swift Driver I believe. cc @artemcm

auto-merge was automatically disabled September 14, 2023 11:53

Head branch was pushed to by a user without write access

@MaxDesiatov
Copy link
Member

@swift-ci test

@MaxDesiatov
Copy link
Member

@swift-ci test windows

@MaxDesiatov MaxDesiatov changed the title Swift SDKs: fix toolset.linker.path not passed to --ld-path Swift SDKs: fix toolset.linker.path not passed to -ld-path Sep 19, 2023
@MaxDesiatov MaxDesiatov enabled auto-merge (squash) September 19, 2023 21:00
Copy link
Collaborator

@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 think that we should really follow up on this to determine the best way forward for the flags. It is unclear how -ld-path= and -use-ld= compose and feels like this is something we should be paying attention to. We should aim to avoid the mistakes of the gcc driver.

@MaxDesiatov MaxDesiatov merged commit d328002 into apple:main Sep 19, 2023
5 checks passed
@neonichu
Copy link
Member

Looks like this broke existing Swift SDKs:

ld.lld: error: unable to find library -ld-path=/Users/neonacho/Library/org.swift.swiftpm/swift-sdks/5.8-RELEASE_rhel_ubi9_aarch64.artifactbundle/5.8-RELEASE_rhel_ubi9_aarch64/aarch64-unknown-linux-gnu/swift.xctoolchain/usr/bin/ld.lld

@tomerd suggested to revert, I'll open a PR for that.

neonichu added a commit that referenced this pull request Sep 20, 2023
#6719)"

This reverts commit d328002.

This broke existing Swift SDKs:

```
ld.lld: error: unable to find library -ld-path=/Users/neonacho/Library/org.swift.swiftpm/swift-sdks/5.8-RELEASE_rhel_ubi9_aarch64.artifactbundle/5.8-RELEASE_rhel_ubi9_aarch64/aarch64-unknown-linux-gnu/swift.xctoolchain/usr/bin/ld.lld
```
neonichu added a commit that referenced this pull request Sep 21, 2023
#6719)" (#6939)

This reverts commit d328002.

This broke existing Swift SDKs:

```
ld.lld: error: unable to find library -ld-path=/Users/neonacho/Library/org.swift.swiftpm/swift-sdks/5.8-RELEASE_rhel_ubi9_aarch64.artifactbundle/5.8-RELEASE_rhel_ubi9_aarch64/aarch64-unknown-linux-gnu/swift.xctoolchain/usr/bin/ld.lld
```
kabiroberai added a commit to kabiroberai/swift-package-manager that referenced this pull request Sep 21, 2023
MaxDesiatov pushed a commit that referenced this pull request Sep 28, 2023
This PR implements support for the `linker.path` field in the Swift SDK toolset spec.

Depends on apple/swift#68495 and apple/swift-driver#1441.

### Motivation:

This field was previously parsed but not respected.

### Modifications:

Add `-ld-path=\(linker.path)` to the toolchain's Swift flags if a linker path override is supplied

### Result:

The linker path is now respected.
MaxDesiatov pushed a commit that referenced this pull request Sep 28, 2023
#6719)" (#6939)

This reverts commit d328002.

This broke existing Swift SDKs:

```
ld.lld: error: unable to find library -ld-path=/Users/neonacho/Library/org.swift.swiftpm/swift-sdks/5.8-RELEASE_rhel_ubi9_aarch64.artifactbundle/5.8-RELEASE_rhel_ubi9_aarch64/aarch64-unknown-linux-gnu/swift.xctoolchain/usr/bin/ld.lld
```
MaxDesiatov pushed a commit that referenced this pull request Sep 28, 2023
This PR implements support for the `linker.path` field in the Swift SDK toolset spec.

Depends on apple/swift#68495 and apple/swift-driver#1441.

### Motivation:

This field was previously parsed but not respected.

### Modifications:

Add `-ld-path=\(linker.path)` to the toolchain's Swift flags if a linker path override is supplied

### Result:

The linker path is now respected.
MaxDesiatov pushed a commit that referenced this pull request Sep 28, 2023
#6719)" (#6939)

This reverts commit d328002.

This broke existing Swift SDKs:

```
ld.lld: error: unable to find library -ld-path=/Users/neonacho/Library/org.swift.swiftpm/swift-sdks/5.8-RELEASE_rhel_ubi9_aarch64.artifactbundle/5.8-RELEASE_rhel_ubi9_aarch64/aarch64-unknown-linux-gnu/swift.xctoolchain/usr/bin/ld.lld
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants