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

Incremental swift compilation #21

Closed
keith opened this issue Apr 17, 2017 · 10 comments
Closed

Incremental swift compilation #21

keith opened this issue Apr 17, 2017 · 10 comments
Labels
P3 Would be nice, but probably next quarter at the earliest

Comments

@keith
Copy link
Member

keith commented Apr 17, 2017

Through some cursory tests to integrate bazel into our all swift project, we noticed that bazel doesn't currently support incremental swift compilation.

We've taken a stab at adding this by adding the -incremental and -emit-dependencies compiler flags and adding the dependency information to the output_file_map.json.

If I then run the commands that are being ran by bazel manually, I get incremental compilation, but running from bazel, it does not work incrementally. It seems as though bazel is removing the previously generated files after each change.

Is there a reason the initial Swift support didn't support incremental compilation? Also are there any plans to add this? I would be happy to submit a PR for the changes we've made if you can point me in the right direction on the problems we've ran in to.

Thanks!

(This was copied over from bazelbuild/bazel#2781)

@dmishe
Copy link
Contributor

dmishe commented Apr 17, 2017

Bazel in general does not support this. Each build gets a clean sandbox, so keeping previous object files is not possible. Changing the way bazel works is a much harder problem, sadly.

That said, we currently use WMO on debug builds to speed up compilation. You can put "-wmo" into copts of a swift_library target to do that.

@keith
Copy link
Member Author

keith commented Apr 17, 2017

Since our project is entirely written in Swift, even wmo builds take minutes, where incremental builds take < 10 seconds normally. Because of that I think it would never be feasible for us to use a tool that didn't support Swift incremental compilation.

I'm surprised to hear that bazel has no support for this for any language? But I guess since this isn't really feasible to change we can close this. Thanks for the context!

@keith keith closed this as completed Apr 17, 2017
@jgavris
Copy link

jgavris commented Apr 17, 2017

+1 Here in case the discussion continues...I understand Swift's compilation model presents unique challenges :) Same with @keith, we have a fairly large Swift application, and for development, incremental builds are the only way we could be productive. We plan on adopting bazel for all the other dependencies, and relying on Xcode for Swift.

@allevato
Copy link
Member

I'm going to reöpen this issue because I think it highlights an important area where we (that is, Bazel) could do better, even if we don't have any immediate clean solutions yet. I'll give it an appropriately low priority.

FWIW, sandboxing can be disabled for individual actions (set nosandbox to True in the execution requirements), but Bazel's hermeticity requirements would imply that you should be able to pass those .o files from previous builds as inputs to subsequent builds, and you have no guarantee that those files will exist at any time (e.g., bazel clean).

@dmishe likely has more info or possible workarounds.

@allevato allevato reopened this Apr 17, 2017
@allevato allevato added the P3 Would be nice, but probably next quarter at the earliest label Apr 17, 2017
@dmishe
Copy link
Contributor

dmishe commented Apr 17, 2017

Right, one way to achieve this is to make swift_library output intermediary files into a location outside of bazel tree, say, /tmp. This way bazel will only cleanup the final products, but swiftc will see previously built objects and use that. You will also need to add a global dependency map output (see https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps) to make this work.

The other, more sophisticated but also not hermetic, approach is to use a relatively new Bazel feature called persistent workers. This is in fact something we wanted to use in the long run. Let's keep this issue open to track this.

@jerrymarino
Copy link
Contributor

First off, kudos to getting swift compiling under bazel 👍 I'm using swift for some small projects - my builds are running exclusively through Xcode, where swiftc's incremental compilation seems to work. I'm wondering if bazel can provide any speedup's over Xcode.

I had a minute to look at the swift rules this morning, based on my ( weak ) understanding of bazel, I think it may work nicely with swifts compilation model. Have you considered:

  • breaking up the swift compilations into individual targets, where each compilation outputs a partial swift model.
  • creating a target that depends on all of the partial targets, and simply links all of the partial modules together.

I think a design similar to this could leverage bazel's hermaticness, caching, and incremental build abilities. This is just speculation: I haven't had a chance to implement this yet.

Tangentially related, I was looking at some of the work the Swift team has done for Swift PM. They have been implementing a quite nice build system, lower level build system, which should also do incremental builds. I wonder how llb overlaps with bazel.

@kastiglione
Copy link
Contributor

Is there a misunderstanding here? According to the user manual, incremental builds are a "primary goal" of Bazel: https://docs.bazel.build/versions/master/user-manual.html#correctness

I made a small cc_library with two files, and when I changed one of the files, only that one file was recompiled (according to --subcommands). This is what I would expect, but this issue is saying Bazel doesn't support this. 🤔

@sergiocampama
Copy link
Contributor

I believe dmishe was referring more about bazel's model being different enough to Swift's model to make incremental builds for Swift incompatible.

@keith
Copy link
Member Author

keith commented Aug 7, 2018

Are there any related issues elsewhere about supporting the Swift-style incremental compilation model? It sounds like kotlin and rust might also benefit from support for this in bazel, although I'm not 100% sure they use exactly the same model.

@allevato
Copy link
Member

Since the swift_library in rules_apple is deprecated in favor of bazelbuild/rules_swift, I've opened an issue over there to track this: bazelbuild/rules_swift#48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 Would be nice, but probably next quarter at the earliest
Projects
None yet
Development

No branches or pull requests

7 participants