X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=buildtool.cpp;h=538a6faa51c92a1619081bace877a7bc92082552;hb=fce046713c4cb905f38bf489cc4a73af425f3037;hp=f4a8d02108363154b8bf84b7826a5f7347aee356;hpb=335ea8bf3fcbebfa83ff1253982934c18fb98d55;p=inkscape.git
diff --git a/buildtool.cpp b/buildtool.cpp
index f4a8d0210..538a6faa5 100644
--- a/buildtool.cpp
+++ b/buildtool.cpp
@@ -3,8 +3,9 @@
*
* Authors:
* Bob Jamison
+ * Jasper van de Gronde
*
- * Copyright (C) 2006-2007 Bob Jamison
+ * Copyright (C) 2006-2008 Bob Jamison
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -25,19 +26,20 @@
* To use this file, compile with:
*
* g++ -O3 buildtool.cpp -o btool.exe
- * (or whatever your compiler might be)
+ * (or whatever your compiler might be)
* Then
* btool
- * or
+ * 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
- *
- */
+ *
+ * Note: if you are using MinGW, and a not very recent version of it,
+ * gettimeofday() might be missing. If so, just build this file with
+ * this command:
+ * g++ -O3 -DNEED_GETTIMEOFDAY buildtool.cpp -o btool.exe
+ *
+ */
-#define BUILDTOOL_VERSION "BuildTool v0.6.7, 2007 Bob Jamison"
+#define BUILDTOOL_VERSION "BuildTool v0.9.9"
#include
#include
@@ -53,6 +55,8 @@
#include
#include
#include
+#include
+
#ifdef __WIN32__
#include
@@ -65,7 +69,7 @@
//########################################################################
//# Definition of gettimeofday() for those who don't have it
//########################################################################
-#ifndef HAVE_GETTIMEOFDAY
+#ifdef NEED_GETTIMEOFDAY
#include
struct timezone {
@@ -203,7 +207,7 @@ TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
#include
//#include "trex.h"
-#ifdef _UINCODE
+#ifdef _UNICODE
#define scisprint iswprint
#define scstrlen wcslen
#define scprintf wprintf
@@ -687,7 +691,7 @@ static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *s
return cur;
}
case OP_WB:
- if(str == exp->_bol && !isspace(*str)
+ if((str == exp->_bol && !isspace(*str))
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
@@ -1149,7 +1153,7 @@ private:
void getLineAndColumn(int pos, int *lineNr, int *colNr);
- void error(char *fmt, ...);
+ void error(const char *fmt, ...);
int peek(int pos);
@@ -1324,7 +1328,7 @@ void Element::print()
typedef struct
{
- char *escaped;
+ const char *escaped;
char value;
} EntityEntry;
@@ -1404,7 +1408,7 @@ void Parser::getLineAndColumn(int pos, int *lineNr, int *colNr)
}
-void Parser::error(char *fmt, ...)
+void Parser::error(const char *fmt, ...)
{
int lineNr;
int colNr;
@@ -1642,7 +1646,7 @@ int Parser::parseElement(int p0, Element *par,int lineNr)
if (ch!='<')
return p0;
- int line, col;
+ //int line, col;
//getLineAndColumn(p, &line, &col);
p++;
@@ -2148,7 +2152,7 @@ private:
int peek(int p);
- int match(int p, char *key);
+ int match(int p, const char *key);
int parseScheme(int p);
@@ -2170,9 +2174,9 @@ private:
typedef struct
{
- int ival;
- char *sval;
- int port;
+ int ival;
+ const char *sval;
+ int port;
} LookupEntry;
LookupEntry schemes[] =
@@ -2500,7 +2504,7 @@ int URI::peek(int p)
-int URI::match(int p0, char *key)
+int URI::match(int p0, const char *key)
{
int p = p0;
while (p < parselen)
@@ -2738,6 +2742,98 @@ bool URI::parse(const String &str)
//########################################################################
//########################################################################
+//########################################################################
+//# Stat cache to speed up stat requests
+//########################################################################
+struct StatResult {
+ int result;
+ struct stat statInfo;
+};
+typedef std::map statCacheType;
+static statCacheType statCache;
+static int cachedStat(const String &f, struct stat *s) {
+ //printf("Stat path: %s\n", f.c_str());
+ std::pair result = statCache.insert(statCacheType::value_type(f, StatResult()));
+ if (result.second) {
+ result.first->second.result = stat(f.c_str(), &(result.first->second.statInfo));
+ }
+ *s = result.first->second.statInfo;
+ return result.first->second.result;
+}
+static void removeFromStatCache(const String f) {
+ //printf("Removing from cache: %s\n", f.c_str());
+ statCache.erase(f);
+}
+
+//########################################################################
+//# Dir cache to speed up dir requests
+//########################################################################
+/*struct DirListing {
+ bool available;
+ std::vector files;
+ std::vector dirs;
+};
+typedef std::map dirCacheType;
+static dirCacheType dirCache;
+static const DirListing &cachedDir(String fullDir)
+{
+ String dirNative = getNativePath(fullDir);
+ std::pair result = dirCache.insert(dirCacheType::value_type(dirNative, DirListing()));
+ if (result.second) {
+ DIR *dir = opendir(dirNative.c_str());
+ if (!dir)
+ {
+ error("Could not open directory %s : %s",
+ dirNative.c_str(), strerror(errno));
+ result.first->second.available = false;
+ }
+ else
+ {
+ result.first->second.available = true;
+ while (true)
+ {
+ struct dirent *de = readdir(dir);
+ if (!de)
+ break;
+
+ //Get the directory member name
+ String s = de->d_name;
+ if (s.size() == 0 || s[0] == '.')
+ continue;
+ String childName;
+ if (dirName.size()>0)
+ {
+ childName.append(dirName);
+ childName.append("/");
+ }
+ childName.append(s);
+ String fullChild = baseDir;
+ fullChild.append("/");
+ fullChild.append(childName);
+
+ if (isDirectory(fullChild))
+ {
+ //trace("directory: %s", childName.c_str());
+ if (!listFiles(baseDir, childName, res))
+ return false;
+ continue;
+ }
+ else if (!isRegularFile(fullChild))
+ {
+ error("unknown file:%s", childName.c_str());
+ return false;
+ }
+
+ //all done!
+ res.push_back(childName);
+
+ }
+ closedir(dir);
+ }
+ }
+ return result.first->second;
+}*/
+
//########################################################################
//# F I L E S E T
//########################################################################
@@ -2775,7 +2871,7 @@ public:
/**
*
*/
- String getDirectory()
+ String getDirectory() const
{ return directory; }
/**
@@ -2793,7 +2889,7 @@ public:
/**
*
*/
- std::vector getFiles()
+ std::vector getFiles() const
{ return files; }
/**
@@ -2805,7 +2901,7 @@ public:
/**
*
*/
- std::vector getIncludes()
+ std::vector getIncludes() const
{ return includes; }
/**
@@ -2817,19 +2913,19 @@ public:
/**
*
*/
- std::vector getExcludes()
+ std::vector getExcludes() const
{ return excludes; }
/**
*
*/
- unsigned int size()
+ unsigned int size() const
{ return files.size(); }
/**
*
*/
- String operator[](int index)
+ String operator[](int index) const
{ return files[index]; }
/**
@@ -2861,6 +2957,99 @@ private:
};
+//########################################################################
+//# F I L E L I S T
+//########################################################################
+/**
+ * This is a simpler, explicitly-named list of files
+ */
+class FileList
+{
+public:
+
+ /**
+ *
+ */
+ FileList()
+ {}
+
+ /**
+ *
+ */
+ FileList(const FileList &other)
+ { assign(other); }
+
+ /**
+ *
+ */
+ FileList &operator=(const FileList &other)
+ { assign(other); return *this; }
+
+ /**
+ *
+ */
+ virtual ~FileList()
+ {}
+
+ /**
+ *
+ */
+ String getDirectory()
+ { return directory; }
+
+ /**
+ *
+ */
+ void setDirectory(const String &val)
+ { directory = val; }
+
+ /**
+ *
+ */
+ void setFiles(const std::vector &val)
+ { files = val; }
+
+ /**
+ *
+ */
+ std::vector getFiles()
+ { return files; }
+
+ /**
+ *
+ */
+ unsigned int size()
+ { return files.size(); }
+
+ /**
+ *
+ */
+ String operator[](int index)
+ { return files[index]; }
+
+ /**
+ *
+ */
+ void clear()
+ {
+ directory = "";
+ files.clear();
+ }
+
+
+private:
+
+ void assign(const FileList &other)
+ {
+ directory = other.directory;
+ files = other.files;
+ }
+
+ String directory;
+ std::vector files;
+};
+
+
//########################################################################
@@ -2895,6 +3084,19 @@ public:
*/
String resolve(const String &otherPath);
+ /**
+ * replace variable refs like ${a} with their values
+ * Assume that the string has already been syntax validated
+ */
+ String eval(const String &s, const String &defaultVal);
+
+ /**
+ * replace variable refs like ${a} with their values
+ * return true or false
+ * Assume that the string has already been syntax validated
+ */
+ bool evalBool(const String &s, bool defaultVal);
+
/**
* Get an element attribute, performing substitutions if necessary
*/
@@ -2917,28 +3119,112 @@ public:
int getLine()
{ return line; }
+
+ /**
+ * Set a property to a given value
+ */
+ virtual void setProperty(const String &name, const String &val)
+ {
+ properties[name] = val;
+ }
+
+ /**
+ * Return a named property is found, else a null string
+ */
+ virtual String getProperty(const String &name)
+ {
+ String val;
+ std::map::iterator iter = properties.find(name);
+ if (iter != properties.end())
+ val = iter->second;
+ String sval;
+ if (!getSubstitutions(val, sval))
+ return false;
+ return sval;
+ }
+
+ /**
+ * Return true if a named property is found, else false
+ */
+ virtual bool hasProperty(const String &name)
+ {
+ std::map::iterator iter = properties.find(name);
+ if (iter == properties.end())
+ return false;
+ return true;
+ }
+
+
protected:
/**
* The path to the file associated with this object
*/
URI uri;
+
+ /**
+ * If this prefix is seen in a substitution, use an environment
+ * variable.
+ * example:
+ * ${env.JAVA_HOME}
+ */
+ String envPrefix;
+
+ /**
+ * If this prefix is seen in a substitution, use as a
+ * pkg-config 'all' query
+ * example:
+ * ${pc.gtkmm}
+ */
+ String pcPrefix;
+
+ /**
+ * If this prefix is seen in a substitution, use as a
+ * pkg-config 'cflags' query
+ * example:
+ * ${pcc.gtkmm}
+ */
+ String pccPrefix;
+
+ /**
+ * If this prefix is seen in a substitution, use as a
+ * pkg-config 'libs' query
+ * example:
+ * ${pcl.gtkmm}
+ */
+ String pclPrefix;
+
+ /**
+ * If this prefix is seen in a substitution, use as a
+ * Subversion "svn info" query
+ * example:
+ * ${svn.Revision}
+ */
+ String svnPrefix;
+
+
+
/**
* Print a printf()-like formatted error message
*/
- void error(char *fmt, ...);
+ void error(const char *fmt, ...);
/**
* Print a printf()-like formatted trace message
*/
- void status(char *fmt, ...);
+ void status(const char *fmt, ...);
+
+ /**
+ * Show target status
+ */
+ void targetstatus(const char *fmt, ...);
/**
* Print a printf()-like formatted trace message
*/
- void trace(char *fmt, ...);
+ void trace(const char *fmt, ...);
/**
* Check if a given string matches a given regex pattern
@@ -2972,6 +3258,11 @@ protected:
*/
String trim(const String &s);
+ /**
+ * Return a lower case version of the given string
+ */
+ String toLower(const String &s);
+
/**
* Return the native format of the canonical
* path which we store
@@ -3022,6 +3313,12 @@ protected:
bool parseFileSet(Element *elem,
MakeBase &propRef,
FileSet &fileSet);
+ /**
+ * Parse a entry
+ */
+ bool parseFileList(Element *elem,
+ MakeBase &propRef,
+ FileList &fileList);
/**
* Return this object's property list
@@ -3029,27 +3326,9 @@ protected:
virtual std::map &getProperties()
{ return properties; }
- /**
- * Return a named property if found, else a null string
- */
- virtual String getProperty(const String &name)
- {
- String val;
- std::map::iterator iter;
- iter = properties.find(name);
- if (iter != properties.end())
- val = iter->second;
- return val;
- }
-
std::map properties;
- /**
- * Turn 'true' and 'false' into boolean values
- */
- bool getBool(const String &str, bool &val);
-
/**
* Create a directory, making intermediate dirs
* if necessary
@@ -3066,6 +3345,16 @@ protected:
*/
bool copyFile(const String &srcFile, const String &destFile);
+ /**
+ * Delete a file
+ */
+ bool removeFile(const String &file);
+
+ /**
+ * Tests if the file exists
+ */
+ bool fileExists(const String &fileName);
+
/**
* Tests if the file exists and is a regular file
*/
@@ -3083,9 +3372,33 @@ protected:
private:
+ bool pkgConfigRecursive(const String packageName,
+ const String &path,
+ const String &prefix,
+ int query,
+ String &result,
+ std::set &deplist);
+
/**
- * replace variable refs like ${a} with their values
- */
+ * utility method to query for "all", "cflags", or "libs" for this package and its
+ * dependencies. 0, 1, 2
+ */
+ bool pkgConfigQuery(const String &packageName, int query, String &result);
+
+ /**
+ * replace a variable ref like ${a} with a value
+ */
+ bool lookupProperty(const String &s, String &result);
+
+ /**
+ * called by getSubstitutions(). This is in case a looked-up string
+ * has substitutions also.
+ */
+ bool getSubstitutionsRecursive(const String &s, String &result, int depth);
+
+ /**
+ * replace variable refs in a string like ${a} with their values
+ */
bool getSubstitutions(const String &s, String &result);
int line;
@@ -3095,60 +3408,402 @@ private:
-
/**
- * Print a printf()-like formatted error message
+ * Define the pkg-config class here, since it will be used in MakeBase method
+ * implementations.
*/
-void MakeBase::error(char *fmt, ...)
+class PkgConfig : public MakeBase
{
- va_list args;
- va_start(args,fmt);
- fprintf(stderr, "Make error line %d: ", line);
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
- va_end(args) ;
-}
+public:
+ /**
+ *
+ */
+ PkgConfig()
+ {
+ path = ".";
+ prefix = "/target";
+ init();
+ }
-/**
- * Print a printf()-like formatted trace message
- */
-void MakeBase::status(char *fmt, ...)
-{
- va_list args;
- va_start(args,fmt);
- //fprintf(stdout, " ");
- vfprintf(stdout, fmt, args);
- fprintf(stdout, "\n");
- va_end(args) ;
-}
+ /**
+ *
+ */
+ PkgConfig(const PkgConfig &other)
+ { assign(other); }
+
+ /**
+ *
+ */
+ PkgConfig &operator=(const PkgConfig &other)
+ { assign(other); return *this; }
+
+ /**
+ *
+ */
+ virtual ~PkgConfig()
+ { }
+
+ /**
+ *
+ */
+ virtual String getName()
+ { return name; }
+
+ /**
+ *
+ */
+ virtual String getPath()
+ { return path; }
+
+ /**
+ *
+ */
+ virtual void setPath(const String &val)
+ { path = val; }
+
+ /**
+ *
+ */
+ virtual String getPrefix()
+ { return prefix; }
+
+ /**
+ * Allow the user to override the prefix in the file
+ */
+ virtual void setPrefix(const String &val)
+ { prefix = val; }
+
+ /**
+ *
+ */
+ virtual String getDescription()
+ { return description; }
+
+ /**
+ *
+ */
+ virtual String getCflags()
+ { return cflags; }
+
+ /**
+ *
+ */
+ virtual String getLibs()
+ { return libs; }
+
+ /**
+ *
+ */
+ virtual String getAll()
+ {
+ String ret = cflags;
+ ret.append(" ");
+ ret.append(libs);
+ return ret;
+ }
+
+ /**
+ *
+ */
+ virtual String getVersion()
+ { return version; }
+
+ /**
+ *
+ */
+ virtual int getMajorVersion()
+ { return majorVersion; }
+
+ /**
+ *
+ */
+ virtual int getMinorVersion()
+ { return minorVersion; }
+
+ /**
+ *
+ */
+ virtual int getMicroVersion()
+ { return microVersion; }
+
+ /**
+ *
+ */
+ virtual std::map &getAttributes()
+ { return attrs; }
+
+ /**
+ *
+ */
+ virtual std::vector &getRequireList()
+ { return requireList; }
+
+ /**
+ * Read a file for its details
+ */
+ virtual bool readFile(const String &fileName);
+
+ /**
+ * Read a file for its details
+ */
+ virtual bool query(const String &name);
+
+private:
+
+ void init()
+ {
+ //do not set path and prefix here
+ name = "";
+ description = "";
+ cflags = "";
+ libs = "";
+ requires = "";
+ version = "";
+ majorVersion = 0;
+ minorVersion = 0;
+ microVersion = 0;
+ fileName = "";
+ attrs.clear();
+ requireList.clear();
+ }
+
+ void assign(const PkgConfig &other)
+ {
+ name = other.name;
+ path = other.path;
+ prefix = other.prefix;
+ description = other.description;
+ cflags = other.cflags;
+ libs = other.libs;
+ requires = other.requires;
+ version = other.version;
+ majorVersion = other.majorVersion;
+ minorVersion = other.minorVersion;
+ microVersion = other.microVersion;
+ fileName = other.fileName;
+ attrs = other.attrs;
+ requireList = other.requireList;
+ }
+
+
+
+ int get(int pos);
+
+ int skipwhite(int pos);
+
+ int getword(int pos, String &ret);
+
+ /**
+ * Very important
+ */
+ bool parseRequires();
+
+ void parseVersion();
+
+ bool parseLine(const String &lineBuf);
+
+ bool parse(const String &buf);
+
+ void dumpAttrs();
+
+ String name;
+
+ String path;
+
+ String prefix;
+
+ String description;
+
+ String cflags;
+
+ String libs;
+
+ String requires;
+
+ String version;
+
+ int majorVersion;
+
+ int minorVersion;
+
+ int microVersion;
+
+ String fileName;
+
+ std::map attrs;
+
+ std::vector requireList;
+
+ char *parsebuf;
+ int parselen;
+};
/**
- * Resolve another path relative to this one
+ * Execute the "svn info" command and parse the result.
+ * This is a simple, small class. Define here, because it
+ * is used by MakeBase implementation methods.
*/
-String MakeBase::resolve(const String &otherPath)
+class SvnInfo : public MakeBase
{
- URI otherURI(otherPath);
- URI fullURI = uri.resolve(otherURI);
- String ret = fullURI.toString();
- return ret;
+public:
+
+#if 0
+ /**
+ * Safe way. Execute "svn info --xml" and parse the result. Search for
+ * elements/attributes. Safe from changes in format.
+ */
+ bool query(const String &name, String &res)
+ {
+ String cmd = "svn info --xml";
+
+ String outString, errString;
+ bool ret = executeCommand(cmd.c_str(), "", outString, errString);
+ if (!ret)
+ {
+ error("error executing '%s': %s", cmd.c_str(), errString.c_str());
+ return false;
+ }
+ Parser parser;
+ Element *elem = parser.parse(outString);
+ if (!elem)
+ {
+ error("error parsing 'svn info' xml result: %s", outString.c_str());
+ return false;
+ }
+
+ res = elem->getTagValue(name);
+ if (res.size()==0)
+ {
+ res = elem->getTagAttribute("entry", name);
+ }
+ return true;
+ }
+#else
+
+
+ /**
+ * Universal way. Parse the file directly. Not so safe from
+ * changes in format.
+ */
+ bool query(const String &name, String &res)
+ {
+ String fileName = resolve(".svn/entries");
+ String nFileName = getNativePath(fileName);
+
+ std::map properties;
+
+ FILE *f = fopen(nFileName.c_str(), "r");
+ if (!f)
+ {
+ error("could not open SVN 'entries' file");
+ return false;
+ }
+
+ const char *fieldNames[] =
+ {
+ "format-nbr",
+ "name",
+ "kind",
+ "revision",
+ "url",
+ "repos",
+ "schedule",
+ "text-time",
+ "checksum",
+ "committed-date",
+ "committed-rev",
+ "last-author",
+ "has-props",
+ "has-prop-mods",
+ "cachable-props",
+ };
+
+ for (int i=0 ; i<15 ; i++)
+ {
+ inbuf[0] = '\0';
+ if (feof(f) || !fgets(inbuf, 255, f))
+ break;
+ properties[fieldNames[i]] = trim(inbuf);
+ }
+ fclose(f);
+
+ res = properties[name];
+
+ return true;
+ }
+
+private:
+
+ char inbuf[256];
+
+#endif
+
+};
+
+
+
+
+
+
+/**
+ * Print a printf()-like formatted error message
+ */
+void MakeBase::error(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args,fmt);
+ fprintf(stderr, "Make error line %d: ", line);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args) ;
}
+
/**
* Print a printf()-like formatted trace message
*/
-void MakeBase::trace(char *fmt, ...)
+void MakeBase::status(const char *fmt, ...)
{
va_list args;
+ //fprintf(stdout, " ");
va_start(args,fmt);
- fprintf(stdout, "Make: ");
vfprintf(stdout, fmt, args);
+ va_end(args);
fprintf(stdout, "\n");
+ fflush(stdout);
+}
+
+
+/**
+ * Print a printf()-like formatted trace message
+ */
+void MakeBase::trace(const char *fmt, ...)
+{
+ va_list args;
+ fprintf(stdout, "Make: ");
+ va_start(args,fmt);
+ vfprintf(stdout, fmt, args);
va_end(args) ;
+ fprintf(stdout, "\n");
+ fflush(stdout);
+}
+
+
+
+/**
+ * Resolve another path relative to this one
+ */
+String MakeBase::resolve(const String &otherPath)
+{
+ URI otherURI(otherPath);
+ URI fullURI = uri.resolve(otherURI);
+ String ret = fullURI.toString();
+ return ret;
}
@@ -3348,6 +4003,24 @@ String MakeBase::trim(const String &s)
return res;
}
+
+/**
+ * Return a lower case version of the given string
+ */
+String MakeBase::toLower(const String &s)
+{
+ if (s.size()==0)
+ return s;
+
+ String ret;
+ for(unsigned int i=0; i
+
+
+
+/**
+ * Execute a system call, using pipes to send data to the
+ * program's stdin, and reading stdout and stderr.
+ */
+bool MakeBase::executeCommand(const String &command,
+ const String &inbuf,
+ String &outbuf,
+ String &errbuf)
+{
+
+ status("============ cmd ============\n%s\n=============================",
+ command.c_str());
+
+ outbuf.clear();
+ errbuf.clear();
+
+
+ int outfds[2];
+ if (pipe(outfds) < 0)
+ return false;
+ int errfds[2];
+ if (pipe(errfds) < 0)
+ return false;
+ int pid = fork();
+ if (pid < 0)
+ {
+ close(outfds[0]);
+ close(outfds[1]);
+ close(errfds[0]);
+ close(errfds[1]);
+ error("launch of command '%s' failed : %s",
+ command.c_str(), strerror(errno));
+ return false;
+ }
+ else if (pid > 0) // parent
+ {
+ close(outfds[1]);
+ close(errfds[1]);
+ }
+ else // == 0, child
+ {
+ close(outfds[0]);
+ dup2(outfds[1], STDOUT_FILENO);
+ close(outfds[1]);
+ close(errfds[0]);
+ dup2(errfds[1], STDERR_FILENO);
+ close(errfds[1]);
+
+ char *args[4];
+ args[0] = (char *)"sh";
+ args[1] = (char *)"-c";
+ args[2] = (char *)command.c_str();
+ args[3] = NULL;
+ execv("/bin/sh", args);
+ exit(EXIT_FAILURE);
+ }
+
+ String outb;
+ String errb;
- String s;
- FILE *f = popen(command.c_str(), "r");
- int errnum = 0;
- if (f)
+ int outRead = outfds[0];
+ int errRead = errfds[0];
+ int max = outRead;
+ if (errRead > max)
+ max = errRead;
+
+ bool outOpen = true;
+ bool errOpen = true;
+
+ while (outOpen || errOpen)
{
- while (true)
+ char ch;
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ if (outOpen)
+ FD_SET(outRead, &fdset);
+ if (errOpen)
+ FD_SET(errRead, &fdset);
+ int ret = select(max+1, &fdset, NULL, NULL, NULL);
+ if (ret < 0)
+ break;
+ if (FD_ISSET(outRead, &fdset))
{
- int ch = fgetc(f);
- if (ch < 0)
- break;
- s.push_back((char)ch);
+ if (read(outRead, &ch, 1) <= 0)
+ { outOpen = false; }
+ else if (ch <= 0)
+ { /* outOpen = false; */ }
+ else
+ { outb.push_back(ch); }
+ }
+ if (FD_ISSET(errRead, &fdset))
+ {
+ if (read(errRead, &ch, 1) <= 0)
+ { errOpen = false; }
+ else if (ch <= 0)
+ { /* errOpen = false; */ }
+ else
+ { errb.push_back(ch); }
}
- errnum = pclose(f);
}
- outbuf = s;
- if (errnum != 0)
+
+ int childReturnValue;
+ wait(&childReturnValue);
+
+ close(outRead);
+ close(errRead);
+
+ outbuf = outb;
+ errbuf = errb;
+
+ if (childReturnValue != 0)
{
error("exec of command '%s' failed : %s",
- command.c_str(), strerror(errno));
+ command.c_str(), strerror(childReturnValue));
return false;
}
- else
- return true;
-#endif
+ return true;
}
+#endif
+
@@ -3635,7 +4416,7 @@ bool MakeBase::listDirectories(const String &baseName,
String fullPath = baseName;
if (dirName.size()>0)
{
- fullPath.append("/");
+ if (dirName[0]!='/') fullPath.append("/");
fullPath.append(dirName);
}
DIR *dir = opendir(fullPath.c_str());
@@ -3658,7 +4439,7 @@ bool MakeBase::listDirectories(const String &baseName,
fullChildPath.append(childName);
struct stat finfo;
String childNative = getNativePath(fullChildPath);
- if (stat(childNative.c_str(), &finfo)<0)
+ if (cachedStat(childNative, &finfo)<0)
{
error("cannot stat file:%s", childNative.c_str());
}
@@ -3739,9 +4520,19 @@ bool MakeBase::listFiles(const String &baseDir,
}
+/**
+ * Several different classes extend MakeBase. By "propRef", we mean
+ * the one holding the properties. Likely "Make" itself
+ */
bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
{
- String baseDir = propRef.resolve(fileSet.getDirectory());
+ //before doing the list, resolve any property references
+ //that might have been specified in the directory name, such as ${src}
+ String fsDir = fileSet.getDirectory();
+ String dir;
+ if (!propRef.getSubstitutions(fsDir, dir))
+ return false;
+ String baseDir = propRef.resolve(dir);
std::vector fileList;
if (!listFiles(baseDir, "", fileList))
return false;
@@ -3762,7 +4553,7 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
{
for (iter = includes.begin() ; iter != includes.end() ; iter++)
{
- String pattern = *iter;
+ String &pattern = *iter;
std::vector::iterator siter;
for (siter = fileList.begin() ; siter != fileList.end() ; siter++)
{
@@ -3785,7 +4576,7 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
std::vector::iterator siter;
for (siter = excludes.begin() ; siter != excludes.end() ; siter++)
{
- String pattern = *siter;
+ String &pattern = *siter;
if (regexMatch(s, pattern))
{
//trace("EXCLUDED:%s", s.c_str());
@@ -3803,11 +4594,159 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
}
+/**
+ * 0 == all, 1 = cflags, 2 = libs
+ */
+bool MakeBase::pkgConfigRecursive(const String packageName,
+ const String &path,
+ const String &prefix,
+ int query,
+ String &result,
+ std::set &deplist)
+{
+ PkgConfig pkgConfig;
+ if (path.size() > 0)
+ pkgConfig.setPath(path);
+ if (prefix.size() > 0)
+ pkgConfig.setPrefix(prefix);
+ if (!pkgConfig.query(packageName))
+ return false;
+ if (query == 0)
+ result = pkgConfig.getAll();
+ else if (query == 1)
+ result = pkgConfig.getCflags();
+ else
+ result = pkgConfig.getLibs();
+ deplist.insert(packageName);
+ std::vector list = pkgConfig.getRequireList();
+ for (unsigned int i = 0 ; i deplist;
+ String path = getProperty("pkg-config-path");
+ if (path.size()>0)
+ path = resolve(path);
+ String prefix = getProperty("pkg-config-prefix");
+ String val;
+ if (!pkgConfigRecursive(packageName, path, prefix, query, val, deplist))
+ return false;
+ result = val;
+ return true;
+}
-bool MakeBase::getSubstitutions(const String &str, String &result)
+/**
+ * replace a variable ref like ${a} with a value
+ */
+bool MakeBase::lookupProperty(const String &propertyName, String &result)
+{
+ String varname = propertyName;
+ if (envPrefix.size() > 0 &&
+ varname.compare(0, envPrefix.size(), envPrefix) == 0)
+ {
+ varname = varname.substr(envPrefix.size());
+ char *envstr = getenv(varname.c_str());
+ if (!envstr)
+ {
+ error("environment variable '%s' not defined", varname.c_str());
+ return false;
+ }
+ result = envstr;
+ }
+ else if (pcPrefix.size() > 0 &&
+ varname.compare(0, pcPrefix.size(), pcPrefix) == 0)
+ {
+ varname = varname.substr(pcPrefix.size());
+ String val;
+ if (!pkgConfigQuery(varname, 0, val))
+ return false;
+ result = val;
+ }
+ else if (pccPrefix.size() > 0 &&
+ varname.compare(0, pccPrefix.size(), pccPrefix) == 0)
+ {
+ varname = varname.substr(pccPrefix.size());
+ String val;
+ if (!pkgConfigQuery(varname, 1, val))
+ return false;
+ result = val;
+ }
+ else if (pclPrefix.size() > 0 &&
+ varname.compare(0, pclPrefix.size(), pclPrefix) == 0)
+ {
+ varname = varname.substr(pclPrefix.size());
+ String val;
+ if (!pkgConfigQuery(varname, 2, val))
+ return false;
+ result = val;
+ }
+ else if (svnPrefix.size() > 0 &&
+ varname.compare(0, svnPrefix.size(), svnPrefix) == 0)
+ {
+ varname = varname.substr(svnPrefix.size());
+ String val;
+ SvnInfo svnInfo;
+ if (varname == "revision")
+ {
+ if (!svnInfo.query(varname, val))
+ return "";
+ result = "r"+val;
+ }
+ if (!svnInfo.query(varname, val))
+ return false;
+ result = val;
+ }
+ else
+ {
+ std::map::iterator iter;
+ iter = properties.find(varname);
+ if (iter != properties.end())
+ {
+ result = iter->second;
+ }
+ else
+ {
+ error("property '%s' not found", varname.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+
+/**
+ * Analyse a string, looking for any substitutions or other
+ * things that need resolution
+ */
+bool MakeBase::getSubstitutionsRecursive(const String &str,
+ String &result, int depth)
{
+ if (depth > 10)
+ {
+ error("nesting of substitutions too deep (>10) for '%s'",
+ str.c_str());
+ return false;
+ }
String s = trim(str);
int len = (int)s.size();
String val;
@@ -3829,17 +4768,15 @@ bool MakeBase::getSubstitutions(const String &str, String &result)
}
else if (ch == '}')
{
- std::map::iterator iter;
- iter = properties.find(trim(varname));
- if (iter != properties.end())
- {
- val.append(iter->second);
- }
- else
- {
- error("property ${%s} not found", varname.c_str());
+ varname = trim(varname);
+ String varval;
+ if (!lookupProperty(varname, varval))
return false;
- }
+ String varval2;
+ //Now see if the answer has ${} in it, too
+ if (!getSubstitutionsRecursive(varval, varval2, depth + 1))
+ return false;
+ val.append(varval2);
break;
}
else
@@ -3858,38 +4795,80 @@ bool MakeBase::getSubstitutions(const String &str, String &result)
return true;
}
-
-bool MakeBase::getAttribute(Element *elem, const String &name,
- String &result)
+/**
+ * Analyse a string, looking for any substitutions or other
+ * things that need resilution
+ */
+bool MakeBase::getSubstitutions(const String &str, String &result)
{
- String s = elem->getAttribute(name);
- return getSubstitutions(s, result);
+ return getSubstitutionsRecursive(str, result, 0);
}
-bool MakeBase::getValue(Element *elem, String &result)
+
+/**
+ * replace variable refs like ${a} with their values
+ * Assume that the string has already been syntax validated
+ */
+String MakeBase::eval(const String &s, const String &defaultVal)
{
- String s = elem->getValue();
- //Replace all runs of whitespace with a single space
- return getSubstitutions(s, result);
+ if (s.size()==0)
+ return defaultVal;
+ String ret;
+ if (getSubstitutions(s, ret))
+ return ret;
+ else
+ return defaultVal;
}
/**
- * Turn 'true' and 'false' into boolean values
- */
-bool MakeBase::getBool(const String &str, bool &val)
-{
- if (str == "true")
- val = true;
- else if (str == "false")
- val = false;
+ * replace variable refs like ${a} with their values
+ * return true or false
+ * Assume that the string has already been syntax validated
+ */
+bool MakeBase::evalBool(const String &s, bool defaultVal)
+{
+ if (s.size()==0)
+ return defaultVal;
+ String val = eval(s, "false");
+ if (val.size()==0)
+ return defaultVal;
+ if (val == "true" || val == "TRUE")
+ return true;
else
- {
- error("expected 'true' or 'false'. found '%s'", str.c_str());
return false;
- }
- return true;
+}
+
+
+/**
+ * Get a string attribute, testing it for proper syntax and
+ * property names.
+ */
+bool MakeBase::getAttribute(Element *elem, const String &name,
+ String &result)
+{
+ String s = elem->getAttribute(name);
+ String tmp;
+ bool ret = getSubstitutions(s, tmp);
+ if (ret)
+ result = s; //assign -if- ok
+ return ret;
+}
+
+
+/**
+ * Get a string value, testing it for proper syntax and
+ * property names.
+ */
+bool MakeBase::getValue(Element *elem, String &result)
+{
+ String s = elem->getValue();
+ String tmp;
+ bool ret = getSubstitutions(s, tmp);
+ if (ret)
+ result = s; //assign -if- ok
+ return ret;
}
@@ -4006,6 +4985,49 @@ bool MakeBase::parseFileSet(Element *elem,
return true;
}
+/**
+ * Parse a entry. This is far simpler than FileSet,
+ * since no directory scanning is needed. The file names are listed
+ * explicitly.
+ */
+bool MakeBase::parseFileList(Element *elem,
+ MakeBase &propRef,
+ FileList &fileList)
+{
+ std::vector fnames;
+ //Look for child tags, namely "file"
+ std::vector children = elem->getChildren();
+ for (unsigned int i=0 ; igetName();
+ if (tagName == "file")
+ {
+ String fname = child->getAttribute("name");
+ if (fname.size()==0)
+ {
+ error(" element requires name="" attribute");
+ return false;
+ }
+ fnames.push_back(fname);
+ }
+ else
+ {
+ error("tag <%s> not allowed in ", tagName.c_str());
+ return false;
+ }
+ }
+
+ String dir;
+ //Get the base directory for reading file names
+ if (!propRef.getAttribute(elem, "dir", dir))
+ return false;
+ fileList.setDirectory(dir);
+ fileList.setFiles(fnames);
+
+ return true;
+}
+
/**
@@ -4023,7 +5045,7 @@ bool MakeBase::createDirectory(const String &dirname)
if (strlen(cnative)==2 && cnative[1]==':')
return true;
#endif
- if (stat(cnative, &finfo)==0)
+ if (cachedStat(nativeDir, &finfo)==0)
{
if (!S_ISDIR(finfo.st_mode))
{
@@ -4059,6 +5081,8 @@ bool MakeBase::createDirectory(const String &dirname)
cnative, strerror(errno));
return false;
}
+
+ removeFromStatCache(nativeDir);
return true;
}
@@ -4102,7 +5126,7 @@ bool MakeBase::removeDirectory(const String &dirName)
struct stat finfo;
String childNative = getNativePath(childName);
char *cnative = (char *)childNative.c_str();
- if (stat(cnative, &finfo)<0)
+ if (cachedStat(childNative, &finfo)<0)
{
error("cannot stat file:%s", cnative);
}
@@ -4121,10 +5145,8 @@ bool MakeBase::removeDirectory(const String &dirName)
else
{
//trace("DEL file: %s", childName.c_str());
- if (remove(cnative)<0)
+ if (!removeFile(childName))
{
- error("error deleting %s : %s",
- cnative, strerror(errno));
return false;
}
}
@@ -4140,6 +5162,8 @@ bool MakeBase::removeDirectory(const String &dirName)
return false;
}
+ removeFromStatCache(native);
+
return true;
}
@@ -4153,7 +5177,7 @@ bool MakeBase::copyFile(const String &srcFile, const String &destFile)
//# 1 Check up-to-date times
String srcNative = getNativePath(srcFile);
struct stat srcinfo;
- if (stat(srcNative.c_str(), &srcinfo)<0)
+ if (cachedStat(srcNative, &srcinfo)<0)
{
error("source file %s for copy does not exist",
srcNative.c_str());
@@ -4162,7 +5186,7 @@ bool MakeBase::copyFile(const String &srcFile, const String &destFile)
String destNative = getNativePath(destFile);
struct stat destinfo;
- if (stat(destNative.c_str(), &destinfo)==0)
+ if (cachedStat(destNative, &destinfo)==0)
{
if (destinfo.st_mtime >= srcinfo.st_mtime)
return true;
@@ -4204,22 +5228,102 @@ bool MakeBase::copyFile(const String &srcFile, const String &destFile)
fclose(destf);
fclose(srcf);
-#else
-
- if (!CopyFile(srcNative.c_str(), destNative.c_str(), false))
+#else
+
+ if (!CopyFile(srcNative.c_str(), destNative.c_str(), false))
+ {
+ error("copyFile from %s to %s failed",
+ srcNative.c_str(), destNative.c_str());
+ return false;
+ }
+
+#endif /* __WIN32__ */
+
+ removeFromStatCache(destNative);
+
+ return true;
+}
+
+
+/**
+ * Delete a file
+ */
+bool MakeBase::removeFile(const String &file)
+{
+ String native = getNativePath(file);
+
+ if (!fileExists(native))
+ {
+ return true;
+ }
+
+#ifdef WIN32
+ // On Windows 'remove' will only delete files
+
+ if (remove(native.c_str())<0)
+ {
+ if (errno==EACCES)
+ {
+ error("File %s is read-only", native.c_str());
+ }
+ else if (errno==ENOENT)
+ {
+ error("File %s does not exist or is a directory", native.c_str());
+ }
+ else
+ {
+ error("Failed to delete file %s: %s", native.c_str(), strerror(errno));
+ }
+ return false;
+ }
+
+#else
+
+ if (!isRegularFile(native))
+ {
+ error("File %s does not exist or is not a regular file", native.c_str());
+ return false;
+ }
+
+ if (remove(native.c_str())<0)
{
- error("copyFile from %s to %s failed",
- srcNative.c_str(), destNative.c_str());
+ if (errno==EACCES)
+ {
+ error("File %s is read-only", native.c_str());
+ }
+ else
+ {
+ error(
+ errno==EACCES ? "File %s is read-only" :
+ errno==ENOENT ? "File %s does not exist or is a directory" :
+ "Failed to delete file %s: %s", native.c_str());
+ }
return false;
}
-
-#endif /* __WIN32__ */
+#endif
+
+ removeFromStatCache(native);
return true;
}
+/**
+ * Tests if the file exists
+ */
+bool MakeBase::fileExists(const String &fileName)
+{
+ String native = getNativePath(fileName);
+ struct stat finfo;
+
+ //Exists?
+ if (cachedStat(native, &finfo)<0)
+ return false;
+
+ return true;
+}
+
/**
* Tests if the file exists and is a regular file
@@ -4230,7 +5334,7 @@ bool MakeBase::isRegularFile(const String &fileName)
struct stat finfo;
//Exists?
- if (stat(native.c_str(), &finfo)<0)
+ if (cachedStat(native, &finfo)<0)
return false;
@@ -4250,7 +5354,7 @@ bool MakeBase::isDirectory(const String &fileName)
struct stat finfo;
//Exists?
- if (stat(native.c_str(), &finfo)<0)
+ if (cachedStat(native, &finfo)<0)
return false;
@@ -4272,7 +5376,7 @@ bool MakeBase::isNewerThan(const String &fileA, const String &fileB)
String nativeA = getNativePath(fileA);
struct stat infoA;
//IF source does not exist, NOT newer
- if (stat(nativeA.c_str(), &infoA)<0)
+ if (cachedStat(nativeA, &infoA)<0)
{
return false;
}
@@ -4280,7 +5384,7 @@ bool MakeBase::isNewerThan(const String &fileA, const String &fileB)
String nativeB = getNativePath(fileB);
struct stat infoB;
//IF dest does not exist, YES, newer
- if (stat(nativeB.c_str(), &infoB)<0)
+ if (cachedStat(nativeB, &infoB)<0)
{
return true;
}
@@ -4299,184 +5403,6 @@ bool MakeBase::isNewerThan(const String &fileA, const String &fileB)
//# P K G C O N F I G
//########################################################################
-/**
- *
- */
-class PkgConfig : public MakeBase
-{
-
-public:
-
- /**
- *
- */
- PkgConfig()
- { init(); }
-
- /**
- *
- */
- PkgConfig(const String &namearg)
- { init(); name = namearg; }
-
- /**
- *
- */
- PkgConfig(const PkgConfig &other)
- { assign(other); }
-
- /**
- *
- */
- PkgConfig &operator=(const PkgConfig &other)
- { assign(other); return *this; }
-
- /**
- *
- */
- virtual ~PkgConfig()
- { }
-
- /**
- *
- */
- virtual String getName()
- { return name; }
-
- /**
- *
- */
- virtual String getDescription()
- { return description; }
-
- /**
- *
- */
- virtual String getCflags()
- { return cflags; }
-
- /**
- *
- */
- virtual String getLibs()
- { return libs; }
-
- /**
- *
- */
- virtual String getVersion()
- { return version; }
-
- /**
- *
- */
- virtual int getMajorVersion()
- { return majorVersion; }
-
- /**
- *
- */
- virtual int getMinorVersion()
- { return minorVersion; }
-
- /**
- *
- */
- virtual int getMicroVersion()
- { return microVersion; }
-
- /**
- *
- */
- virtual std::map &getAttributes()
- { return attrs; }
-
- /**
- *
- */
- virtual std::vector &getRequireList()
- { return requireList; }
-
- virtual bool readFile(const String &fileName);
-
-private:
-
- void init()
- {
- name = "";
- description = "";
- cflags = "";
- libs = "";
- requires = "";
- version = "";
- majorVersion = 0;
- minorVersion = 0;
- microVersion = 0;
- fileName = "";
- attrs.clear();
- requireList.clear();
- }
-
- void assign(const PkgConfig &other)
- {
- name = other.name;
- description = other.description;
- cflags = other.cflags;
- libs = other.libs;
- requires = other.requires;
- version = other.version;
- majorVersion = other.majorVersion;
- minorVersion = other.minorVersion;
- microVersion = other.microVersion;
- fileName = other.fileName;
- attrs = other.attrs;
- requireList = other.requireList;
- }
-
-
-
- int get(int pos);
-
- int skipwhite(int pos);
-
- int getword(int pos, String &ret);
-
- void parseRequires();
-
- void parseVersion();
-
- bool parse(const String &buf);
-
- void dumpAttrs();
-
- String name;
-
- String description;
-
- String cflags;
-
- String libs;
-
- String requires;
-
- String version;
-
- int majorVersion;
-
- int minorVersion;
-
- int microVersion;
-
- String fileName;
-
- std::map attrs;
-
- std::vector requireList;
-
- char *parsebuf;
- int parselen;
-};
-
/**
* Get a character from the buffer at pos. If out of range,
@@ -4494,6 +5420,7 @@ int PkgConfig::get(int pos)
/**
* Skip over all whitespace characters beginning at pos. Return
* the position of the first non-whitespace character.
+ * Pkg-config is line-oriented, so check for newline
*/
int PkgConfig::skipwhite(int pos)
{
@@ -4522,7 +5449,7 @@ int PkgConfig::getword(int pos, String &ret)
int ch = get(pos);
if (ch < 0)
break;
- if (!isalnum(ch) && ch != '_' && ch != '-'&& ch != '.')
+ if (!isalnum(ch) && ch != '_' && ch != '-' && ch != '+' && ch != '.')
break;
ret.push_back((char)ch);
pos++;
@@ -4530,10 +5457,10 @@ int PkgConfig::getword(int pos, String &ret)
return pos;
}
-void PkgConfig::parseRequires()
+bool PkgConfig::parseRequires()
{
if (requires.size() == 0)
- return;
+ return true;
parsebuf = (char *)requires.c_str();
parselen = requires.size();
int pos = 0;
@@ -4548,8 +5475,10 @@ void PkgConfig::parseRequires()
//trace("val %s", val.c_str());
requireList.push_back(val);
}
+ return true;
}
+
static int getint(const String str)
{
char *s = (char *)str.c_str();
@@ -4603,15 +5532,12 @@ void PkgConfig::parseVersion()
}
-bool PkgConfig::parse(const String &buf)
+bool PkgConfig::parseLine(const String &lineBuf)
{
- init();
-
- parsebuf = (char *)buf.c_str();
- parselen = buf.size();
+ parsebuf = (char *)lineBuf.c_str();
+ parselen = lineBuf.size();
int pos = 0;
-
-
+
while (pos < parselen)
{
String attrName;
@@ -4632,6 +5558,7 @@ bool PkgConfig::parse(const String &buf)
pos = getword(pos, attrName);
if (attrName.size() == 0)
continue;
+
pos = skipwhite(pos);
ch = get(pos);
if (ch != ':' && ch != '=')
@@ -4666,10 +5593,18 @@ bool PkgConfig::parse(const String &buf)
subName.push_back((char)ch);
pos++;
}
- //trace("subName:%s", subName.c_str());
- String subVal = attrs[subName];
- //trace("subVal:%s", subVal.c_str());
- attrVal.append(subVal);
+ //trace("subName:%s %s", subName.c_str(), prefix.c_str());
+ if (subName == "prefix" && prefix.size()>0)
+ {
+ attrVal.append(prefix);
+ //trace("prefix override:%s", prefix.c_str());
+ }
+ else
+ {
+ String subVal = attrs[subName];
+ //trace("subVal:%s", subVal.c_str());
+ attrVal.append(subVal);
+ }
}
else
attrVal.push_back((char)ch);
@@ -4679,23 +5614,55 @@ bool PkgConfig::parse(const String &buf)
attrVal = trim(attrVal);
attrs[attrName] = attrVal;
- if (attrName == "Name")
+ String attrNameL = toLower(attrName);
+
+ if (attrNameL == "name")
name = attrVal;
- else if (attrName == "Description")
+ else if (attrNameL == "description")
description = attrVal;
- else if (attrName == "Cflags")
+ else if (attrNameL == "cflags")
cflags = attrVal;
- else if (attrName == "Libs")
+ else if (attrNameL == "libs")
libs = attrVal;
- else if (attrName == "Requires")
+ else if (attrNameL == "requires")
requires = attrVal;
- else if (attrName == "Version")
+ else if (attrNameL == "version")
version = attrVal;
//trace("name:'%s' value:'%s'",
// attrName.c_str(), attrVal.c_str());
}
+ return true;
+}
+
+
+bool PkgConfig::parse(const String &buf)
+{
+ init();
+
+ String line;
+ int lineNr = 0;
+ for (unsigned int p=0 ; p0)
+ {
+ if (!parseLine(line))
+ return false;
+ }
parseRequires();
parseVersion();
@@ -4703,6 +5670,9 @@ bool PkgConfig::parse(const String &buf)
return true;
}
+
+
+
void PkgConfig::dumpAttrs()
{
//trace("### PkgConfig attributes for %s", fileName.c_str());
@@ -4714,9 +5684,9 @@ void PkgConfig::dumpAttrs()
}
-bool PkgConfig::readFile(const String &fileNameArg)
+bool PkgConfig::readFile(const String &fname)
{
- fileName = fileNameArg;
+ fileName = getNativePath(fname);
FILE *f = fopen(fileName.c_str(), "r");
if (!f)
@@ -4739,16 +5709,34 @@ bool PkgConfig::readFile(const String &fileNameArg)
{
return false;
}
-
- dumpAttrs();
-
+
+ //dumpAttrs();
+
+ return true;
+}
+
+
+
+bool PkgConfig::query(const String &pkgName)
+{
+ name = pkgName;
+
+ String fname = path;
+ fname.append("/");
+ fname.append(name);
+ fname.append(".pc");
+
+ if (!readFile(fname))
+ {
+ error("Cannot find package '%s'. Do you have it installed?",
+ pkgName.c_str());
+ return false;
+ }
+
return true;
}
-
-
-
//########################################################################
//# D E P T O O L
//########################################################################
@@ -4774,23 +5762,23 @@ public:
* Constructor
*/
FileRec()
- {init(); type = UNKNOWN;}
+ { init(); type = UNKNOWN; }
/**
* Copy constructor
*/
FileRec(const FileRec &other)
- {init(); assign(other);}
+ { init(); assign(other); }
/**
* Constructor
*/
FileRec(int typeVal)
- {init(); type = typeVal;}
+ { init(); type = typeVal; }
/**
* Assignment operator
*/
FileRec &operator=(const FileRec &other)
- {init(); assign(other); return *this;}
+ { init(); assign(other); return *this; }
/**
@@ -4912,7 +5900,7 @@ private:
path = other.path;
name = other.name;
suffix = other.suffix;
- files = other.files;
+ files = other.files; //avoid recursion
}
};
@@ -4926,19 +5914,19 @@ public:
* Constructor
*/
DepTool()
- {init();}
+ { init(); }
/**
* Copy constructor
*/
DepTool(const DepTool &other)
- {init(); assign(other);}
+ { init(); assign(other); }
/**
* Assignment operator
*/
DepTool &operator=(const DepTool &other)
- {init(); assign(other); return *this;}
+ { init(); assign(other); return *this; }
/**
@@ -5044,7 +6032,7 @@ private:
/**
*
*/
- bool sequ(int pos, char *key);
+ bool sequ(int pos, const char *key);
/**
*
@@ -5059,9 +6047,7 @@ private:
/**
*
*/
- bool processDependency(FileRec *ofile,
- FileRec *include,
- int depth);
+ bool processDependency(FileRec *ofile, FileRec *include);
/**
*
@@ -5080,8 +6066,7 @@ private:
/**
* A list of all files which will be processed for
- * dependencies. This is the only list that has the actual
- * records. All other lists have pointers to these records.
+ * dependencies.
*/
std::map allFiles;
@@ -5089,7 +6074,7 @@ private:
* The list of .o files, and the
* dependencies upon them.
*/
- std::map depFiles;
+ std::map oFiles;
int depFileSize;
char *depFileBuf;
@@ -5114,13 +6099,15 @@ void DepTool::init()
fileList.clear();
directories.clear();
- //clear refs
- depFiles.clear();
- //clear records
+ //clear output file list
std::map::iterator iter;
- for (iter=allFiles.begin() ; iter!=allFiles.end() ; iter++)
- delete iter->second;
+ for (iter=oFiles.begin(); iter!=oFiles.end() ; iter++)
+ delete iter->second;
+ oFiles.clear();
+ //allFiles actually contains the master copies. delete them
+ for (iter= allFiles.begin(); iter!=allFiles.end() ; iter++)
+ delete iter->second;
allFiles.clear();
}
@@ -5265,7 +6252,7 @@ int DepTool::getword(int pos, String &ret)
* Return whether the sequence of characters in the buffer
* beginning at pos match the key, for the length of the key
*/
-bool DepTool::sequ(int pos, char *key)
+bool DepTool::sequ(int pos, const char *key)
{
while (*key)
{
@@ -5285,7 +6272,8 @@ bool DepTool::sequ(int pos, char *key)
*/
bool DepTool::addIncludeFile(FileRec *frec, const String &iname)
{
-
+ //# if the name is an exact match to a path name
+ //# in allFiles, like "myinc.h"
std::map::iterator iter =
allFiles.find(iname);
if (iter != allFiles.end()) //already exists
@@ -5298,6 +6286,7 @@ bool DepTool::addIncludeFile(FileRec *frec, const String &iname)
}
else
{
+ //## Ok, it was not found directly
//look in other dirs
std::vector::iterator diter;
for (diter=directories.begin() ;
@@ -5306,12 +6295,17 @@ bool DepTool::addIncludeFile(FileRec *frec, const String &iname)
String dfname = *diter;
dfname.append("/");
dfname.append(iname);
- iter = allFiles.find(dfname);
+ URI fullPathURI(dfname); //normalize path name
+ String fullPath = fullPathURI.getPath();
+ if (fullPath[0] == '/')
+ fullPath = fullPath.substr(1);
+ //trace("Normalized %s to %s", dfname.c_str(), fullPath.c_str());
+ iter = allFiles.find(fullPath);
if (iter != allFiles.end())
{
FileRec *other = iter->second;
//trace("other: '%s'", iname.c_str());
- frec->files[dfname] = other;
+ frec->files[fullPath] = other;
return true;
}
}
@@ -5345,8 +6339,8 @@ bool DepTool::scanFile(const String &fname, FileRec *frec)
String buf;
while (!feof(f))
{
- int len = fread(readBuf, 1, readBufSize, f);
- readBuf[len] = '\0';
+ int nrbytes = fread(readBuf, 1, readBufSize, f);
+ readBuf[nrbytes] = '\0';
buf.append(readBuf);
}
fclose(f);
@@ -5418,9 +6412,7 @@ bool DepTool::scanFile(const String &fname, FileRec *frec)
* Recursively check include lists to find all files in allFiles to which
* a given file is dependent.
*/
-bool DepTool::processDependency(FileRec *ofile,
- FileRec *include,
- int depth)
+bool DepTool::processDependency(FileRec *ofile, FileRec *include)
{
std::map::iterator iter;
for (iter=include->files.begin() ; iter!=include->files.end() ; iter++)
@@ -5434,7 +6426,7 @@ bool DepTool::processDependency(FileRec *ofile,
FileRec *child = iter->second;
ofile->files[fname] = child;
- processDependency(ofile, child, depth+1);
+ processDependency(ofile, child);
}
@@ -5467,23 +6459,23 @@ bool DepTool::generateDependencies()
FileRec *include = iter->second;
if (include->type == FileRec::CFILE)
{
- String cFileName = iter->first;
- FileRec *ofile = new FileRec(FileRec::OFILE);
- ofile->path = include->path;
- ofile->baseName = include->baseName;
- ofile->suffix = include->suffix;
- String fname = include->path;
+ //String cFileName = iter->first;
+ FileRec *ofile = new FileRec(FileRec::OFILE);
+ ofile->path = include->path;
+ ofile->baseName = include->baseName;
+ ofile->suffix = include->suffix;
+ String fname = include->path;
if (fname.size()>0)
fname.append("/");
fname.append(include->baseName);
fname.append(".o");
- depFiles[fname] = ofile;
+ oFiles[fname] = ofile;
//add the .c file first? no, don't
//ofile->files[cFileName] = include;
//trace("ofile:%s", fname.c_str());
- processDependency(ofile, include, 0);
+ processDependency(ofile, include);
}
}
@@ -5531,7 +6523,7 @@ bool DepTool::saveDepFile(const String &fileName)
fprintf(f, "\n\n", sourceDir.c_str());
std::map::iterator iter;
- for (iter=depFiles.begin() ; iter!=depFiles.end() ; iter++)
+ for (iter=oFiles.begin() ; iter!=oFiles.end() ; iter++)
{
FileRec *frec = iter->second;
if (frec->type == FileRec::OFILE)
@@ -5582,7 +6574,7 @@ std::vector DepTool::loadDepFile(const String &depFile)
if (root->getChildren().size()==0 ||
root->getChildren()[0]->getName()!="dependencies")
{
- error("Main xml element should be ");
+ error("loadDepFile: main xml element should be ");
delete root;
return result;
}
@@ -5595,47 +6587,53 @@ std::vector DepTool::loadDepFile(const String &depFile)
{
Element *objectElem = objects[i];
String tagName = objectElem->getName();
- if (tagName == "object")
- {
- String objName = objectElem->getAttribute("name");
- //trace("object:%s", objName.c_str());
- DepRec depObject(objName);
- depObject.path = objectElem->getAttribute("path");
- depObject.suffix = objectElem->getAttribute("suffix");
- //########## DESCRIPTION
- std::vector depElems = objectElem->getChildren();
- for (unsigned int i=0 ; i should have only children");
+ return result;
+ }
+
+ String objName = objectElem->getAttribute("name");
+ //trace("object:%s", objName.c_str());
+ DepRec depObject(objName);
+ depObject.path = objectElem->getAttribute("path");
+ depObject.suffix = objectElem->getAttribute("suffix");
+ //########## DESCRIPTION
+ std::vector depElems = objectElem->getChildren();
+ for (unsigned int i=0 ; igetName();
+ if (tagName != "dep")
{
- Element *depElem = depElems[i];
- tagName = depElem->getName();
- if (tagName == "dep")
- {
- String depName = depElem->getAttribute("name");
- //trace(" dep:%s", depName.c_str());
- depObject.files.push_back(depName);
- }
+ error("loadDepFile: should have only children");
+ return result;
}
- //Insert into the result list, in a sorted manner
- bool inserted = false;
- std::vector::iterator iter;
- for (iter = result.begin() ; iter != result.end() ; iter++)
+ String depName = depElem->getAttribute("name");
+ //trace(" dep:%s", depName.c_str());
+ depObject.files.push_back(depName);
+ }
+
+ //Insert into the result list, in a sorted manner
+ bool inserted = false;
+ std::vector::iterator iter;
+ for (iter = result.begin() ; iter != result.end() ; iter++)
+ {
+ String vpath = iter->path;
+ vpath.append("/");
+ vpath.append(iter->name);
+ String opath = depObject.path;
+ opath.append("/");
+ opath.append(depObject.name);
+ if (vpath > opath)
{
- String vpath = iter->path;
- vpath.append("/");
- vpath.append(iter->name);
- String opath = depObject.path;
- opath.append("/");
- opath.append(depObject.name);
- if (vpath > opath)
- {
- inserted = true;
- iter = result.insert(iter, depObject);
- break;
- }
+ inserted = true;
+ iter = result.insert(iter, depObject);
+ break;
}
- if (!inserted)
- result.push_back(depObject);
}
+ if (!inserted)
+ result.push_back(depObject);
}
delete root;
@@ -5693,13 +6691,18 @@ public:
TASK_NONE,
TASK_CC,
TASK_COPY,
+ TASK_CXXTEST_PART,
+ TASK_CXXTEST_ROOT,
+ TASK_CXXTEST_RUN,
TASK_DELETE,
+ TASK_ECHO,
TASK_JAR,
TASK_JAVAC,
TASK_LINK,
TASK_MAKEFILE,
TASK_MKDIR,
TASK_MSGFMT,
+ TASK_PKG_CONFIG,
TASK_RANLIB,
TASK_RC,
TASK_SHAREDLIB,
@@ -5791,6 +6794,19 @@ protected:
name = other.name;
}
+ /**
+ * Show task status
+ */
+ void taskstatus(const char *fmt, ...)
+ {
+ va_list args;
+ va_start(args,fmt);
+ fprintf(stdout, " %s : ", name.c_str());
+ vfprintf(stdout, fmt, args);
+ fprintf(stdout, "\n");
+ va_end(args) ;
+ }
+
String getAttribute(Element *elem, const String &attrName)
{
String str;
@@ -5817,39 +6833,49 @@ public:
TaskCC(MakeBase &par) : Task(par)
{
- type = TASK_CC; name = "cc";
- ccCommand = "gcc";
- cxxCommand = "g++";
- source = ".";
- dest = ".";
- flags = "";
- defines = "";
- includes = "";
- fileSet.clear();
+ type = TASK_CC;
+ name = "cc";
}
virtual ~TaskCC()
{}
-
- virtual bool needsCompiling(const DepRec &depRec,
- const String &src, const String &dest)
+
+ virtual bool isExcludedInc(const String &dirname)
{
+ for (unsigned int i=0 ; i::iterator setIter;
for (setIter=paths.begin() ; setIter!=paths.end() ; setIter++)
{
+ String dirName = *setIter;
+ //check excludeInc to see if we dont want to include this dir
+ if (isExcludedInc(dirName))
+ continue;
incs.append(" -I");
String dname;
if (source.size()>0)
@@ -5892,9 +6922,14 @@ public:
dname.append(source);
dname.append("/");
}
- dname.append(*setIter);
+ dname.append(dirName);
incs.append(parent.resolve(dname));
}
+
+ /**
+ * Compile each of the C files that need it
+ */
+ bool errorOccurred = false;
std::vector cfiles;
for (viter=deps.begin() ; viter!=deps.end() ; viter++)
{
@@ -5903,8 +6938,8 @@ public:
//## Select command
String sfx = dep.suffix;
String command = ccCommand;
- if (sfx == "cpp" || sfx == "c++" || sfx == "cc"
- || sfx == "CC")
+ if (sfx == "cpp" || sfx == "cxx" || sfx == "c++" ||
+ sfx == "cc" || sfx == "CC")
command = cxxCommand;
//## Make paths
@@ -5942,27 +6977,33 @@ public:
srcName.append(dep.suffix);
String srcFullName = parent.resolve(srcName);
bool compileMe = false;
+ //# First we check if the source is newer than the .o
if (isNewerThan(srcFullName, destFullName))
{
- status(" : compile of %s required by %s",
+ taskstatus("compile of %s required by source: %s",
destFullName.c_str(), srcFullName.c_str());
compileMe = true;
}
else
{
+ //# secondly, we check if any of the included dependencies
+ //# of the .c/.cpp is newer than the .o
for (unsigned int i=0 ; i0)
+ if (source.size()>0)
{
- depName.append(srcPath);
+ depName.append(source);
depName.append("/");
}
depName.append(dep.files[i]);
String depFullName = parent.resolve(depName);
- if (isNewerThan(depFullName, destFullName))
+ bool depRequires = isNewerThan(depFullName, destFullName);
+ //trace("%d %s %s\n", depRequires,
+ // destFullName.c_str(), depFullName.c_str());
+ if (depRequires)
{
- status(" : compile of %s required by %s",
+ taskstatus("compile of %s required by included: %s",
destFullName.c_str(), depFullName.c_str());
compileMe = true;
break;
@@ -5998,7 +7039,7 @@ public:
srcFullName.c_str());
fprintf(f, "#### COMMAND ###\n");
int col = 0;
- for (int i = 0 ; i < cmd.size() ; i++)
+ for (unsigned int i = 0 ; i < cmd.size() ; i++)
{
char ch = cmd[i];
if (isspace(ch) && col > 63)
@@ -6020,13 +7061,17 @@ public:
fprintf(f, "\n");
fprintf(f, "#### STDOUT ###\n%s\n", outString.c_str());
fprintf(f, "#### STDERR ###\n%s\n\n", errString.c_str());
+ fflush(f);
}
if (!ret)
{
error("problem compiling: %s", errString.c_str());
- return false;
+ errorOccurred = true;
}
-
+ if (errorOccurred && !continueOnError)
+ break;
+
+ removeFromStatCache(getNativePath(destFullName));
}
if (f)
@@ -6034,24 +7079,27 @@ public:
fclose(f);
}
- return true;
+ return !errorOccurred;
}
+
virtual bool parse(Element *elem)
{
String s;
- if (!parent.getAttribute(elem, "command", s))
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (commandOpt.size()>0)
+ { cxxCommandOpt = ccCommandOpt = commandOpt; }
+ if (!parent.getAttribute(elem, "cc", ccCommandOpt))
return false;
- if (s.size()>0) { ccCommand = s; cxxCommand = s; }
- if (!parent.getAttribute(elem, "cc", s))
+ if (!parent.getAttribute(elem, "cxx", cxxCommandOpt))
return false;
- if (s.size()>0) ccCommand = s;
- if (!parent.getAttribute(elem, "cxx", s))
+ if (!parent.getAttribute(elem, "destdir", destOpt))
return false;
- if (s.size()>0) cxxCommand = s;
- if (!parent.getAttribute(elem, "destdir", s))
+ if (!parent.getAttribute(elem, "continueOnError", continueOnErrorOpt))
+ return false;
+ if (!parent.getAttribute(elem, "refreshCache", refreshCacheOpt))
return false;
- if (s.size()>0) dest = s;
std::vector children = elem->getChildren();
for (unsigned int i=0 ; igetName();
if (tagName == "flags")
{
- if (!parent.getValue(child, flags))
+ if (!parent.getValue(child, flagsOpt))
return false;
- flags = strip(flags);
+ flagsOpt = strip(flagsOpt);
}
else if (tagName == "includes")
{
- if (!parent.getValue(child, includes))
+ if (!parent.getValue(child, includesOpt))
return false;
- includes = strip(includes);
+ includesOpt = strip(includesOpt);
}
else if (tagName == "defines")
{
- if (!parent.getValue(child, defines))
+ if (!parent.getValue(child, definesOpt))
return false;
- defines = strip(defines);
+ definesOpt = strip(definesOpt);
}
else if (tagName == "fileset")
{
if (!parseFileSet(child, parent, fileSet))
return false;
- source = fileSet.getDirectory();
+ sourceOpt = fileSet.getDirectory();
+ }
+ else if (tagName == "excludeinc")
+ {
+ if (!parseFileList(child, parent, excludeInc))
+ return false;
}
}
@@ -6089,14 +7142,18 @@ public:
protected:
- String ccCommand;
- String cxxCommand;
- String source;
- String dest;
- String flags;
- String defines;
- String includes;
- FileSet fileSet;
+ String commandOpt;
+ String ccCommandOpt;
+ String cxxCommandOpt;
+ String sourceOpt;
+ String destOpt;
+ String flagsOpt;
+ String definesOpt;
+ String includesOpt;
+ String continueOnErrorOpt;
+ String refreshCacheOpt;
+ FileSet fileSet;
+ FileList excludeInc;
};
@@ -6118,9 +7175,9 @@ public:
TaskCopy(MakeBase &par) : Task(par)
{
- type = TASK_COPY; name = "copy";
- cptype = CP_NONE;
- verbose = false;
+ type = TASK_COPY;
+ name = "copy";
+ cptype = CP_NONE;
haveFileSet = false;
}
@@ -6129,18 +7186,23 @@ public:
virtual bool execute()
{
+ String fileName = parent.eval(fileNameOpt , ".");
+ String toFileName = parent.eval(toFileNameOpt , ".");
+ String toDirName = parent.eval(toDirNameOpt , ".");
+ bool verbose = parent.evalBool(verboseOpt, false);
switch (cptype)
{
case CP_TOFILE:
{
if (fileName.size()>0)
{
- status(" : %s to %s",
+ taskstatus("%s to %s",
fileName.c_str(), toFileName.c_str());
String fullSource = parent.resolve(fileName);
String fullDest = parent.resolve(toFileName);
- //trace("copy %s to file %s", fullSource.c_str(),
- // fullDest.c_str());
+ if (verbose)
+ taskstatus("copy %s to file %s", fullSource.c_str(),
+ fullDest.c_str());
if (!isRegularFile(fullSource))
{
error("copy : file %s does not exist", fullSource.c_str());
@@ -6148,11 +7210,12 @@ public:
}
if (!isNewerThan(fullSource, fullDest))
{
+ taskstatus("skipped");
return true;
}
if (!copyFile(fullSource, fullDest))
return false;
- status(" : 1 file copied");
+ taskstatus("1 file copied");
}
return true;
}
@@ -6162,9 +7225,9 @@ public:
{
if (!listFiles(parent, fileSet))
return false;
- String fileSetDir = fileSet.getDirectory();
+ String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
- status(" : %s to %s",
+ taskstatus("%s to %s",
fileSetDir.c_str(), toDirName.c_str());
int nrFiles = 0;
@@ -6204,24 +7267,26 @@ public:
destPath.append(fileName);
String fullDest = parent.resolve(destPath);
//trace("fileName:%s", fileName.c_str());
- //trace("copy %s to new dir : %s", fullSource.c_str(),
- // fullDest.c_str());
+ if (verbose)
+ taskstatus("copy %s to new dir : %s",
+ fullSource.c_str(), fullDest.c_str());
if (!isNewerThan(fullSource, fullDest))
{
- //trace("copy skipping %s", fullSource.c_str());
+ if (verbose)
+ taskstatus("copy skipping %s", fullSource.c_str());
continue;
}
if (!copyFile(fullSource, fullDest))
return false;
nrFiles++;
}
- status(" : %d file(s) copied", nrFiles);
+ taskstatus("%d file(s) copied", nrFiles);
}
else //file source
{
//For file->dir we want only the basename of
//the source appended to the dest dir
- status(" : %s to %s",
+ taskstatus("%s to %s",
fileName.c_str(), toDirName.c_str());
String baseName = fileName;
unsigned int pos = baseName.find_last_of('/');
@@ -6236,8 +7301,9 @@ public:
}
destPath.append(baseName);
String fullDest = parent.resolve(destPath);
- //trace("copy %s to new dir : %s", fullSource.c_str(),
- // fullDest.c_str());
+ if (verbose)
+ taskstatus("file %s to new dir : %s", fullSource.c_str(),
+ fullDest.c_str());
if (!isRegularFile(fullSource))
{
error("copy : file %s does not exist", fullSource.c_str());
@@ -6245,11 +7311,12 @@ public:
}
if (!isNewerThan(fullSource, fullDest))
{
+ taskstatus("skipped");
return true;
}
if (!copyFile(fullSource, fullDest))
return false;
- status(" : 1 file copied");
+ taskstatus("1 file copied");
}
return true;
}
@@ -6260,20 +7327,17 @@ public:
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (!parent.getAttribute(elem, "tofile", toFileName))
+ if (!parent.getAttribute(elem, "tofile", toFileNameOpt))
return false;
- if (toFileName.size() > 0)
+ if (toFileNameOpt.size() > 0)
cptype = CP_TOFILE;
- if (!parent.getAttribute(elem, "todir", toDirName))
+ if (!parent.getAttribute(elem, "todir", toDirNameOpt))
return false;
- if (toDirName.size() > 0)
+ if (toDirNameOpt.size() > 0)
cptype = CP_TODIR;
- String ret;
- if (!parent.getAttribute(elem, "verbose", ret))
- return false;
- if (ret.size()>0 && !getBool(ret, verbose))
+ if (!parent.getAttribute(elem, "verbose", verboseOpt))
return false;
haveFileSet = false;
@@ -6292,47 +7356,343 @@ public:
}
haveFileSet = true;
}
- }
+ }
+
+ //Perform validity checks
+ if (fileNameOpt.size()>0 && fileSet.size()>0)
+ {
+ error(" can only have one of : file= and ");
+ return false;
+ }
+ if (toFileNameOpt.size()>0 && toDirNameOpt.size()>0)
+ {
+ error(" can only have one of : tofile= or todir=");
+ return false;
+ }
+ if (haveFileSet && toDirNameOpt.size()==0)
+ {
+ error("a task with a must have : todir=");
+ return false;
+ }
+ if (cptype == CP_TOFILE && fileNameOpt.size()==0)
+ {
+ error(" tofile= must be associated with : file=");
+ return false;
+ }
+ if (cptype == CP_TODIR && fileNameOpt.size()==0 && !haveFileSet)
+ {
+ error(" todir= must be associated with : file= or ");
+ return false;
+ }
+
+ return true;
+ }
+
+private:
+
+ int cptype;
+ bool haveFileSet;
+
+ FileSet fileSet;
+ String fileNameOpt;
+ String toFileNameOpt;
+ String toDirNameOpt;
+ String verboseOpt;
+};
+
+
+/**
+ * Generate CxxTest files
+ */
+class TaskCxxTestPart: public Task
+{
+public:
+
+ TaskCxxTestPart(MakeBase &par) : Task(par)
+ {
+ type = TASK_CXXTEST_PART;
+ name = "cxxtestpart";
+ }
+
+ virtual ~TaskCxxTestPart()
+ {}
+
+ virtual bool execute()
+ {
+ if (!listFiles(parent, fileSet))
+ return false;
+ String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
+
+ String fullDest = parent.resolve(parent.eval(destPathOpt, "."));
+ String cmd = parent.eval(commandOpt, "cxxtestgen.py");
+ cmd.append(" --part -o ");
+ cmd.append(fullDest);
+
+ unsigned int newFiles = 0;
+ for (unsigned int i=0 ; i0)
+ {
+ sourcePath.append(fileSetDir);
+ sourcePath.append("/");
+ }
+ sourcePath.append(fileName);
+ String fullSource = parent.resolve(sourcePath);
+
+ cmd.append(" ");
+ cmd.append(fullSource);
+ if (isNewerThan(fullSource, fullDest)) newFiles++;
+ }
+
+ if (newFiles>0) {
+ size_t const lastSlash = fullDest.find_last_of('/');
+ if (lastSlash != fullDest.npos) {
+ String directory(fullDest, 0, lastSlash);
+ if (!createDirectory(directory))
+ return false;
+ }
+
+ String outString, errString;
+ if (!executeCommand(cmd.c_str(), "", outString, errString))
+ {
+ error(" problem: %s", errString.c_str());
+ return false;
+ }
+ removeFromStatCache(getNativePath(fullDest));
+ }
+
+ return true;
+ }
+
+ virtual bool parse(Element *elem)
+ {
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (!parent.getAttribute(elem, "out", destPathOpt))
+ return false;
+
+ std::vector children = elem->getChildren();
+ for (unsigned int i=0 ; igetName();
+ if (tagName == "fileset")
+ {
+ if (!parseFileSet(child, parent, fileSet))
+ return false;
+ }
+ }
+ return true;
+ }
+
+private:
+
+ String commandOpt;
+ String destPathOpt;
+ FileSet fileSet;
+
+};
+
+
+/**
+ * Generate the CxxTest root file
+ */
+class TaskCxxTestRoot: public Task
+{
+public:
+
+ TaskCxxTestRoot(MakeBase &par) : Task(par)
+ {
+ type = TASK_CXXTEST_ROOT;
+ name = "cxxtestroot";
+ }
+
+ virtual ~TaskCxxTestRoot()
+ {}
+
+ virtual bool execute()
+ {
+ if (!listFiles(parent, fileSet))
+ return false;
+ String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
+ unsigned int newFiles = 0;
+
+ String fullDest = parent.resolve(parent.eval(destPathOpt, "."));
+ String cmd = parent.eval(commandOpt, "cxxtestgen.py");
+ cmd.append(" --root -o ");
+ cmd.append(fullDest);
+ String templateFile = parent.eval(templateFileOpt, "");
+ if (templateFile.size()>0) {
+ String fullTemplate = parent.resolve(templateFile);
+ cmd.append(" --template=");
+ cmd.append(fullTemplate);
+ if (isNewerThan(fullTemplate, fullDest)) newFiles++;
+ }
+
+ for (unsigned int i=0 ; i0)
+ {
+ sourcePath.append(fileSetDir);
+ sourcePath.append("/");
+ }
+ sourcePath.append(fileName);
+ String fullSource = parent.resolve(sourcePath);
+
+ cmd.append(" ");
+ cmd.append(fullSource);
+ if (isNewerThan(fullSource, fullDest)) newFiles++;
+ }
+
+ if (newFiles>0) {
+ size_t const lastSlash = fullDest.find_last_of('/');
+ if (lastSlash != fullDest.npos) {
+ String directory(fullDest, 0, lastSlash);
+ if (!createDirectory(directory))
+ return false;
+ }
+
+ String outString, errString;
+ if (!executeCommand(cmd.c_str(), "", outString, errString))
+ {
+ error(" problem: %s", errString.c_str());
+ return false;
+ }
+ removeFromStatCache(getNativePath(fullDest));
+ }
+
+ return true;
+ }
+
+ virtual bool parse(Element *elem)
+ {
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (!parent.getAttribute(elem, "template", templateFileOpt))
+ return false;
+ if (!parent.getAttribute(elem, "out", destPathOpt))
+ return false;
+
+ std::vector children = elem->getChildren();
+ for (unsigned int i=0 ; igetName();
+ if (tagName == "fileset")
+ {
+ if (!parseFileSet(child, parent, fileSet))
+ return false;
+ }
+ }
+ return true;
+ }
+
+private:
+
+ String commandOpt;
+ String templateFileOpt;
+ String destPathOpt;
+ FileSet fileSet;
+
+};
+
+
+/**
+ * Execute the CxxTest test executable
+ */
+class TaskCxxTestRun: public Task
+{
+public:
+
+ TaskCxxTestRun(MakeBase &par) : Task(par)
+ {
+ type = TASK_CXXTEST_RUN;
+ name = "cxxtestrun";
+ }
+
+ virtual ~TaskCxxTestRun()
+ {}
+
+ virtual bool execute()
+ {
+ unsigned int newFiles = 0;
+
+ String workingDir = parent.resolve(parent.eval(workingDirOpt, "inkscape"));
+ String rawCmd = parent.eval(commandOpt, "build/cxxtests");
+
+ String cmdExe;
+ if (fileExists(rawCmd)) {
+ cmdExe = rawCmd;
+ } else if (fileExists(rawCmd + ".exe")) {
+ cmdExe = rawCmd + ".exe";
+ } else {
+ error(" problem: cxxtests executable not found! (command=\"%s\")", rawCmd.c_str());
+ }
+ // Note that the log file names are based on the exact name used to call cxxtests (it uses argv[0] + ".log"/".xml")
+ if (isNewerThan(cmdExe, rawCmd + ".log") || isNewerThan(cmdExe, rawCmd + ".xml")) newFiles++;
+
+ // Prepend the necessary ../'s
+ String cmd = rawCmd;
+ unsigned int workingDirDepth = 0;
+ bool wasSlash = true;
+ for(size_t i=0; i0) {
+ char olddir[1024];
+ if (workingDir.size()>0) {
+ // TODO: Double-check usage of getcwd and handle chdir errors
+ getcwd(olddir, 1024);
+ chdir(workingDir.c_str());
+ }
+
+ String outString;
+ if (!executeCommand(cmd.c_str(), "", outString, outString))
+ {
+ error(" problem: %s", outString.c_str());
+ return false;
+ }
- //Perform validity checks
- if (fileName.size()>0 && fileSet.size()>0)
- {
- error(" can only have one of : file= and ");
- return false;
- }
- if (toFileName.size()>0 && toDirName.size()>0)
- {
- error(" can only have one of : tofile= or todir=");
- return false;
- }
- if (haveFileSet && toDirName.size()==0)
- {
- error("a task with a must have : todir=");
- return false;
+ if (workingDir.size()>0) {
+ // TODO: Handle errors?
+ chdir(olddir);
}
- if (cptype == CP_TOFILE && fileName.size()==0)
- {
- error(" tofile= must be associated with : file=");
+
+ removeFromStatCache(getNativePath(cmd + ".log"));
+ removeFromStatCache(getNativePath(cmd + ".xml"));
+ }
+
+ return true;
+ }
+
+ virtual bool parse(Element *elem)
+ {
+ if (!parent.getAttribute(elem, "command", commandOpt))
return false;
- }
- if (cptype == CP_TODIR && fileName.size()==0 && !haveFileSet)
- {
- error(" todir= must be associated with : file= or ");
+ if (!parent.getAttribute(elem, "workingdir", workingDirOpt))
return false;
- }
-
return true;
}
-
+
private:
- int cptype;
- String fileName;
- FileSet fileSet;
- String toFileName;
- String toDirName;
- bool verbose;
- bool haveFileSet;
+ String commandOpt;
+ String workingDirOpt;
+
};
@@ -6352,12 +7712,9 @@ public:
TaskDelete(MakeBase &par) : Task(par)
{
- type = TASK_DELETE;
- name = "delete";
- delType = DEL_FILE;
- verbose = false;
- quiet = false;
- failOnError = true;
+ type = TASK_DELETE;
+ name = "delete";
+ delType = DEL_FILE;
}
virtual ~TaskDelete()
@@ -6365,37 +7722,38 @@ public:
virtual bool execute()
{
- struct stat finfo;
+ String dirName = parent.eval(dirNameOpt, ".");
+ String fileName = parent.eval(fileNameOpt, ".");
+ bool verbose = parent.evalBool(verboseOpt, false);
+ bool quiet = parent.evalBool(quietOpt, false);
+ bool failOnError = parent.evalBool(failOnErrorOpt, true);
switch (delType)
{
case DEL_FILE:
{
- status(" : %s", fileName.c_str());
+ taskstatus("file: %s", fileName.c_str());
String fullName = parent.resolve(fileName);
char *fname = (char *)fullName.c_str();
- //does not exist
- if (stat(fname, &finfo)<0)
- return true;
- //exists but is not a regular file
- if (!S_ISREG(finfo.st_mode))
- {
- error(" failed. '%s' exists and is not a regular file",
- fname);
- return false;
- }
- if (remove(fname)<0)
+ if (!quiet && verbose)
+ taskstatus("path: %s", fname);
+ if (failOnError && !removeFile(fullName))
{
- error(" failed: %s", strerror(errno));
+ //error("Could not delete file '%s'", fullName.c_str());
return false;
}
return true;
}
case DEL_DIR:
{
- status(" : %s", dirName.c_str());
+ taskstatus("dir: %s", dirName.c_str());
String fullDir = parent.resolve(dirName);
- if (!removeDirectory(fullDir))
+ if (!quiet && verbose)
+ taskstatus("path: %s", fullDir.c_str());
+ if (failOnError && !removeDirectory(fullDir))
+ {
+ //error("Could not delete directory '%s'", fullDir.c_str());
return false;
+ }
return true;
}
}
@@ -6404,51 +7762,91 @@ public:
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (fileName.size() > 0)
+ if (fileNameOpt.size() > 0)
delType = DEL_FILE;
- if (!parent.getAttribute(elem, "dir", dirName))
+ if (!parent.getAttribute(elem, "dir", dirNameOpt))
return false;
- if (dirName.size() > 0)
+ if (dirNameOpt.size() > 0)
delType = DEL_DIR;
- if (fileName.size()>0 && dirName.size()>0)
+ if (fileNameOpt.size()>0 && dirNameOpt.size()>0)
{
error(" can have one attribute of file= or dir=");
return false;
}
- if (fileName.size()==0 && dirName.size()==0)
+ if (fileNameOpt.size()==0 && dirNameOpt.size()==0)
{
error(" must have one attribute of file= or dir=");
return false;
}
- String ret;
- if (!parent.getAttribute(elem, "verbose", ret))
+ if (!parent.getAttribute(elem, "verbose", verboseOpt))
return false;
- if (ret.size()>0 && !getBool(ret, verbose))
+ if (!parent.getAttribute(elem, "quiet", quietOpt))
return false;
- if (!parent.getAttribute(elem, "quiet", ret))
+ if (!parent.getAttribute(elem, "failonerror", failOnErrorOpt))
return false;
- if (ret.size()>0 && !getBool(ret, quiet))
- return false;
- if (!parent.getAttribute(elem, "failonerror", ret))
+ return true;
+ }
+
+private:
+
+ int delType;
+ String dirNameOpt;
+ String fileNameOpt;
+ String verboseOpt;
+ String quietOpt;
+ String failOnErrorOpt;
+};
+
+
+/**
+ * Send a message to stdout
+ */
+class TaskEcho : public Task
+{
+public:
+
+ TaskEcho(MakeBase &par) : Task(par)
+ { type = TASK_ECHO; name = "echo"; }
+
+ virtual ~TaskEcho()
+ {}
+
+ virtual bool execute()
+ {
+ //let message have priority over text
+ String message = parent.eval(messageOpt, "");
+ String text = parent.eval(textOpt, "");
+ if (message.size() > 0)
+ {
+ fprintf(stdout, "%s\n", message.c_str());
+ }
+ else if (text.size() > 0)
+ {
+ fprintf(stdout, "%s\n", text.c_str());
+ }
+ return true;
+ }
+
+ virtual bool parse(Element *elem)
+ {
+ if (!parent.getValue(elem, textOpt))
return false;
- if (ret.size()>0 && !getBool(ret, failOnError))
+ textOpt = leftJustify(textOpt);
+ if (!parent.getAttribute(elem, "message", messageOpt))
return false;
return true;
}
private:
- int delType;
- String dirName;
- String fileName;
- bool verbose;
- bool quiet;
- bool failOnError;
+ String messageOpt;
+ String textOpt;
};
+
/**
*
*/
@@ -6464,13 +7862,52 @@ public:
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "jar");
+ String basedir = parent.eval(basedirOpt, ".");
+ String destfile = parent.eval(destfileOpt, ".");
+
+ String cmd = command;
+ cmd.append(" -cf ");
+ cmd.append(destfile);
+ cmd.append(" -C ");
+ cmd.append(basedir);
+ cmd.append(" .");
+
+ String execCmd = cmd;
+
+ String outString, errString;
+ bool ret = executeCommand(execCmd.c_str(), "", outString, errString);
+ if (!ret)
+ {
+ error(" command '%s' failed :\n %s",
+ execCmd.c_str(), errString.c_str());
+ return false;
+ }
+ removeFromStatCache(getNativePath(destfile));
return true;
}
virtual bool parse(Element *elem)
{
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (!parent.getAttribute(elem, "basedir", basedirOpt))
+ return false;
+ if (!parent.getAttribute(elem, "destfile", destfileOpt))
+ return false;
+ if (basedirOpt.size() == 0 || destfileOpt.size() == 0)
+ {
+ error(" required both basedir and destfile attributes to be set");
+ return false;
+ }
return true;
}
+
+private:
+
+ String commandOpt;
+ String basedirOpt;
+ String destfileOpt;
};
@@ -6482,20 +7919,118 @@ class TaskJavac : public Task
public:
TaskJavac(MakeBase &par) : Task(par)
- { type = TASK_JAVAC; name = "javac"; }
+ {
+ type = TASK_JAVAC; name = "javac";
+ }
virtual ~TaskJavac()
{}
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "javac");
+ String srcdir = parent.eval(srcdirOpt, ".");
+ String destdir = parent.eval(destdirOpt, ".");
+ String target = parent.eval(targetOpt, "");
+
+ std::vector fileList;
+ if (!listFiles(srcdir, "", fileList))
+ {
+ return false;
+ }
+ String cmd = command;
+ cmd.append(" -d ");
+ cmd.append(destdir);
+ cmd.append(" -classpath ");
+ cmd.append(destdir);
+ cmd.append(" -sourcepath ");
+ cmd.append(srcdir);
+ cmd.append(" ");
+ if (target.size()>0)
+ {
+ cmd.append(" -target ");
+ cmd.append(target);
+ cmd.append(" ");
+ }
+ String fname = "javalist.btool";
+ FILE *f = fopen(fname.c_str(), "w");
+ int count = 0;
+ for (unsigned int i=0 ; i command '%s' failed :\n %s",
+ execCmd.c_str(), errString.c_str());
+ return false;
+ }
+ // TODO:
+ //removeFromStatCache(getNativePath(........));
return true;
}
virtual bool parse(Element *elem)
{
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (!parent.getAttribute(elem, "srcdir", srcdirOpt))
+ return false;
+ if (!parent.getAttribute(elem, "destdir", destdirOpt))
+ return false;
+ if (srcdirOpt.size() == 0 || destdirOpt.size() == 0)
+ {
+ error(" required both srcdir and destdir attributes to be set");
+ return false;
+ }
+ if (!parent.getAttribute(elem, "target", targetOpt))
+ return false;
return true;
}
+
+private:
+
+ String commandOpt;
+ String srcdirOpt;
+ String destdirOpt;
+ String targetOpt;
+
};
@@ -6509,10 +8044,6 @@ public:
TaskLink(MakeBase &par) : Task(par)
{
type = TASK_LINK; name = "link";
- command = "g++";
- doStrip = false;
- stripCommand = "strip";
- objcopyCommand = "objcopy";
}
virtual ~TaskLink()
@@ -6520,9 +8051,18 @@ public:
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "g++");
+ String fileName = parent.eval(fileNameOpt, "");
+ String flags = parent.eval(flagsOpt, "");
+ String libs = parent.eval(libsOpt, "");
+ bool doStrip = parent.evalBool(doStripOpt, false);
+ String symFileName = parent.eval(symFileNameOpt, "");
+ String stripCommand = parent.eval(stripCommandOpt, "strip");
+ String objcopyCommand = parent.eval(objcopyCommandOpt, "objcopy");
+
if (!listFiles(parent, fileSet))
return false;
- String fileSetDir = fileSet.getDirectory();
+ String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
//trace("%d files in %s", fileSet.size(), fileSetDir.c_str());
bool doit = false;
String fullTarget = parent.resolve(fileName);
@@ -6542,7 +8082,8 @@ public:
}
obj.append(fileSet[i]);
String fullObj = parent.resolve(obj);
- cmd.append(fullObj);
+ String nativeFullObj = getNativePath(fullObj);
+ cmd.append(nativeFullObj);
//trace("link: tgt:%s obj:%s", fullTarget.c_str(),
// fullObj.c_str());
if (isNewerThan(fullObj, fullTarget))
@@ -6564,6 +8105,7 @@ public:
error("LINK problem: %s", errbuf.c_str());
return false;
}
+ removeFromStatCache(getNativePath(fullTarget));
if (symFileName.size()>0)
{
@@ -6578,6 +8120,7 @@ public:
error(" symbol file failed : %s", errbuf.c_str());
return false;
}
+ removeFromStatCache(getNativePath(symFullName));
}
if (doStrip)
@@ -6590,6 +8133,7 @@ public:
error(" failed : %s", errbuf.c_str());
return false;
}
+ removeFromStatCache(getNativePath(fullTarget));
}
return true;
@@ -6597,26 +8141,17 @@ public:
virtual bool parse(Element *elem)
{
- String s;
- if (!parent.getAttribute(elem, "command", s))
+ if (!parent.getAttribute(elem, "command", commandOpt))
return false;
- if (s.size()>0)
- command = s;
- if (!parent.getAttribute(elem, "objcopycommand", s))
+ if (!parent.getAttribute(elem, "objcopycommand", objcopyCommandOpt))
return false;
- if (s.size()>0)
- objcopyCommand = s;
- if (!parent.getAttribute(elem, "stripcommand", s))
+ if (!parent.getAttribute(elem, "stripcommand", stripCommandOpt))
return false;
- if (s.size()>0)
- stripCommand = s;
- if (!parent.getAttribute(elem, "out", fileName))
+ if (!parent.getAttribute(elem, "out", fileNameOpt))
return false;
- if (!parent.getAttribute(elem, "strip", s))
+ if (!parent.getAttribute(elem, "strip", doStripOpt))
return false;
- if (s.size()>0 && !getBool(s, doStrip))
- return false;
- if (!parent.getAttribute(elem, "symfile", symFileName))
+ if (!parent.getAttribute(elem, "symfile", symFileNameOpt))
return false;
std::vector children = elem->getChildren();
@@ -6631,15 +8166,15 @@ public:
}
else if (tagName == "flags")
{
- if (!parent.getValue(child, flags))
+ if (!parent.getValue(child, flagsOpt))
return false;
- flags = strip(flags);
+ flagsOpt = strip(flagsOpt);
}
else if (tagName == "libs")
{
- if (!parent.getValue(child, libs))
+ if (!parent.getValue(child, libsOpt))
return false;
- libs = strip(libs);
+ libsOpt = strip(libsOpt);
}
}
return true;
@@ -6647,22 +8182,23 @@ public:
private:
- String command;
- String fileName;
- String flags;
- String libs;
FileSet fileSet;
- bool doStrip;
- String symFileName;
- String stripCommand;
- String objcopyCommand;
+
+ String commandOpt;
+ String fileNameOpt;
+ String flagsOpt;
+ String libsOpt;
+ String doStripOpt;
+ String symFileNameOpt;
+ String stripCommandOpt;
+ String objcopyCommandOpt;
};
/**
- * Create a named directory
+ * Create a named file
*/
class TaskMakeFile : public Task
{
@@ -6676,15 +8212,20 @@ public:
virtual bool execute()
{
- status(" : %s", fileName.c_str());
+ String fileName = parent.eval(fileNameOpt, "");
+ bool force = parent.evalBool(forceOpt, false);
+ String text = parent.eval(textOpt, "");
+
+ taskstatus("%s", fileName.c_str());
String fullName = parent.resolve(fileName);
- if (!isNewerThan(parent.getURI().getPath(), fullName))
+ if (!force && !isNewerThan(parent.getURI().getPath(), fullName))
{
- //trace("skipped ");
+ taskstatus("skipped");
return true;
}
+ String fullNative = getNativePath(fullName);
//trace("fullName:%s", fullName.c_str());
- FILE *f = fopen(fullName.c_str(), "w");
+ FILE *f = fopen(fullNative.c_str(), "w");
if (!f)
{
error(" could not open %s for writing : %s",
@@ -6695,29 +8236,33 @@ public:
fputc(text[i], f);
fputc('\n', f);
fclose(f);
+ removeFromStatCache(fullNative);
return true;
}
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (fileName.size() == 0)
+ if (!parent.getAttribute(elem, "force", forceOpt))
+ return false;
+ if (fileNameOpt.size() == 0)
{
error(" requires 'file=\"filename\"' attribute");
return false;
}
- if (!parent.getValue(elem, text))
+ if (!parent.getValue(elem, textOpt))
return false;
- text = leftJustify(text);
+ textOpt = leftJustify(textOpt);
//trace("dirname:%s", dirName.c_str());
return true;
}
private:
- String fileName;
- String text;
+ String fileNameOpt;
+ String forceOpt;
+ String textOpt;
};
@@ -6737,7 +8282,9 @@ public:
virtual bool execute()
{
- status(" : %s", dirName.c_str());
+ String dirName = parent.eval(dirNameOpt, ".");
+
+ taskstatus("%s", dirName.c_str());
String fullDir = parent.resolve(dirName);
//trace("fullDir:%s", fullDir.c_str());
if (!createDirectory(fullDir))
@@ -6747,9 +8294,9 @@ public:
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "dir", dirName))
+ if (!parent.getAttribute(elem, "dir", dirNameOpt))
return false;
- if (dirName.size() == 0)
+ if (dirNameOpt.size() == 0)
{
error(" requires 'dir=\"dirname\"' attribute");
return false;
@@ -6759,7 +8306,7 @@ public:
private:
- String dirName;
+ String dirNameOpt;
};
@@ -6772,19 +8319,18 @@ class TaskMsgFmt: public Task
public:
TaskMsgFmt(MakeBase &par) : Task(par)
- {
- type = TASK_MSGFMT;
- name = "msgfmt";
- command = "msgfmt";
- owndir = false;
- outName = "";
- }
+ { type = TASK_MSGFMT; name = "msgfmt"; }
virtual ~TaskMsgFmt()
{}
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "msgfmt");
+ String toDirName = parent.eval(toDirNameOpt, ".");
+ String outName = parent.eval(outNameOpt, "");
+ bool owndir = parent.evalBool(owndirOpt, false);
+
if (!listFiles(parent, fileSet))
return false;
String fileSetDir = fileSet.getDirectory();
@@ -6860,6 +8406,7 @@ public:
error(" problem: %s", errString.c_str());
return false;
}
+ removeFromStatCache(getNativePath(fullDest));
}
return true;
@@ -6867,18 +8414,13 @@ public:
virtual bool parse(Element *elem)
{
- String s;
- if (!parent.getAttribute(elem, "command", s))
- return false;
- if (s.size()>0)
- command = s;
- if (!parent.getAttribute(elem, "todir", toDirName))
+ if (!parent.getAttribute(elem, "command", commandOpt))
return false;
- if (!parent.getAttribute(elem, "out", outName))
+ if (!parent.getAttribute(elem, "todir", toDirNameOpt))
return false;
- if (!parent.getAttribute(elem, "owndir", s))
+ if (!parent.getAttribute(elem, "out", outNameOpt))
return false;
- if (s.size()>0 && !getBool(s, owndir))
+ if (!parent.getAttribute(elem, "owndir", owndirOpt))
return false;
std::vector children = elem->getChildren();
@@ -6897,11 +8439,114 @@ public:
private:
- String command;
- String toDirName;
- String outName;
FileSet fileSet;
- bool owndir;
+
+ String commandOpt;
+ String toDirNameOpt;
+ String outNameOpt;
+ String owndirOpt;
+
+};
+
+
+
+/**
+ * Perform a Package-Config query similar to pkg-config
+ */
+class TaskPkgConfig : public Task
+{
+public:
+
+ typedef enum
+ {
+ PKG_CONFIG_QUERY_CFLAGS,
+ PKG_CONFIG_QUERY_LIBS,
+ PKG_CONFIG_QUERY_ALL
+ } QueryTypes;
+
+ TaskPkgConfig(MakeBase &par) : Task(par)
+ {
+ type = TASK_PKG_CONFIG;
+ name = "pkg-config";
+ }
+
+ virtual ~TaskPkgConfig()
+ {}
+
+ virtual bool execute()
+ {
+ String pkgName = parent.eval(pkgNameOpt, "");
+ String prefix = parent.eval(prefixOpt, "");
+ String propName = parent.eval(propNameOpt, "");
+ String pkgConfigPath = parent.eval(pkgConfigPathOpt,"");
+ String query = parent.eval(queryOpt, "all");
+
+ String path = parent.resolve(pkgConfigPath);
+ PkgConfig pkgconfig;
+ pkgconfig.setPath(path);
+ pkgconfig.setPrefix(prefix);
+ if (!pkgconfig.query(pkgName))
+ {
+ error(" query failed for '%s", name.c_str());
+ return false;
+ }
+
+ String val = "";
+ if (query == "cflags")
+ val = pkgconfig.getCflags();
+ else if (query == "libs")
+ val =pkgconfig.getLibs();
+ else if (query == "all")
+ val = pkgconfig.getAll();
+ else
+ {
+ error(" unhandled query : %s", query.c_str());
+ return false;
+ }
+ taskstatus("property %s = '%s'", propName.c_str(), val.c_str());
+ parent.setProperty(propName, val);
+ return true;
+ }
+
+ virtual bool parse(Element *elem)
+ {
+ //# NAME
+ if (!parent.getAttribute(elem, "name", pkgNameOpt))
+ return false;
+ if (pkgNameOpt.size()==0)
+ {
+ error(" requires 'name=\"package\"' attribute");
+ return false;
+ }
+
+ //# PROPERTY
+ if (!parent.getAttribute(elem, "property", propNameOpt))
+ return false;
+ if (propNameOpt.size()==0)
+ {
+ error(" requires 'property=\"name\"' attribute");
+ return false;
+ }
+ //# PATH
+ if (!parent.getAttribute(elem, "path", pkgConfigPathOpt))
+ return false;
+ //# PREFIX
+ if (!parent.getAttribute(elem, "prefix", prefixOpt))
+ return false;
+ //# QUERY
+ if (!parent.getAttribute(elem, "query", queryOpt))
+ return false;
+
+ return true;
+ }
+
+private:
+
+ String queryOpt;
+ String pkgNameOpt;
+ String prefixOpt;
+ String propNameOpt;
+ String pkgConfigPathOpt;
};
@@ -6909,6 +8554,7 @@ private:
+
/**
* Process an archive to allow random access
*/
@@ -6917,16 +8563,16 @@ class TaskRanlib : public Task
public:
TaskRanlib(MakeBase &par) : Task(par)
- {
- type = TASK_RANLIB; name = "ranlib";
- command = "ranlib";
- }
+ { type = TASK_RANLIB; name = "ranlib"; }
virtual ~TaskRanlib()
{}
virtual bool execute()
{
+ String fileName = parent.eval(fileNameOpt, "");
+ String command = parent.eval(commandOpt, "ranlib");
+
String fullName = parent.resolve(fileName);
//trace("fullDir:%s", fullDir.c_str());
String cmd = command;
@@ -6935,19 +8581,18 @@ public:
String outbuf, errbuf;
if (!executeCommand(cmd, "", outbuf, errbuf))
return false;
+ // TODO:
+ //removeFromStatCache(getNativePath(fullDest));
return true;
}
virtual bool parse(Element *elem)
{
- String s;
- if (!parent.getAttribute(elem, "command", s))
+ if (!parent.getAttribute(elem, "command", commandOpt))
return false;
- if (s.size()>0)
- command = s;
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (fileName.size() == 0)
+ if (fileNameOpt.size() == 0)
{
error(" requires 'file=\"fileNname\"' attribute");
return false;
@@ -6957,30 +8602,32 @@ public:
private:
- String fileName;
- String command;
+ String fileNameOpt;
+ String commandOpt;
};
/**
- * Run the "ar" command to archive .o's into a .a
+ * Compile a resource file into a binary object
*/
class TaskRC : public Task
{
public:
TaskRC(MakeBase &par) : Task(par)
- {
- type = TASK_RC; name = "rc";
- command = "windres";
- }
+ { type = TASK_RC; name = "rc"; }
virtual ~TaskRC()
{}
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "windres");
+ String flags = parent.eval(flagsOpt, "");
+ String fileName = parent.eval(fileNameOpt, "");
+ String outName = parent.eval(outNameOpt, "");
+
String fullFile = parent.resolve(fileName);
String fullOut = parent.resolve(outName);
if (!isNewerThan(fullFile, fullOut))
@@ -6999,16 +8646,17 @@ public:
error("RC problem: %s", errString.c_str());
return false;
}
+ removeFromStatCache(getNativePath(fullOut));
return true;
}
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "command", command))
+ if (!parent.getAttribute(elem, "command", commandOpt))
return false;
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (!parent.getAttribute(elem, "out", outName))
+ if (!parent.getAttribute(elem, "out", outNameOpt))
return false;
std::vector children = elem->getChildren();
for (unsigned int i=0 ; igetName();
if (tagName == "flags")
{
- if (!parent.getValue(child, flags))
+ if (!parent.getValue(child, flagsOpt))
return false;
}
}
@@ -7026,10 +8674,10 @@ public:
private:
- String command;
- String flags;
- String fileName;
- String outName;
+ String commandOpt;
+ String flagsOpt;
+ String fileNameOpt;
+ String outNameOpt;
};
@@ -7043,16 +8691,19 @@ class TaskSharedLib : public Task
public:
TaskSharedLib(MakeBase &par) : Task(par)
- {
- type = TASK_SHAREDLIB; name = "dll";
- command = "dllwrap";
- }
+ { type = TASK_SHAREDLIB; name = "dll"; }
virtual ~TaskSharedLib()
{}
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "dllwrap");
+ String fileName = parent.eval(fileNameOpt, "");
+ String defFileName = parent.eval(defFileNameOpt, "");
+ String impFileName = parent.eval(impFileNameOpt, "");
+ String libs = parent.eval(libsOpt, "");
+
//trace("###########HERE %d", fileSet.size());
bool doit = false;
@@ -7061,7 +8712,7 @@ public:
if (!listFiles(parent, fileSet))
return false;
- String fileSetDir = fileSet.getDirectory();
+ String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
for (unsigned int i=0 ; i problem: %s", errString.c_str());
return false;
}
-
+ removeFromStatCache(getNativePath(fullOut));
return true;
}
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (!parent.getAttribute(elem, "import", impFileName))
+ if (!parent.getAttribute(elem, "import", impFileNameOpt))
return false;
- if (!parent.getAttribute(elem, "def", defFileName))
+ if (!parent.getAttribute(elem, "def", defFileNameOpt))
return false;
std::vector children = elem->getChildren();
@@ -7146,9 +8799,9 @@ public:
}
else if (tagName == "libs")
{
- if (!parent.getValue(child, libs))
+ if (!parent.getValue(child, libsOpt))
return false;
- libs = strip(libs);
+ libsOpt = strip(libsOpt);
}
}
return true;
@@ -7156,12 +8809,13 @@ public:
private:
- String command;
- String fileName;
- String defFileName;
- String impFileName;
FileSet fileSet;
- String libs;
+
+ String commandOpt;
+ String fileNameOpt;
+ String defFileNameOpt;
+ String impFileNameOpt;
+ String libsOpt;
};
@@ -7175,17 +8829,16 @@ class TaskStaticLib : public Task
public:
TaskStaticLib(MakeBase &par) : Task(par)
- {
- type = TASK_STATICLIB; name = "staticlib";
- command = "ar crv";
- }
+ { type = TASK_STATICLIB; name = "staticlib"; }
virtual ~TaskStaticLib()
{}
virtual bool execute()
{
- //trace("###########HERE %d", fileSet.size());
+ String command = parent.eval(commandOpt, "ar crv");
+ String fileName = parent.eval(fileNameOpt, "");
+
bool doit = false;
String fullOut = parent.resolve(fileName);
@@ -7193,7 +8846,8 @@ public:
if (!listFiles(parent, fileSet))
return false;
- String fileSetDir = fileSet.getDirectory();
+ String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
+ //trace("###########HERE %s", fileSetDir.c_str());
for (unsigned int i=0 ; i problem: %s", errString.c_str());
return false;
}
-
+ removeFromStatCache(getNativePath(fullOut));
return true;
}
virtual bool parse(Element *elem)
{
- String s;
- if (!parent.getAttribute(elem, "command", s))
+ if (!parent.getAttribute(elem, "command", commandOpt))
return false;
- if (s.size()>0)
- command = s;
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
std::vector children = elem->getChildren();
@@ -7270,10 +8921,11 @@ public:
private:
- String command;
- String fileName;
FileSet fileSet;
+ String commandOpt;
+ String fileNameOpt;
+
};
@@ -7294,6 +8946,10 @@ public:
virtual bool execute()
{
+ String command = parent.eval(commandOpt, "strip");
+ String fileName = parent.eval(fileNameOpt, "");
+ String symFileName = parent.eval(symFileNameOpt, "");
+
String fullName = parent.resolve(fileName);
//trace("fullDir:%s", fullDir.c_str());
String cmd;
@@ -7313,23 +8969,26 @@ public:
}
}
- cmd = "strip ";
+ cmd = command;
cmd.append(getNativePath(fullName));
if (!executeCommand(cmd, "", outbuf, errbuf))
{
error(" failed : %s", errbuf.c_str());
return false;
}
+ removeFromStatCache(getNativePath(fullName));
return true;
}
virtual bool parse(Element *elem)
{
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "command", commandOpt))
+ return false;
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (!parent.getAttribute(elem, "symfile", symFileName))
+ if (!parent.getAttribute(elem, "symfile", symFileNameOpt))
return false;
- if (fileName.size() == 0)
+ if (fileNameOpt.size() == 0)
{
error(" requires 'file=\"fileName\"' attribute");
return false;
@@ -7339,8 +8998,9 @@ public:
private:
- String fileName;
- String symFileName;
+ String commandOpt;
+ String fileNameOpt;
+ String symFileNameOpt;
};
@@ -7359,6 +9019,8 @@ public:
virtual bool execute()
{
+ String fileName = parent.eval(fileNameOpt, "");
+
String fullName = parent.resolve(fileName);
String nativeFile = getNativePath(fullName);
if (!isRegularFile(fullName) && !isDirectory(fullName))
@@ -7380,15 +9042,16 @@ public:
nativeFile.c_str(), strerror(ret));
return false;
}
+ removeFromStatCache(nativeFile);
return true;
}
virtual bool parse(Element *elem)
{
//trace("touch parse");
- if (!parent.getAttribute(elem, "file", fileName))
+ if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
- if (fileName.size() == 0)
+ if (fileNameOpt.size() == 0)
{
error(" requires 'file=\"fileName\"' attribute");
return false;
@@ -7396,7 +9059,7 @@ public:
return true;
}
- String fileName;
+ String fileNameOpt;
};
@@ -7439,8 +9102,16 @@ Task *Task::createTask(Element *elem, int lineNr)
task = new TaskCC(parent);
else if (tagName == "copy")
task = new TaskCopy(parent);
+ else if (tagName == "cxxtestpart")
+ task = new TaskCxxTestPart(parent);
+ else if (tagName == "cxxtestroot")
+ task = new TaskCxxTestRoot(parent);
+ else if (tagName == "cxxtestrun")
+ task = new TaskCxxTestRun(parent);
else if (tagName == "delete")
task = new TaskDelete(parent);
+ else if (tagName == "echo")
+ task = new TaskEcho(parent);
else if (tagName == "jar")
task = new TaskJar(parent);
else if (tagName == "javac")
@@ -7453,6 +9124,8 @@ Task *Task::createTask(Element *elem, int lineNr)
task = new TaskMkDir(parent);
else if (tagName == "msgfmt")
task = new TaskMsgFmt(parent);
+ else if (tagName == "pkg-config")
+ task = new TaskPkgConfig(parent);
else if (tagName == "ranlib")
task = new TaskRanlib(parent);
else if (tagName == "rc")
@@ -7798,8 +9471,6 @@ private:
String description;
- String envAlias;
-
//std::vector properties;
std::map targets;
@@ -7827,7 +9498,11 @@ void Make::init()
specifiedTarget = "";
baseDir = "";
description = "";
- envAlias = "";
+ envPrefix = "env.";
+ pcPrefix = "pc.";
+ pccPrefix = "pcc.";
+ pclPrefix = "pcl.";
+ svnPrefix = "svn.";
properties.clear();
for (unsigned int i = 0 ; i < allTasks.size() ; i++)
delete allTasks[i];
@@ -7920,14 +9595,15 @@ bool Make::executeTarget(Target &target,
}
}
- status("## Target : %s", name.c_str());
+ status("##### Target : %s\n##### %s", name.c_str(),
+ target.getDescription().c_str());
//Now let's do the tasks
std::vector &tasks = target.getTasks();
for (unsigned int i=0 ; igetName().c_str());
+ status("--- %s / %s", name.c_str(), task->getName().c_str());
if (!task->execute())
{
return false;
@@ -8207,12 +9883,53 @@ bool Make::parseProperty(Element *elem)
}
else if (attrName == "environment")
{
- if (envAlias.size() > 0)
+ if (attrVal.find('.') != attrVal.npos)
+ {
+ error("environment prefix cannot have a '.' in it");
+ return false;
+ }
+ envPrefix = attrVal;
+ envPrefix.push_back('.');
+ }
+ else if (attrName == "pkg-config")
+ {
+ if (attrVal.find('.') != attrVal.npos)
+ {
+ error("pkg-config prefix cannot have a '.' in it");
+ return false;
+ }
+ pcPrefix = attrVal;
+ pcPrefix.push_back('.');
+ }
+ else if (attrName == "pkg-config-cflags")
+ {
+ if (attrVal.find('.') != attrVal.npos)
+ {
+ error("pkg-config-cflags prefix cannot have a '.' in it");
+ return false;
+ }
+ pccPrefix = attrVal;
+ pccPrefix.push_back('.');
+ }
+ else if (attrName == "pkg-config-libs")
+ {
+ if (attrVal.find('.') != attrVal.npos)
+ {
+ error("pkg-config-libs prefix cannot have a '.' in it");
+ return false;
+ }
+ pclPrefix = attrVal;
+ pclPrefix.push_back('.');
+ }
+ else if (attrName == "subversion")
+ {
+ if (attrVal.find('.') != attrVal.npos)
{
- error("environment property can only be set once");
+ error("subversion prefix cannot have a '.' in it");
return false;
}
- envAlias = attrVal;
+ svnPrefix = attrVal;
+ svnPrefix.push_back('.');
}
}
@@ -8449,7 +10166,7 @@ typedef buildtool::String String;
/**
* Format an error message in printf() style
*/
-static void error(char *fmt, ...)
+static void error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -8489,7 +10206,7 @@ static bool parseProperty(const String &s, String &name, String &val)
/**
* Compare a buffer with a key, for the length of the key
*/
-static bool sequ(const String &buf, char *key)
+static bool sequ(const String &buf, const char *key)
{
int len = buf.size();
for (int i=0 ; key[i] && i2 && sequ(arg, "-D"))
{
- String s = arg.substr(2, s.size());
+ String s = arg.substr(2, arg.size());
String name, value;
if (!parseProperty(s, name, value))
{
@@ -8623,7 +10340,7 @@ static bool depTest()
deptool.setSourceDirectory("/dev/ink/inkscape/src");
if (!deptool.generateDependencies("build.dep"))
return false;
- std::vector res =
+ std::vector res =
deptool.loadDepFile("build.dep");
if (res.size() == 0)
return false;