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

Add prepare for index experimental build argument #7574

Merged
merged 12 commits into from
Jun 2, 2024

Conversation

dschaefer2
Copy link
Contributor

This will be used by sourcekit-lsp to build the swiftmodule files it needs for indexing.

Adds experimental-prepare-for-indexing flag to swift build. Creates a llbuild manifest specific for the prepare build that skips generating object files and linking of those files and calls swiftc to only create the swiftmodule as quickly as it can.

Motivation:

To support background indexing in sourcekit-lsp, it will request a prepare for index build to build the swiftmodule files it needs to do indexing. This build should be minimal to ensure indexing is fast so it can respond to language server requests that require the index as soon as possible.

Modifications:

  • Add an experimental-prepare-for-indexing flag to the BuildOptions and pass it around to every that needs it.
  • Build a custom llbuild manifest so that only the commands necessary are added to the prepare build
  • Add a target property that also ensures tool builds required for the prepare build are performed as usual.
  • In SwiftTargetBuildDescription, pass compile options that put the swift compiler in prepare "mode".
  • Ensure object files and binaries are not generated when in prepare mode.

Result:

Implements prepare build mode without affecting regular build mode.

@dschaefer2
Copy link
Contributor Author

@swift-ci please test

1 similar comment
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

@bnbarham bnbarham requested a review from xedin May 17, 2024 21:24
"-Xfrontend", "-experimental-skip-all-function-bodies",
"-Xfrontend", "-experimental-allow-module-with-compiler-errors",
"-Xfrontend", "-empty-abi-descriptor"
]
Copy link
Contributor

Choose a reason for hiding this comment

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

We could also try out -experimental-lazy-typecheck and -experimental-skip-non-exportable-decls (sorry, meant to send these to you earlier). They're newer than the others, but should hopefully skip a reasonable amount of typechecking.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do. Currently just trying to get all the xplatform tests passing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wow, those two chopped my previous prepare time in half for sourcekit-lsp which happened in 30 seconds versus 95 for the debug build.

I had to enable-library-evolution for those to work, but that should be fine?

Copy link
Contributor

@bnbarham bnbarham May 22, 2024

Choose a reason for hiding this comment

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

Hmmm, enabling library evolution would result in different diagnostics (eg. need to add @unknown case for switching over non-frozen enums). @tshortli is library evolution a hard requirement for these?

Wow, those two chopped my previous prepare time in half for sourcekit-lsp which happened in 30 seconds versus 95 for the debug build.

Just to be clear, 95s is the full debug build and a prepare used to be 60s without these and is now 30s?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to be clear, 95s is the full debug build and a prepare used to be 60s without these and is now 30s?

Correct. For sourcekit-lsp. I've been bouncing around. I need to do a more complete benchmark on a few different projects to get a better picture.

Copy link
Contributor

@bnbarham bnbarham May 22, 2024

Choose a reason for hiding this comment

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

Although that restriction is about making sure the emitted module is suitable for use during compilation of downstream dependents

Yeah, sounds like we could probably gate the library evolution requirement check on -experimental-skip-all-function-bodies since we don't produce a swiftmodule that would be usable for compilation in that case anyway.

Choose a reason for hiding this comment

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

I've lifted the restriction so that -enable-library-evolution is no longer required when indexing:
apple/swift#73905
apple/swift#73905

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice, thanks @tshortli!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am still getting

<unknown>:0: warning: ignoring -experimental-skip-non-exportable-decls (requires -enable-library-evolution)
<unknown>:0: warning: ignoring -experimental-lazy-typecheck (requires -enable-library-evolution)

in the latest 6.0 toolchain from May 26. Not sure this change got in after that build?

Copy link
Contributor

Choose a reason for hiding this comment

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

Would have been just after:
apple/swift#73906

Copy link
Contributor

@bnbarham bnbarham left a comment

Choose a reason for hiding this comment

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

Exciting!

Tests/BuildTests/PrepareForIndexTests.swift Outdated Show resolved Hide resolved
Tests/BuildTests/PrepareForIndexTests.swift Outdated Show resolved Hide resolved
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

1 similar comment
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

@dschaefer2
Copy link
Contributor Author

LOL, oh yeah, because the test is actually failing. The object files are getting created on Linux. Need to find out why.

@MaxDesiatov MaxDesiatov changed the title Adds prepare for index experimental build argument. Add prepare for index experimental build argument May 19, 2024
@dschaefer2
Copy link
Contributor Author

@swift-ci Please test

