-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
llvm-rc: Error parsing file: expected BLOCK or VALUE, got... #57334
Comments
@mstorsjo I've been trying to build LLVM in Debug mode, but nothing I can do ends up with llvm-rc.exe being debuggable. Is there anything else I need to do, besides setting the CMAKE build type to Debug? |
It's an error not a crash so there is no need for debugging. |
As @mati865 noted, this isn't a crash so you shouldn't need debugging info - although I guess you're wanting to step around in the codebase at runtime to understand what's going on. (In general, I haven't really tried to debug LLVM much on Windows, so I don't have much of value to add on that point.) However, your issue is tricky. When GNU windres does preprocessing, it invokes GCC in a subprocess, and includes the relevant In your case, when you have the preprocessor doing the quoting of the passed string,
Then you clearly want
If we execute the same GCC command, we'll see how the shell consumes the quotes before invoking GCC:
However in the case of llvm-windres:
Here you see that llvm-windres preserved the quotes around goat-exercise as-is when invoking clang, which means that the preprocessing output contained those quotes:
In your case, since you are expecting to have the processor quote the string for you in the end, I'd suggest just dropping any extra manual escaped quotes from the preprocessor argument. That wouldn't work if you wanted to pass a string that contains spaces, but that breaks in various unexpected ways today anyway, so I guess you aren't really doing that. The other alternative is to use the same way of quoting strings that libiconv uses, as referenced in the binutils bug report above. Then you can do this kind of passing of string literals to windres this way:
This is the usecase I was aware of from before, which I've made sure that works exactly the same across both GNU windres and llvm-windres. Finally, I think this patch to llvm-windres would fix the issue for your particular case, to make the subshell invoking closer match what happens in GNU windres: diff --git a/llvm/tools/llvm-rc/llvm-rc.cpp b/llvm/tools/llvm-rc/llvm-rc.cpp
index 312cc15e222f..2e669f17c5c7 100644
--- a/llvm/tools/llvm-rc/llvm-rc.cpp
+++ b/llvm/tools/llvm-rc/llvm-rc.cpp
@@ -308,6 +308,9 @@ std::string unescape(StringRef S) {
else
fatalError("Unterminated escape");
continue;
+ } else if (S[I] == '"') {
+ // This eats an individual unescaped quote, like a shell would do.
+ continue;
}
Out.push_back(S[I]);
} I'm not sure if that is safe for all the various use of llvm-windres elsewhere, but it might be - I could consider trying to do that, test it with my build corpus to see that it doesn't break something else, add a testcase and propose an upstream patch at some point. |
…d quotes Some background context: GNU windres invokes the preprocessor in a subprocess. Some windres options are passed through to the preproocessor, e.g. -D options for predefining defines. When GNU windres passes these options onwards, it takes the options in exact the form they are received (in argv or similar) and assembles them into a single preprocessor command string which gets interpreted by a shell (IIRC via the popen() function, or similar). When LLVM invokes subprocesses, it does so via APIs that take properly split argument vectors, to avoid needing to worry about shell quoting/escaping/unescaping. But in the case of LLVM windres, we have to emulate the effect of the shell parsing done by popen(). Most of the relevant cases are already taken care of here, but this patch fixes an uncommon case encountered in #57334. (This case is uncommon since it doesn't do what one would want to; the quotes need to be escaped more to work as intended through the popen() shell). Differential Revision: https://reviews.llvm.org/D146848
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 tukaani-project/xz@6b117d3. 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 0f4c6b1 / https://reviews.llvm.org/D146848 (fixing a discrepancy to GNU windres as found in #57334), and this was reported in mstorsjo/llvm-mingw#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). (See https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=21c33bcbe36377abf01614fb1b9be439a3b6de20, https://sourceware.org/bugzilla/show_bug.cgi?id=27594 and https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=5edb8e3f5ad8d74a83fc0df7f6e4514eed0aa77f;hp=3abbafc2aacc6706fea3e3e326e2f08d107c3672 for the behaviour change.) Differential Revision: https://reviews.llvm.org/D159223
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 tukaani-project/xz@6b117d3. 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 0f4c6b1 / https://reviews.llvm.org/D146848 (fixing a discrepancy to GNU windres as found in llvm/llvm-project#57334), and this was reported in mstorsjo/llvm-mingw#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). (See https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=21c33bcbe36377abf01614fb1b9be439a3b6de20, https://sourceware.org/bugzilla/show_bug.cgi?id=27594 and https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=5edb8e3f5ad8d74a83fc0df7f6e4514eed0aa77f;hp=3abbafc2aacc6706fea3e3e326e2f08d107c3672 for the behaviour change.) Differential Revision: https://reviews.llvm.org/D159223 (cherry picked from commit 2bcc0fdc58a220cb9921b47ec8a32c85f2511a47)
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 tukaani-project/xz@6b117d3. 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 0f4c6b1 / https://reviews.llvm.org/D146848 (fixing a discrepancy to GNU windres as found in llvm/llvm-project#57334), and this was reported in mstorsjo/llvm-mingw#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). (See https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=21c33bcbe36377abf01614fb1b9be439a3b6de20, https://sourceware.org/bugzilla/show_bug.cgi?id=27594 and https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=5edb8e3f5ad8d74a83fc0df7f6e4514eed0aa77f;hp=3abbafc2aacc6706fea3e3e326e2f08d107c3672 for the behaviour change.) Differential Revision: https://reviews.llvm.org/D159223 (cherry picked from commit 2bcc0fdc58a220cb9921b47ec8a32c85f2511a47)
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 tukaani-project/xz@6b117d3. 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 0f4c6b1 / https://reviews.llvm.org/D146848 (fixing a discrepancy to GNU windres as found in llvm#57334), and this was reported in mstorsjo/llvm-mingw#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). (See https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=21c33bcbe36377abf01614fb1b9be439a3b6de20, https://sourceware.org/bugzilla/show_bug.cgi?id=27594 and https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=5edb8e3f5ad8d74a83fc0df7f6e4514eed0aa77f;hp=3abbafc2aacc6706fea3e3e326e2f08d107c3672 for the behaviour change.) Differential Revision: https://reviews.llvm.org/D159223
Looks like this was fixed by 0f4c6b1. Can this be closed? The first reproducer works fine here now with 17.0.1 GIMP itself still fails, but due a different problem:
|
Without looking into this, the error sounds like #51286 |
Thanks, yes looks like it. So I think this can be closed then. |
Fixed by 0f4c6b1. |
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 tukaani-project/xz@6b117d3. 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 0f4c6b1 / https://reviews.llvm.org/D146848 (fixing a discrepancy to GNU windres as found in llvm/llvm-project#57334), and this was reported in mstorsjo/llvm-mingw#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). (See https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=21c33bcbe36377abf01614fb1b9be439a3b6de20, https://sourceware.org/bugzilla/show_bug.cgi?id=27594 and https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=5edb8e3f5ad8d74a83fc0df7f6e4514eed0aa77f;hp=3abbafc2aacc6706fea3e3e326e2f08d107c3672 for the behaviour change.) Differential Revision: https://reviews.llvm.org/D159223
This was found while trying to build GIMP 3 with Clang, using Meson as the build generator. The example below is an attempt to simplify a reproducible error.
The following rc file:
Compiles correctly with
windres "--define" "INTERNALNAME_STR=\"goat-exercise\"" error.rc error.o
when using Mingw64's windres, but fails with LLVM's:Version info
This is an example from the real build:
Where the full rc file is:
The text was updated successfully, but these errors were encountered: