1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the qmake application of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "makefiledeps.h"
45 #include <qdatetime.h>
46 #include <qfileinfo.h>
48 #include <qplatformdefs.h>
49 #if defined(Q_OS_UNIX)
59 #include <sys/types.h>
61 #if defined(_MSC_VER) && _MSC_VER >= 1400
68 #define qmake_endOfLine(c) (c == '\r' || c == '\n')
70 inline bool qmake_endOfLine(const char &c) { return (c == '\r' || c == '\n'); }
73 //#define QMAKE_USE_CACHE
75 QMakeLocalFileName::QMakeLocalFileName(const QString &name) : is_null(name.isNull())
78 if(name.at(0) == QLatin1Char('"') && name.at(name.length()-2) == QLatin1Char('"'))
79 real_name = name.mid(1, name.length()-2);
85 &QMakeLocalFileName::local() const
87 if(!is_null && local_name.isNull())
88 local_name = Option::fixPathToLocalOS(real_name, true);
92 struct SourceDependChildren;
94 SourceFile() : deps(0), type(QMakeSourceFileInfo::TYPE_UNKNOWN),
95 mocable(0), traversed(0), exists(1),
96 moc_checked(0), dep_checked(0), included_count(0) { }
98 QMakeLocalFileName file;
99 SourceDependChildren *deps;
100 QMakeSourceFileInfo::SourceFileType type;
101 uint mocable : 1, traversed : 1, exists : 1;
102 uint moc_checked : 1, dep_checked : 1;
103 uchar included_count;
105 struct SourceDependChildren {
106 SourceFile **children;
107 int num_nodes, used_nodes;
108 SourceDependChildren() : children(0), num_nodes(0), used_nodes(0) { }
109 ~SourceDependChildren() { if(children) free(children); children = 0; }
110 void addChild(SourceFile *s) {
111 if(num_nodes <= used_nodes) {
113 children = (SourceFile**)realloc(children, sizeof(SourceFile*)*(num_nodes));
115 children[used_nodes++] = s;
118 SourceFile::~SourceFile() { delete deps; }
120 int hash(const char *);
125 SourceFile *lookupFile(const char *);
126 inline SourceFile *lookupFile(const QString &f) { return lookupFile(f.toLatin1().constData()); }
127 inline SourceFile *lookupFile(const QMakeLocalFileName &f) { return lookupFile(f.local().toLatin1().constData()); }
128 void addFile(SourceFile *, const char *k=0, bool own=true);
130 struct SourceFileNode {
131 SourceFileNode() : key(0), next(0), file(0), own_file(1) { }
138 SourceFileNode *next;
144 SourceFiles::SourceFiles()
146 nodes = (SourceFileNode**)malloc(sizeof(SourceFileNode*)*(num_nodes=3037));
147 for(int n = 0; n < num_nodes; n++)
151 SourceFiles::~SourceFiles()
153 for(int n = 0; n < num_nodes; n++) {
154 for(SourceFileNode *next = nodes[n]; next;) {
155 SourceFileNode *next_next = next->next;
163 int SourceFiles::hash(const char *file)
167 h = (h << 4) + *file;
168 if ((g = (h & 0xf0000000)) != 0)
176 SourceFile *SourceFiles::lookupFile(const char *file)
178 int h = hash(file) % num_nodes;
179 for(SourceFileNode *p = nodes[h]; p; p = p->next) {
180 if(!strcmp(p->key, file))
186 void SourceFiles::addFile(SourceFile *p, const char *k, bool own_file)
188 QByteArray ba = p->file.local().toLatin1();
191 int h = hash(k) % num_nodes;
192 SourceFileNode *pn = new SourceFileNode;
193 pn->own_file = own_file;
194 pn->key = qstrdup(k);
200 void QMakeSourceFileInfo::dependTreeWalker(SourceFile *node, SourceDependChildren *place)
202 if(node->traversed || !node->exists)
204 place->addChild(node);
205 node->traversed = true; //set flag
207 for(int i = 0; i < node->deps->used_nodes; i++)
208 dependTreeWalker(node->deps->children[i], place);
212 void QMakeSourceFileInfo::setDependencyPaths(const QList<QMakeLocalFileName> &l)
214 // Ensure that depdirs does not contain the same paths several times, to minimize the stats
215 QList<QMakeLocalFileName> ll;
216 for (int i = 0; i < l.count(); ++i) {
217 if (!ll.contains(l.at(i)))
223 QStringList QMakeSourceFileInfo::dependencies(const QString &file)
229 if(SourceFile *node = files->lookupFile(QMakeLocalFileName(file))) {
231 /* I stick them into a SourceDependChildren here because it is faster to just
232 iterate over the list to stick them in the list, and reset the flag, then it is
233 to loop over the tree (about 50% faster I saw) --Sam */
234 SourceDependChildren place;
235 for(int i = 0; i < node->deps->used_nodes; i++)
236 dependTreeWalker(node->deps->children[i], &place);
238 for(int i = 0; i < place.used_nodes; i++) {
239 place.children[i]->traversed = false; //reset flag
240 ret.append(place.children[i]->file.real());
249 QMakeSourceFileInfo::included(const QString &file)
254 if(SourceFile *node = files->lookupFile(QMakeLocalFileName(file)))
255 return node->included_count;
259 bool QMakeSourceFileInfo::mocable(const QString &file)
261 if(SourceFile *node = files->lookupFile(QMakeLocalFileName(file)))
262 return node->mocable;
266 QMakeSourceFileInfo::QMakeSourceFileInfo(const QString &cf)
269 dep_mode = Recursive;
271 //quick project lookups
272 includes = files = 0;
273 files_changed = false;
277 spare_buffer_size = 0;
281 if(!cachefile.isEmpty())
282 loadCache(cachefile);
285 QMakeSourceFileInfo::~QMakeSourceFileInfo()
288 if(!cachefile.isEmpty() /*&& files_changed*/)
289 saveCache(cachefile);
295 spare_buffer_size = 0;
298 //quick project lookup
303 void QMakeSourceFileInfo::setCacheFile(const QString &cf)
306 loadCache(cachefile);
309 void QMakeSourceFileInfo::addSourceFiles(const QStringList &l, uchar seek,
310 QMakeSourceFileInfo::SourceFileType type)
312 for(int i=0; i<l.size(); ++i)
313 addSourceFile(l.at(i), seek, type);
315 void QMakeSourceFileInfo::addSourceFile(const QString &f, uchar seek,
316 QMakeSourceFileInfo::SourceFileType type)
319 files = new SourceFiles;
321 QMakeLocalFileName fn(f);
322 SourceFile *file = files->lookupFile(fn);
324 file = new SourceFile;
326 files->addFile(file);
328 if(file->type != type && file->type != TYPE_UNKNOWN && type != TYPE_UNKNOWN)
329 warn_msg(WarnLogic, "%s is marked as %d, then %d!", f.toLatin1().constData(),
332 if(type != TYPE_UNKNOWN)
335 if(seek & SEEK_MOCS && !file->moc_checked)
337 if(seek & SEEK_DEPS && !file->dep_checked)
341 bool QMakeSourceFileInfo::containsSourceFile(const QString &f, SourceFileType type)
343 if(SourceFile *file = files->lookupFile(QMakeLocalFileName(f)))
344 return (file->type == type || file->type == TYPE_UNKNOWN || type == TYPE_UNKNOWN);
348 char *QMakeSourceFileInfo::getBuffer(int s) {
349 if(!spare_buffer || spare_buffer_size < s)
350 spare_buffer = (char *)realloc(spare_buffer, spare_buffer_size=s);
355 #define S_ISDIR(x) (x & _S_IFDIR)
358 QMakeLocalFileName QMakeSourceFileInfo::fixPathForFile(const QMakeLocalFileName &f, bool)
363 QMakeLocalFileName QMakeSourceFileInfo::findFileForDep(const QMakeLocalFileName &/*dep*/,
364 const QMakeLocalFileName &/*file*/)
366 return QMakeLocalFileName();
369 QFileInfo QMakeSourceFileInfo::findFileInfo(const QMakeLocalFileName &dep)
371 return QFileInfo(dep.real());
374 bool QMakeSourceFileInfo::findDeps(SourceFile *file)
376 if(file->dep_checked || file->type == TYPE_UNKNOWN)
378 files_changed = true;
379 file->dep_checked = true;
381 const QMakeLocalFileName sourceFile = fixPathForFile(file->file, true);
388 #if defined(_MSC_VER) && _MSC_VER >= 1400
389 if (_sopen_s(&fd, sourceFile.local().toLatin1().constData(),
390 _O_RDONLY, _SH_DENYNO, _S_IREAD) != 0)
393 fd = open(sourceFile.local().toLatin1().constData(), O_RDONLY);
395 if(fd == -1 || fstat(fd, &fst) || S_ISDIR(fst.st_mode))
397 buffer = getBuffer(fst.st_size);
398 for(int have_read = 0;
399 (have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len));
400 buffer_len += have_read) ;
406 file->deps = new SourceDependChildren;
410 for(int x = 0; x < buffer_len; ++x) {
411 bool try_local = true;
413 if(file->type == QMakeSourceFileInfo::TYPE_UI) {
415 while(x < buffer_len && (*(buffer+x) == ' ' || *(buffer+x) == '\t'))
417 if(*(buffer + x) == '<') {
419 if(buffer_len >= x + 12 && !strncmp(buffer + x, "includehint", 11) &&
420 (*(buffer + x + 11) == ' ' || *(buffer + x + 11) == '>')) {
421 for(x += 11; *(buffer + x) != '>'; ++x) ;
423 for(x += 1 ; *(buffer + x + inc_len) != '<'; ++inc_len) ;
424 *(buffer + x + inc_len) = '\0';
426 } else if(buffer_len >= x + 13 && !strncmp(buffer + x, "customwidget", 12) &&
427 (*(buffer + x + 12) == ' ' || *(buffer + x + 12) == '>')) {
428 for(x += 13; *(buffer + x) != '>'; ++x) ; //skip up to >
429 while(x < buffer_len) {
430 for(x++; *(buffer + x) != '<'; ++x) ; //skip up to <
432 if(buffer_len >= x + 7 && !strncmp(buffer+x, "header", 6) &&
433 (*(buffer + x + 6) == ' ' || *(buffer + x + 6) == '>')) {
434 for(x += 7; *(buffer + x) != '>'; ++x) ; //skip up to >
436 for(x += 1 ; *(buffer + x + inc_len) != '<'; ++inc_len) ;
437 *(buffer + x + inc_len) = '\0';
440 } else if(buffer_len >= x + 14 && !strncmp(buffer+x, "/customwidget", 13) &&
441 (*(buffer + x + 13) == ' ' || *(buffer + x + 13) == '>')) {
446 } else if(buffer_len >= x + 8 && !strncmp(buffer + x, "include", 7) &&
447 (*(buffer + x + 7) == ' ' || *(buffer + x + 7) == '>')) {
448 for(x += 8; *(buffer + x) != '>'; ++x) {
449 if(buffer_len >= x + 9 && *(buffer + x) == 'i' &&
450 !strncmp(buffer + x, "impldecl", 8)) {
451 for(x += 8; *(buffer + x) != '='; ++x) ;
452 if(*(buffer + x) != '=')
454 for(++x; *(buffer+x) == '\t' || *(buffer+x) == ' '; ++x) ;
456 if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
457 quote = *(buffer + x);
461 for(val_len = 0; true; ++val_len) {
463 if(*(buffer+x+val_len) == quote)
465 } else if(*(buffer + x + val_len) == '>' ||
466 *(buffer + x + val_len) == ' ') {
470 //? char saved = *(buffer + x + val_len);
471 *(buffer + x + val_len) = '\0';
472 if(!strcmp(buffer+x, "in implementation")) {
478 for(x += 1 ; *(buffer + x + inc_len) != '<'; ++inc_len) ;
479 *(buffer + x + inc_len) = '\0';
483 //read past new line now..
484 for(; x < buffer_len && !qmake_endOfLine(*(buffer + x)); ++x) ;
486 } else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
487 } else if(file->type == QMakeSourceFileInfo::TYPE_C) {
488 for(int beginning=1; x < buffer_len; ++x) {
489 // whitespace comments and line-endings
490 for(; x < buffer_len; ++x) {
491 if(*(buffer+x) == ' ' || *(buffer+x) == '\t') {
493 } else if(*(buffer+x) == '/') {
495 if(buffer_len >= x) {
496 if(*(buffer+x) == '/') { //c++ style comment
497 for(; x < buffer_len && !qmake_endOfLine(*(buffer + x)); ++x) ;
499 } else if(*(buffer+x) == '*') { //c style comment
500 for(++x; x < buffer_len; ++x) {
501 if(*(buffer+x) == '*') {
502 if(x+1 < buffer_len && *(buffer + (x+1)) == '/') {
506 } else if(qmake_endOfLine(*(buffer+x))) {
512 } else if(qmake_endOfLine(*(buffer+x))) {
523 // preprocessor directive
524 if(beginning && *(buffer+x) == '#')
528 if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
529 const char term = *(buffer+(x++));
530 for(; x < buffer_len; ++x) {
531 if(*(buffer+x) == term) {
534 } else if(*(buffer+x) == '\\') {
536 } else if(qmake_endOfLine(*(buffer+x))) {
546 //got a preprocessor symbol
548 while(x < buffer_len) {
549 if(*(buffer+x) != ' ' && *(buffer+x) != '\t')
555 const char *keyword = buffer+x;
556 while(x+keyword_len < buffer_len) {
557 if(((*(buffer+x+keyword_len) < 'a' || *(buffer+x+keyword_len) > 'z')) &&
558 *(buffer+x+keyword_len) != '_') {
559 for(x+=keyword_len; //skip spaces after keyword
560 x < buffer_len && (*(buffer+x) == ' ' || *(buffer+x) == '\t');
563 } else if(qmake_endOfLine(*(buffer+x+keyword_len))) {
571 if(keyword_len == 7 && !strncmp(keyword, "include", keyword_len)) {
572 char term = *(buffer + x);
576 } else if(term != '"') { //wtf?
582 for(inc_len = 0; *(buffer + x + inc_len) != term && !qmake_endOfLine(*(buffer + x + inc_len)); ++inc_len) ;
583 *(buffer + x + inc_len) = '\0';
586 } else if(keyword_len == 13 && !strncmp(keyword, "qmake_warning", keyword_len)) {
588 if(*(buffer + x) == '"')
590 if(*(buffer + x) == '\'')
596 for(msg_len = 0; (term && *(buffer + x + msg_len) != term) &&
597 !qmake_endOfLine(*(buffer + x + msg_len)); ++msg_len) ;
598 *(buffer + x + msg_len) = '\0';
599 debug_msg(0, "%s:%d %s -- %s", file->file.local().toLatin1().constData(), line_count, keyword, buffer+x);
601 } else if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
602 const char term = *(buffer+(x++));
603 while(x < buffer_len) {
604 if(*(buffer+x) == term)
606 if(*(buffer+x) == '\\') {
609 if(qmake_endOfLine(*(buffer+x)))
621 includes = new SourceFiles;
622 SourceFile *dep = includes->lookupFile(inc);
625 QMakeLocalFileName lfn(inc);
626 if(QDir::isRelativePath(lfn.real())) {
628 QDir sourceDir = findFileInfo(sourceFile).dir();
629 QMakeLocalFileName f(sourceDir.absoluteFilePath(lfn.local()));
630 if(findFileInfo(f).exists()) {
631 lfn = fixPathForFile(f);
635 if(!exists) { //path lookup
636 for(QList<QMakeLocalFileName>::Iterator it = depdirs.begin(); it != depdirs.end(); ++it) {
637 QMakeLocalFileName f((*it).real() + Option::dir_sep + lfn.real());
638 QFileInfo fi(findFileInfo(f));
639 if(fi.exists() && !fi.isDir()) {
640 lfn = fixPathForFile(f);
646 if(!exists) { //heuristic lookup
647 lfn = findFileForDep(QMakeLocalFileName(inc), file->file);
648 if((exists = !lfn.isNull()))
649 lfn = fixPathForFile(lfn);
652 exists = QFile::exists(lfn.real());
655 dep = files->lookupFile(lfn);
657 dep = new SourceFile;
659 dep->type = QMakeSourceFileInfo::TYPE_C;
661 includes->addFile(dep, inc, false);
663 dep->exists = exists;
666 if(dep && dep->file != file->file) {
667 dep->included_count++;
669 debug_msg(5, "%s:%d Found dependency to %s", file->file.real().toLatin1().constData(),
670 line_count, dep->file.local().toLatin1().constData());
671 file->deps->addChild(dep);
676 if(dependencyMode() == Recursive) { //done last because buffer is shared
677 for(int i = 0; i < file->deps->used_nodes; i++) {
678 if(!file->deps->children[i]->deps)
679 findDeps(file->deps->children[i]);
685 bool QMakeSourceFileInfo::findMocs(SourceFile *file)
687 if(file->moc_checked)
689 files_changed = true;
690 file->moc_checked = true;
697 #if defined(_MSC_VER) && _MSC_VER >= 1400
698 if (_sopen_s(&fd, fixPathForFile(file->file, true).local().toLocal8Bit().constData(),
699 _O_RDONLY, _SH_DENYRW, _S_IREAD) != 0)
702 fd = open(fixPathForFile(file->file, true).local().toLocal8Bit().constData(), O_RDONLY);
704 if(fd == -1 || fstat(fd, &fst) || S_ISDIR(fst.st_mode))
705 return false; //shouldn't happen
706 buffer = getBuffer(fst.st_size);
707 for(int have_read = buffer_len = 0;
708 (have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len));
709 buffer_len += have_read) ;
713 debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData());
715 bool ignore_qobject = false, ignore_qgadget = false;
716 /* qmake ignore Q_GADGET */
717 /* qmake ignore Q_OBJECT */
718 for(int x = 0; x < buffer_len; x++) {
719 if(*(buffer + x) == '/') {
721 if(buffer_len >= x) {
722 if(*(buffer + x) == '/') { //c++ style comment
723 for(;x < buffer_len && !qmake_endOfLine(*(buffer + x)); ++x) ;
724 } else if(*(buffer + x) == '*') { //c style comment
725 for(++x; x < buffer_len; ++x) {
726 if(*(buffer + x) == 't' || *(buffer + x) == 'q') { //ignore
727 if(buffer_len >= (x + 20) &&
728 !strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
729 debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
730 file->file.real().toLatin1().constData(), line_count);
732 ignore_qobject = true;
733 } else if(buffer_len >= (x + 20) &&
734 !strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
735 debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
736 file->file.real().toLatin1().constData(), line_count);
738 ignore_qgadget = true;
740 } else if(*(buffer + x) == '*') {
741 if(buffer_len >= (x+1) && *(buffer + (x+1)) == '/') {
745 } else if(Option::debug_level && qmake_endOfLine(*(buffer + x))) {
751 } else if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
752 const char term = *(buffer+(x++));
753 while(x < buffer_len) {
754 if(*(buffer+x) == term)
756 if(*(buffer+x) == '\\') {
759 if(qmake_endOfLine(*(buffer+x)))
765 if(Option::debug_level && qmake_endOfLine(*(buffer+x)))
767 if(((buffer_len > x+2 && *(buffer+x+1) == 'Q' && *(buffer+x+2) == '_')
769 (buffer_len > x+4 && *(buffer+x+1) == 'Q' && *(buffer+x+2) == 'O'
770 && *(buffer+x+3) == 'M' && *(buffer+x+4) == '_'))
772 *(buffer + x) != '_' &&
773 (*(buffer + x) < 'a' || *(buffer + x) > 'z') &&
774 (*(buffer + x) < 'A' || *(buffer + x) > 'Z') &&
775 (*(buffer + x) < '0' || *(buffer + x) > '9')) {
778 static const char *interesting[] = { "OBJECT", "GADGET",
780 for(int interest = 0, m1, m2; interest < 3; ++interest) {
781 if(interest == 0 && ignore_qobject)
783 else if(interest == 1 && ignore_qgadget)
785 for(m1 = 0, m2 = 0; *(interesting[interest]+m1); ++m1) {
786 if(*(interesting[interest]+m1) != *(buffer+x+2+m1)) {
797 if(match && *(buffer+x+match) != '_' &&
798 (*(buffer+x+match) < 'a' || *(buffer+x+match) > 'z') &&
799 (*(buffer+x+match) < 'A' || *(buffer+x+match) > 'Z') &&
800 (*(buffer+x+match) < '0' || *(buffer+x+match) > '9')) {
801 if(Option::debug_level) {
802 *(buffer+x+match) = '\0';
803 debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", file->file.real().toLatin1().constData(),
804 line_count, buffer+x);
806 file->mocable = true;
815 void QMakeSourceFileInfo::saveCache(const QString &cf)
817 #ifdef QMAKE_USE_CACHE
821 QFile file(QMakeLocalFileName(cf).local());
822 if(file.open(QIODevice::WriteOnly)) {
823 QTextStream stream(&file);
824 stream << qmake_version() << endl << endl; //version
825 { //cache verification
826 QMap<QString, QStringList> verify = getCacheVerification();
827 stream << verify.count() << endl;
828 for(QMap<QString, QStringList>::iterator it = verify.begin();
829 it != verify.end(); ++it) {
830 stream << it.key() << endl << it.value().join(";") << endl;
835 for(int file = 0; file < files->num_nodes; ++file) {
836 for(SourceFiles::SourceFileNode *node = files->nodes[file]; node; node = node->next) {
837 stream << node->file->file.local() << endl; //source
838 stream << node->file->type << endl; //type
842 if(node->file->deps) {
843 for(int depend = 0; depend < node->file->deps->used_nodes; ++depend) {
846 stream << node->file->deps->children[depend]->file.local();
851 stream << node->file->mocable << endl; //mocable
852 stream << endl; //just for human readability
864 void QMakeSourceFileInfo::loadCache(const QString &cf)
869 #ifdef QMAKE_USE_CACHE
870 QMakeLocalFileName cache_file(cf);
871 int fd = open(QMakeLocalFileName(cf).local().toLatin1(), O_RDONLY);
874 QFileInfo cache_fi = findFileInfo(cache_file);
875 if(!cache_fi.exists() || cache_fi.isDir())
879 if(!file.open(QIODevice::ReadOnly, fd))
881 QTextStream stream(&file);
883 if(stream.readLine() == qmake_version()) { //version check
884 stream.skipWhiteSpace();
886 bool verified = true;
887 { //cache verification
888 QMap<QString, QStringList> verify;
889 int len = stream.readLine().toInt();
890 for(int i = 0; i < len; ++i) {
891 QString var = stream.readLine();
892 QString val = stream.readLine();
893 verify.insert(var, val.split(';', QString::SkipEmptyParts));
895 verified = verifyCache(verify);
898 stream.skipWhiteSpace();
900 files = new SourceFiles;
901 while(!stream.atEnd()) {
902 QString source = stream.readLine();
903 QString type = stream.readLine();
904 QString depends = stream.readLine();
905 QString mocable = stream.readLine();
906 stream.skipWhiteSpace();
908 QMakeLocalFileName fn(source);
909 QFileInfo fi = findFileInfo(fn);
911 SourceFile *file = files->lookupFile(fn);
913 file = new SourceFile;
915 files->addFile(file);
916 file->type = (SourceFileType)type.toInt();
917 file->exists = fi.exists();
919 if(fi.exists() && fi.lastModified() < cache_fi.lastModified()) {
920 if(!file->dep_checked) { //get depends
922 file->deps = new SourceDependChildren;
923 file->dep_checked = true;
924 QStringList depend_list = depends.split(";", QString::SkipEmptyParts);
925 for(int depend = 0; depend < depend_list.size(); ++depend) {
926 QMakeLocalFileName dep_fn(depend_list.at(depend));
927 QFileInfo dep_fi(findFileInfo(dep_fn));
928 SourceFile *dep = files->lookupFile(dep_fn);
930 dep = new SourceFile;
932 dep->exists = dep_fi.exists();
933 dep->type = QMakeSourceFileInfo::TYPE_UNKNOWN;
936 dep->included_count++;
937 file->deps->addChild(dep);
940 if(!file->moc_checked) { //get mocs
941 file->moc_checked = true;
942 file->mocable = mocable.toInt();
951 QMap<QString, QStringList> QMakeSourceFileInfo::getCacheVerification()
953 return QMap<QString, QStringList>();
956 bool QMakeSourceFileInfo::verifyCache(const QMap<QString, QStringList> &v)
958 return v == getCacheVerification();