Skip to content

Commit

Permalink
Added checks for precompiled header usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
fstromback committed Jan 11, 2016
1 parent 8822125 commit ca2921b
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ mymake

*.exe
*.lib
*.pch
*.gch
1 change: 1 addition & 0 deletions src/cmdline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ bool CmdLine::parseOption(char opt) {
break;
case 'a':
state = sArguments;
execute = tYes;
break;
case 'e':
execute = (state == sNegate) ? tNo : tYes;
Expand Down
12 changes: 11 additions & 1 deletion src/compile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ namespace compile {
String outputName = config.getStr("output");

// Compile pre-compiled header first.
addFile(q, config.getStr("pch"), true);
String pchStr = config.getStr("pch");
addFile(q, pchStr, true);

// Add initial files.
addFiles(q, config.getArray("input"));
Expand Down Expand Up @@ -73,6 +74,15 @@ namespace compile {

// Add all other files we need.
IncludeInfo info = includes.info(now);

// Check so that any pch file is included first.
if (!pchStr.empty() && pchStr != info.firstInclude) {
PLN("ERROR: Precompiled header " << pchStr << " must be included first in each implementation file.");
PLN("This is not the case for " << now.makeRelative(wd) << ".");
PLN("You need to use '#include \"" << pchStr << "\"' (exactly like that), and use 'include=./'.");
return false;
}

for (set<Path>::const_iterator i = info.includes.begin(); i != info.includes.end(); ++i) {
DEBUG(now << " depends on " << *i, VERBOSE);
addFile(q, *i);
Expand Down
47 changes: 40 additions & 7 deletions src/includes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Timestamp IncludeInfo::lastModified() const {

ostream &operator <<(ostream &to, const IncludeInfo &i) {
to << i.file << ": ";
if (!i.firstInclude.empty())
to << "(first: " << i.firstInclude << ") ";
join(to, i.includes);
return to;
}
Expand Down Expand Up @@ -47,8 +49,7 @@ IncludeInfo Includes::info(const Path &file) {
}

// We need to update the cache...
IncludeInfo r(file);
r.includes = recursiveIncludesIn(file);
IncludeInfo r = recursiveIncludesIn(file);

cache[file] = Info(r, Timestamp());

Expand All @@ -69,17 +70,23 @@ Path Includes::resolveInclude(const Path &fromFile, const String &src) const {
throw IncludeError("The include " + src + " in file " + toS(fromFile) + " was not found!");
}

set<Path> Includes::recursiveIncludesIn(const Path &file) {
set<Path> result;
IncludeInfo Includes::recursiveIncludesIn(const Path &file) {
bool first = true;
IncludeInfo result(file);

PathQueue to;
to.push(file);

while (to.any()) {
Path now = to.pop();
result << now;
result.includes << now;

includesIn(now, to);
if (first) {
includesIn(now, to, &result.firstInclude);
first = false;
} else {
includesIn(now, to, null);
}
}

return result;
Expand Down Expand Up @@ -108,18 +115,38 @@ static bool isInclude(const String &line, String &out) {
return true;
}

void Includes::includesIn(const Path &file, PathQueue &to) {
static bool isBlank(const String &line) {
for (nat i = 0; i < line.size(); i++) {
switch (line[i]) {
case ' ':
case '\t':
case '\r':
break;
default:
return false;
}
}
return true;
}

void Includes::includesIn(const Path &file, PathQueue &to, String *firstInclude) {
ifstream in(toS(file).c_str());
bool first = true;

String include;
String line;
while (getline(in, line)) {
if (isInclude(line, include)) {
try {
if (first && firstInclude)
*firstInclude = include;
to << resolveInclude(file, include);
} catch (const IncludeError &e) {
WARNING(e.what());
}
first = false;
} else if (!isBlank(line)) {
first = false;
}
}
}
Expand Down Expand Up @@ -163,6 +190,11 @@ void Includes::load(const Path &from) {

cache[path] = Info(path, time);
current = &cache[path];
} else if (type == '>') {
if (!current)
return;

getline(src, current->info.firstInclude);
} else if (type == '-') {
if (!current)
return;
Expand All @@ -185,6 +217,7 @@ void Includes::save(const Path &to) const {
const Info &info = i->second;

dest << "+" << info.lastModified.time << ' ' << info.info.file << endl;
dest << ">" << info.info.firstInclude << endl;

for (set<Path>::const_iterator i = info.info.includes.begin(); i != info.info.includes.end(); ++i) {
dest << "-" << *i << endl;
Expand Down
7 changes: 5 additions & 2 deletions src/includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class IncludeInfo {
// The file itself.
Path file;

// The first included file (if any).
String firstInclude;

// All files included from this file.
set<Path> includes;

Expand Down Expand Up @@ -83,9 +86,9 @@ class Includes {
InfoMap cache;

// Find includes in file, and all files included from there.
set<Path> recursiveIncludesIn(const Path &file);
IncludeInfo recursiveIncludesIn(const Path &file);

// Find includes in file.
void includesIn(const Path &file, PathQueue &to);
void includesIn(const Path &file, PathQueue &to, String *firstInclude);

};
1 change: 0 additions & 1 deletion todo.org
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

Move constants used with Config into string constants somewhere.

We should check so that precompiled headers are always included first in every .cpp-file.



Expand Down

0 comments on commit ca2921b

Please sign in to comment.