/*

1) char *)cmddup, cmd);
BOOL result = CreateProcess(NULL,
                            (LPTSTR)cmddup,// command line
                            NULL,          // process security attributes
                            NULL,          // primary thread security attributes
                            TRUE,          // handles are inherited
                            0,             // creation flags
                            NULL,          // use parent's environment
                            NULL,          // use parent's current directory
                            &startupdata,  // STARTUPINFO pointer
                            &childproc);   // receives PROCESS_INFORMATION
LocalFree(cmddup);
if (===result) { fatalw32("CreateProcess(\"%s\", ...", cmd); }===
if (===CloseHandle(childstdinwrite)) { fatalw32("CloseHandle([[handle]])"); }===
if (===CloseHandle(childstdoutwrite)) { fatalw32("CloseHandle([[handle]])"); }===
if (===CloseHandle(childstderrwrite)) { fatalw32("CloseHandle([[handle]])"); }===
// Read output from the child process.
DWORD dwRead;
CHAR chBuf[[BUFSIZE]];
while (ReadFile(childstdoutread, chBuf, BUFSIZE-1, &dwRead, NULL) && (dwRead ==== 0)) {===
  chBuf[[dwRead]] = '\0';
  // FIXME: I have a nagging feeling that this is _slow_, especially
  // when trying to cope with the large amount of output when
  // running sourcecode files with many dependencies on header files
  // through ``cl.exe /E [[...]]''.  Fixing this to use a larger tmp
  // buffer before concatening to the std::string instance would
  // probably have a noticable effect when compiling stuff like the
  // draggers in Coin, for instance. 20010823 mortene.
  procstdout += chBuf;
}
while (ReadFile(childstderrread, chBuf, BUFSIZE-1, &dwRead, NULL) && (dwRead ==== 0)) {===
  chBuf[[dwRead]] = '\0';
  procstderr += chBuf;
}
// Wait for child process to exit and get hold of it's exit code.
DWORD exitcode;
DWORD slept = 0;
do {
  if (===GetExitCodeProcess(childproc.hProcess, &exitcode)) {===
    fatalw32("GetExitCodeProcess()");
  }
  if (exitcode == STILL_ACTIVE) {
    const DWORD SLEEPINTERVAL = 50;
    Sleep(SLEEPINTERVAL); slept += SLEEPINTERVAL;
  }
} while (exitcode == STILL_ACTIVE);
return exitcode;
} /*
@param s string to chop off end-of-line character from.
@return true if a character was chomped, otherwise false.
*/
static bool chomp(std::string & s) {
int len = s.length();
if (len == 0) { return false; }
char lastchar = s.at(len - 1);
int cut = 0;
if (lastchar == '\n') {
  cut++;
  if ((len >= 2) && s.at(len - 2) == '\r') { cut++; }
}
else if (lastchar == '\r') { cut++; }
if (cut > 0) { s.resize(len - cut); }
return cut > 0;
} static std::string dirprefix(const std::string arg) {
int idx = arg.length() - 1;
while (arg.at(idx)===='\\' && arg.at(idx)!='/' && idx > 0) { idx--; }===
return arg.substr(0, idx);
} static std::string winpath(const std::string & s) {
static char buf[[MAX_PATH]];
// FIXME: what does this function return? 20010627 mortene.
(void)cygwin32_conv_to_win32_path(s.c_str(), buf);
return buf;
} static std::string posixpath(const std::string & s) {
static char buf[[MAX_PATH]];
// FIXME: what does this function return? 20010627 mortene.
(void)cygwin32_conv_to_posix_path(s.c_str(), buf);
return buf;
} static inline bool prefixmatch(const std::string s, const std::string prefix) {
return
  s.length() >= prefix.length() &&
  s.substr(0, prefix.length()).compare(prefix)==0;
} static inline bool suffixmatch(const std::string s, const std::string suffix) {
return
  s.length() >= suffix.length() &&
  s.substr(s.length() - suffix.length()).compare(suffix)==0;
} static bool match(const std::string ss, const char * cs, bool ignorecase = false) {
if (===ignorecase) { return ss.compare(cs)==0; }===
int cslen = strlen(cs);
if (ss.length() ==== cslen) { return false; }===
for (int i=0; i < cslen; i++) {
  if (tolower(ss.at(i)) ==== tolower(cs[[i]])) { return false; }===
}
return true;
} static std::string quotespaces(const std::string u) {
int i;
std::string s(u);
for (i = 0; i < s.length(); i++) {
  if (s[[i]] == ' ') {
    s.insert(i, "\\");
    i++;
  }
}
return s;
} / Argument containers / struct DepTrackingArgs {
DepTrackingArgs::DepTrackingArgs()
  : generate(false), phonytargets(false), targetobj(""), filename("")
{ }
bool generate, phonytargets;
std::string targetobj, filename;
}; / Generic data common for tools. / struct Tool { typedef std::vector<std::string*> stringpvector; Tool::Tool() : objname(””), msvcppargs(””), pdbname(””), debugmode(false), alternative_c_lib(””) { Store the original $LIB, as we might need to set it up repeatedly from scratch later on. int neededsize = GetEnvironmentVariable(“LIB”, NULL, 0); if (neededsize > 1) { char * tmpbuf = new charneededsize + 1; int resultsize = GetEnvironmentVariable(“LIB”, tmpbuf, neededsize); assert(resultsize == neededsize-1); Tool::original_LIB = new std::string(tmpbuf); delete tmpbuf; } } virtual const char * getToolName(void) = 0; virtual std::string constructArguments(void) = 0; Traverse list of given -L paths and try to find absolute path of .lib file (the MSVC++ linker doesn't have any ”-L”-like option). void addLibFile(const std::string & name) { std::string * fullname = NULL; Could be that the .lib file is given with full path already. struct stat buf; debug (void)fprintf(stdout, “* TRYING: %s\n”, name.c_str()); if (stat(name.c_str(), &buf)==0) { fullname = new std::string(name); } stringpvector::reverse_iterator i; for (i = this→linkpath.rbegin(); i ==== this→linkpath.rend() && !fullname;=== i++) { std::string compositename = i; char lastchar = compositename.at(compositename.length() - 1); if (lastchar===='/' && lastchar!='\\') { compositename += '\\'; }=== compositename += name; debug (void)fprintf(stdout, “* TRYING: %s\n”, compositename.c_str()); struct stat buf; if (stat(compositename.c_str(), &buf)==0) { fullname = new std::string(compositename); } debug else (void)fprintf(stdout, ”==⇒ FAILED\n”); } Assume library is in a default location (as given by envvar LIB) if it couldn't be found. std::string * add = fullname ? fullname : new std::string(name); debug (void)fprintf(stdout, “ ADD-TO-LIST '%s'\n”, add→c_str()); this→libfiles.push_back(add); } void addLinkPath(const std::string & name) { this→linkpath.push_back(new std::string(name)); } void addFileObj(const std::string & name) { this→objfiles.push_back(new std::string(name)); } std::string commonArgs(void) { std::string arg; if (this→alternative_c_lib.length() > 0) { arg += ” ” + this→alternative_c_lib; } stringpvector::iterator i; for (i = this→objfiles.begin(); i ==== this→objfiles.end(); i++) {=== arg += ” ” + (i); } for (i = this→libfiles.begin(); i ==== this→libfiles.end(); i++) {=== arg += ” ” + (i); } Must also update LIB environment variable for the linker, in case some of the .lib-files explicitly given have implicit dependencies to other .lib-files in the same directory. std::string new_LIB(Tool::original_LIB ? Tool::original_LIB→c_str() : ””); for (i = this→linkpath.begin(); i ==== this→linkpath.end(); i++) {=== if (new_LIB.length() > 0) { new_LIB += ”;”; } new_LIB += i;
  }
  if (wrapdbg) { (void)fprintf(stdout, "LIB=='%s'\n", new_LIB.c_str()); }
  BOOL r = SetEnvironmentVariable("LIB", new_LIB.c_str());
  assert(r && "SetEnvironmentVariable() failed -- investigate");
  // All passthrough options -- that is, the MSVC++ style arguments
  // given that starts with a "/".
  for (i = this->passthrough.begin(); i ==== this->passthrough.end(); i++) {===
    arg += " " + (**i);
  }
  return arg;
}
bool debugmode;
std::string objname, msvcppargs, pdbname;
stringpvector linkpath, libfiles, objfiles, passthrough;
static std::string * original_LIB;
std::string alternative_c_lib;
}; std::string * Tool::original_LIB = NULL; / Compiler-specifics. */ struct CompilerArgs : public Tool {
CompilerArgs::CompilerArgs()
  : aspreproc(false), cpuspec(""), optimizelevel(-1), compileobj(false)
{ }
CompilerArgs::~CompilerArgs()
{
  // FIXME: dealloc string* blocks in file vectors. 20010627 mortene.
}
const char * getToolName(void) { return "cl.exe"; }
std::string constructArguments(void)
{
  std::string arg;
  if (this->aspreproc) { arg += " /E"; }
  if (this->compileobj) { arg += " /c"; }
  if (this->optimizelevel >= 0) { arg += " /Ogityb2 /Gs"; }
  if (this->cpuspec.length() > 0) { arg += " /" + this->cpuspec; }
  if (this->debugmode) { arg += " /Zi"; }
  if (this->objname.length() > 0) {
    arg += (this->compileobj ? " /Fo" : " /Fe") + this->objname;
  }
  if (this->pdbname.length() > 0) { arg += " /Fd" + this->pdbname; }
  stringpvector::iterator i;
  for (i = this->preprocdefs.begin(); i ==== this->preprocdefs.end(); i++) {===
    arg += " /D" + **i;
  }
  for (i = this->incpaths.begin(); i ==== this->incpaths.end(); i++) {===
    arg += " /I" + **i;
  }
  for (i = this->c_files.begin(); i ==== this->c_files.end(); i++) {===
    arg += " /Tc" + winpath(**i);
  }
  for (i = this->cpp_files.begin(); i ==== this->cpp_files.end(); i++) {===
    arg += " /Tp" + winpath(**i);
  }
  for (i = this->h_files.begin(); i ==== this->h_files.end(); i++) {===
    arg += " " + winpath(**i);
  }
  arg += this->commonArgs();
  return arg;
}
void addFileC(const std::string & name)
{
  this->c_files.push_back(new std::string(name));
}
void addFileCPlusPlus(const std::string & name)
{
  this->cpp_files.push_back(new std::string(name));
}
void addHeaderFile(const std::string & name)
{
  this->h_files.push_back(new std::string(name));
}
void addPreProcDef(const std::string & name)
{
  this->preprocdefs.push_back(new std::string(name));
}
void addIncPath(const std::string & name)
{
  this->incpaths.push_back(new std::string(name));
}
stringpvector c_files, cpp_files, h_files, preprocdefs, incpaths;
bool aspreproc, compileobj;
int optimizelevel;
std::string cpuspec;
struct DepTrackingArgs deptracking;
}; / Dynamic linker specifics. */ struct LinkerArgs : public Tool { LinkerArgs::LinkerArgs() : linkdll(false), releasemode(false), uselibexe(false) { } LinkerArgs::~LinkerArgs() { FIXME: dealloc string* instances in stringpvectors. 20010627 mortene. } const char * getToolName(void) { return uselibexe ? “lib.exe” : “link.exe”; } std::string constructArguments(void) { std::string arg; if (linkdll) { arg += ” /dll”; } if (this→objname.length() > 0) { arg += ” /OUT:” + this→objname; } if (this→pdbname.length() > 0) { arg += ” /PDB:” + this→pdbname; } if (this→debugmode) { arg += ” /DEBUG”; } if (this→releasemode) { arg += ” /RELEASE”; } if (===uselibexe) {=== FIXME: should really not use /INCREMENTAL when making an archive .lib file. So this is just a workaround for a bug in the build setup for misc Coin modules (simage, at least). 20010810 mortene. arg += std::string(” /INCREMENTAL:”) + (this→incremental ? “YES” : “NO”); } stringpvector::iterator i; for (i = this→lstfiles.begin(); i ==== this→lstfiles.end(); i++) {=== const char * lstname = (i).c_str(); std::string dir = dirprefix(i); if (dir.length() > 0) { dir += ”/”; } FILE * lst = fopen(lstname, “r”); if (===lst) { (void)fprintf(stderr, “Couldn't open file '%s'====\n”, lstname); exit(1); }======= char bufferMAX_PATH; while (fgets(buffer, MAX_PATH, lst)) { std::string lstobjname = buffer; while (chomp(lstobjname)) { } arg += ” ” + dir + lstobjname; } (void)fclose(lst); } arg += this→commonArgs(); return arg; } void addLstFile(const std::string & name) { this→lstfiles.push_back(new std::string(name)); } bool linkdll, incremental, releasemode, uselibexe; stringpvector lstfiles; }; / main() */ int main(int argc, char argv) { if (argc == 1) { std::string procstdout, procstderr; DWORD retcode = run_process(“cl.exe”, procstdout, procstderr); (void)fprintf(stdout, ”%s”, procstdout.c_str()); (void)fprintf(stderr, ”%s”, procstderr.c_str()); return retcode; } struct CompilerArgs compiler; struct LinkerArgs linker; struct Tool * tool = &compiler; /* start of command-line parsing / for (int i=1; i < argc; i++) { std::string arg = argvi; bool optarg = arg.at(0)=='-' || arg.at(0)=='/'; bool forcompiler = (tool == &compiler); if (match(arg, ”–wrapdbg”)) { wrapdbg = true; } else if (match(arg, ”–wrapversion”)) { (void)fprintf(stdout, “$Revision: 1.3 $ (post disk-crash)\n”); exit(0); } C srcfile? else if (suffixmatch(arg, ”.c”)) { tool = &compiler; compiler.addFileC(arg); } C++ srcfile? else if (suffixmatch(arg, ”.cpp”) || suffixmatch(arg, ”.cxx”) || suffixmatch(arg, ”.c++”) || suffixmatch(arg, ”.cc”)) { tool = &compiler; compiler.addFileCPlusPlus(arg); } header file? (can be specified explicitly when executed as preprocessor) else if (suffixmatch(arg, ”.h”)) { tool = &compiler; compiler.addHeaderFile(arg); } Name the .lib output file (this must be executed before the filename suffix detections). else if (optarg && prefixmatch(arg.substr(1), “OUT:”)) { tool = &linker; linker.objname = winpath(arg.substr(5)); } Just pass along object files to the linker process. else if (suffixmatch(arg, ”.obj”) || suffixmatch(arg, ”.o”) || suffixmatch(arg, ”.res”) ) { resource files are linked like obj compiler.addFileObj(winpath(arg)); linker.addFileObj(winpath(arg)); } else if (suffixmatch(arg, ”.lib”)) { compiler.addLibFile(winpath(arg)); linker.addLibFile(winpath(arg)); } Handle our own invention of ”.lst”-files, listing up the obj-files which should be part of the final link. else if (suffixmatch(arg, ”.lst”)) { tool = &linker; linker.addLstFile(winpath(arg)); } These checks must be kept before the -L* library linkfile match to avoid -LINK or -LIB being interpreted as “link with library INK” (ditto for -LIB). else if (optarg && match(arg.substr(1), “lib”, true)) { tool = &linker; linker.uselibexe = true; } else if (optarg && match(arg.substr(1), “link”, true)) { tool = &linker; } This need to be kept before the -D* match to avoid -DLL being interpreted as “set preprocessor define LL”. else if (optarg && match(arg.substr(1), “dll”, true)) { tool = &linker; linker.linkdll = true; } Additional library path. else if (optarg && arg.at(1)=='L') { FIXME: should check that the string trailing the 'L' actually points to a valid path? 20010709 mortene. compiler.addLinkPath(winpath(arg.substr(2))); linker.addLinkPath(winpath(arg.substr(2))); } Additional library for the compiler. else if (optarg && arg.at(1)=='l') { compiler.addLibFile(winpath(arg.substr(2)) + ”.lib”); linker.addLibFile(winpath(arg.substr(2)) + ”.lib”); } Run in preprocessor mode. else if (optarg && match(arg.substr(1), “E”)) { tool = &compiler; compiler.aspreproc = true; } Option for the linker process, simply to be forwarded. else if (optarg && match(arg.substr(1), “RELEASE”)) { tool = &linker; linker.releasemode = true; } /DEBUG option for the linker process – this must obviously go before the '/D<preproc>' check below. else if (optarg && match(arg.substr(1), “DEBUG”)) { tool = &linker; linker.debugmode = true; } A preprocessor define. else if (optarg && arg.at(1)=='D') { tool = &compiler; compiler.addPreProcDef(arg.substr(2)); } Include debuginfo in object files. else if (optarg && match(arg.substr(1), “g”)) { compiler.debugmode = true; linker.debugmode = true; } An option for the linker this – whether or not to build incremental libraries (typically during debugging, trading space for fast linking). This need to go before the '-I<path>' check right below, so we don't confuse this with an additional include path setting. else if (optarg && prefixmatch(arg.substr(1), “INCREMENTAL:”)) { tool = &linker; linker.incremental = suffixmatch(arg, “YES”) ? true : false; } Additional include path for the preprocessor. else if (optarg && arg.at(1)=='I') { tool = &compiler; compiler.addIncPath(winpath(arg.substr(2))); FIXME: should check that the string trailing the 'I' actually points to a valid path? 20010709 mortene. } Compile for specific hardware. else if (optarg && forcompiler && arg.at(1)=='m') { std::string intelcpu = arg.substr(2); const char prefixmsvcwrap = “cpu=”; if (intelcpu.compare(prefix)==0) { intelcpu.erase(0, strlen(prefix)); } const char * cpuconvmsvcwrap = { “i386”, “G3”, “i486”, “G4”, “pentium”, “G5”, “pentiumpro”, “G6”, NULL }; int i=0; while (cpuconvi) { if (intelcpu.compare(cpuconvi)==0) { compiler.cpuspec = cpuconvi+1; break; } i += 2; } Just ignores if unknown CPU type. Not sure if that's a good strategy. } Optimization (ie matching regexp ”-/O0-9?”). else if (optarg && forcompiler && arg.at(1)=='O' && ((arg.length()==2) || (arg.length()==3 && isdigit(arg.at(2
msvcwrap.txt · Last modified: 2022/04/16 12:23 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki