* `dependencyClosure' now allows a search path, e.g.,

dependencyClosure { ... searchPath = [ ../foo ../bar ]; ... }

* Primop `dirOf' to return the directory part of a path (e.g., dirOf
  /a/b/c == /a/b).

* Primop `relativise' (according to Webster that's a real word!) that
  given paths A and B returns a string representing path B relative
  path to A; e.g., relativise /a/b/c a/b/x/y => "../x/y".
This commit is contained in:
Eelco Dolstra 2005-08-14 14:00:39 +00:00
parent 08c53923db
commit e1a6fb7870
5 changed files with 89 additions and 32 deletions

View file

@ -4,7 +4,7 @@ let {
inherit (import ../aterm {}) libATerm; inherit (import ../aterm {}) libATerm;
compileTest = main: link { compileTest = main: link {
objects = [(compileC {inherit main; cFlags = "-I../aterm";})]; objects = [(compileC {inherit main; localIncludePath = [ ../aterm ];})];
libraries = libATerm; libraries = libATerm;
}; };

View file

@ -70,5 +70,4 @@ fi
mkdir $out mkdir $out
test "$prefix" && cd $prefix test "$prefix" && cd $prefix
ls -l
gcc -Wall $cFlags -c $mainName -o $out/$mainName.o gcc -Wall $cFlags -c $mainName -o $out/$mainName.o

View file

@ -8,10 +8,17 @@ rec {
stdenv = pkgs.stdenv; stdenv = pkgs.stdenv;
compileC = {main, localIncludes ? "auto", cFlags ? "", sharedLib ? false}: compileC =
{ main
, localIncludes ? "auto"
, localIncludePath ? []
, cFlags ? ""
, sharedLib ? false
}:
stdenv.mkDerivation { stdenv.mkDerivation {
name = "compile-c"; name = "compile-c";
builder = ./compile-c.sh; builder = ./compile-c.sh;
localIncludes = localIncludes =
if localIncludes == "auto" then if localIncludes == "auto" then
dependencyClosure { dependencyClosure {
@ -19,24 +26,21 @@ rec {
import (findIncludes { import (findIncludes {
inherit main; inherit main;
}); });
searchPath = localIncludePath;
startSet = [main]; startSet = [main];
} }
else else
localIncludes; localIncludes;
inherit main; inherit main;
cFlags = [ cFlags = [
cFlags cFlags
(if sharedLib then ["-fpic"] else []) (if sharedLib then ["-fpic"] else [])
(map (p: "-I" + (relativise (dirOf main) p)) localIncludePath)
]; ];
}; };
/*
runCommand = {command}: {
name = "run-command";
builder = ./run-command.sh;
inherit command;
};
*/
findIncludes = {main}: stdenv.mkDerivation { findIncludes = {main}: stdenv.mkDerivation {
name = "find-includes"; name = "find-includes";
@ -45,12 +49,14 @@ rec {
inherit main; inherit main;
}; };
link = {objects, programName ? "program", libraries ? []}: stdenv.mkDerivation { link = {objects, programName ? "program", libraries ? []}: stdenv.mkDerivation {
name = "link"; name = "link";
builder = ./link.sh; builder = ./link.sh;
inherit objects programName libraries; inherit objects programName libraries;
}; };
makeLibrary = {objects, libraryName ? [], sharedLib ? false}: makeLibrary = {objects, libraryName ? [], sharedLib ? false}:
# assert sharedLib -> fold (obj: x: assert obj.sharedLib && x) false objects # assert sharedLib -> fold (obj: x: assert obj.sharedLib && x) false objects
stdenv.mkDerivation { stdenv.mkDerivation {
@ -59,4 +65,5 @@ rec {
inherit objects libraryName sharedLib; inherit objects libraryName sharedLib;
}; };
} }

View file

@ -9,7 +9,9 @@ print OUT "[\n";
open IN, "<$root" or die "$!"; open IN, "<$root" or die "$!";
while (<IN>) { while (<IN>) {
if (/^\#include\s+\"(.*)\"/) { if (/^\#include\s+\"(.*)\"/) {
print "DEP $1\n"; print OUT "\"$1\"\n";
}
if (/^\#include\s+\<(.*)\>/) {
print OUT "\"$1\"\n"; print OUT "\"$1\"\n";
} }
} }

View file

@ -372,6 +372,14 @@ static Expr primBaseNameOf(EvalState & state, const ATermVector & args)
} }
/* Return the directory of the given path, i.e., everything before the
last slash. */
static Expr primDirOf(EvalState & state, const ATermVector & args)
{
return makePath(toATerm(dirOf(evalPath(state, args[0]))));
}
/* Convert the argument (which can be a path or a uri) to a string. */ /* Convert the argument (which can be a path or a uri) to a string. */
static Expr primToString(EvalState & state, const ATermVector & args) static Expr primToString(EvalState & state, const ATermVector & args)
{ {
@ -410,12 +418,12 @@ static Expr primIsNull(EvalState & state, const ATermVector & args)
} }
static Path findDependency(Path start, string dep) static Path findDependency(Path dir, string dep)
{ {
if (dep[0] == '/') throw Error( if (dep[0] == '/') throw Error(
format("illegal absolute dependency `%1%'") % dep); format("illegal absolute dependency `%1%'") % dep);
Path p = canonPath(dirOf(start) + "/" + dep); Path p = canonPath(dir + "/" + dep);
if (pathExists(p)) if (pathExists(p))
return p; return p;
@ -464,11 +472,11 @@ static string relativise(Path pivot, Path p)
static Expr primDependencyClosure(EvalState & state, const ATermVector & args) static Expr primDependencyClosure(EvalState & state, const ATermVector & args)
{ {
startNest(nest, lvlDebug, "finding dependencies");
Expr attrs = evalExpr(state, args[0]); Expr attrs = evalExpr(state, args[0]);
Expr scanner = queryAttr(attrs, "scanner"); /* Get the start set. */
if (!scanner) throw Error("attribute `scanner' required");
Expr startSet = queryAttr(attrs, "startSet"); Expr startSet = queryAttr(attrs, "startSet");
if (!startSet) throw Error("attribute `startSet' required"); if (!startSet) throw Error("attribute `startSet' required");
ATermList startSet2 = evalList(state, startSet); ATermList startSet2 = evalList(state, startSet);
@ -481,6 +489,20 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args)
pivot = dirOf(p); pivot = dirOf(p);
} }
/* Get the search path. */
PathSet searchPath;
Expr e = queryAttr(attrs, "searchPath");
if (e) {
ATermList list = evalList(state, e);
for (ATermIterator i(list); i; ++i) {
Path p = evalPath(state, *i);
searchPath.insert(p);
}
}
Expr scanner = queryAttr(attrs, "scanner");
if (!scanner) throw Error("attribute `scanner' required");
/* Construct the dependency closure by querying the dependency of /* Construct the dependency closure by querying the dependency of
each path in `workSet', adding the dependencies to each path in `workSet', adding the dependencies to
`workSet'. */ `workSet'. */
@ -492,19 +514,38 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args)
if (doneSet.find(path) != doneSet.end()) continue; if (doneSet.find(path) != doneSet.end()) continue;
doneSet.insert(path); doneSet.insert(path);
/* Call the `scanner' function with `path' as argument. */ try {
printMsg(lvlError, format("finding dependencies in `%1%'") % path);
ATermList deps = evalList(state, makeCall(scanner, makePath(toATerm(path))));
/* Try to find the dependencies relative to the `path'. */ /* Call the `scanner' function with `path' as argument. */
for (ATermIterator i(deps); i; ++i) { debug(format("finding dependencies in `%1%'") % path);
Path dep = findDependency(path, evalString(state, *i)); ATermList deps = evalList(state, makeCall(scanner, makePath(toATerm(path))));
if (dep == "")
printMsg(lvlError, format("did NOT find dependency `%1%'") % dep); /* Try to find the dependencies relative to the `path'. */
else { for (ATermIterator i(deps); i; ++i) {
printMsg(lvlError, format("found dependency `%1%'") % dep); string s = evalString(state, *i);
workSet.insert(dep);
Path dep = findDependency(dirOf(path), s);
if (dep == "") {
for (PathSet::iterator j = searchPath.begin();
j != searchPath.end(); ++j)
{
dep = findDependency(*j, s);
if (dep != "") break;
}
}
if (dep == "")
debug(format("did NOT find dependency `%1%'") % s);
else {
debug(format("found dependency `%1%'") % dep);
workSet.insert(dep);
}
} }
} catch (Error & e) {
throw Error(format("while finding dependencies in `%1%':\n%2%")
% path % e.msg());
} }
} }
@ -515,7 +556,7 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args)
deps = ATinsert(deps, makePath(toATerm(*i))); deps = ATinsert(deps, makePath(toATerm(*i)));
} }
printMsg(lvlError, format("RESULT is `%1%'") % makeList(deps)); debug(format("dependency list is `%1%'") % makeList(deps));
return makeList(deps); return makeList(deps);
} }
@ -566,6 +607,14 @@ static Expr primRemoveAttrs(EvalState & state, const ATermVector & args)
} }
static Expr primRelativise(EvalState & state, const ATermVector & args)
{
Path pivot = evalPath(state, args[0]);
Path path = evalPath(state, args[1]);
return makeStr(toATerm(relativise(pivot, path)));
}
void EvalState::addPrimOps() void EvalState::addPrimOps()
{ {
addPrimOp("true", 0, primTrue); addPrimOp("true", 0, primTrue);
@ -578,12 +627,12 @@ void EvalState::addPrimOps()
addPrimOp("derivation!", 1, primDerivationStrict); addPrimOp("derivation!", 1, primDerivationStrict);
addPrimOp("derivation", 1, primDerivationLazy); addPrimOp("derivation", 1, primDerivationLazy);
addPrimOp("baseNameOf", 1, primBaseNameOf); addPrimOp("baseNameOf", 1, primBaseNameOf);
addPrimOp("dirOf", 1, primDirOf);
addPrimOp("toString", 1, primToString); addPrimOp("toString", 1, primToString);
addPrimOp("isNull", 1, primIsNull); addPrimOp("isNull", 1, primIsNull);
addPrimOp("dependencyClosure", 1, primDependencyClosure); addPrimOp("dependencyClosure", 1, primDependencyClosure);
addPrimOp("map", 2, primMap); addPrimOp("map", 2, primMap);
addPrimOp("removeAttrs", 2, primRemoveAttrs); addPrimOp("removeAttrs", 2, primRemoveAttrs);
addPrimOp("relativise", 2, primRelativise);
} }