This is an archive of the discontinued LLVM Phabricator instance.

[lld/COFF] Improve handling of the /manifestdependency: flag
ClosedPublic

Authored by thakis on Aug 24 2021, 7:23 AM.

Details

Summary

If multiple /manifestdependency: flags are passed, they are
naively deduped, but after that each of them should have an
effect, instead of just the last one.

Also, /manifestdependency: flags are allowed in .drectve sections
(from #pragma comment(linker, ...). To make the interaction between
/manifestdependency: flags enabling manifest by default but
/manifest:no overriding this work, add an explict ManifestKind::Default
state to represent no explicit /manifest flag being passed.
To make /manifestdependency: flags from input file .drectve sections
work with /manifest:embed, delay embedded manifest emission until
after input files have been read.

This in turn requires undoing D38975: The .res file is now created only
sometimes, and only after the repro response file has been created.
Moving the response file creation is tricky (see review for details), so
move back to having the manifest inputs in the repro file instead. Now
that we don't rely on cvt.exe, that's less bad than it used to be.

Diff Detail

Event Timeline

thakis requested review of this revision.Aug 24 2021, 7:23 AM
thakis created this revision.
thakis added inline comments.
lld/test/COFF/manifest.test
82

(This matches link.exe: Even just an additional space right after the : causes the flags to not be uniq'd.)

thakis updated this revision to Diff 368339.Aug 24 2021, 7:26 AM

git add new input file

I didn't see the test failure because linkrepro-manifest.test requires gnutar, which on macOS apparently isn't present (only BSD tar is). The test runs fine without this patch on macOS though; maybe that REQUIRES is overly strict.

Anyways, that test failure is real and kind of annoying. The problem is that my patch moves addBuffer(createManifestRes(), false, false); after the response file has been written, and so the .res file that is internally created by that is added to filePaths only after filePaths has been copied to the response file.

However, /manifestdependency: in input files means we can't create the inputs to the .res file much earlier. So we have to call createResponseFile() later I suppose, but there are several early exits (for writing import .lib files, or for writing thin indexes only) that then also have to call it, which is a bit messy.

Another option, which seems maybe a bit nicer and more consistent with the change here, is to undo D38975 and instead of putting the generated .res file in the response file, put the input flags in it instead. We have llvm-cvtres now, so we no longer need cvtres.exe to link repro files that bundle the inputs.

I like that last idea most.

thakis added a subscriber: pcc.Aug 24 2021, 11:35 AM

@pcc too, in case he has opinions on the last comment, given that D38975 was his change :)

Another option is to extract a method that computes the name of the generated .res file and adds it to the response file eagerly, and only do so if we don't create an import lib or thin lto indices only. That'd work too, but it's also a bit brittle since it needs to match early exit patterns.

Yet another option is to call createResponseFile() from the destructor of some RAII class so that it's always created as late as possible. That sounds like an ok option too.

Yet another option is to call createResponseFile() from the destructor of some RAII class so that it's always created as late as possible. That sounds like an ok option too.

One drawback of that is that that'd also add lib files referenced by e.g. /defaultlib: flags in .drectve entries from obj files to the response file, so that when replaying the link from the response file, we'd now see those libs twice (once from the response file, and another time from the .drectve).

It's probably best if the repro is as close as possible to the input, which suggests undoing D38975.

thakis updated this revision to Diff 368454.Aug 24 2021, 1:43 PM
thakis edited the summary of this revision. (Show Details)
thakis added a reviewer: pcc.

undo D38975

thakis updated this revision to Diff 368530.Aug 24 2021, 6:47 PM

try to fix test on windows where we still call external cvtres

thakis updated this revision to Diff 368616.Aug 25 2021, 5:32 AM

clang-format

rnk accepted this revision.Aug 25 2021, 11:20 AM

lgtm

lld/COFF/Config.h
184

I worry that MSVC may do more things to deduplicate manifest files. They could canonicalize the path first and ignore case, for example. However, I really don't think it matters. The main thing is that repeated, identical directives should not add the same file twice, and this handles that well enough.

This revision is now accepted and ready to land.Aug 25 2021, 11:20 AM

Thanks!

lld/COFF/Config.h
184

This flag doesn't contain a path, but raw text that's copied into the manifest xml. As far as I can tell (link main.obj /manifestdependency:foo=bar /manifestdependency:Foo=bar ; type foo.exe.manifest) both an additional space or a difference just in upper/lowercase makes link.exe emit ore than one dependentAssembly element.

Herald added a project: Restricted Project. · View Herald TranscriptAug 25 2021, 11:36 AM