FFmpeg
Loading...
Searching...
No Matches
mscl.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/*
20 * msvc compiler wrapper, used as: mscl <compiler> <arguments...>
21 *
22 * cl.exe cannot write a GNU style dependency file directly. When
23 * -showIncludes is present on the command line, this wrapper converts the
24 * include records from the compiler's stdout into a .d file, written next to
25 * the object file as a byproduct of compilation.
26 *
27 * Dependency paths are rewritten relative to the current directory, which
28 * keeps the .d files independent of how the environment maps Windows drives
29 * (MSYS, Cygwin and WSL all differ). Paths on a different drive or share are
30 * kept absolute, in forward slash form. Spaces, '#' and '$' are escaped the
31 * same way gcc escapes them in -MD output.
32 *
33 * On a POSIX host driving a Windows compiler (cl.exe through WSL interop, for
34 * example) the records carry Windows paths. Each distinct drive or share root
35 * is translated once with wslpath or cygpath and the result is reused for
36 * every path below it.
37 */
38
39#include <ctype.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
44#include "libavutil/macros.h"
45
46#ifdef _WIN32
47#define WIN32_LEAN_AND_MEAN
48#include <windows.h>
49#else
50#include <errno.h>
51#include <sys/wait.h>
52#include <unistd.h>
53#endif
54
55#define INC_PREFIX "Note: including file:"
56
57static const char *obj;
58static const char *src;
59
60static char *cwd;
61
62static char **deps;
63static size_t nb_deps, max_deps;
64
65static char *linebuf;
66static size_t line_len, line_max;
67
68static void die(const char *msg)
69{
70 fprintf(stderr, "mscl: %s\n", msg);
71 exit(1);
72}
73
74static void *xrealloc(void *ptr, size_t size)
75{
76 ptr = realloc(ptr, size);
77 if (!ptr)
78 die("out of memory");
79 return ptr;
80}
81
82static char *xstrdup(const char *s)
83{
84 size_t size = strlen(s) + 1;
85 return memcpy(xrealloc(NULL, size), s, size);
86}
87
88#ifdef _WIN32
89
90/* code page the compiler writes its output in */
91static UINT out_cp;
92
93static wchar_t *mb_to_wide(const char *s, UINT cp)
94{
95 int n = MultiByteToWideChar(cp, 0, s, -1, NULL, 0);
96 wchar_t *w = xrealloc(NULL, (n ? n : 1) * sizeof(*w));
97 if (!n)
98 *w = 0;
99 else
100 MultiByteToWideChar(cp, 0, s, -1, w, n);
101 return w;
102}
103
104static char *wide_to_mb(const wchar_t *w, UINT cp)
105{
106 int n = WideCharToMultiByte(cp, 0, w, -1, NULL, 0, NULL, NULL);
107 char *s = xrealloc(NULL, n ? n : 1);
108 if (!n)
109 *s = 0;
110 else
111 WideCharToMultiByte(cp, 0, w, -1, s, n, NULL, NULL);
112 return s;
113}
114
115static char *recode(const char *s, UINT from, UINT to)
116{
117 wchar_t *w = mb_to_wide(s, from);
118 char *out = wide_to_mb(w, to);
119 free(w);
120 return out;
121}
122
123static FILE *open_wb(const char *path)
124{
125 wchar_t *w = mb_to_wide(path, CP_UTF8);
126 FILE *f = _wfopen(w, L"wb");
127 free(w);
128 return f;
129}
130
131static int unlink_file(const char *path)
132{
133 wchar_t *w = mb_to_wide(path, CP_UTF8);
134 int ret = _wremove(w);
135 free(w);
136 return ret;
137}
138
139static int replace_file(const char *from, const char *to)
140{
141 wchar_t *wfrom = mb_to_wide(from, CP_UTF8), *wto = mb_to_wide(to, CP_UTF8);
142 int ret = !MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING);
143 free(wfrom);
144 free(wto);
145 return ret;
146}
147
148#else
149
150static FILE *open_wb(const char *path)
151{
152 return fopen(path, "wb");
153}
154
155static int unlink_file(const char *path)
156{
157 return remove(path);
158}
159
160static int replace_file(const char *from, const char *to)
161{
162 return rename(from, to);
163}
164
165#endif
166
167static const char *file_basename(const char *p)
168{
169 for (const char *q = p; *q; q++)
170 if (*q == '/' || *q == '\\')
171 p = q + 1;
172 return p;
173}
174
175static int is_source(const char *arg)
176{
177 static const char *const exts[] = {
178 ".c", ".cc", ".cpp", ".cxx", ".m", ".mm", ".s", ".S", ".asm"
179 };
180 const char *dot = strrchr(file_basename(arg), '.');
181 if (!dot)
182 return 0;
183 for (size_t i = 0; i < FF_ARRAY_ELEMS(exts); i++)
184 if (!strcmp(dot, exts[i]))
185 return 1;
186 return 0;
187}
188
189static int chr_eq(char a, char b)
190{
191#ifdef _WIN32
192 return tolower(a) == tolower(b);
193#else
194 return a == b;
195#endif
196}
197
198/* Length of the root that "../" cannot climb out of, "//server/share" for
199 * UNC paths and "X:" for drive letter paths, 0 otherwise. Forward slashes only. */
200static size_t root_len(const char *p)
201{
202 size_t i = 0;
203
204 if (p[0] == '/' && p[1] == '/') {
205 for (i = 2; p[i] && p[i] != '/'; i++)
206 ;
207 if (p[i])
208 for (i++; p[i] && p[i] != '/'; i++)
209 ;
210 } else if (isalpha(p[0]) && p[1] == ':') {
211 i = 2;
212 }
213 return i;
214}
215
216static char *make_relative(const char *path)
217{
218 size_t i, tail = 0, updirs = 0, root = root_len(path);
219 int found = 0;
220 const char *rest;
221 char *out, *q;
222
223 /* longest common prefix ending on a component boundary */
224 for (i = 0;; i++) {
225 int pb = !path[i] || path[i] == '/';
226 int cb = !cwd[i] || cwd[i] == '/';
227 if (pb && cb) {
228 tail = i;
229 found = 1;
230 }
231 if (!path[i] || !cwd[i] || !chr_eq(path[i], cwd[i]))
232 break;
233 }
234 /* nothing to name, or a different drive or share */
235 if (!found || !path[tail] || tail < root || root_len(cwd) != root)
236 return NULL;
237
238 if (cwd[tail])
239 for (i = tail + 1;; i++) {
240 if (!cwd[i] || cwd[i] == '/')
241 updirs++;
242 if (!cwd[i])
243 break;
244 }
245
246 rest = path + tail + 1;
247 out = q = xrealloc(NULL, 3 * updirs + strlen(rest) + 1);
248 for (i = 0; i < updirs; i++, q += 3)
249 memcpy(q, "../", 3);
250 strcpy(q, rest);
251 return out;
252}
253
254static void add_dep(char *path)
255{
256 for (size_t i = 0; i < nb_deps; i++)
257 if (!strcmp(deps[i], path)) {
258 free(path);
259 return;
260 }
261 if (nb_deps >= max_deps) {
262 max_deps = max_deps ? 2 * max_deps : 64;
263 deps = xrealloc(deps, max_deps * sizeof(*deps));
264 }
265 deps[nb_deps++] = path;
266}
267
268static const char *unmapped;
269
270#ifndef _WIN32
271
272static struct {
273 char *root;
274 char *host;
276static size_t nb_roots;
277
278static char *path_helper(const char *prog, const char *root)
279{
280 char *args[] = { (char *)prog, "-u", (char *)root, NULL };
281 char buf[4096];
282 size_t len = 0;
283 int fds[2], st;
284 pid_t pid;
285
286 if (pipe(fds) < 0)
287 die("pipe failed");
288 pid = fork();
289 if (pid < 0)
290 die("fork failed");
291 if (!pid) {
292 dup2(fds[1], STDOUT_FILENO);
293 close(fds[0]);
294 close(fds[1]);
295 execvp(prog, args);
296 _exit(127);
297 }
298 close(fds[1]);
299 for (;;) {
300 char tmp[512];
301 ssize_t n = read(fds[0], tmp, sizeof(tmp));
302 if (n < 0 && errno == EINTR)
303 continue;
304 if (n <= 0)
305 break;
306 if (len + n < sizeof(buf)) {
307 memcpy(buf + len, tmp, n);
308 len += n;
309 }
310 }
311 close(fds[0]);
312 if (waitpid(pid, &st, 0) < 0)
313 die("waitpid failed");
314 if (!WIFEXITED(st) || WEXITSTATUS(st) || !len)
315 return NULL;
316 buf[len] = 0;
317 len = strcspn(buf, "\r\n");
318 while (len && buf[len - 1] == '/')
319 len--;
320 buf[len] = 0;
321 return xstrdup(buf);
322}
323
324/* Translate a Windows path to the host namespace, NULL if impossible. */
325static char *host_path(const char *path)
326{
327 size_t r = root_len(path), i;
328 char *root, *host = NULL, *out;
329
330 if (path[r] == '/')
331 r++;
332 root = xstrdup(path);
333 root[r] = 0;
334 for (char *q = root; *q; q++)
335 *q = tolower(*q);
336
337 for (i = 0; i < nb_roots; i++)
338 if (!strcmp(roots[i].root, root))
339 break;
340 if (i == nb_roots) {
341 host = path_helper("wslpath", root);
342 if (!host)
343 host = path_helper("cygpath", root);
344 roots = xrealloc(roots, (nb_roots + 1) * sizeof(*roots));
345 roots[nb_roots].root = root;
346 roots[nb_roots].host = host;
347 nb_roots++;
348 } else {
349 host = roots[i].host;
350 free(root);
351 }
352 if (!host)
353 return NULL;
354
355 /* the root keeps its slash, the host form lost it */
356 out = xrealloc(NULL, strlen(host) + strlen(path + r) + 2);
357 strcpy(out, host);
358 strcat(out, "/");
359 strcat(out, path + r);
360 return out;
361}
362
363#endif
364
365static void add_include(char *p)
366{
367 char *own = NULL, *rel;
368
369#ifdef _WIN32
370 p = own = recode(p, out_cp, CP_UTF8);
371#endif
372
373 for (char *q = p; *q; q++)
374 if (*q == '\\')
375 *q = '/';
376
377#ifndef _WIN32
378 if (root_len(p)) {
379 own = host_path(p);
380 if (!own) {
381 if (!unmapped)
382 unmapped = xstrdup(p);
383 return;
384 }
385 p = own;
386 }
387#endif
388
389 rel = make_relative(p);
390 if (rel) {
391 free(own);
392 add_dep(rel);
393 } else {
394 add_dep(own ? own : xstrdup(p));
395 }
396}
397
398static void process_line(char *line)
399{
400 size_t len = strlen(line);
401 while (len && line[len - 1] == '\r')
402 line[--len] = 0;
403
404 if (!strncmp(line, INC_PREFIX, sizeof(INC_PREFIX) - 1)) {
405 char *p = line + sizeof(INC_PREFIX) - 1;
406 while (*p == ' ')
407 p++;
408 if (*p)
409 add_include(p);
410 return;
411 }
412 /* cl.exe echoes the source file name; drop it and empty lines */
413 if (*line && !(src && !strcmp(line, src)))
414 puts(line);
415}
416
417static void feed(const char *buf, size_t n)
418{
419 for (size_t i = 0; i < n; i++) {
420 if (buf[i] == '\n') {
421 linebuf[line_len] = 0;
423 line_len = 0;
424 } else {
425 if (line_len + 2 > line_max) {
426 line_max = line_max ? 2 * line_max : 4096;
428 }
429 linebuf[line_len++] = buf[i];
430 }
431 }
432}
433
434static void feed_flush(void)
435{
436 if (line_len) {
437 linebuf[line_len] = 0;
439 line_len = 0;
440 }
441}
442
443static void init_deps(void)
444{
445 size_t len;
446
447#ifdef _WIN32
448 DWORD size = GetCurrentDirectoryW(0, NULL);
449 wchar_t *wcwd = xrealloc(NULL, size * sizeof(*wcwd));
450 if (!GetCurrentDirectoryW(size, wcwd))
451 die("GetCurrentDirectory failed");
452 cwd = wide_to_mb(wcwd, CP_UTF8);
453 free(wcwd);
454#else
455 cwd = getcwd(NULL, 0);
456 if (!cwd)
457 die("getcwd failed");
458#endif
459 for (char *q = cwd; *q; q++)
460 if (*q == '\\')
461 *q = '/';
462 len = strlen(cwd);
463 while (len && cwd[len - 1] == '/')
464 cwd[--len] = 0;
465
466 linebuf = xrealloc(NULL, line_max = 4096);
467}
468
469#ifdef _WIN32
470
471/* Return the command line as received, minus our own program name, so the
472 * compiler gets its arguments verbatim without a requoting round-trip. */
473static wchar_t *cmdline_tail(void)
474{
475 wchar_t *p = GetCommandLineW();
476 if (*p == L'"') {
477 p++;
478 while (*p && *p != L'"')
479 p++;
480 if (*p)
481 p++;
482 } else {
483 while (*p && *p != L' ' && *p != L'\t')
484 p++;
485 }
486 while (*p == L' ' || *p == L'\t')
487 p++;
488 return _wcsdup(p);
489}
490
491/* Split the command line into UTF-8 arguments. CommandLineToArgvW would do the
492 * same, but we want to avoid pulling in shell32.dll. */
493static char **split_cmdline(const wchar_t *p, int *argc)
494{
495 wchar_t *buf = xrealloc(NULL, (wcslen(p) + 1) * sizeof(*buf));
496 char **argv = NULL;
497 int n = 0;
498
499 for (;;) {
500 wchar_t *q = buf;
501 int quoted = 0;
502
503 while (*p == L' ' || *p == L'\t')
504 p++;
505 if (!*p)
506 break;
507 for (;;) {
508 size_t bs = 0;
509 while (*p == L'\\') {
510 bs++;
511 p++;
512 }
513 if (*p == L'"') {
514 for (size_t i = 0; i < bs / 2; i++)
515 *q++ = L'\\';
516 if (bs & 1) {
517 *q++ = L'"';
518 } else if (quoted && p[1] == L'"') {
519 *q++ = L'"';
520 p++;
521 } else {
522 quoted = !quoted;
523 }
524 p++;
525 continue;
526 }
527 for (size_t i = 0; i < bs; i++)
528 *q++ = L'\\';
529 if (!*p || (!quoted && (*p == L' ' || *p == L'\t')))
530 break;
531 *q++ = *p++;
532 }
533 *q = 0;
534 argv = xrealloc(argv, (n + 2) * sizeof(*argv));
535 argv[n++] = wide_to_mb(buf, CP_UTF8);
536 }
537 if (argv)
538 argv[n] = NULL;
539 free(buf);
540 *argc = n;
541 return argv;
542}
543
544static int run(wchar_t *cmdline, int want_pipe)
545{
546 HANDLE rd = NULL, wr = NULL;
547 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
548 STARTUPINFOW si = { .cb = sizeof(si) };
549 PROCESS_INFORMATION pi;
550 DWORD code = 1;
551
552 si.dwFlags = STARTF_USESTDHANDLES;
553 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
554 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
555 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
556 SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, 1);
557 SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, 1);
558 SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, 1);
559
560 if (want_pipe) {
561 if (!CreatePipe(&rd, &wr, &sa, 0))
562 die("CreatePipe failed");
563 SetHandleInformation(rd, HANDLE_FLAG_INHERIT, 0);
564 si.hStdOutput = wr;
565 /* English include records are required for the parsing above */
566 SetEnvironmentVariableA("VSLANG", "1033");
567 }
568
569 if (!CreateProcessW(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL,
570 &si, &pi))
571 die("cannot execute compiler");
572 CloseHandle(pi.hThread);
573
574 if (want_pipe) {
575 char buf[65536];
576 DWORD n;
577 CloseHandle(wr);
578 while (ReadFile(rd, buf, sizeof(buf), &n, NULL) && n > 0)
579 feed(buf, n);
580 CloseHandle(rd);
581 feed_flush();
582 }
583
584 WaitForSingleObject(pi.hProcess, INFINITE);
585 GetExitCodeProcess(pi.hProcess, &code);
586 CloseHandle(pi.hProcess);
587 return (int)code;
588}
589
590#else
591
592static int run(char **args)
593{
594 const char *wslenv;
595 int fds[2], st;
596 pid_t pid;
597
598 if (pipe(fds) < 0)
599 die("pipe failed");
600 setenv("VSLANG", "1033", 1);
601 /* WSL hands the environment to Windows programs only for the variables
602 * listed in WSLENV */
603 wslenv = getenv("WSLENV");
604 if (wslenv && *wslenv) {
605 char *e = xrealloc(NULL, strlen(wslenv) + sizeof(":VSLANG"));
606 strcpy(e, wslenv);
607 strcat(e, ":VSLANG");
608 setenv("WSLENV", e, 1);
609 free(e);
610 } else {
611 setenv("WSLENV", "VSLANG", 1);
612 }
613 pid = fork();
614 if (pid < 0)
615 die("fork failed");
616 if (!pid) {
617 dup2(fds[1], STDOUT_FILENO);
618 close(fds[0]);
619 close(fds[1]);
620 execvp(args[0], args);
621 perror(args[0]);
622 _exit(127);
623 }
624 close(fds[1]);
625 for (;;) {
626 char buf[65536];
627 ssize_t n = read(fds[0], buf, sizeof(buf));
628 if (n < 0 && errno == EINTR)
629 continue;
630 if (n <= 0)
631 break;
632 feed(buf, n);
633 }
634 close(fds[0]);
635 feed_flush();
636
637 if (waitpid(pid, &st, 0) < 0)
638 die("waitpid failed");
639 return WIFEXITED(st) ? WEXITSTATUS(st) : 128 + WTERMSIG(st);
640}
641
642#endif
643
644/* gcc style escaping for make: '\ ', '\#' and '$$' */
645static void fput_escaped(const char *s, FILE *f)
646{
647 for (; *s; s++) {
648 if (*s == ' ' || *s == '#')
649 fputc('\\', f);
650 else if (*s == '$')
651 fputc('$', f);
652 fputc(*s, f);
653 }
654}
655
656/* A failure to write the dependency file fails the build. */
657static int write_depfile(void)
658{
659 size_t len = strlen(obj);
660 char *path = xrealloc(NULL, len + 3), *tmp;
661 FILE *f;
662 int err;
663
664 memcpy(path, obj, len + 1);
665 if (len > 2 && !strcmp(path + len - 2, ".o"))
666 len -= 2;
667 strcpy(path + len, ".d");
668
669 if (unmapped) {
670 fprintf(stderr, "mscl: cannot map %s to a host path, "
671 "wslpath or cygpath is required\n", unmapped);
672 return 1;
673 }
674
675 tmp = xrealloc(NULL, len + 7);
676 memcpy(tmp, path, len + 2);
677 strcpy(tmp + len + 2, ".tmp");
678
679 f = open_wb(tmp);
680 if (f) {
682 fputc(':', f);
683 for (size_t i = 0; i < nb_deps; i++) {
684 fputc(' ', f);
685 fput_escaped(deps[i], f);
686 }
687 fputc('\n', f);
688 /* -MP style dummy rules; make then treats a vanished header as out
689 * of date instead of erroring out on a missing prerequisite */
690 for (size_t i = 0; i < nb_deps; i++) {
691 fput_escaped(deps[i], f);
692 fputs(":\n", f);
693 }
694 err = ferror(f);
695 if (!fclose(f) && !err && !replace_file(tmp, path))
696 return 0;
698 }
699 fprintf(stderr, "mscl: cannot write %s\n", path);
700 return 1;
701}
702
703int main(int argc, char **argv)
704{
705 int show_includes = 0;
706 int status;
707
708#ifdef _WIN32
709 argv = split_cmdline(GetCommandLineW(), &argc);
710 out_cp = GetConsoleOutputCP();
711 if (!out_cp)
712 out_cp = GetACP();
713#endif
714
715 if (argc < 2) {
716 fprintf(stderr, "usage: mscl <compiler> <arguments...>\n");
717 return 2;
718 }
719
720 for (int i = 2; i < argc; i++) {
721 const char *arg = argv[i];
722 if (!strcmp(arg, "-showIncludes") || !strcmp(arg, "/showIncludes"))
723 show_includes = 1;
724 else if (!strncmp(arg, "-Fo", 3) || !strncmp(arg, "/Fo", 3))
725 obj = arg + 3;
726 else if (is_source(arg))
728 }
729#ifdef _WIN32
730 if (src)
731 src = recode(src, CP_UTF8, out_cp);
732#endif
733
734 /* without an object there is nothing to write a .d file for, leave the
735 * include records alone in that case */
736 if (!obj)
737 show_includes = 0;
738
739#ifdef _WIN32
740 wchar_t *cmdline = cmdline_tail();
741 if (!show_includes)
742 return run(cmdline, 0);
743 init_deps();
744 status = run(cmdline, 1);
745#else
746 if (!show_includes) {
747 execvp(argv[1], argv + 1);
748 perror(argv[1]);
749 return 127;
750 }
751 init_deps();
752 status = run(argv + 1);
753#endif
754
755 /* A failed compilation is the primary result; do not write a dependency
756 * file from its truncated output. */
757 if (status != 0)
758 return status;
759 if (!write_depfile())
760 return 0;
762 return 1;
763}
static FILE * out
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
#define L(x)
Definition vpx_arith.h:36
static uint32_t BS_FUNC read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
int main
Definition dovi_rpuenc.c:38
int a
#define r
Definition input.c:42
#define b
Definition input.c:43
const char * arg
Definition jacosubdec.c:65
const char * from
Definition jacosubdec.c:64
const char * to
Definition webvttdec.c:36
uint8_t w
Definition llvidencdsp.c:39
Utility Preprocessor macros.
static void feed(const char *buf, size_t n)
Definition mscl.c:417
static const char * file_basename(const char *p)
Definition mscl.c:167
static void fput_escaped(const char *s, FILE *f)
Definition mscl.c:645
char * host
Definition mscl.c:274
static int unlink_file(const char *path)
Definition mscl.c:155
static int replace_file(const char *from, const char *to)
Definition mscl.c:160
static char * make_relative(const char *path)
Definition mscl.c:216
static void * xrealloc(void *ptr, size_t size)
Definition mscl.c:74
static size_t line_len
Definition mscl.c:66
static void add_dep(char *path)
Definition mscl.c:254
static void die(const char *msg)
Definition mscl.c:68
static struct @247131355217247325142334070304237061366312316121 * roots
#define INC_PREFIX
Definition mscl.c:55
static char * linebuf
Definition mscl.c:65
static size_t root_len(const char *p)
Definition mscl.c:200
static size_t line_max
Definition mscl.c:66
static int is_source(const char *arg)
Definition mscl.c:175
static const char * unmapped
Definition mscl.c:268
static size_t max_deps
Definition mscl.c:63
static char * cwd
Definition mscl.c:60
static void init_deps(void)
Definition mscl.c:443
char * root
Definition mscl.c:273
static size_t nb_deps
Definition mscl.c:63
static char * path_helper(const char *prog, const char *root)
Definition mscl.c:278
static char ** deps
Definition mscl.c:62
static FILE * open_wb(const char *path)
Definition mscl.c:150
static void feed_flush(void)
Definition mscl.c:434
static void process_line(char *line)
Definition mscl.c:398
static const char * obj
Definition mscl.c:57
static void add_include(char *p)
Definition mscl.c:365
static size_t nb_roots
Definition mscl.c:276
static int write_depfile(void)
Definition mscl.c:657
static int chr_eq(char a, char b)
Definition mscl.c:189
static char * host_path(const char *path)
Definition mscl.c:325
static char * xstrdup(const char *s)
Definition mscl.c:82
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
#define FF_ARRAY_ELEMS(a)
const uint8_t * code
Definition spdifenc.c:433
uint8_t run
Definition svq3.c:207
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src
Definition vp8dsp.c:248
int size
static double cb(void *priv, double x, double y)
Definition vf_geq.c:247
int len
#define WaitForSingleObject(a, b)
Definition w32pthreads.h:64