Code

More cleanup of piping. Add ccompiler listing.
[inkscape.git] / buildtool.cpp
index af1b033e7c73ad224da3d0dfd8863e2e71c34cce..458fca5a4d08ae2fdd06599fed38eebfdf4ca027 100644 (file)
@@ -4,7 +4,7 @@
  * 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>
@@ -40,6 +45,7 @@
 #include <sys/stat.h>
 #include <time.h>
 #include <sys/time.h>
+#include <utime.h>
 #include <dirent.h>
 
 #include <string>
@@ -58,8 +64,9 @@
 //########################################################################
 //# 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 */
@@ -82,6 +89,7 @@ static int gettimeofday (struct timeval *tv, struct timezone *tz)
         }
     return 0;
 }
+
 #endif
 
 
@@ -1868,8 +1876,6 @@ Element *Parser::parseFile(const String &fileName)
     return n;
 }
 
-
-
 //########################################################################
 //########################################################################
 //##  E N D    X M L
@@ -1877,6 +1883,10 @@ Element *Parser::parseFile(const String &fileName)
 //########################################################################
 
 
+
+
+
+
 //########################################################################
 //########################################################################
 //##  U R I
@@ -2322,6 +2332,7 @@ URI URI::resolve(const URI &other) const
 }
 
 
+
 /**
  *  This follows the Java URI algorithm:
  *   1. All "." segments are removed.
@@ -2440,6 +2451,7 @@ void URI::trace(const char *fmt, ...)
 
 
 
+
 //#########################################################################
 //# P A R S I N G
 //#########################################################################
@@ -3386,6 +3398,9 @@ bool MakeBase::executeCommand(const String &command,
        }
     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); 
@@ -3436,6 +3451,8 @@ bool MakeBase::executeCommand(const String &command,
         ret = false;
         }
 
+    delete[] paramBuf;
+
     DWORD bytesWritten;
     if (inbuf.size()>0 &&
         !WriteFile(stdinWrite, inbuf.c_str(), inbuf.size(), 
@@ -3459,46 +3476,52 @@ bool MakeBase::executeCommand(const String &command,
         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))
@@ -3520,11 +3543,9 @@ bool MakeBase::executeCommand(const String &command,
         ret = false;
         }
     
-    // Clean up
     CloseHandle(piProcessInfo.hProcess);
     CloseHandle(piProcessInfo.hThread);
 
-
     return ret;
 
 #else //do it unix-style
@@ -5637,6 +5658,7 @@ public:
         TASK_SHAREDLIB,
         TASK_STATICLIB,
         TASK_STRIP,
+        TASK_TOUCH,
         TASK_TSTAMP
         } TaskType;
         
@@ -5772,6 +5794,9 @@ public:
         {
         if (!listFiles(parent, fileSet))
             return false;
+            
+        FILE *f = NULL;
+        f = fopen("compile.lst", "w");
 
         bool refreshCache = false;
         String fullName = parent.resolve("build.dep");
@@ -5918,11 +5943,47 @@ public:
             //## 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;
@@ -6500,7 +6561,7 @@ public:
             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;
@@ -6663,6 +6724,7 @@ public:
          name    = "msgfmt";
          command = "msgfmt";
          owndir  = false;
+         outName = "";
          }
 
     virtual ~TaskMsgFmt()
@@ -6704,8 +6766,17 @@ public:
                 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))
@@ -6750,9 +6821,11 @@ public:
             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();
@@ -6771,10 +6844,11 @@ public:
 
 private:
 
-    String command;
-    String toDirName;
+    String  command;
+    String  toDirName;
+    String  outName;
     FileSet fileSet;
-    bool owndir;
+    bool    owndir;
 
 };
 
@@ -7039,6 +7113,7 @@ private:
 };
 
 
+
 /**
  * Run the "ar" command to archive .o's into a .a
  */
@@ -7115,6 +7190,7 @@ public:
         return true;
         }
 
+
     virtual bool parse(Element *elem)
         {
         String s;
@@ -7148,6 +7224,8 @@ private:
 };
 
 
+
+
 /**
  * Strip an executable
  */
@@ -7213,6 +7291,62 @@ private:
 };
 
 
+/**
+ *
+ */
+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;
+};
+
+
 /**
  *
  */
@@ -7276,6 +7410,8 @@ Task *Task::createTask(Element *elem)
         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
@@ -7508,7 +7644,7 @@ public:
      *
      */
     virtual String version()
-        { return "BuildTool v0.6, 2006 Bob Jamison"; }
+        { return BUILDTOOL_VERSION; }
 
     /**
      * Overload a <property>
@@ -7945,8 +8081,9 @@ bool Make::parsePropertyFile(const String &fileName,
             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
@@ -7991,10 +8128,8 @@ bool Make::parseProperty(Element *elem)
                 {
                 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 =
@@ -8208,7 +8343,7 @@ timeDiffString(struct timeval &x, struct timeval &y)
     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;