diff --git a/buildtool.cpp b/buildtool.cpp
index af1b033e7c73ad224da3d0dfd8863e2e71c34cce..458fca5a4d08ae2fdd06599fed38eebfdf4ca027 100644 (file)
--- a/buildtool.cpp
+++ b/buildtool.cpp
* Authors:
* Bob Jamison
*
- * Copyright (C) 2006 Bob Jamison
+ * Copyright (C) 2006-2007 Bob Jamison
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* btool
* or
* btool {target}
+ *
+ * Note: recent win32api builds from MinGW have gettimeofday()
+ * defined, so you might need to build with
+ * g++ -O3 -DHAVE_GETTIMEOFDAY buildtool.cpp -o btool.exe
+ *
*/
-
+#define BUILDTOOL_VERSION "BuildTool v0.6.4, 2007 Bob Jamison"
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
+#include <utime.h>
#include <dirent.h>
#include <string>
//########################################################################
//# Definition of gettimeofday() for those who don't have it
//########################################################################
-#ifdef __WIN32__
+#ifndef HAVE_GETTIMEOFDAY
#include <sys/timeb.h>
+
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
}
return 0;
}
+
#endif
return n;
}
-
-
//########################################################################
//########################################################################
//## E N D X M L
//########################################################################
+
+
+
+
//########################################################################
//########################################################################
//## U R I
}
+
/**
* This follows the Java URI algorithm:
* 1. All "." segments are removed.
+
//#########################################################################
//# P A R S I N G
//#########################################################################
}
strcpy(paramBuf, (char *)command.c_str());
+ //# Go to http://msdn2.microsoft.com/en-us/library/ms682499.aspx
+ //# to see how Win32 pipes work
+
//# Create pipes
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
ret = false;
}
+ delete[] paramBuf;
+
DWORD bytesWritten;
if (inbuf.size()>0 &&
!WriteFile(stdinWrite, inbuf.c_str(), inbuf.size(),
error("executeCommand: could not close read pipe");
return false;
}
+
+ bool lastLoop = false;
while (true)
{
- //trace("## stderr");
DWORD avail;
- if (!PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL))
- break;
+ DWORD bytesRead;
+ char readBuf[4096];
+
+ //trace("## stderr");
+ PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL);
if (avail > 0)
{
- DWORD bytesRead = 0;
- char readBuf[1025];
- if (avail>1024) avail = 1024;
- if (!ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL)
- || bytesRead == 0)
+ bytesRead = 0;
+ if (avail>4096) avail = 4096;
+ ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL);
+ if (bytesRead > 0)
{
- break;
+ for (unsigned int i=0 ; i<bytesRead ; i++)
+ errbuf.push_back(readBuf[i]);
}
- for (unsigned int i=0 ; i<bytesRead ; i++)
- errbuf.push_back(readBuf[i]);
}
+
//trace("## stdout");
- if (!PeekNamedPipe(stdoutRead, NULL, 0, NULL, &avail, NULL))
- break;
+ PeekNamedPipe(stdoutRead, NULL, 0, NULL, &avail, NULL);
if (avail > 0)
{
- DWORD bytesRead = 0;
- char readBuf[1025];
- if (avail>1024) avail = 1024;
- if (!ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL)
- || bytesRead==0)
+ bytesRead = 0;
+ if (avail>4096) avail = 4096;
+ ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL);
+ if (bytesRead > 0)
{
- break;
+ for (unsigned int i=0 ; i<bytesRead ; i++)
+ outbuf.push_back(readBuf[i]);
}
- for (unsigned int i=0 ; i<bytesRead ; i++)
- outbuf.push_back(readBuf[i]);
}
+
+ //Was this the final check after program done?
+ if (lastLoop)
+ break;
+
DWORD exitCode;
GetExitCodeProcess(piProcessInfo.hProcess, &exitCode);
if (exitCode != STILL_ACTIVE)
- break;
- Sleep(100);
+ lastLoop = true;
+
+ Sleep(50);
}
//trace("outbuf:%s", outbuf.c_str());
if (!CloseHandle(stdoutRead))
ret = false;
}
- // Clean up
CloseHandle(piProcessInfo.hProcess);
CloseHandle(piProcessInfo.hThread);
-
return ret;
#else //do it unix-style
TASK_SHAREDLIB,
TASK_STATICLIB,
TASK_STRIP,
+ TASK_TOUCH,
TASK_TSTAMP
} TaskType;
{
if (!listFiles(parent, fileSet))
return false;
+
+ FILE *f = NULL;
+ f = fopen("compile.lst", "w");
bool refreshCache = false;
String fullName = parent.resolve("build.dep");
//## Execute the command
String outString, errString;
- if (!executeCommand(cmd.c_str(), "", outString, errString))
+ bool ret = executeCommand(cmd.c_str(), "", outString, errString);
+ if (f)
+ {
+ fprintf(f, "########################### File : %s\n",
+ srcFullName.c_str());
+ fprintf(f, "#### COMMAND ###\n");
+ int col = 0;
+ for (int i = 0 ; i < cmd.size() ; i++)
+ {
+ char ch = cmd[i];
+ if (isspace(ch) && col > 63)
+ {
+ fputc('\n', f);
+ col = 0;
+ }
+ else
+ {
+ fputc(ch, f);
+ col++;
+ }
+ if (col > 76)
+ {
+ fputc('\n', f);
+ col = 0;
+ }
+ }
+ fprintf(f, "\n");
+ fprintf(f, "#### STDOUT ###\n%s\n", outString.c_str());
+ fprintf(f, "#### STDERR ###\n%s\n\n", errString.c_str());
+ }
+ if (!ret)
{
error("problem compiling: %s", errString.c_str());
return false;
}
+
+ }
+
+ if (f)
+ {
+ fclose(f);
}
return true;
return false;
if (!parent.getAttribute(elem, "strip", s))
return false;
- if (!getBool(s, doStrip))
+ if (s.size()>0 && !getBool(s, doStrip))
return false;
if (!parent.getAttribute(elem, "symfile", symFileName))
return false;
name = "msgfmt";
command = "msgfmt";
owndir = false;
+ outName = "";
}
virtual ~TaskMsgFmt()
destPath.append(subdir);
destPath.append("/");
}
- destPath.append(fileName);
- destPath[destPath.size()-2] = 'm';
+ //Pick the output file name
+ if (outName.size() > 0)
+ {
+ destPath.append(outName);
+ }
+ else
+ {
+ destPath.append(fileName);
+ destPath[destPath.size()-2] = 'm';
+ }
+
String fullDest = parent.resolve(destPath);
if (!isNewerThan(fullSource, fullDest))
command = s;
if (!parent.getAttribute(elem, "todir", toDirName))
return false;
+ if (!parent.getAttribute(elem, "out", outName))
+ return false;
if (!parent.getAttribute(elem, "owndir", s))
return false;
- if (!getBool(s, owndir))
+ if (s.size()>0 && !getBool(s, owndir))
return false;
std::vector<Element *> children = elem->getChildren();
private:
- String command;
- String toDirName;
+ String command;
+ String toDirName;
+ String outName;
FileSet fileSet;
- bool owndir;
+ bool owndir;
};
};
+
/**
* Run the "ar" command to archive .o's into a .a
*/
return true;
}
+
virtual bool parse(Element *elem)
{
String s;
};
+
+
/**
* Strip an executable
*/
};
+/**
+ *
+ */
+class TaskTouch : public Task
+{
+public:
+
+ TaskTouch(MakeBase &par) : Task(par)
+ { type = TASK_TOUCH; name = "touch"; }
+
+ virtual ~TaskTouch()
+ {}
+
+ virtual bool execute()
+ {
+ String fullName = parent.resolve(fileName);
+ String nativeFile = getNativePath(fullName);
+ if (!isRegularFile(fullName) && !isDirectory(fullName))
+ {
+ // S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
+ int ret = creat(nativeFile.c_str(), 0666);
+ if (ret != 0)
+ {
+ error("<touch> could not create '%s' : %s",
+ nativeFile.c_str(), strerror(ret));
+ return false;
+ }
+ return true;
+ }
+ int ret = utime(nativeFile.c_str(), (struct utimbuf *)0);
+ if (ret != 0)
+ {
+ error("<touch> could not update the modification time for '%s' : %s",
+ nativeFile.c_str(), strerror(ret));
+ return false;
+ }
+ return true;
+ }
+
+ virtual bool parse(Element *elem)
+ {
+ //trace("touch parse");
+ if (!parent.getAttribute(elem, "file", fileName))
+ return false;
+ if (fileName.size() == 0)
+ {
+ error("<touch> requires 'file=\"fileName\"' attribute");
+ return false;
+ }
+ return true;
+ }
+
+ String fileName;
+};
+
+
/**
*
*/
task = new TaskStaticLib(parent);
else if (tagName == "strip")
task = new TaskStrip(parent);
+ else if (tagName == "touch")
+ task = new TaskTouch(parent);
else if (tagName == "tstamp")
task = new TaskTstamp(parent);
else
*
*/
virtual String version()
- { return "BuildTool v0.6, 2006 Bob Jamison"; }
+ { return BUILDTOOL_VERSION; }
/**
* Overload a <property>
return false;
}
val = s.substr(p);
- if (key.size()==0 || val.size()==0)
+ if (key.size()==0)
continue;
+ //allow property to be set, even if val=""
//trace("key:'%s' val:'%s'", key.c_str(), val.c_str());
//See if we wanted to overload this property
{
if (!getAttribute(elem, "location", val))
return false;
- if (val.size() > 0)
- {
- properties[attrVal] = val;
- }
+ //let the property exist, even if not defined
+ properties[attrVal] = val;
}
//See if we wanted to overload this property
std::map<String, String>::iterator iter =
int millis = (int)((microsX - microsY)/1000);
int minutes = seconds/60;
- seconds += minutes*60;
+ seconds -= minutes*60;
char buf[80];
snprintf(buf, 79, "%dm %d.%03ds", minutes, seconds, millis);
String ret = buf;