wrappers: Use a response file on Windows, if the new command line seems too long

This should properly fix the issue that was reported at
https://github.com/mstorsjo/llvm-mingw/issues/296.
This commit is contained in:
Martin Storsjö committed 2024-06-03 12:36:17 +03:00
1 parent 089c625e66
commit ebde97faaf
1 file changed
+31 -5
+31 -5
View File
@@ -89,6 +89,27 @@ static inline const TCHAR *escape(const TCHAR *str) {
return out; return out;
} }
static inline TCHAR *concat(const TCHAR *prefix, const TCHAR *suffix);
static TCHAR *make_response_file(const TCHAR **argv) {
if (!argv[1])
return NULL;
TCHAR *temp_path = malloc(MAX_PATH * sizeof(*temp_path));
if (GetTempPath(MAX_PATH, temp_path) == 0)
return NULL;
TCHAR *rsp_file = malloc(MAX_PATH * sizeof(*rsp_file));
if (GetTempFileName(temp_path, _T("ctw"), 0, rsp_file) == 0)
return NULL;
FILE *f = _tfopen(rsp_file, _T("w, ccs=UNICODE"));
for (int i = 1; argv[i]; i++)
_ftprintf(f, _T(TS"\n"), argv[i]);
fclose(f);
argv[1] = escape(concat(_T("@"), rsp_file));
argv[2] = NULL;
return rsp_file;
}
static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR * const *argv) { static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR * const *argv) {
int num_args = 0; int num_args = 0;
while (argv[num_args]) while (argv[num_args])
@@ -100,12 +121,17 @@ static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR
total += 1 + _tcslen(escaped_argv[i]); total += 1 + _tcslen(escaped_argv[i]);
} }
escaped_argv[num_args] = NULL; escaped_argv[num_args] = NULL;
int ret = _tspawnvp(mode, filename, escaped_argv); const TCHAR *temp_file = NULL;
if (ret == -1 && total >= 32767) { if (total > 32000) {
int err = errno; // If we are getting close to the limit, write the arguments to
fprintf(stderr, "command line too long; %d characters\n", total); // a temporary response file.
errno = err; temp_file = make_response_file(escaped_argv);
if (temp_file)
total = _tcslen(escaped_argv[0]) + _tcslen(escaped_argv[1]) + 2;
} }
int ret = _tspawnvp(mode, filename, escaped_argv);
if (temp_file)
DeleteFile(temp_file);
return ret; return ret;
} }
#else #else