diff --git a/make/examples/aterm/test/default.nix b/make/examples/aterm/test/default.nix index 8d2bed5f..e59b86b9 100644 --- a/make/examples/aterm/test/default.nix +++ b/make/examples/aterm/test/default.nix @@ -4,7 +4,7 @@ let { inherit (import ../aterm {}) libATerm; compileTest = main: link { - objects = [(compileC {inherit main; cFlags = "-I../aterm";})]; + objects = [(compileC {inherit main; localIncludePath = [ ../aterm ];})]; libraries = libATerm; }; diff --git a/make/lib/compile-c.sh b/make/lib/compile-c.sh index 04d2595d..3558dd89 100644 --- a/make/lib/compile-c.sh +++ b/make/lib/compile-c.sh @@ -70,5 +70,4 @@ fi mkdir $out test "$prefix" && cd $prefix -ls -l gcc -Wall $cFlags -c $mainName -o $out/$mainName.o diff --git a/make/lib/default.nix b/make/lib/default.nix index b2f26a93..81440ca6 100644 --- a/make/lib/default.nix +++ b/make/lib/default.nix @@ -8,10 +8,17 @@ rec { stdenv = pkgs.stdenv; - compileC = {main, localIncludes ? "auto", cFlags ? "", sharedLib ? false}: + compileC = + { main + , localIncludes ? "auto" + , localIncludePath ? [] + , cFlags ? "" + , sharedLib ? false + }: stdenv.mkDerivation { name = "compile-c"; builder = ./compile-c.sh; + localIncludes = if localIncludes == "auto" then dependencyClosure { @@ -19,38 +26,37 @@ rec { import (findIncludes { inherit main; }); + searchPath = localIncludePath; startSet = [main]; } else localIncludes; + inherit main; + cFlags = [ cFlags (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 { name = "find-includes"; realBuilder = pkgs.perl ~ "bin/perl"; args = [ ./find-includes.pl ]; inherit main; }; - + + link = {objects, programName ? "program", libraries ? []}: stdenv.mkDerivation { name = "link"; builder = ./link.sh; inherit objects programName libraries; }; + makeLibrary = {objects, libraryName ? [], sharedLib ? false}: # assert sharedLib -> fold (obj: x: assert obj.sharedLib && x) false objects stdenv.mkDerivation { @@ -59,4 +65,5 @@ rec { inherit objects libraryName sharedLib; }; + } diff --git a/make/lib/find-includes.pl b/make/lib/find-includes.pl index f4f1f432..43406825 100644 --- a/make/lib/find-includes.pl +++ b/make/lib/find-includes.pl @@ -9,7 +9,9 @@ print OUT "[\n"; open IN, "<$root" or die "$!"; while () { if (/^\#include\s+\"(.*)\"/) { - print "DEP $1\n"; + print OUT "\"$1\"\n"; + } + if (/^\#include\s+\<(.*)\>/) { print OUT "\"$1\"\n"; } } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index f4e7b7b8..bd8f95e4 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -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. */ 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( format("illegal absolute dependency `%1%'") % dep); - Path p = canonPath(dirOf(start) + "/" + dep); + Path p = canonPath(dir + "/" + dep); if (pathExists(p)) return p; @@ -464,11 +472,11 @@ static string relativise(Path pivot, Path p) static Expr primDependencyClosure(EvalState & state, const ATermVector & args) { + startNest(nest, lvlDebug, "finding dependencies"); + Expr attrs = evalExpr(state, args[0]); - Expr scanner = queryAttr(attrs, "scanner"); - if (!scanner) throw Error("attribute `scanner' required"); - + /* Get the start set. */ Expr startSet = queryAttr(attrs, "startSet"); if (!startSet) throw Error("attribute `startSet' required"); ATermList startSet2 = evalList(state, startSet); @@ -481,6 +489,20 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args) 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 each path in `workSet', adding the dependencies to `workSet'. */ @@ -492,19 +514,38 @@ static Expr primDependencyClosure(EvalState & state, const ATermVector & args) if (doneSet.find(path) != doneSet.end()) continue; doneSet.insert(path); - /* Call the `scanner' function with `path' as argument. */ - printMsg(lvlError, format("finding dependencies in `%1%'") % path); - ATermList deps = evalList(state, makeCall(scanner, makePath(toATerm(path)))); + try { + + /* Call the `scanner' function with `path' as argument. */ + debug(format("finding dependencies in `%1%'") % path); + ATermList deps = evalList(state, makeCall(scanner, makePath(toATerm(path)))); - /* Try to find the dependencies relative to the `path'. */ - for (ATermIterator i(deps); i; ++i) { - Path dep = findDependency(path, evalString(state, *i)); - if (dep == "") - printMsg(lvlError, format("did NOT find dependency `%1%'") % dep); - else { - printMsg(lvlError, format("found dependency `%1%'") % dep); - workSet.insert(dep); + /* Try to find the dependencies relative to the `path'. */ + for (ATermIterator i(deps); i; ++i) { + string s = evalString(state, *i); + + 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))); } - printMsg(lvlError, format("RESULT is `%1%'") % makeList(deps)); + debug(format("dependency list is `%1%'") % 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() { addPrimOp("true", 0, primTrue); @@ -578,12 +627,12 @@ void EvalState::addPrimOps() addPrimOp("derivation!", 1, primDerivationStrict); addPrimOp("derivation", 1, primDerivationLazy); addPrimOp("baseNameOf", 1, primBaseNameOf); + addPrimOp("dirOf", 1, primDirOf); addPrimOp("toString", 1, primToString); addPrimOp("isNull", 1, primIsNull); addPrimOp("dependencyClosure", 1, primDependencyClosure); addPrimOp("map", 2, primMap); addPrimOp("removeAttrs", 2, primRemoveAttrs); + addPrimOp("relativise", 2, primRelativise); } - -