X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=buildtool.cpp;h=94a430da38fcfb06f2f44c389d0e07a985ae5e3b;hb=8283ce7ee10f55326dff69df260418eccea35633;hp=5a53f745a97ed3f17d8bb7a4b2f051cd47b665eb;hpb=3c208ff1f520c7b749a005157391bea0d7e60b0f;p=inkscape.git diff --git a/buildtool.cpp b/buildtool.cpp index 5a53f745a..94a430da3 100644 --- a/buildtool.cpp +++ b/buildtool.cpp @@ -31,20 +31,23 @@ * 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.2, 2007 Bob Jamison" +#define BUILDTOOL_VERSION "BuildTool v0.7.1, 2007 Bob Jamison" #include +#include #include #include #include #include #include +#include #include #include @@ -63,7 +66,7 @@ //######################################################################## //# Definition of gettimeofday() for those who don't have it //######################################################################## -#ifndef HAVE_GETTIMEOFDAY +#ifdef NEED_GETTIMEOFDAY #include struct timezone { @@ -959,18 +962,18 @@ friend class Parser; public: Element() { - parent = NULL; + init(); } Element(const String &nameArg) { - parent = NULL; + init(); name = nameArg; } Element(const String &nameArg, const String &valueArg) { - parent = NULL; + init(); name = nameArg; value = valueArg; } @@ -1038,9 +1041,18 @@ public: * @param elem the element to output */ void print(); + + int getLine() + { return line; } protected: + void init() + { + parent = NULL; + line = 0; + } + void assign(const Element &other) { parent = other.parent; @@ -1049,6 +1061,7 @@ protected: namespaces = other.namespaces; name = other.name; value = other.value; + line = other.line; } void findElementsRecursive(std::vector&res, const String &name); @@ -1064,7 +1077,8 @@ protected: String name; String value; - + + int line; }; @@ -1132,15 +1146,17 @@ private: currentPosition = 0; } - void getLineAndColumn(long pos, long *lineNr, long *colNr); + int countLines(int begin, int end); + + void getLineAndColumn(int pos, int *lineNr, int *colNr); - void error(char *fmt, ...); + void error(const char *fmt, ...); - int peek(long pos); + int peek(int pos); - int match(long pos, const char *text); + int match(int pos, const char *text); - int skipwhite(long p); + int skipwhite(int p); int getWord(int p0, String &buf); @@ -1156,12 +1172,10 @@ private: bool keepGoing; Element *currentNode; - long parselen; + int parselen; XMLCh *parsebuf; - String cdatabuf; - long currentPosition; - int colNr; - + String cdatabuf; + int currentPosition; }; @@ -1177,6 +1191,7 @@ Element *Element::clone() elem->parent = parent; elem->attributes = attributes; elem->namespaces = namespaces; + elem->line = line; std::vector::iterator iter; for (iter = children.begin(); iter != children.end() ; iter++) @@ -1310,7 +1325,7 @@ void Element::print() typedef struct { - char *escaped; + const char *escaped; char value; } EntityEntry; @@ -1355,10 +1370,24 @@ String Parser::trim(const String &s) return res; } -void Parser::getLineAndColumn(long pos, long *lineNr, long *colNr) + +int Parser::countLines(int begin, int end) +{ + int count = 0; + for (int i=begin ; i= parselen) return -1; @@ -1427,7 +1456,7 @@ String Parser::encode(const String &str) } -int Parser::match(long p0, const char *text) +int Parser::match(int p0, const char *text) { int p = p0; while (*text) @@ -1441,7 +1470,7 @@ int Parser::match(long p0, const char *text) -int Parser::skipwhite(long p) +int Parser::skipwhite(int p) { while (pline = lineNr + countLines(p0, p); n->parent = par; par->addChild(n); @@ -1716,7 +1751,7 @@ int Parser::parseElement(int p0, Element *par,int depth) //# CHILD ELEMENT if (ch == '<') { - p2 = parseElement(p, n, depth+1); + p2 = parseElement(p, n, lineNr + countLines(p0, p)); if (p2 == p) { /* @@ -1808,7 +1843,7 @@ Element *Parser::parse(XMLCh *buf,int pos,int len) Element *rootNode = new Element("root"); pos = parseVersion(pos); pos = parseDoctype(pos); - pos = parseElement(pos, rootNode, 0); + pos = parseElement(pos, rootNode, 1); return rootNode; } @@ -1875,8 +1910,6 @@ Element *Parser::parseFile(const String &fileName) return n; } - - //######################################################################## //######################################################################## //## E N D X M L @@ -1884,6 +1917,10 @@ Element *Parser::parseFile(const String &fileName) //######################################################################## + + + + //######################################################################## //######################################################################## //## U R I @@ -2112,7 +2149,7 @@ private: int peek(int p); - int match(int p, char *key); + int match(int p, const char *key); int parseScheme(int p); @@ -2134,9 +2171,9 @@ private: typedef struct { - int ival; - char *sval; - int port; + int ival; + const char *sval; + int port; } LookupEntry; LookupEntry schemes[] = @@ -2329,6 +2366,7 @@ URI URI::resolve(const URI &other) const } + /** * This follows the Java URI algorithm: * 1. All "." segments are removed. @@ -2447,6 +2485,7 @@ void URI::trace(const char *fmt, ...) + //######################################################################### //# P A R S I N G //######################################################################### @@ -2462,7 +2501,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) @@ -2834,8 +2873,9 @@ private: class MakeBase { public: + MakeBase() - {} + { line = 0; } virtual ~MakeBase() {} @@ -2865,6 +2905,51 @@ public: * Get an element value, performing substitutions if necessary */ bool getValue(Element *elem, String &result); + + /** + * Set the current line number in the file + */ + void setLine(int val) + { line = val; } + + /** + * Get the current line number in the file + */ + 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; + return val; + } + + /** + * 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: @@ -2877,17 +2962,17 @@ protected: /** * 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, ...); /** * 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 @@ -2921,6 +3006,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 @@ -2978,19 +3068,6 @@ 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; @@ -3037,6 +3114,7 @@ private: */ bool getSubstitutions(const String &s, String &result); + int line; }; @@ -3047,11 +3125,11 @@ private: /** * Print a printf()-like formatted error message */ -void MakeBase::error(char *fmt, ...) +void MakeBase::error(const char *fmt, ...) { va_list args; va_start(args,fmt); - fprintf(stderr, "Make error: "); + fprintf(stderr, "Make error line %d: ", line); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args) ; @@ -3062,7 +3140,7 @@ void MakeBase::error(char *fmt, ...) /** * Print a printf()-like formatted trace message */ -void MakeBase::status(char *fmt, ...) +void MakeBase::status(const char *fmt, ...) { va_list args; va_start(args,fmt); @@ -3089,7 +3167,7 @@ String MakeBase::resolve(const String &otherPath) /** * Print a printf()-like formatted trace message */ -void MakeBase::trace(char *fmt, ...) +void MakeBase::trace(const char *fmt, ...) { va_list args; va_start(args,fmt); @@ -3296,6 +3374,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; i0 && !WriteFile(stdinWrite, inbuf.c_str(), inbuf.size(), @@ -3466,50 +3567,52 @@ bool MakeBase::executeCommand(const String &command, error("executeCommand: could not close read pipe"); return false; } + + bool lastLoop = false; while (true) { - //trace("## stderr"); DWORD avail; - if (!PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL)) - break; + DWORD bytesRead; + char readBuf[4096]; + + //trace("## stderr"); + PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL); if (avail > 0) { - DWORD bytesRead = 0; - char readBuf[1025]; - if (avail>1024) avail = 1024; - if (!ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL) - || bytesRead == 0) + bytesRead = 0; + if (avail>4096) avail = 4096; + ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL); + if (bytesRead > 0) { - break; + for (unsigned int i=0 ; i 0) { - DWORD bytesRead = 0; - char readBuf[1025]; - if (avail>1024) avail = 1024; - if (!ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL) - || bytesRead==0) + bytesRead = 0; + if (avail>4096) avail = 4096; + ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL); + if (bytesRead > 0) { - break; + for (unsigned int i=0 ; i &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 or prefix here name = ""; description = ""; cflags = ""; @@ -4363,6 +4502,8 @@ private: void assign(const PkgConfig &other) { name = other.name; + path = other.path; + prefix = other.prefix; description = other.description; cflags = other.cflags; libs = other.libs; @@ -4388,12 +4529,18 @@ private: void parseVersion(); + bool parseLine(const String &lineBuf); + bool parse(const String &buf); void dumpAttrs(); String name; + String path; + + String prefix; + String description; String cflags; @@ -4437,6 +4584,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) { @@ -4546,15 +4694,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; @@ -4575,6 +4720,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 != '=') @@ -4609,10 +4755,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); @@ -4622,23 +4776,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(); @@ -4646,6 +4832,9 @@ bool PkgConfig::parse(const String &buf) return true; } + + + void PkgConfig::dumpAttrs() { //trace("### PkgConfig attributes for %s", fileName.c_str()); @@ -4657,9 +4846,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) @@ -4683,8 +4872,25 @@ 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)) + return false; + return true; } @@ -4717,23 +4923,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; } /** @@ -4855,7 +5061,7 @@ private: path = other.path; name = other.name; suffix = other.suffix; - files = other.files; + files = other.files; //avoid recursion } }; @@ -4869,19 +5075,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; } /** @@ -4987,7 +5193,7 @@ private: /** * */ - bool sequ(int pos, char *key); + bool sequ(int pos, const char *key); /** * @@ -5002,9 +5208,7 @@ private: /** * */ - bool processDependency(FileRec *ofile, - FileRec *include, - int depth); + bool processDependency(FileRec *ofile, FileRec *include); /** * @@ -5023,8 +5227,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; @@ -5032,7 +5235,7 @@ private: * The list of .o files, and the * dependencies upon them. */ - std::map depFiles; + std::map oFiles; int depFileSize; char *depFileBuf; @@ -5057,13 +5260,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(); } @@ -5208,7 +5413,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) { @@ -5228,7 +5433,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 @@ -5241,6 +5447,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() ; @@ -5249,12 +5456,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; } } @@ -5361,9 +5573,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++) @@ -5377,7 +5587,7 @@ bool DepTool::processDependency(FileRec *ofile, FileRec *child = iter->second; ofile->files[fname] = child; - processDependency(ofile, child, depth+1); + processDependency(ofile, child); } @@ -5410,23 +5620,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); } } @@ -5474,7 +5684,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) @@ -5525,7 +5735,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; } @@ -5538,47 +5748,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; @@ -5643,11 +5859,13 @@ public: TASK_MAKEFILE, TASK_MKDIR, TASK_MSGFMT, + TASK_PKG_CONFIG, TASK_RANLIB, TASK_RC, TASK_SHAREDLIB, TASK_STATICLIB, TASK_STRIP, + TASK_TOUCH, TASK_TSTAMP } TaskType; @@ -5716,7 +5934,7 @@ public: /** * */ - Task *createTask(Element *elem); + Task *createTask(Element *elem, int lineNr); protected: @@ -5773,7 +5991,7 @@ public: virtual ~TaskCC() {} - virtual bool needsCompiling(const DepRec &depRec, + virtual bool needsCompiling(const FileRec &depRec, const String &src, const String &dest) { return false; @@ -5783,6 +6001,9 @@ public: { if (!listFiles(parent, fileSet)) return false; + + FILE *f = NULL; + f = fopen("compile.lst", "w"); bool refreshCache = false; String fullName = parent.resolve("build.dep"); @@ -5842,8 +6063,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 @@ -5881,6 +6102,7 @@ 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", @@ -5889,17 +6111,22 @@ public: } 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", destFullName.c_str(), depFullName.c_str()); @@ -5929,11 +6156,48 @@ public: //## Execute the command String outString, errString; - if (!executeCommand(cmd.c_str(), "", outString, errString)) + bool ret = executeCommand(cmd.c_str(), "", outString, errString); + + if (f) + { + fprintf(f, "########################### File : %s\n", + srcFullName.c_str()); + fprintf(f, "#### COMMAND ###\n"); + int col = 0; + for (unsigned int i = 0 ; i < cmd.size() ; i++) + { + char ch = cmd[i]; + if (isspace(ch) && col > 63) + { + fputc('\n', f); + col = 0; + } + else + { + fputc(ch, f); + col++; + } + if (col > 76) + { + fputc('\n', f); + col = 0; + } + } + fprintf(f, "\n"); + fprintf(f, "#### STDOUT ###\n%s\n", outString.c_str()); + fprintf(f, "#### STDERR ###\n%s\n\n", errString.c_str()); + } + if (!ret) { error("problem compiling: %s", errString.c_str()); return false; } + + } + + if (f) + { + fclose(f); } return true; @@ -6050,6 +6314,7 @@ public: } if (!isNewerThan(fullSource, fullDest)) { + status(" : skipped"); return true; } if (!copyFile(fullSource, fullDest)) @@ -6147,6 +6412,7 @@ public: } if (!isNewerThan(fullSource, fullDest)) { + status(" : skipped"); return true; } if (!copyFile(fullSource, fullDest)) @@ -6316,7 +6582,12 @@ public: delType = DEL_DIR; if (fileName.size()>0 && dirName.size()>0) { - error(" can only have one attribute of file= or dir="); + error(" can have one attribute of file= or dir="); + return false; + } + if (fileName.size()==0 && dirName.size()==0) + { + error(" must have one attribute of file= or dir="); return false; } String ret; @@ -6439,7 +6710,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)) @@ -6580,8 +6852,9 @@ public: //trace("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", @@ -6804,6 +7077,145 @@ private: +/** + * 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 path = parent.resolve(pkg_config_path); + PkgConfig pkgconfig; + pkgconfig.setPath(path); + pkgconfig.setPrefix(prefix); + if (!pkgconfig.query(pkgName)) + { + error(" query failed for '%s", name.c_str()); + return false; + } + String ret; + switch (query) + { + case PKG_CONFIG_QUERY_CFLAGS: + { + ret = pkgconfig.getCflags(); + break; + } + case PKG_CONFIG_QUERY_LIBS: + { + ret = pkgconfig.getLibs(); + break; + } + case PKG_CONFIG_QUERY_ALL: + { + ret = pkgconfig.getAll(); + break; + } + default: + { + error(" unhandled query : %d", query); + return false; + } + + } + status(" : %s", ret.c_str()); + parent.setProperty(propName, ret); + return true; + } + + virtual bool parse(Element *elem) + { + String s; + //# NAME + if (!parent.getAttribute(elem, "name", s)) + return false; + if (s.size()>0) + pkgName = s; + else + { + error(" requires 'name=\"package\"' attribute"); + return false; + } + + //# PROPERTY + if (!parent.getAttribute(elem, "property", s)) + return false; + if (s.size()>0) + propName = s; + else + { + error(" requires 'property=\"name\"' attribute"); + return false; + } + if (parent.hasProperty(propName)) + { + error(" property '%s' is already defined", + propName.c_str()); + return false; + } + parent.setProperty(propName, "undefined"); + + //# PATH + if (!parent.getAttribute(elem, "path", s)) + return false; + if (s.size()>0) + pkg_config_path = s; + + //# PREFIX + if (!parent.getAttribute(elem, "prefix", s)) + return false; + if (s.size()>0) + prefix = s; + + //# QUERY + if (!parent.getAttribute(elem, "query", s)) + return false; + if (s == "cflags") + query = PKG_CONFIG_QUERY_CFLAGS; + else if (s == "libs") + query = PKG_CONFIG_QUERY_LIBS; + else if (s == "both") + query = PKG_CONFIG_QUERY_ALL; + else + { + error(" requires 'query=\"type\"' attribute"); + error("where type = cflags, libs, or both"); + return false; + } + return true; + } + +private: + + String pkgName; + String prefix; + String propName; + String pkg_config_path; + int query; + +}; + + + + /** @@ -6942,7 +7354,7 @@ public: TaskSharedLib(MakeBase &par) : Task(par) { type = TASK_SHAREDLIB; name = "dll"; - command = "ar crv"; + command = "dllwrap"; } virtual ~TaskSharedLib() @@ -7063,6 +7475,7 @@ private: }; + /** * Run the "ar" command to archive .o's into a .a */ @@ -7139,6 +7552,7 @@ public: return true; } + virtual bool parse(Element *elem) { String s; @@ -7172,6 +7586,8 @@ private: }; + + /** * Strip an executable */ @@ -7237,6 +7653,62 @@ private: }; +/** + * + */ +class TaskTouch : public Task +{ +public: + + TaskTouch(MakeBase &par) : Task(par) + { type = TASK_TOUCH; name = "touch"; } + + virtual ~TaskTouch() + {} + + virtual bool execute() + { + String fullName = parent.resolve(fileName); + String nativeFile = getNativePath(fullName); + if (!isRegularFile(fullName) && !isDirectory(fullName)) + { + // S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH + int ret = creat(nativeFile.c_str(), 0666); + if (ret != 0) + { + error(" could not create '%s' : %s", + nativeFile.c_str(), strerror(ret)); + return false; + } + return true; + } + int ret = utime(nativeFile.c_str(), (struct utimbuf *)0); + if (ret != 0) + { + error(" could not update the modification time for '%s' : %s", + nativeFile.c_str(), strerror(ret)); + return false; + } + return true; + } + + virtual bool parse(Element *elem) + { + //trace("touch parse"); + if (!parent.getAttribute(elem, "file", fileName)) + return false; + if (fileName.size() == 0) + { + error(" requires 'file=\"fileName\"' attribute"); + return false; + } + return true; + } + + String fileName; +}; + + /** * */ @@ -7267,7 +7739,7 @@ public: /** * */ -Task *Task::createTask(Element *elem) +Task *Task::createTask(Element *elem, int lineNr) { String tagName = elem->getName(); //trace("task:%s", tagName.c_str()); @@ -7290,6 +7762,8 @@ Task *Task::createTask(Element *elem) 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") @@ -7300,6 +7774,8 @@ Task *Task::createTask(Element *elem) task = new TaskStaticLib(parent); else if (tagName == "strip") task = new TaskStrip(parent); + else if (tagName == "touch") + task = new TaskTouch(parent); else if (tagName == "tstamp") task = new TaskTstamp(parent); else @@ -7308,6 +7784,8 @@ Task *Task::createTask(Element *elem) return NULL; } + task->setLine(lineNr); + if (!task->parse(elem)) { delete task; @@ -7604,11 +8082,6 @@ private: */ bool parseProperty(Element *elem); - /** - * - */ - bool parseTask(Task &task, Element *elem); - /** * */ @@ -7758,7 +8231,8 @@ bool Make::executeTarget(Target &target, } } - status("## Target : %s", name.c_str()); + status("## Target : %s : %s", name.c_str(), + target.getDescription().c_str()); //Now let's do the tasks std::vector &tasks = target.getTasks(); @@ -8067,6 +8541,8 @@ bool Make::parseFile() { status("######## PARSE : %s", uri.getPath().c_str()); + setLine(0); + Parser parser; Element *root = parser.parseFile(uri.getNativePath()); if (!root) @@ -8075,6 +8551,8 @@ bool Make::parseFile() uri.getNativePath().c_str()); return false; } + + setLine(root->getLine()); if (root->getChildren().size()==0 || root->getChildren()[0]->getName()!="project") @@ -8101,6 +8579,7 @@ bool Make::parseFile() for (unsigned int i=0 ; igetLine()); String tagName = elem->getName(); //########## DESCRIPTION @@ -8135,7 +8614,7 @@ bool Make::parseFile() { Element *telem = telems[i]; Task breeder(*this); - Task *task = breeder.createTask(telem); + Task *task = breeder.createTask(telem, telem->getLine()); if (!task) return false; allTasks.push_back(task); @@ -8157,6 +8636,12 @@ bool Make::parseFile() //more work than targets[tname]=target, but avoids default allocator targets.insert(std::make_pair(tname, target)); } + //######### none of the above + else + { + error("unknown toplevel tag: <%s>", tagName.c_str()); + return false; + } } @@ -8276,7 +8761,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); @@ -8316,7 +8801,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] && i res = + std::vector res = deptool.loadDepFile("build.dep"); if (res.size() == 0) return false;