This is an archive of the discontinued LLVM Phabricator instance.

[llvm-windres] Implement the windres flag --use-temp-file
ClosedPublic

Authored by mstorsjo on Aug 30 2023, 1:39 PM.

Details

Summary

Whether a temp file or a pipe is used for preprocessing is an
internal detail, this flag has a notable effect on the preprocessing
in GNU windres. Without this flag, GNU windres passes command
arguments as-is to popen(), which means they get evaluated by a
shell without being re-escaped for this case. To mimic this,
llvm-windres has manually tried to unescape arguments.

When GNU windres is given the --use-temp-file flag, it uses a
different API for invoking the preprocessor, and this API takes care
of preserving special characters in the command line arguments.
For users of GNU windres, this means that by using --use-temp-file,
they don't need to do the (quite terrible) double escaping of
quotes/spaces etc.

The xz project uses the --use-temp-file flag when invoking
GNU windres, see
https://github.com/tukaani-project/xz/commit/6b117d3b1fe91eb26d533ab16a2e552f84148d47.
However as llvm-windres didn't implement this flag and just
assumed the GNU windres popen() behaviour, they had to use a
different codepath for llvm-windres.

That separate codepath for llvm-windres broke later when llvm-windres
got slightly more accurate unescaping of lone quotes in
0f4c6b120f21d582ab7c5c4f2b2a475086c34938 /
https://reviews.llvm.org/D146848 (fixing a discrepancy to GNU
windres as found in https://github.com/llvm/llvm-project/issues/57334),
and this was reported in
https://github.com/mstorsjo/llvm-mingw/issues/363.

Not touching the implementation of the --preprocessor option
with respect to the --use-temp-file flag; that option is doubly
tricky as GNU windres changed its behaviour in a backwards incompatible
way recently (and llvm-windres currently matches the old behaviour).

TL;DR, previously we ignored this flag, but it turned out it has an
observeable effect and it allows entirely avoiding one of the more
insane parts of the windres command line interface.
Plus the earlier change from D146848 fixed one case but broke another
(a 17.x regression), and implementing this allows fixing the broken
case.

Diff Detail

Event Timeline

mstorsjo created this revision.Aug 30 2023, 1:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2023, 1:39 PM
mstorsjo requested review of this revision.Aug 30 2023, 1:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2023, 1:39 PM
alvinhochun accepted this revision.Sep 1 2023, 6:39 AM

The code looks fine to me, and I trust that you have tested it.

llvm/tools/llvm-rc/llvm-rc.cpp
496–497

I presume you plan to resolve this soon? Since you mentioned that GNU windres changed its behaviour in a backwards incompatible
way do you have a reference to any upstream bug reports or commits regarding this?

This revision is now accepted and ready to land.Sep 1 2023, 6:39 AM
mstorsjo added inline comments.Sep 1 2023, 8:26 AM
llvm/tools/llvm-rc/llvm-rc.cpp
496–497

I'm kinda unsure about what to do about it.

It broke, unintentionally, in this binutils commit: https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=21c33bcbe36377abf01614fb1b9be439a3b6de20

There were bug reports about it filed here: https://github.com/msys2/MSYS2-packages/issues/2379 and here: https://sourceware.org/bugzilla/show_bug.cgi?id=27594

But there was no acknowledgement that this indeed broke the existing uses of the option according to the documentation, instead the documentation was updated to document how the option works now: https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=5edb8e3f5ad8d74a83fc0df7f6e4514eed0aa77f;hp=3abbafc2aacc6706fea3e3e326e2f08d107c3672

Before this, llvm-windres was implemented mimicing GNU windres behaviour from this change - to make llvm-windres work with projects that were using it according to the old behaviour, e.g. in ffmpeg. Due to this breakage, it's hard for third party projects to sensibly use this option at all - so in ffmpeg I had to opt to change it to use another option instead: https://github.com/ffmpeg/ffmpeg/commit/f9626d1065c43f1d51afe66bdf988b9f33729440 Not sure how other projects that were affected dealt with it.

As 2 years has passed since, and I guess most projects that were using the option have had to adapt (i.e. stop using it? or switch to the new form and not work with llvm-windres), I guess we could/should update. I feel we didn't really get proper closure on those bug reports though - that why I haven't taken action on matching this behaviour yet.

mati865 accepted this revision.Sep 1 2023, 8:32 AM

I don't have any experience with --use-temp-file so I'll trust your judgement.
Let's get this regression fixed but I'm also curious about the plan for future `--preprocessor changes.

Let's get this regression fixed

Technically this bit isn't a regression - I just hadn't realized that --use-temp-file inhibits the messier parts of the windres interface (and hadn't run into projects using it before). But for other reasons, a project that wanted to use --use-temp-file but couldn't use it with llvm-windres, had used a different parameter passing which was broken by 0f4c6b120f21d582ab7c5c4f2b2a475086c34938 / D146848 - where this option made llvm-windres match GNU windres better.

So no regression, but for this usecase we placed that particular user of the tool in a tricky spot - correctly implementing this option gives a better way forward. (This issue has normally been solved by double-escaping parameters to windres elsewhere - but the use in xz where the same defines are passed both to windres and to the C compiler breaks if using that double-escaping fix.)

but I'm also curious about the plan for future `--preprocessor changes.

I guess I could look into changing it to the new behaviour form at some point. But as the referenced bugzilla thread shows, it was all left in a bit of undefined state (attempts to revert something to appease some users, but actually reverting the wrong thing, etc...)

So no regression, but for this usecase we placed that particular user of the tool in a tricky spot

Oh, that's tricky situation indeed

I guess I could look into changing it to the new behaviour form at some point.

Phabricator didn't refresh after you replied to Alvin, that comment answers my question.

This revision was landed with ongoing or failed builds.Sep 1 2023, 9:49 AM
This revision was automatically updated to reflect the committed changes.