diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/build-msvctools/cc-msvc.cc	Mon Jun 17 22:43:11 2013 -0400
@@ -0,0 +1,896 @@
+/*
+ * cc-msvc
+ * This code is a C translation of the cccl script from Geoffrey Wossum
+ * (http://cccl.sourceforge.net), with minor modifications and support for
+ * additional compilation flags. This tool is primarily intended to compile
+ * Octave source code with MSVC compiler.
+ *
+ * Copyright (C) 2006 Michael Goffioul
+ * 
+ * cccl
+ * Wrapper around MS's cl.exe and link.exe to make them act more like
+ * Unix cc and ld
+ * 
+ * Copyright (C) 2000-2003 Geoffrey Wossum (gwossum@acm.org)
+ *
+ * =========================================================================
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * =========================================================================
+ *
+ * Compile this file with "cl -EHs -O2 cc-msvc.cc" and install it into
+ * your PATH environment variable.
+ * 
+ */
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <io.h>
+#include <stdio.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifdef _MSC_VER
+#define popen _popen
+#define pclose _pclose
+#endif
+
+using namespace std;
+
+static string usage_msg = 
+"Usage: cc-msvc [OPTIONS]\n"
+"\n"
+"cc-msvc is a wrapper around Microsoft's cl.exe and link.exe.  It translates\n"
+"parameters that Unix cc's and ld's understand to parameters that cl and link\n"
+"understand.";
+static string version_msg =
+"cc-msvc 0.1\n"
+"\n"
+"Copyright 2006 Michael Goffioul\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"waranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
+
+inline bool starts_with(const string& s, const string& prefix)
+{
+	return (s.length() >= prefix.length() && s.find(prefix) == 0);
+}
+
+inline bool ends_with(const string& s, const string& suffix)
+{
+	return (s.length() >= suffix.length() && s.rfind(suffix) == s.length()-suffix.length());
+}
+
+static list<string> split(const string& s, char delim)
+{
+	list<string> result;
+	size_t current = 0, pos, len = s.length ();
+
+	while (current < len)
+	{
+        	pos = s.find (delim, current);
+		if (pos == string::npos)
+		{
+			result.push_back (s.substr (current));
+			break;
+		}
+		else
+		{
+			result.push_back (s.substr (current, pos - current));
+			current = pos + 1;
+		}
+	}
+
+	return result;
+}
+
+static string get_line(FILE *fp)
+{
+	static vector<char> buf(100);
+	int idx = 0;
+	char c;
+
+	while (1)
+	{
+		c = (char)fgetc(fp);
+		if (c == '\n' || c == EOF)
+			break;
+		if (buf.size() <= idx)
+			buf.resize(buf.size() + 100);
+		buf[idx++] = c;
+	}
+	if (idx == 0)
+		return string("");
+	else
+		return string(&buf[0], idx);
+}
+
+static string process_depend(const string& s)
+{
+	string result;
+	string tmp(s);
+
+	if (tmp.find(' ') != std::string::npos)
+	  {
+	    std::string sp;
+	    int len;
+
+	    sp.resize(tmp.length()+1);
+	    len = GetShortPathName(tmp.c_str(), &sp[0], tmp.length()+1);
+	    sp.resize(len);
+	    tmp = sp;
+	  }
+
+	for (int i=0; i<tmp.length(); i++)
+	{
+		if (tmp[i] == ' ')
+			result += "\\ ";
+		else if (tmp[i] == '\\' && i < tmp.length()-1 && tmp[i+1] == '\\')
+		{
+			result.push_back('/');
+			i++;
+		}
+		else
+			result.push_back(tmp[i]);
+	}
+	return result;
+}
+
+static string de_cygwin_path(const string& s)
+{
+	string result = s;
+
+        if (starts_with(s, "/cygdrive/"))
+	{
+		string cmd = "cygpath -m \"" + s + "\"";
+		FILE* pout = _popen(cmd.c_str(), "r");
+
+		if (pout != NULL)
+		{
+			result = get_line(pout);
+			_pclose(pout);
+		}
+	}
+
+	return result;
+}
+
+static string quote_path(const string& s)
+{
+	string result = de_cygwin_path(s);
+
+	if (result.find(' ') != string::npos)
+		return "\"" + result + "\"";
+	return result;
+}
+
+static string quote_define(const string& name, const string& value)
+{
+	if (value[0] == '"')
+	{
+		string result;
+
+		for (int i=0; i<value.length(); i++)
+			switch (value[i])
+			{
+			case '"':
+				result += "\\\"";
+				break;
+			case '&':
+			case '<':
+			case '>':
+			case '(':
+			case ')':
+			case '|':
+			case '^':
+			case '@':
+				result.push_back('^');
+			default:
+				result.push_back(value[i]);
+				break;
+			}
+		return ("\"" + name + "=" + result + "\"");
+	}
+	else
+	{
+		if (value.find_first_of("&<>()@^| ") != string::npos)
+			return ("\"" + name + "=" + value + "\"");
+		else
+			return (name + "=" + value);
+	}
+}
+
+static string quote_quotes(const string& s)
+{
+	string result;
+
+	if (s.find('"') != string::npos)
+	{
+		for (int i=0; i<s.length(); i++)
+			if (s[i] == '"')
+				result += "\\\"";
+			else
+				result.push_back(s[i]);
+	}
+	else
+		result = s;
+
+	if (result.find_first_of("&<>()@^| ") != string::npos)
+		result = "\"" + result + "\"";
+
+#if 0
+	if (result.find_first_of("<>") != string::npos)
+	{
+		/* Could not find a better way to avoid the problem
+		 * with those characters. */
+		replace(result.begin(), result.end(), '<', '[');
+		replace(result.begin(), result.end(), '>', ']');
+	}
+#endif
+
+	return result;
+}
+
+static int do_system(const string& cmd)
+{
+  STARTUPINFO info;
+  PROCESS_INFORMATION proc;
+  DWORD	 result;
+
+  ZeroMemory (&info, sizeof (info));
+  info.cb = sizeof (info);
+  ZeroMemory (&proc, sizeof (proc));
+
+  if (CreateProcess (NULL, (char*)cmd.c_str (), NULL, NULL, TRUE, 0, NULL, NULL,
+		     &info, &proc))
+    {
+      WaitForSingleObject (proc.hProcess, INFINITE);
+      GetExitCodeProcess (proc.hProcess, &result);
+      CloseHandle (proc.hProcess);
+      CloseHandle (proc.hThread);
+    }
+  else
+    result = (DWORD)-1;
+
+  return result;
+}
+
+static bool read_stdin(const char *filename)
+{
+	char buf[1024];
+	int n;
+	FILE *fout = fopen(filename, "wb");
+
+	if (fout == NULL)
+	{
+		cerr << filename << ": cannot open file for writing" << endl;
+		return false;
+	}
+	while ((n = fread(buf, 1, 1024, stdin)) > 0)
+		fwrite(buf, 1, n, fout);
+	fclose(fout);
+	return true;
+}
+
+static void replace_option(string& s, const string& opt, const string& val = string())
+{
+  if (starts_with(s, opt))
+    s.erase(0, opt.length()).insert(0, val);
+  if (ends_with(s, opt))
+    s.erase(s.length()-opt.length()).append(val);
+
+  string look_str = (" " + opt + " ");
+  int n = opt.length();
+  int pos;
+
+  while ((pos = s.find(look_str)) != string::npos)
+    s.replace(pos+1, n, val);
+}
+
+static void update_environment (void)
+{
+  char name_buffer[1024];
+  DWORD len = GetModuleFileName (NULL, name_buffer, sizeof (name_buffer));
+
+  if (len == 0 && len >= sizeof (name_buffer))
+    return;
+
+  string root (name_buffer);
+  size_t pos = root.find_last_of ("\\/");
+
+  if (pos != string::npos)
+    root.resize (pos);
+
+  if (root == "bin"
+      || ends_with (root, "\\bin")
+      || ends_with (root, "/bin"))
+    {
+      if (root.size () == 3)
+        root.clear ();
+      else
+        root.resize (root.size () - 4);
+
+      string include_var = getenv ("INCLUDE");
+      string lib_var = getenv ("LIB");
+
+      if (include_var.empty ())
+        include_var = "INCLUDE=" + root + "\\include";
+      else
+        include_var = "INCLUDE=" + root + "\\include;" + include_var;
+
+      if (lib_var.empty ())
+        lib_var = "LIB=" + root + "\\lib";
+      else
+        lib_var = "LIB=" + root + "\\lib;" + lib_var;
+
+      putenv (include_var.c_str ());
+      putenv (lib_var.c_str ());
+    }
+}
+
+int main(int argc, char **argv)
+{
+	string clopt, linkopt, cllinkopt, sourcefile, objectfile, optarg, prog, exefile;
+	list<string> Xlinkopt;
+	bool gotparam, dodepend, exeoutput, doshared, debug = false, read_from_stdin, gotXlinker;
+	bool mt_embed = true;
+	bool no_exceptions = false, default_libs = true, incremental_link = false;
+        bool cppmode = false;
+
+	prog = "cl";
+	clopt = "-nologo -MD -DWIN32 -D_WIN32 -D__WIN32__";
+	linkopt = "-nologo";
+	cllinkopt = "";
+	sourcefile = "";
+	objectfile = "";
+	gotparam = false;
+	dodepend = false;
+	exeoutput = true;
+	exefile = "";
+	doshared = false;
+	read_from_stdin = false;
+	gotXlinker = false;
+
+        cppmode = (ends_with (argv[0], "c++-msvc.exe")
+                   || ends_with (argv[0], "c++-msvc")
+                   || ends_with (argv[0], "clg++.exe")
+                   || ends_with (argv[0], "clg++"));
+        if (cppmode)
+                clopt += " -EHsc";
+
+        update_environment ();
+
+	if (argc == 1)
+	{
+		cout << usage_msg << endl;
+		return 1;
+	}
+
+	for (int i=1; i<argc; i++)
+	{
+		string arg = argv[i];
+		size_t pos;
+
+		optarg = "";
+		gotparam = true;
+
+		if (gotXlinker)
+		{
+			Xlinkopt.push_back(arg);
+			gotXlinker = false;
+			continue;
+		}
+
+		if (!starts_with(arg, "-D") && (pos=arg.find('=')) != string::npos)
+		{
+			optarg = arg.substr(pos+1);
+		}
+
+		if (starts_with(arg, "-D"))
+		{
+			if ((pos=arg.find('=')) != string::npos)
+			{
+				optarg = arg.substr(pos+1);
+				arg.resize(pos);
+				arg = quote_define(arg, optarg);
+			}
+			clopt += " " + arg;
+			continue;
+		}
+
+		if (arg == "--version" || arg == "-V")
+		{
+			cout << version_msg << endl;
+			return 0;
+		}
+		else if (arg == "-M")
+		{
+			dodepend = true;
+			if (!exeoutput)
+				clopt += " -E";
+			else
+			{
+				exeoutput = false;
+				clopt += " -E -c";
+			}
+		}
+		else if (arg == "-P")
+		{
+			clopt += " -EP";
+		}
+		else if (arg == "-ansi")
+		{
+			clopt += " -Za";
+		}
+		else if (arg == "-c")
+		{
+			if (!dodepend)
+			{
+				clopt += " -c";
+				exeoutput = false;
+			}
+		}
+		else if (arg == "-g" || (starts_with(arg, "-g") && arg.length() == 3 && arg[2] >= '0' && arg[2] <= '9'))
+		{
+			clopt += " -Zi";
+			linkopt += " -debug";
+		}
+		else if (arg == "-d")
+		{
+			debug = true;
+		}
+		else if (arg == "-shared")
+		{
+			clopt += " -LD";
+			linkopt += " -DLL";
+			doshared = true;
+		}
+		else if (arg == "-mwindows")
+		{
+			linkopt += " -subsystem:windows";
+		}
+		else if (arg == "-O2" || arg == "-MD")
+		{
+			// do not pass those to the linker
+			clopt += (" " + arg);
+		}
+		else if (starts_with(arg, "-I"))
+		{
+			string path = arg.substr(2);
+			clopt += " -I" + quote_path(path);
+		}
+		else if (arg == "-isystem")
+		{
+			// Convert -isystem arguments into regular -I flags
+			if (i < argc-1)
+			{
+				arg = argv[++i];
+				// sysroot include prefix is not supported!!
+				if (arg.length () > 0 && arg[0] == '=')
+				{
+					cerr << "ERROR: isystem argument starting with '=' is not supported" << endl;
+					return 1;
+				}
+				clopt += " -I" + quote_path(arg);
+			}
+			else
+			{
+				cerr << "ERROR: isystem argument missing" << endl;
+				return 1;
+			}
+		}
+		else if (arg == "-isysroot"
+			 || arg == "--sysroot")
+		{
+			// Ignore directory specifications (for the time being)
+			if (i < argc-1)
+				++i;
+			else
+			{
+				cerr << "ERROR: missing argument for " << arg << endl;
+				return 1;
+			}
+		}
+		else if (starts_with(arg, "-L"))
+		{
+			string path = arg.substr(2);
+			linkopt += " -LIBPATH:" + quote_path(path);
+			cllinkopt += " -LIBPATH:" + quote_path(path);
+		}
+                else if (arg == "-link")
+                {
+                        while (++i < argc)
+                        {
+                                arg = argv[i];
+                                cllinkopt += " " + arg;
+                                linkopt += " " + arg;
+                        }
+                }
+		else if (starts_with(arg, "-l"))
+		{
+			string libname = arg.substr(2) + ".lib";
+			if (sourcefile.empty())
+				clopt += " " + libname;
+			else
+				cllinkopt += " " + libname;
+			linkopt += " " + libname;
+		}
+		else if (starts_with(arg, "-Wl,"))
+		{
+                        list<string> flags = split (arg.substr (4), ',');
+			Xlinkopt.splice (Xlinkopt.end (), flags);
+		}
+		else if (arg == "-Xlinker")
+		{
+			gotXlinker = true;
+		}
+		else if (arg == "-Werror")
+		{
+			clopt += " -WX";
+		}
+		else if (arg == "-Wall")
+		{
+			//clopt += " -Wall";
+		}
+		else if (arg == "-fno-rtti")
+		{
+			clopt += " -GR-";
+		}
+		else if (arg == "-fno-exceptions")
+		{
+			no_exceptions = true;
+		}
+		else if (arg == "-m386" || arg == "-m486" || arg == "-mpentium" ||
+			 arg == "-mpentiumpro" || arg == "-pedantic" || starts_with(arg, "-W") ||
+			 arg == "-fPIC" || arg == "-nostdlib")
+		{
+			// ignore
+		}
+		else if (arg == "-noembed")
+		{
+			mt_embed = false;
+		}
+		else if (arg == "-nodefaultlibs")
+		{
+			default_libs = false;
+		}
+		else if (arg == "-incremental-link")
+		{
+			incremental_link = true;
+		}
+		else if (arg == "-o")
+		{
+			if (i < argc-1)
+			{
+				arg = argv[++i];
+				if (ends_with(arg, ".o") || ends_with(arg, ".obj"))
+				{
+					clopt += " -Fo" + quote_path(arg);
+					objectfile = arg;
+				}
+				else if (ends_with(arg, ".exe") || ends_with(arg, ".dll") || ends_with(arg, ".oct")
+					 || ends_with(arg, ".mex"))
+				{
+					clopt += " -Fe" + quote_path(arg);
+					linkopt += " -out:" + quote_path(arg);
+					exefile = arg;
+				}
+				else
+				{
+					cerr << "WARNING: unrecognized output file type " << arg << ", assuming executable" << endl;
+					arg += ".exe";
+					clopt += " -Fe" + quote_path(arg);
+					linkopt += " -out:" + quote_path(arg);
+					exefile = arg;
+				}
+			}
+			else
+			{
+				cerr << "ERROR: output file name missing" << endl;
+				return 1;
+			}
+		}
+		else if (ends_with(arg, ".cc") || ends_with(arg, ".cxx") || ends_with(arg, ".C"))
+		{
+			clopt += " -Tp" + quote_path(arg);
+			sourcefile = arg;
+		}
+		else if (ends_with(arg, ".o") || ends_with(arg, ".obj") || ends_with(arg, ".a") ||
+			 ends_with(arg, ".lib") || ends_with(arg, ".so"))
+		{
+			if (ends_with(arg, ".a"))
+			{
+				if (_access(arg.c_str(), 00) != 0)
+				{
+					string libarg;
+					int pos1 = arg.rfind('/');
+
+					if (pos1 != string::npos)
+						libarg = arg.substr(pos1+1);
+					else
+						libarg = arg;
+					if (starts_with(libarg, "lib"))
+						libarg = libarg.substr(3);
+					libarg = arg.substr(0, pos1+1) + libarg.substr(0, libarg.length()-1) + "lib";
+					if (_access(libarg.c_str(), 00) == 0)
+					{
+						cerr << "WARNING: Converting " << arg << " into " << libarg << endl;
+						arg = libarg;
+					}
+				}
+			}
+
+			if (sourcefile.empty())
+			{
+				linkopt += " " + quote_path(arg);
+				prog = "link";
+			}
+			else
+			{
+				cllinkopt += " " + quote_path(arg);
+			}
+		}
+		else if (ends_with(arg, ".c") || ends_with(arg, ".cpp"))
+		{
+			clopt += " " + quote_path(arg);
+			sourcefile = arg;
+		}
+		else if (ends_with(arg, ".dll"))
+		{
+			// trying to link against a DLL: convert to .lib file, keeping the same basename
+			string libarg = (" " + arg.substr(0, arg.length()-4) + ".lib");
+			clopt += libarg;
+			linkopt += libarg;
+		}
+		else if (ends_with (arg, ".def"))
+		{
+			cllinkopt += " -DEF:" + arg;
+			linkopt += " -DEF:" + arg;
+		}
+		else if (arg == "-")
+		{
+			// read source file from stdin
+			read_from_stdin = true;
+		}
+		else
+		{
+			clopt += " " + quote_quotes(arg);
+			linkopt += " " + quote_quotes(arg);
+			if (!optarg.empty())
+			{
+				clopt += "=" + quote_quotes(optarg);
+				linkopt += "=" + quote_quotes(optarg);
+			}
+		}
+	}
+
+	for (list<string>::const_iterator it = Xlinkopt.begin(); it != Xlinkopt.end(); ++it)
+	{
+		string arg = *it;
+
+		if (arg == "--out-implib"
+		    || starts_with (arg, "--out-implib="))
+		{
+			string implib;
+
+			if (arg == "--out-implib")
+			{
+				++it;
+				if (it != Xlinkopt.end ())
+					implib = *it;
+				else
+				{
+					cerr << "WARNING: missing import library name, ignored" << endl;
+					continue;
+				}
+			}
+			else
+				implib = arg.substr (13);
+
+			cllinkopt += " -IMPLIB:" + implib;
+			linkopt += " -IMPLIB:" + implib;
+		}
+		else if (arg == "--enable-auto-import"
+			 || arg == "--enable-auto-image-base")
+		{
+			// Ignore these.
+		}
+		else if (arg == "--output-def")
+		{
+			++it;
+			if (it == Xlinkopt.end ())
+				break;
+		}
+		else
+		{
+			cllinkopt += " " + arg;
+			linkopt += " " + arg;
+		}
+	}
+
+	if (! incremental_link)
+	{
+                std::string arg ("-incremental:no");
+
+		cllinkopt += " " + arg;
+		linkopt += " " + arg;
+	}
+
+	if (no_exceptions)
+	{
+		replace_option(clopt, "-EHsc");
+		replace_option(clopt, "-EHcs");
+		replace_option(clopt, "-EHs");
+		replace_option(clopt, "-EHc");
+		replace_option(clopt, "-EHa");
+		replace_option(clopt, "-GX-");
+		replace_option(clopt, "-GX");
+	}
+
+	if (dodepend && prog != "cl")
+	{
+		cerr << "ERROR: dependency generation only possible for source file" << endl;
+		return 1;
+	}
+
+	if (read_from_stdin)
+	{
+		sourcefile = "cc-msvc-tmp.c";
+		if (!read_stdin(sourcefile.c_str()))
+		{
+			unlink(sourcefile.c_str());
+			return 1;
+		}
+		clopt += (" " + sourcefile);
+	}
+
+	if (!exeoutput && !sourcefile.empty() && objectfile.empty())
+	{
+		// use .o suffix by default
+		int pos = sourcefile.rfind('.');
+		if (pos == string::npos)
+			objectfile = sourcefile + ".o";
+		else
+			objectfile = sourcefile.substr(0, pos) + ".o";
+		pos = objectfile.rfind('/');
+		if (pos != string::npos)
+			objectfile = objectfile.substr(pos+1);
+		clopt += " -Fo" + objectfile;
+	}
+
+        if (exeoutput && exefile.empty())
+        {
+                if (doshared)
+                        exefile = "a.dll";
+                else
+                        exefile = "a.exe";
+                clopt += " -Fe" + exefile;
+                linkopt += " -out:" + exefile;
+        }
+
+	if (exeoutput && default_libs)
+	{
+		cllinkopt += " dirent.lib msvcmath.lib shell32.lib advapi32.lib user32.lib kernel32.lib";
+		linkopt += " dirent.lib msvcmath.lib shell32.lib advapi32.lib user32.lib kernel32.lib";
+	}
+
+	string opts;
+	if (prog == "cl")
+	{
+		opts = clopt;
+		if (!cllinkopt.empty())
+			opts += " -link " + cllinkopt;
+	}
+	else
+		opts = linkopt;
+
+	if (dodepend)
+	{
+		FILE *fd;
+		string cmd = prog + " " + opts, line;
+		list<string> depend_list;
+
+		if (objectfile.empty())
+		{
+			cerr << "ERROR: object file name missing and cannot be determined" << endl;
+			return 1;
+		}
+		cout << objectfile << ":";
+
+		fd = popen(cmd.c_str(), "r");
+		if (fd == NULL)
+		{
+			cerr << "ERROR: cannot execute " << cmd << endl;
+			return 1;
+		}
+		while (!feof(fd))
+		{
+			line = get_line(fd);
+			if (starts_with(line, "#line"))
+			{
+				int pos1 = line.find('"'), pos2 = line.find('"', pos1+1);
+				depend_list.push_back(process_depend(line.substr(pos1+1, pos2-pos1-1)));
+			}
+		}
+		pclose(fd);
+
+		depend_list.sort();
+		depend_list.unique();
+		for (list<string>::const_iterator it=depend_list.begin(); it!=depend_list.end(); ++it)
+			cout << " \\" << endl << "  " << *it;
+		cout << endl;
+		return 0;
+	}
+	else
+	{
+		string cmd = prog + " " + opts;
+		int cmdresult;
+
+		if (debug)
+			cout << cmd << endl;
+		if ((cmdresult=do_system(cmd)) == 0 && exeoutput)
+		{
+			// auto-embed the manifest, if any
+			if (exefile.empty())
+			{
+				if (!sourcefile.empty())
+				{
+					if (doshared)
+						exefile = sourcefile + ".dll";
+					else
+						exefile = sourcefile + ".exe";
+				}
+				else
+				{
+					cerr << "ERROR: cannot determine the output executable file" << endl;
+					return 1;
+				}
+			}
+
+			if (_access((exefile + ".manifest").c_str(), 00) == 0)
+			{
+				// Do not auto-embed for conftest.exe (temporary executable generated
+				// by configure scripts): this avoids wrong test results when an AV
+				// software is scanning the executable while mt.exe tries to update it
+				// (results in "mt.exe:general error c101008d:..."
+				//
+				// This should be harmless for common situations (can only be a problem
+				// if the target application uses conftest.exe as executable name; but
+				// I don't know any).
+
+				if (mt_embed && exefile != "conftest.exe")
+				{
+					cmd = "mt -nologo -outputresource:" + exefile
+					      + (doshared ? ";2" : ";1") + " -manifest " + exefile + ".manifest";
+
+					if (debug)
+						cout << cmd << endl;
+
+					cmdresult = do_system(cmd);
+
+					if (cmdresult == 0)
+						_unlink((exefile + ".manifest").c_str());
+				}
+			}
+		}
+
+		if (read_from_stdin)
+			unlink(sourcefile.c_str());
+
+		return cmdresult;
+	}
+}