-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
[SR-12345] Swift Driver Outputs Invalid Commands For Incremental Builds #54779
Comments
@swift-ci create |
> Inability to fully control parallelism across the build process The desire for clients to have a better understanding of swift compiler jobs for scheduling purposes is actually one reason we're rewriting the driver in Swift. Turning it into a framework will allow for smarter tooling... |
Right, that document has a serious disconnect from the current state of affairs when running incremental builds. You present two explanations for the current behavior, and I believe the correct choice given what you observe is
Observe that if you follow your reproduction steps then actually run the driver by replacing -### with -driver-show-incremental, you will see the piece you're missing here:
Those two top lines correspond to the frontend and merge-modules commands that you observed before. The last is the part you're missing: You have to run the incremental build to a fixed point. Now, given that, you would think that executing the compile commands from one -### then asking for -### again until you only see e.g. a single merge-modules command or something would be sufficient, but it appears the driver doesn't report the second-wave correctly. Unfortunately, I'm not the domain expert here. davidungar (JIRA User)? |
After speaking with David I believe I have an explanation for the behavior you're seeing. Let's follow all of the steps you have up until step 8. At this point, you would expect that the driver would read the state of the swiftdeps files, notice that there is some extra work to do in the second wave that it never got around to. This would naturally lead you to expect running `-###` to report another frontend compile job for ConstantUser.swift. Repeating this process would allow you to run the build to a fix point and extract all the relevant frontend commands. But this model is forgetting one additional variable: The driver maintains a record of the state of jobs it has executed, and that build record is not being updated by your build system when you just naively schedule frontend commands. Thus, the second wave command is never seen because the second wave command's status is never recorded by the driver in the build record. So, this raises the question of what to do about it. Certainly, my answer to the above does not change in light of this information: -### is incompatible with what you're trying to do here, and I don't think it makes sense to go to the effort of making it compatible. You literally cannot discover additional dependencies without running more frontend jobs, and if you're already doing that then there's no point in scheduling them yourself. I will be updating the documentation to account for this. |
(I really dislike that the best classification I have here is "Won't Do") Anyhow, in light of the above, and that we cannot extend -### to support this use case, I am resolving this issue. I do hope we come to support better 3rd-party incremental build infrastructure in the future. |
Comment by David Ungar (JIRA) Thanks, @CodaFi . That's a very clear explanation! |
Attachment: Download
Environment
Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
Target: x86_64-apple-darwin18.7.0
macOS 10.14.6
Additional Detail from JIRA
md5: e3a191af65d865ab008c6a0bb2b514d7
Issue Description:
The Problem
When swiftc is asked to output object file commands in incremental mode (i.e.,
-c
, -incremental
and-###
) with prior state, it does not correctly output all commands necessary to recompile affected files.Context
The [driver documentation|https://github.com/apple/swift/blob/master/docs/Driver.md] outlines three ways for build systems to compile Swift code:
-emit-executable
or-emit-library
-c
to produce object files (can be combined with-incremental
)-c -###
to emit commands to be executed externally (can be combined with-incremental
)Option 1 is not practical for production build systems (e.g., mixed libraries; control over compilation process).
Option 2 places two important constraints/restrictions on build systems:
Inability to fully control parallelism across the build process.
For example, build systems want to control parallelisation across all jobs.
Fine grained control is not possible using just
-j
/-num-threads
.Inability to distribute command execution across multiple machines.
By design, all compilation will be performed on the local machine.
This prohibits the build system distributing jobs over a cluster of machines.
Due to the above, option 3 is the most suitable for scalable build systems.
Documentation
Regarding Option 3, the [documentation|https://github.com/apple/swift/blob/master/docs/Driver.md] states:
There are two possibilities here regarding the current behaviour:
-c -###
is incompatible with-incremental
by designIn that case, the driver should return an error rather than a subset of the appropriate commands.
The documentation can be adjusted as well.
-c -###
is compatible with-incremental
by designWhy's That Important
The current bug precludes the usage of Option 3 and restricts external build systems to Option 2. This limits scalability and parallelism control.
Reproducible Steps
Setup
Verify Behaviour
In this step, we verify that incremental compilation works correctly.
cd $ROOT_DIR
rm -rf build
mkdir build
swiftc -c ConstantUser.swift ConstantHolder.swift -module-name Constants -emit-module -emit-module-path build/Constants.swiftmodule -incremental -output-file-map output.map
shasum build/*.o
Open
ConstantHolder.swift
Comment out
static let SomeValue = 5
Uncomment
static let SomeValue = "Hello"
Save file
swiftc -c ConstantUser.swift ConstantHolder.swift -module-name Constants -emit-module -emit-module-path build/Constants.swiftmodule -incremental -output-file-map output.map
shasum build/*.o
Note that the SHA1 checksums of both files have changed
Let's call these "Final Values"
rm -rf build
mkdir build
swiftc -c ConstantUser.swift ConstantHolder.swift -module-name Constants -emit-module -emit-module-path build/Constants.swiftmodule -output-file-map output.map
-incremental
flagshasum build/*.o
Compare values against "Final Values". They're identical.
This demonstrates incremental and non-incremental produce the results.
Restore
ConstantHolder.swift
to its original stateBroken Behaviour
Here, we will demonstrate that the Swift driver will not recompile ConstantUser.o even though it should.
cd $ROOT_DIR
Ensure that
ConstantHolder.swift
is restored to its original statestatic let SomeValue = 5
should be uncommentedrm -rf build
mkdir build
swiftc -c ConstantUser.swift ConstantHolder.swift -module-name Constants -emit-module -emit-module-path build/Constants.swiftmodule -incremental -output-file-map output.map
shasum build/*.o
Open
ConstantHolder.swift
Comment out
static let SomeValue = 5
Uncomment
static let SomeValue = "Hello"
Save file
swiftc -c ConstantUser.swift ConstantHolder.swift -module-name Constants -emit-module -emit-module-path build/Constants.swiftmodule -incremental -output-file-map output.map -###
BUG: You will notice that the driver will output two commands: one to recompile
ConstantHolder.o
and the other merge the newConstants.swiftmodule
Execute both commands from the output
shasum build/*.o
Note that the SHA1 checksums of just
ConstantHolder.o
has changed (BUG)Note that
ConstantHolder.o
has the same SHA1 hash as in "Final Values" butConstantUser.o
does notswiftc -emit-executable main.swift -I build build/ConstantUser.o build/ConstantHolder.o -o build/main
ConstantUser.o
was not recompiled and it still references a symbol of the wrong type (i.e., before the change)The text was updated successfully, but these errors were encountered: