Skip to content

Fix build failures when two or more plugin-generated build commands have the same name #3585

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

Conversation

abertelrud
Copy link
Contributor

@abertelrud abertelrud commented Jul 1, 2021

When two or more commands produced by plugins (either the same plugin or different plugins) had the same name, only one of them would run.

Motivation:

This is a critical build failure for plugins that don't incorporate some unique variable such as the input name in the command name.

Modifications:

  • add a digest of the command line to the command name (note that this does not affect the description, which remains the same)
  • modify one of the unit test fixtures to fail to build if this fix doesn't work

Result:

Two build commands generated by plugins can have the same name and the build will still work.

rdar://79872414

@abertelrud abertelrud self-assigned this Jul 1, 2021
@abertelrud abertelrud added the ready Author believes the PR is ready to be merged & any feedback has been addressed label Jul 1, 2021
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@@ -586,8 +586,9 @@ extension LLBuildManifestBuilder {
for command in target.pluginInvocationResults.reduce([], { $0 + $1.buildCommands }) {
// Create a shell command to invoke the executable. We include the path of the executable as a dependency.
let execPath = AbsolutePath(command.configuration.executable, relativeTo: buildParameters.buildPath)
let uniquedName = ([command.configuration.displayName] + (command.inputFiles + command.outputFiles ).map{ $0.pathString }).joined(separator: "|")
Copy link
Contributor

@tomerd tomerd Jul 1, 2021

Choose a reason for hiding this comment

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

would it make sense to use something like UUID to make sure this is always unique, or do you want this to match if inputs + outputs are the same?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main thing is to make sure that's stable, so that running the same inputs generates the same llbuild manifest. Otherwise we will have spurious rebuilds. The combination of inputs and outputs seems sufficient to make it unique — if it's the same inputs and outputs then from llbuild's perspective there is nothing to distinguish when they run.

I suppose we could include the command line in the hash as well — I'm not really sure what happens if you have two commands with the same inputs and outputs — would you expect both commands to run? Perhaps using the whole command line would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But UUIDs and things like that are usually the bane of build systems, since they introduce randomness, which generally defeats null builds, etc.

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 general case, the question of whether a command that changes arguments from one run to the next is still the "same" command can be tricky. It can for example affect how things are shown in IDEs, but it's unlikely to matter from a correctness standpoint here. So even if, say, adding a "-v" flag from one run to the next doesn't change the identity of the command in a conceptual way, having it appear as a different command in the llbuild manifest might not cause any problems. I'm therefore inclined to hash the whole command line.

Perhaps the plugin identity and the target to which it was applied should factor in here, although it should be noted that they are already baked into the output paths, since every combination of plugin and target is given its own subdirectory under the intermediates directory.

Copy link
Contributor

@neonichu neonichu Jul 1, 2021

Choose a reason for hiding this comment

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

Not entirely sure what the plain llbuild behavior is, but XCBuild will error if there are multiple commands producing the same output file in a single build operation.

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 this case the llbuild manifest logic was discarding the older commands. In the case of a plugin that emits two commands with the same outputs, we should probably catch that earlier and emit an error. I'll write up an enhancement request for that.

@abertelrud
Copy link
Contributor Author

abertelrud commented Jul 1, 2021

Aha, we're already in the business of silently dropping commands on Linux:

13:39:26 LLBuildManifest/BuildManifest.swift:129: Assertion failed: aleady had a command named '/home/buildnode/jenkins/workspace/swift-package-manager-self-hosted-Linux-smoke-test/branch-main/tmp/TemporaryDirectory.ZDQ9CD/_Concurrency-STBYDBT15F2G.swiftmodule'
13:39:26 Current stack trace:

Perhaps that's a bug that we haven't detected before, or just a benign duplication. That warrants further investigation.

Perhaps I should separate out those assertions into a separate PR from the plugin fix.

@abertelrud
Copy link
Contributor Author

Split out the assertions here: #3587

…y including the command line as well.

Otherwise the llbuild manifest will contain only the last defined command with the same name, leading to build failures.

To avoid having the name be exceedingly long, what we append to the name is a digest of the command line and not the full command line itself.

rdar://79872414
@abertelrud abertelrud force-pushed the eng/anders/79872414-plugin-commands-with-same-names-dont-work branch from 62bf7f7 to 5c3d5fa Compare July 1, 2021 22:11
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud abertelrud merged commit d1ad079 into swiftlang:main Jul 2, 2021
@abertelrud abertelrud deleted the eng/anders/79872414-plugin-commands-with-same-names-dont-work branch July 2, 2021 16:56
@ktoso
Copy link
Contributor

ktoso commented Jul 6, 2021

Seems I missed this -- but thanks a lot! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready Author believes the PR is ready to be merged & any feedback has been addressed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants