comparison src/build-msvctools/cc-msvc.cc @ 3061:f8299bb6c872

Initial support for native MSVC compilation. * add MSVC support files: compiler wrappers and support libraries * adapt libiconv to work with MSVC * adapt gettext to work with MSVC
author Michael Goffioul <michael.goffioul@gmail.com>
date Mon, 17 Jun 2013 22:43:11 -0400
parents
children b39e8dc859f7
comparison
equal deleted inserted replaced
3060:cbdf4575016d 3061:f8299bb6c872
1 /*
2 * cc-msvc
3 * This code is a C translation of the cccl script from Geoffrey Wossum
4 * (http://cccl.sourceforge.net), with minor modifications and support for
5 * additional compilation flags. This tool is primarily intended to compile
6 * Octave source code with MSVC compiler.
7 *
8 * Copyright (C) 2006 Michael Goffioul
9 *
10 * cccl
11 * Wrapper around MS's cl.exe and link.exe to make them act more like
12 * Unix cc and ld
13 *
14 * Copyright (C) 2000-2003 Geoffrey Wossum (gwossum@acm.org)
15 *
16 * =========================================================================
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; If not, see <http://www.gnu.org/licenses/>.
30 *
31 * =========================================================================
32 *
33 * Compile this file with "cl -EHs -O2 cc-msvc.cc" and install it into
34 * your PATH environment variable.
35 *
36 */
37
38 #include <iostream>
39 #include <string>
40 #include <vector>
41 #include <list>
42 #include <algorithm>
43 #include <io.h>
44 #include <stdio.h>
45 #define WIN32_LEAN_AND_MEAN
46 #include <windows.h>
47
48 #ifdef _MSC_VER
49 #define popen _popen
50 #define pclose _pclose
51 #endif
52
53 using namespace std;
54
55 static string usage_msg =
56 "Usage: cc-msvc [OPTIONS]\n"
57 "\n"
58 "cc-msvc is a wrapper around Microsoft's cl.exe and link.exe. It translates\n"
59 "parameters that Unix cc's and ld's understand to parameters that cl and link\n"
60 "understand.";
61 static string version_msg =
62 "cc-msvc 0.1\n"
63 "\n"
64 "Copyright 2006 Michael Goffioul\n"
65 "This is free software; see the source for copying conditions. There is NO\n"
66 "waranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
67
68 inline bool starts_with(const string& s, const string& prefix)
69 {
70 return (s.length() >= prefix.length() && s.find(prefix) == 0);
71 }
72
73 inline bool ends_with(const string& s, const string& suffix)
74 {
75 return (s.length() >= suffix.length() && s.rfind(suffix) == s.length()-suffix.length());
76 }
77
78 static list<string> split(const string& s, char delim)
79 {
80 list<string> result;
81 size_t current = 0, pos, len = s.length ();
82
83 while (current < len)
84 {
85 pos = s.find (delim, current);
86 if (pos == string::npos)
87 {
88 result.push_back (s.substr (current));
89 break;
90 }
91 else
92 {
93 result.push_back (s.substr (current, pos - current));
94 current = pos + 1;
95 }
96 }
97
98 return result;
99 }
100
101 static string get_line(FILE *fp)
102 {
103 static vector<char> buf(100);
104 int idx = 0;
105 char c;
106
107 while (1)
108 {
109 c = (char)fgetc(fp);
110 if (c == '\n' || c == EOF)
111 break;
112 if (buf.size() <= idx)
113 buf.resize(buf.size() + 100);
114 buf[idx++] = c;
115 }
116 if (idx == 0)
117 return string("");
118 else
119 return string(&buf[0], idx);
120 }
121
122 static string process_depend(const string& s)
123 {
124 string result;
125 string tmp(s);
126
127 if (tmp.find(' ') != std::string::npos)
128 {
129 std::string sp;
130 int len;
131
132 sp.resize(tmp.length()+1);
133 len = GetShortPathName(tmp.c_str(), &sp[0], tmp.length()+1);
134 sp.resize(len);
135 tmp = sp;
136 }
137
138 for (int i=0; i<tmp.length(); i++)
139 {
140 if (tmp[i] == ' ')
141 result += "\\ ";
142 else if (tmp[i] == '\\' && i < tmp.length()-1 && tmp[i+1] == '\\')
143 {
144 result.push_back('/');
145 i++;
146 }
147 else
148 result.push_back(tmp[i]);
149 }
150 return result;
151 }
152
153 static string de_cygwin_path(const string& s)
154 {
155 string result = s;
156
157 if (starts_with(s, "/cygdrive/"))
158 {
159 string cmd = "cygpath -m \"" + s + "\"";
160 FILE* pout = _popen(cmd.c_str(), "r");
161
162 if (pout != NULL)
163 {
164 result = get_line(pout);
165 _pclose(pout);
166 }
167 }
168
169 return result;
170 }
171
172 static string quote_path(const string& s)
173 {
174 string result = de_cygwin_path(s);
175
176 if (result.find(' ') != string::npos)
177 return "\"" + result + "\"";
178 return result;
179 }
180
181 static string quote_define(const string& name, const string& value)
182 {
183 if (value[0] == '"')
184 {
185 string result;
186
187 for (int i=0; i<value.length(); i++)
188 switch (value[i])
189 {
190 case '"':
191 result += "\\\"";
192 break;
193 case '&':
194 case '<':
195 case '>':
196 case '(':
197 case ')':
198 case '|':
199 case '^':
200 case '@':
201 result.push_back('^');
202 default:
203 result.push_back(value[i]);
204 break;
205 }
206 return ("\"" + name + "=" + result + "\"");
207 }
208 else
209 {
210 if (value.find_first_of("&<>()@^| ") != string::npos)
211 return ("\"" + name + "=" + value + "\"");
212 else
213 return (name + "=" + value);
214 }
215 }
216
217 static string quote_quotes(const string& s)
218 {
219 string result;
220
221 if (s.find('"') != string::npos)
222 {
223 for (int i=0; i<s.length(); i++)
224 if (s[i] == '"')
225 result += "\\\"";
226 else
227 result.push_back(s[i]);
228 }
229 else
230 result = s;
231
232 if (result.find_first_of("&<>()@^| ") != string::npos)
233 result = "\"" + result + "\"";
234
235 #if 0
236 if (result.find_first_of("<>") != string::npos)
237 {
238 /* Could not find a better way to avoid the problem
239 * with those characters. */
240 replace(result.begin(), result.end(), '<', '[');
241 replace(result.begin(), result.end(), '>', ']');
242 }
243 #endif
244
245 return result;
246 }
247
248 static int do_system(const string& cmd)
249 {
250 STARTUPINFO info;
251 PROCESS_INFORMATION proc;
252 DWORD result;
253
254 ZeroMemory (&info, sizeof (info));
255 info.cb = sizeof (info);
256 ZeroMemory (&proc, sizeof (proc));
257
258 if (CreateProcess (NULL, (char*)cmd.c_str (), NULL, NULL, TRUE, 0, NULL, NULL,
259 &info, &proc))
260 {
261 WaitForSingleObject (proc.hProcess, INFINITE);
262 GetExitCodeProcess (proc.hProcess, &result);
263 CloseHandle (proc.hProcess);
264 CloseHandle (proc.hThread);
265 }
266 else
267 result = (DWORD)-1;
268
269 return result;
270 }
271
272 static bool read_stdin(const char *filename)
273 {
274 char buf[1024];
275 int n;
276 FILE *fout = fopen(filename, "wb");
277
278 if (fout == NULL)
279 {
280 cerr << filename << ": cannot open file for writing" << endl;
281 return false;
282 }
283 while ((n = fread(buf, 1, 1024, stdin)) > 0)
284 fwrite(buf, 1, n, fout);
285 fclose(fout);
286 return true;
287 }
288
289 static void replace_option(string& s, const string& opt, const string& val = string())
290 {
291 if (starts_with(s, opt))
292 s.erase(0, opt.length()).insert(0, val);
293 if (ends_with(s, opt))
294 s.erase(s.length()-opt.length()).append(val);
295
296 string look_str = (" " + opt + " ");
297 int n = opt.length();
298 int pos;
299
300 while ((pos = s.find(look_str)) != string::npos)
301 s.replace(pos+1, n, val);
302 }
303
304 static void update_environment (void)
305 {
306 char name_buffer[1024];
307 DWORD len = GetModuleFileName (NULL, name_buffer, sizeof (name_buffer));
308
309 if (len == 0 && len >= sizeof (name_buffer))
310 return;
311
312 string root (name_buffer);
313 size_t pos = root.find_last_of ("\\/");
314
315 if (pos != string::npos)
316 root.resize (pos);
317
318 if (root == "bin"
319 || ends_with (root, "\\bin")
320 || ends_with (root, "/bin"))
321 {
322 if (root.size () == 3)
323 root.clear ();
324 else
325 root.resize (root.size () - 4);
326
327 string include_var = getenv ("INCLUDE");
328 string lib_var = getenv ("LIB");
329
330 if (include_var.empty ())
331 include_var = "INCLUDE=" + root + "\\include";
332 else
333 include_var = "INCLUDE=" + root + "\\include;" + include_var;
334
335 if (lib_var.empty ())
336 lib_var = "LIB=" + root + "\\lib";
337 else
338 lib_var = "LIB=" + root + "\\lib;" + lib_var;
339
340 putenv (include_var.c_str ());
341 putenv (lib_var.c_str ());
342 }
343 }
344
345 int main(int argc, char **argv)
346 {
347 string clopt, linkopt, cllinkopt, sourcefile, objectfile, optarg, prog, exefile;
348 list<string> Xlinkopt;
349 bool gotparam, dodepend, exeoutput, doshared, debug = false, read_from_stdin, gotXlinker;
350 bool mt_embed = true;
351 bool no_exceptions = false, default_libs = true, incremental_link = false;
352 bool cppmode = false;
353
354 prog = "cl";
355 clopt = "-nologo -MD -DWIN32 -D_WIN32 -D__WIN32__";
356 linkopt = "-nologo";
357 cllinkopt = "";
358 sourcefile = "";
359 objectfile = "";
360 gotparam = false;
361 dodepend = false;
362 exeoutput = true;
363 exefile = "";
364 doshared = false;
365 read_from_stdin = false;
366 gotXlinker = false;
367
368 cppmode = (ends_with (argv[0], "c++-msvc.exe")
369 || ends_with (argv[0], "c++-msvc")
370 || ends_with (argv[0], "clg++.exe")
371 || ends_with (argv[0], "clg++"));
372 if (cppmode)
373 clopt += " -EHsc";
374
375 update_environment ();
376
377 if (argc == 1)
378 {
379 cout << usage_msg << endl;
380 return 1;
381 }
382
383 for (int i=1; i<argc; i++)
384 {
385 string arg = argv[i];
386 size_t pos;
387
388 optarg = "";
389 gotparam = true;
390
391 if (gotXlinker)
392 {
393 Xlinkopt.push_back(arg);
394 gotXlinker = false;
395 continue;
396 }
397
398 if (!starts_with(arg, "-D") && (pos=arg.find('=')) != string::npos)
399 {
400 optarg = arg.substr(pos+1);
401 }
402
403 if (starts_with(arg, "-D"))
404 {
405 if ((pos=arg.find('=')) != string::npos)
406 {
407 optarg = arg.substr(pos+1);
408 arg.resize(pos);
409 arg = quote_define(arg, optarg);
410 }
411 clopt += " " + arg;
412 continue;
413 }
414
415 if (arg == "--version" || arg == "-V")
416 {
417 cout << version_msg << endl;
418 return 0;
419 }
420 else if (arg == "-M")
421 {
422 dodepend = true;
423 if (!exeoutput)
424 clopt += " -E";
425 else
426 {
427 exeoutput = false;
428 clopt += " -E -c";
429 }
430 }
431 else if (arg == "-P")
432 {
433 clopt += " -EP";
434 }
435 else if (arg == "-ansi")
436 {
437 clopt += " -Za";
438 }
439 else if (arg == "-c")
440 {
441 if (!dodepend)
442 {
443 clopt += " -c";
444 exeoutput = false;
445 }
446 }
447 else if (arg == "-g" || (starts_with(arg, "-g") && arg.length() == 3 && arg[2] >= '0' && arg[2] <= '9'))
448 {
449 clopt += " -Zi";
450 linkopt += " -debug";
451 }
452 else if (arg == "-d")
453 {
454 debug = true;
455 }
456 else if (arg == "-shared")
457 {
458 clopt += " -LD";
459 linkopt += " -DLL";
460 doshared = true;
461 }
462 else if (arg == "-mwindows")
463 {
464 linkopt += " -subsystem:windows";
465 }
466 else if (arg == "-O2" || arg == "-MD")
467 {
468 // do not pass those to the linker
469 clopt += (" " + arg);
470 }
471 else if (starts_with(arg, "-I"))
472 {
473 string path = arg.substr(2);
474 clopt += " -I" + quote_path(path);
475 }
476 else if (arg == "-isystem")
477 {
478 // Convert -isystem arguments into regular -I flags
479 if (i < argc-1)
480 {
481 arg = argv[++i];
482 // sysroot include prefix is not supported!!
483 if (arg.length () > 0 && arg[0] == '=')
484 {
485 cerr << "ERROR: isystem argument starting with '=' is not supported" << endl;
486 return 1;
487 }
488 clopt += " -I" + quote_path(arg);
489 }
490 else
491 {
492 cerr << "ERROR: isystem argument missing" << endl;
493 return 1;
494 }
495 }
496 else if (arg == "-isysroot"
497 || arg == "--sysroot")
498 {
499 // Ignore directory specifications (for the time being)
500 if (i < argc-1)
501 ++i;
502 else
503 {
504 cerr << "ERROR: missing argument for " << arg << endl;
505 return 1;
506 }
507 }
508 else if (starts_with(arg, "-L"))
509 {
510 string path = arg.substr(2);
511 linkopt += " -LIBPATH:" + quote_path(path);
512 cllinkopt += " -LIBPATH:" + quote_path(path);
513 }
514 else if (arg == "-link")
515 {
516 while (++i < argc)
517 {
518 arg = argv[i];
519 cllinkopt += " " + arg;
520 linkopt += " " + arg;
521 }
522 }
523 else if (starts_with(arg, "-l"))
524 {
525 string libname = arg.substr(2) + ".lib";
526 if (sourcefile.empty())
527 clopt += " " + libname;
528 else
529 cllinkopt += " " + libname;
530 linkopt += " " + libname;
531 }
532 else if (starts_with(arg, "-Wl,"))
533 {
534 list<string> flags = split (arg.substr (4), ',');
535 Xlinkopt.splice (Xlinkopt.end (), flags);
536 }
537 else if (arg == "-Xlinker")
538 {
539 gotXlinker = true;
540 }
541 else if (arg == "-Werror")
542 {
543 clopt += " -WX";
544 }
545 else if (arg == "-Wall")
546 {
547 //clopt += " -Wall";
548 }
549 else if (arg == "-fno-rtti")
550 {
551 clopt += " -GR-";
552 }
553 else if (arg == "-fno-exceptions")
554 {
555 no_exceptions = true;
556 }
557 else if (arg == "-m386" || arg == "-m486" || arg == "-mpentium" ||
558 arg == "-mpentiumpro" || arg == "-pedantic" || starts_with(arg, "-W") ||
559 arg == "-fPIC" || arg == "-nostdlib")
560 {
561 // ignore
562 }
563 else if (arg == "-noembed")
564 {
565 mt_embed = false;
566 }
567 else if (arg == "-nodefaultlibs")
568 {
569 default_libs = false;
570 }
571 else if (arg == "-incremental-link")
572 {
573 incremental_link = true;
574 }
575 else if (arg == "-o")
576 {
577 if (i < argc-1)
578 {
579 arg = argv[++i];
580 if (ends_with(arg, ".o") || ends_with(arg, ".obj"))
581 {
582 clopt += " -Fo" + quote_path(arg);
583 objectfile = arg;
584 }
585 else if (ends_with(arg, ".exe") || ends_with(arg, ".dll") || ends_with(arg, ".oct")
586 || ends_with(arg, ".mex"))
587 {
588 clopt += " -Fe" + quote_path(arg);
589 linkopt += " -out:" + quote_path(arg);
590 exefile = arg;
591 }
592 else
593 {
594 cerr << "WARNING: unrecognized output file type " << arg << ", assuming executable" << endl;
595 arg += ".exe";
596 clopt += " -Fe" + quote_path(arg);
597 linkopt += " -out:" + quote_path(arg);
598 exefile = arg;
599 }
600 }
601 else
602 {
603 cerr << "ERROR: output file name missing" << endl;
604 return 1;
605 }
606 }
607 else if (ends_with(arg, ".cc") || ends_with(arg, ".cxx") || ends_with(arg, ".C"))
608 {
609 clopt += " -Tp" + quote_path(arg);
610 sourcefile = arg;
611 }
612 else if (ends_with(arg, ".o") || ends_with(arg, ".obj") || ends_with(arg, ".a") ||
613 ends_with(arg, ".lib") || ends_with(arg, ".so"))
614 {
615 if (ends_with(arg, ".a"))
616 {
617 if (_access(arg.c_str(), 00) != 0)
618 {
619 string libarg;
620 int pos1 = arg.rfind('/');
621
622 if (pos1 != string::npos)
623 libarg = arg.substr(pos1+1);
624 else
625 libarg = arg;
626 if (starts_with(libarg, "lib"))
627 libarg = libarg.substr(3);
628 libarg = arg.substr(0, pos1+1) + libarg.substr(0, libarg.length()-1) + "lib";
629 if (_access(libarg.c_str(), 00) == 0)
630 {
631 cerr << "WARNING: Converting " << arg << " into " << libarg << endl;
632 arg = libarg;
633 }
634 }
635 }
636
637 if (sourcefile.empty())
638 {
639 linkopt += " " + quote_path(arg);
640 prog = "link";
641 }
642 else
643 {
644 cllinkopt += " " + quote_path(arg);
645 }
646 }
647 else if (ends_with(arg, ".c") || ends_with(arg, ".cpp"))
648 {
649 clopt += " " + quote_path(arg);
650 sourcefile = arg;
651 }
652 else if (ends_with(arg, ".dll"))
653 {
654 // trying to link against a DLL: convert to .lib file, keeping the same basename
655 string libarg = (" " + arg.substr(0, arg.length()-4) + ".lib");
656 clopt += libarg;
657 linkopt += libarg;
658 }
659 else if (ends_with (arg, ".def"))
660 {
661 cllinkopt += " -DEF:" + arg;
662 linkopt += " -DEF:" + arg;
663 }
664 else if (arg == "-")
665 {
666 // read source file from stdin
667 read_from_stdin = true;
668 }
669 else
670 {
671 clopt += " " + quote_quotes(arg);
672 linkopt += " " + quote_quotes(arg);
673 if (!optarg.empty())
674 {
675 clopt += "=" + quote_quotes(optarg);
676 linkopt += "=" + quote_quotes(optarg);
677 }
678 }
679 }
680
681 for (list<string>::const_iterator it = Xlinkopt.begin(); it != Xlinkopt.end(); ++it)
682 {
683 string arg = *it;
684
685 if (arg == "--out-implib"
686 || starts_with (arg, "--out-implib="))
687 {
688 string implib;
689
690 if (arg == "--out-implib")
691 {
692 ++it;
693 if (it != Xlinkopt.end ())
694 implib = *it;
695 else
696 {
697 cerr << "WARNING: missing import library name, ignored" << endl;
698 continue;
699 }
700 }
701 else
702 implib = arg.substr (13);
703
704 cllinkopt += " -IMPLIB:" + implib;
705 linkopt += " -IMPLIB:" + implib;
706 }
707 else if (arg == "--enable-auto-import"
708 || arg == "--enable-auto-image-base")
709 {
710 // Ignore these.
711 }
712 else if (arg == "--output-def")
713 {
714 ++it;
715 if (it == Xlinkopt.end ())
716 break;
717 }
718 else
719 {
720 cllinkopt += " " + arg;
721 linkopt += " " + arg;
722 }
723 }
724
725 if (! incremental_link)
726 {
727 std::string arg ("-incremental:no");
728
729 cllinkopt += " " + arg;
730 linkopt += " " + arg;
731 }
732
733 if (no_exceptions)
734 {
735 replace_option(clopt, "-EHsc");
736 replace_option(clopt, "-EHcs");
737 replace_option(clopt, "-EHs");
738 replace_option(clopt, "-EHc");
739 replace_option(clopt, "-EHa");
740 replace_option(clopt, "-GX-");
741 replace_option(clopt, "-GX");
742 }
743
744 if (dodepend && prog != "cl")
745 {
746 cerr << "ERROR: dependency generation only possible for source file" << endl;
747 return 1;
748 }
749
750 if (read_from_stdin)
751 {
752 sourcefile = "cc-msvc-tmp.c";
753 if (!read_stdin(sourcefile.c_str()))
754 {
755 unlink(sourcefile.c_str());
756 return 1;
757 }
758 clopt += (" " + sourcefile);
759 }
760
761 if (!exeoutput && !sourcefile.empty() && objectfile.empty())
762 {
763 // use .o suffix by default
764 int pos = sourcefile.rfind('.');
765 if (pos == string::npos)
766 objectfile = sourcefile + ".o";
767 else
768 objectfile = sourcefile.substr(0, pos) + ".o";
769 pos = objectfile.rfind('/');
770 if (pos != string::npos)
771 objectfile = objectfile.substr(pos+1);
772 clopt += " -Fo" + objectfile;
773 }
774
775 if (exeoutput && exefile.empty())
776 {
777 if (doshared)
778 exefile = "a.dll";
779 else
780 exefile = "a.exe";
781 clopt += " -Fe" + exefile;
782 linkopt += " -out:" + exefile;
783 }
784
785 if (exeoutput && default_libs)
786 {
787 cllinkopt += " dirent.lib msvcmath.lib shell32.lib advapi32.lib user32.lib kernel32.lib";
788 linkopt += " dirent.lib msvcmath.lib shell32.lib advapi32.lib user32.lib kernel32.lib";
789 }
790
791 string opts;
792 if (prog == "cl")
793 {
794 opts = clopt;
795 if (!cllinkopt.empty())
796 opts += " -link " + cllinkopt;
797 }
798 else
799 opts = linkopt;
800
801 if (dodepend)
802 {
803 FILE *fd;
804 string cmd = prog + " " + opts, line;
805 list<string> depend_list;
806
807 if (objectfile.empty())
808 {
809 cerr << "ERROR: object file name missing and cannot be determined" << endl;
810 return 1;
811 }
812 cout << objectfile << ":";
813
814 fd = popen(cmd.c_str(), "r");
815 if (fd == NULL)
816 {
817 cerr << "ERROR: cannot execute " << cmd << endl;
818 return 1;
819 }
820 while (!feof(fd))
821 {
822 line = get_line(fd);
823 if (starts_with(line, "#line"))
824 {
825 int pos1 = line.find('"'), pos2 = line.find('"', pos1+1);
826 depend_list.push_back(process_depend(line.substr(pos1+1, pos2-pos1-1)));
827 }
828 }
829 pclose(fd);
830
831 depend_list.sort();
832 depend_list.unique();
833 for (list<string>::const_iterator it=depend_list.begin(); it!=depend_list.end(); ++it)
834 cout << " \\" << endl << " " << *it;
835 cout << endl;
836 return 0;
837 }
838 else
839 {
840 string cmd = prog + " " + opts;
841 int cmdresult;
842
843 if (debug)
844 cout << cmd << endl;
845 if ((cmdresult=do_system(cmd)) == 0 && exeoutput)
846 {
847 // auto-embed the manifest, if any
848 if (exefile.empty())
849 {
850 if (!sourcefile.empty())
851 {
852 if (doshared)
853 exefile = sourcefile + ".dll";
854 else
855 exefile = sourcefile + ".exe";
856 }
857 else
858 {
859 cerr << "ERROR: cannot determine the output executable file" << endl;
860 return 1;
861 }
862 }
863
864 if (_access((exefile + ".manifest").c_str(), 00) == 0)
865 {
866 // Do not auto-embed for conftest.exe (temporary executable generated
867 // by configure scripts): this avoids wrong test results when an AV
868 // software is scanning the executable while mt.exe tries to update it
869 // (results in "mt.exe:general error c101008d:..."
870 //
871 // This should be harmless for common situations (can only be a problem
872 // if the target application uses conftest.exe as executable name; but
873 // I don't know any).
874
875 if (mt_embed && exefile != "conftest.exe")
876 {
877 cmd = "mt -nologo -outputresource:" + exefile
878 + (doshared ? ";2" : ";1") + " -manifest " + exefile + ".manifest";
879
880 if (debug)
881 cout << cmd << endl;
882
883 cmdresult = do_system(cmd);
884
885 if (cmdresult == 0)
886 _unlink((exefile + ".manifest").c_str());
887 }
888 }
889 }
890
891 if (read_from_stdin)
892 unlink(sourcefile.c_str());
893
894 return cmdresult;
895 }
896 }