// Don't include the object nodes on prepare builds
cmdOutputs = [moduleNode]
} else {
cmdOutputs = objectNodes + [moduleNode]
Copy link
Member

Choose a reason for hiding this comment

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

Have you considered adjusting objects to produce [] if the target is in "preparation" mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I've been slowing moving these checks closer to the source of the values. I'll do one more pass with the help of your comments to clean that up. Thanks!

@@ -446,8 +455,15 @@ extension LLBuildManifestBuilder {
case .swift(let target)?:
inputs.append(file: target.moduleOutputPath)
case .clang(let target)?:
for object in try target.objects {
inputs.append(file: object)
if prepareForIndexing {
Copy link
Member

Choose a reason for hiding this comment

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

Could you elaborate on why this is necessary? This is handling a clang target, supposedly preparation doesn't apply here at all and these object files are produced by other clang targets?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the normal case this adds a dependency on the object files from the clang modules to force a rebuild when they change. In preparation, there are no object files generated so this was a haphazard attempt to propagate the dependencies to their sources. This should actually be the headers. Let me give this one a bit more thought.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After giving this more thought, I need to keep the clang commands around so I can map the swiftmodule dependencies on C source files so that the modules get re-prepared when the C files change. I'll just replace them with phony commands so they don't actually get built.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After looking at the clang commands, I realized that the header dependencies are coming from the generated .d files. Since I'm not running the compiler they won't be there. So my original idea of adding the dependencies on the headers instead of the object files seems to be working.

Sources/Build/BuildManifest/LLBuildManifestBuilder.swift Outdated Show resolved Hide resolved
Sources/CoreCommands/Options.swift Show resolved Hide resolved
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

@bnbarham
Copy link
Contributor

@swift-ci please test macOS platform

@bnbarham
Copy link
Contributor

@swift-ci please test Windows platform

@apple apple deleted a comment from domciiiiix May 27, 2024
This will be used by sourcekit-lsp to build the swiftmodule
files it needs for indexing.

Adds experimental-prepare-for-indexing flag to swift build.
Creates a llbuild manifest specific for the prepare build that
skips generating object files and linking of those files and
calls swiftc to only create the swiftmodule as quickly as it can.
This was causing the builds to fail on other machines.
Simplify the tests to not assume names of the output and just
check extensions.
At least until I can get a Linux dev env that actually works so
I can run these locally.
Turns this off too when in prepare mode. Appears to be the default
mode on Linux.
Moves the prepareForIndexing checks to more common points
simplifing the checks. Also adds two more compile flags which
makes the preparation much faster.
Makes it clearer there are no object files involved with the
swift build for preparation.
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

@dschaefer2
Copy link
Contributor Author

@swift-ci please test Windows platform

We're already testing for swiftmodules and object files in the
other asserts.
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

@dschaefer2
Copy link
Contributor Author

@swift-ci please test Windows platform

@@ -582,6 +582,17 @@ public final class SwiftTargetBuildDescription {
args += ["-emit-module-interface-path", self.parseableModuleInterfaceOutputPath.pathString]
}

if self.defaultBuildParameters.prepareForIndexing {
args += [
"-Xfrontend", "-enable-library-evolution",
Copy link
Member

Choose a reason for hiding this comment

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

Is -enable-library-evolution needed here now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was waiting for an update toolchain. There's one there now. Should be ready to remove.

Copy link
Member

Choose a reason for hiding this comment

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

Would you mind updating the diff accordingly before merging?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do. That will be the last piece. Once I can make sure it works 😀

Copy link
Contributor

Choose a reason for hiding this comment

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

If this is the only thing blocking the PR from being merged, I’d prefer to get the PR merged with -enable-library-evolution still set because it could unblock me to test preparation in sourcekit-lsp. I know that I’ll get spurious warnings because of library evolution but I can ignore those for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. As mentioned above, I'm not even sure if the change that was made even fixes it. I have one more fix Ben B mentioned about hiding the flag and then I'll kick off the tests.

@dschaefer2
Copy link
Contributor Author

@ahoppen really wants me to checkout multi target prepare. I will look at that next.

@bnbarham
Copy link
Contributor

@ahoppen really wants me to checkout multi target prepare. I will look at that next.

We can merge this without that. That's also something we should all discuss a bit, since it would be weird to have that for only preparation.

@dschaefer2
Copy link
Contributor Author

@ahoppen really wants me to checkout multi target prepare. I will look at that next.

We can merge this without that. That's also something we should all discuss a bit, since it would be weird to have that for only preparation.

Agreed. I'm not even sure I can make it work cleanly with the current architecture. I'd rather not rush it.

ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 31, 2024
…o the prepare command

The main purpose for now is that this makes it easier for me to live on background indexing combined with apple/swift-package-manager#7574.
@@ -437,6 +437,9 @@ public struct BuildOptions: ParsableArguments {
@Flag(help: "Enable or disable indexing-while-building feature")
public var indexStoreMode: StoreMode = .autoIndexStore

@Flag(name: .customLong("experimental-prepare-for-indexing"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be a good idea to have this hidden (noticed in apple/sourcekit-lsp#1373)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. This option isn't really useful to humans :).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 31, 2024
…o the prepare command

The main purpose for now is that this makes it easier for me to live on background indexing combined with apple/swift-package-manager#7574.
@dschaefer2
Copy link
Contributor Author

@swift-ci please test

@dschaefer2
Copy link
Contributor Author

@swift-ci please test Windows platform

@dschaefer2 dschaefer2 merged commit 7bd34cc into apple:main Jun 2, 2024
5 checks passed
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.

None yet

6 participants