Compare commits
11 commits
Author | SHA1 | Date | |
---|---|---|---|
f1ed34081e | |||
17e20716c0 | |||
5d48dd6912 | |||
af54a60204 | |||
7d386d5c29 | |||
fa50c0849e | |||
321be4649d | |||
0920fe3038 | |||
08de98f8b6 | |||
15646244ba | |||
a2e33d200e |
30
examples/aterm/aterm/default.nix
Normal file
30
examples/aterm/aterm/default.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
rec {
|
||||||
|
|
||||||
|
inherit (import ../../../lib) compileC makeLibrary;
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
./afun.c
|
||||||
|
./aterm.c
|
||||||
|
./bafio.c
|
||||||
|
./byteio.c
|
||||||
|
./gc.c
|
||||||
|
./hash.c
|
||||||
|
./list.c
|
||||||
|
./make.c
|
||||||
|
./md5c.c
|
||||||
|
./memory.c
|
||||||
|
./tafio.c
|
||||||
|
./version.c
|
||||||
|
];
|
||||||
|
|
||||||
|
compile = fn: compileC {
|
||||||
|
main = fn;
|
||||||
|
localIncludes = "auto";
|
||||||
|
};
|
||||||
|
|
||||||
|
libATerm = makeLibrary {
|
||||||
|
libraryName = "ATerm";
|
||||||
|
objects = map {function = compile; list = sources;};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
1
examples/aterm/default.nix
Normal file
1
examples/aterm/default.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import test/default.nix
|
16
examples/aterm/test/default.nix
Normal file
16
examples/aterm/test/default.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
let {
|
||||||
|
|
||||||
|
inherit (import ../../../lib) compileC link;
|
||||||
|
|
||||||
|
inherit (import ../aterm) libATerm;
|
||||||
|
|
||||||
|
compile = fn: compileC {
|
||||||
|
main = fn;
|
||||||
|
localIncludes = "auto";
|
||||||
|
cFlags = "-I../aterm";
|
||||||
|
};
|
||||||
|
|
||||||
|
fib = link {objects = compile ./fib.c; libraries = libATerm;};
|
||||||
|
|
||||||
|
body = [fib];
|
||||||
|
}
|
6
examples/default.nix
Normal file
6
examples/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[ (import ./trivial)
|
||||||
|
(import ./simple-header)
|
||||||
|
(import ./not-so-simple-header)
|
||||||
|
(import ./not-so-simple-header-auto)
|
||||||
|
(import ./aterm)
|
||||||
|
]
|
1
examples/not-so-simple-header-auto/bar/hello.h
Normal file
1
examples/not-so-simple-header-auto/bar/hello.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#define WHAT "World"
|
11
examples/not-so-simple-header-auto/default.nix
Normal file
11
examples/not-so-simple-header-auto/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
let {
|
||||||
|
|
||||||
|
inherit (import ../../lib) compileC findIncludes link;
|
||||||
|
|
||||||
|
hello = link {programName = "hello"; objects = compileC {
|
||||||
|
main = ./foo/hello.c;
|
||||||
|
localIncludes = "auto";
|
||||||
|
};};
|
||||||
|
|
||||||
|
body = [hello];
|
||||||
|
}
|
3
examples/not-so-simple-header-auto/foo/fnord/indirect.h
Normal file
3
examples/not-so-simple-header-auto/foo/fnord/indirect.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define HELLO "Hello"
|
||||||
|
|
||||||
|
#include "../../bar/hello.h"
|
9
examples/not-so-simple-header-auto/foo/hello.c
Normal file
9
examples/not-so-simple-header-auto/foo/hello.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "fnord/indirect.h"
|
||||||
|
|
||||||
|
int main(int argc, char * * argv)
|
||||||
|
{
|
||||||
|
printf(HELLO " " WHAT "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
1
examples/not-so-simple-header/bar/hello.h
Normal file
1
examples/not-so-simple-header/bar/hello.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#define WHAT "World"
|
14
examples/not-so-simple-header/default.nix
Normal file
14
examples/not-so-simple-header/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
let {
|
||||||
|
|
||||||
|
inherit (import ../../lib) compileC link;
|
||||||
|
|
||||||
|
hello = link {programName = "hello"; objects = compileC {
|
||||||
|
main = ./foo/hello.c;
|
||||||
|
localIncludes = [
|
||||||
|
[./foo/fnord/indirect.h "fnord/indirect.h"]
|
||||||
|
[./bar/hello.h "fnord/../../bar/hello.h"]
|
||||||
|
];
|
||||||
|
};};
|
||||||
|
|
||||||
|
body = [hello];
|
||||||
|
}
|
3
examples/not-so-simple-header/foo/fnord/indirect.h
Normal file
3
examples/not-so-simple-header/foo/fnord/indirect.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define HELLO "Hello"
|
||||||
|
|
||||||
|
#include "../../bar/hello.h"
|
9
examples/not-so-simple-header/foo/hello.c
Normal file
9
examples/not-so-simple-header/foo/hello.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "fnord/indirect.h"
|
||||||
|
|
||||||
|
int main(int argc, char * * argv)
|
||||||
|
{
|
||||||
|
printf(HELLO " " WHAT "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
11
examples/simple-header/default.nix
Normal file
11
examples/simple-header/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
let {
|
||||||
|
|
||||||
|
inherit (import ../../lib) compileC link;
|
||||||
|
|
||||||
|
hello = link {objects = compileC {
|
||||||
|
main = ./hello.c;
|
||||||
|
localIncludes = [ [./hello.h "hello.h"] ];
|
||||||
|
};};
|
||||||
|
|
||||||
|
body = [hello];
|
||||||
|
}
|
9
examples/simple-header/hello.c
Normal file
9
examples/simple-header/hello.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hello.h"
|
||||||
|
|
||||||
|
int main(int argc, char * * argv)
|
||||||
|
{
|
||||||
|
printf("Hello " WHAT "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
1
examples/simple-header/hello.h
Normal file
1
examples/simple-header/hello.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#define WHAT "World"
|
8
examples/trivial/default.nix
Normal file
8
examples/trivial/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
let {
|
||||||
|
|
||||||
|
inherit (import ../../lib) compileC link;
|
||||||
|
|
||||||
|
hello = link {objects = compileC {main = ./hello.c;};};
|
||||||
|
|
||||||
|
body = [hello];
|
||||||
|
}
|
7
examples/trivial/hello.c
Normal file
7
examples/trivial/hello.c
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char * * argv)
|
||||||
|
{
|
||||||
|
printf("Hello World\n");
|
||||||
|
return 0;
|
||||||
|
}
|
73
lib/compile-c.sh
Normal file
73
lib/compile-c.sh
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
. $stdenv/setup
|
||||||
|
|
||||||
|
mainName=$(basename $main | cut -c34-)
|
||||||
|
|
||||||
|
echo "compiling \`$mainName'..."
|
||||||
|
|
||||||
|
# Turn $localIncludes into an array.
|
||||||
|
localIncludes=($localIncludes)
|
||||||
|
|
||||||
|
# Determine how many `..' levels appear in the header file references.
|
||||||
|
# E.g., if there is some reference `../../foo.h', then we have to
|
||||||
|
# insert two extra levels in the directory structure, so that `a.c' is
|
||||||
|
# stored at `dotdot/dotdot/a.c', and a reference from it to
|
||||||
|
# `../../foo.h' resolves to `dotdot/dotdot/../../foo.h' == `foo.h'.
|
||||||
|
n=0
|
||||||
|
maxDepth=0
|
||||||
|
for ((n = 0; n < ${#localIncludes[*]}; n += 2)); do
|
||||||
|
target=${localIncludes[$((n + 1))]}
|
||||||
|
|
||||||
|
# Split the target name into path components using some IFS magic.
|
||||||
|
savedIFS="$IFS"
|
||||||
|
IFS=/
|
||||||
|
components=($target)
|
||||||
|
depth=0
|
||||||
|
for ((m = 0; m < ${#components[*]}; m++)); do
|
||||||
|
c=${components[m]}
|
||||||
|
if test "$c" = ".."; then
|
||||||
|
depth=$((depth + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$savedIFS"
|
||||||
|
|
||||||
|
if test $depth -gt $maxDepth; then
|
||||||
|
maxDepth=$depth;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create the extra levels in the directory hierarchy.
|
||||||
|
prefix=
|
||||||
|
for ((n = 0; n < maxDepth; n++)); do
|
||||||
|
prefix="dotdot/$prefix"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create symlinks to the header files.
|
||||||
|
for ((n = 0; n < ${#localIncludes[*]}; n += 2)); do
|
||||||
|
source=${localIncludes[n]}
|
||||||
|
target=${localIncludes[$((n + 1))]}
|
||||||
|
|
||||||
|
# Create missing directories. We use IFS magic to split the path
|
||||||
|
# into path components.
|
||||||
|
savedIFS="$IFS"
|
||||||
|
IFS=/
|
||||||
|
components=($prefix$target)
|
||||||
|
fullPath=(.)
|
||||||
|
for ((m = 0; m < ${#components[*]} - 1; m++)); do
|
||||||
|
fullPath=("${fullPath[@]}" ${components[m]})
|
||||||
|
if ! test -d "${fullPath[*]}"; then
|
||||||
|
mkdir "${fullPath[*]}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$savedIFS"
|
||||||
|
|
||||||
|
ln -s $source $prefix$target
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create a symlink to the main file.
|
||||||
|
if ! test "$(readlink $prefix$mainName)" = $main; then
|
||||||
|
ln -s $main $prefix$mainName
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir $out
|
||||||
|
test "$prefix" && cd $prefix
|
||||||
|
gcc -Wall $cFlags -c $mainName -o $out/$mainName.o
|
46
lib/default.nix
Normal file
46
lib/default.nix
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
rec {
|
||||||
|
|
||||||
|
inherit (import /home/eelco/nixpkgs/pkgs/system/i686-linux.nix) stdenv;
|
||||||
|
|
||||||
|
compileC = {main, localIncludes ? [], cFlags ? ""}: stdenv.mkDerivation {
|
||||||
|
name = "compile-c";
|
||||||
|
builder = ./compile-c.sh;
|
||||||
|
localIncludes =
|
||||||
|
if localIncludes == "auto" then
|
||||||
|
import (findIncludes {
|
||||||
|
main = toString main;
|
||||||
|
hack = curTime;
|
||||||
|
inherit cFlags;
|
||||||
|
})
|
||||||
|
else
|
||||||
|
localIncludes;
|
||||||
|
inherit main cFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
runCommand = {command}: {
|
||||||
|
name = "run-command";
|
||||||
|
builder = ./run-command.sh;
|
||||||
|
inherit command;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
findIncludes = {main, hack, cFlags ? ""}: stdenv.mkDerivation {
|
||||||
|
name = "find-includes";
|
||||||
|
builder = ./find-includes.sh;
|
||||||
|
inherit main hack cFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
link = {objects, programName ? "program", libraries ? []}: stdenv.mkDerivation {
|
||||||
|
name = "link";
|
||||||
|
builder = ./link.sh;
|
||||||
|
inherit objects programName libraries;
|
||||||
|
};
|
||||||
|
|
||||||
|
makeLibrary = {objects, libraryName ? []}: stdenv.mkDerivation {
|
||||||
|
name = "library";
|
||||||
|
builder = ./make-library.sh;
|
||||||
|
inherit objects libraryName;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
20
lib/find-includes.sh
Normal file
20
lib/find-includes.sh
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
. $stdenv/setup
|
||||||
|
|
||||||
|
echo "finding includes of \`$(basename $main)'..."
|
||||||
|
|
||||||
|
makefile=$NIX_BUILD_TOP/makefile
|
||||||
|
|
||||||
|
mainDir=$(dirname $main)
|
||||||
|
(cd $mainDir && gcc $cFlags -MM $(basename $main) -MF $makefile) || false
|
||||||
|
|
||||||
|
echo "[" >$out
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
line=$(echo "$line" | sed 's/.*://')
|
||||||
|
for i in $line; do
|
||||||
|
fullPath=$(readlink -f $mainDir/$i)
|
||||||
|
echo " [ $fullPath \"$i\" ]" >>$out
|
||||||
|
done
|
||||||
|
done < $makefile
|
||||||
|
|
||||||
|
echo "]" >>$out
|
19
lib/link.sh
Normal file
19
lib/link.sh
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
. $stdenv/setup
|
||||||
|
|
||||||
|
objs=
|
||||||
|
for i in $objects; do
|
||||||
|
obj=$(echo $i/*.o)
|
||||||
|
objs="$objs $obj"
|
||||||
|
done
|
||||||
|
|
||||||
|
libs=
|
||||||
|
for i in $libraries; do
|
||||||
|
lib=$(echo $i/*.a)
|
||||||
|
name=$(echo $(basename $lib) | sed -e 's/^lib//' -e 's/.a$//')
|
||||||
|
libs="$libs -L$(dirname $lib) -l$name"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "linking object files into \`$programName'..."
|
||||||
|
|
||||||
|
mkdir $out
|
||||||
|
gcc -o $out/$programName $objs $libs
|
15
lib/make-library.sh
Normal file
15
lib/make-library.sh
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
. $stdenv/setup
|
||||||
|
|
||||||
|
objs=
|
||||||
|
for i in $objects; do
|
||||||
|
obj=$(echo $i/*.o)
|
||||||
|
objs="$objs $obj"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "archiving object files into library \`$libraryName'..."
|
||||||
|
|
||||||
|
outPath=$out/lib${libraryName}.a
|
||||||
|
|
||||||
|
mkdir $out
|
||||||
|
ar crs $outPath $objs
|
||||||
|
ranlib $outPath
|
|
@ -28,12 +28,14 @@ EvalState::EvalState()
|
||||||
addPrimOp0("true", primTrue);
|
addPrimOp0("true", primTrue);
|
||||||
addPrimOp0("false", primFalse);
|
addPrimOp0("false", primFalse);
|
||||||
addPrimOp0("null", primNull);
|
addPrimOp0("null", primNull);
|
||||||
|
addPrimOp0("curTime", primCurTime);
|
||||||
|
|
||||||
addPrimOp1("import", primImport);
|
addPrimOp1("import", primImport);
|
||||||
addPrimOp1("derivation", primDerivation);
|
addPrimOp1("derivation", primDerivation);
|
||||||
addPrimOp1("baseNameOf", primBaseNameOf);
|
addPrimOp1("baseNameOf", primBaseNameOf);
|
||||||
addPrimOp1("toString", primToString);
|
addPrimOp1("toString", primToString);
|
||||||
addPrimOp1("isNull", primIsNull);
|
addPrimOp1("isNull", primIsNull);
|
||||||
|
addPrimOp1("map", primMap);
|
||||||
|
|
||||||
primOpsAll.add(primOps0);
|
primOpsAll.add(primOps0);
|
||||||
primOpsAll.add(primOps1);
|
primOpsAll.add(primOps1);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "primops.hh"
|
#include "primops.hh"
|
||||||
#include "normalise.hh"
|
#include "normalise.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
@ -6,9 +8,35 @@
|
||||||
Expr primImport(EvalState & state, Expr arg)
|
Expr primImport(EvalState & state, Expr arg)
|
||||||
{
|
{
|
||||||
ATMatcher m;
|
ATMatcher m;
|
||||||
string path;
|
ATermList es;
|
||||||
if (!(atMatch(m, arg) >> "Path" >> path))
|
Path path;
|
||||||
throw Error("path expected");
|
|
||||||
|
arg = evalExpr(state, arg);
|
||||||
|
|
||||||
|
if (atMatch(m, arg) >> "Path" >> path)
|
||||||
|
;
|
||||||
|
|
||||||
|
else if (atMatch(m, arg) >> "Attrs" >> es) {
|
||||||
|
Expr a = queryAttr(arg, "type");
|
||||||
|
|
||||||
|
/* If it is a derivation, we have to realise it and load the
|
||||||
|
Nix expression created at the derivation's output path. */
|
||||||
|
if (a && evalString(state, a) == "derivation") {
|
||||||
|
a = queryAttr(arg, "drvPath");
|
||||||
|
if (!a) throw Error("bad derivation in import");
|
||||||
|
Path drvPath = evalPath(state, a);
|
||||||
|
|
||||||
|
realiseStoreExpr(drvPath);
|
||||||
|
|
||||||
|
a = queryAttr(arg, "outPath");
|
||||||
|
if (!a) throw Error("bad derivation in import");
|
||||||
|
path = evalPath(state, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == "")
|
||||||
|
throw Error("path or derivation expected in import");
|
||||||
|
|
||||||
return evalFile(state, path);
|
return evalFile(state, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +295,7 @@ Expr primToString(EvalState & state, Expr arg)
|
||||||
atMatch(m, arg) >> "Path" >> s ||
|
atMatch(m, arg) >> "Path" >> s ||
|
||||||
atMatch(m, arg) >> "Uri" >> s)
|
atMatch(m, arg) >> "Uri" >> s)
|
||||||
return ATmake("Str(<str>)", s.c_str());
|
return ATmake("Str(<str>)", s.c_str());
|
||||||
else throw Error("cannot coerce value to string");
|
throw Error("cannot coerce value to string");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -295,3 +323,41 @@ Expr primIsNull(EvalState & state, Expr arg)
|
||||||
ATMatcher m;
|
ATMatcher m;
|
||||||
return makeBool(atMatch(m, arg) >> "Null");
|
return makeBool(atMatch(m, arg) >> "Null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Expr primCurTime(EvalState & state)
|
||||||
|
{
|
||||||
|
return ATmake("Int(<int>)", time(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Expr primMap(EvalState & state, Expr arg)
|
||||||
|
{
|
||||||
|
arg = evalExpr(state, arg);
|
||||||
|
|
||||||
|
ATMatcher m;
|
||||||
|
ATermList es;
|
||||||
|
if (!(atMatch(m, arg) >> "Attrs" >> es))
|
||||||
|
throw Error("function `map' expects an attribute set");
|
||||||
|
|
||||||
|
Expr function = queryAttr(arg, "function");
|
||||||
|
if (!function)
|
||||||
|
throw Error("function `map' expects an attribute `function'");
|
||||||
|
|
||||||
|
Expr list = queryAttr(arg, "list");
|
||||||
|
if (!list)
|
||||||
|
throw Error("function `map' expects an attribute `list'");
|
||||||
|
|
||||||
|
list = evalExpr(state, list);
|
||||||
|
|
||||||
|
ATermList es2;
|
||||||
|
if (!(atMatch(m, list) >> "List" >> es2))
|
||||||
|
throw Error("attribute `list' in call to `map' must be a list");
|
||||||
|
|
||||||
|
ATermList res = ATempty;
|
||||||
|
for (ATermIterator i(es2); i; ++i)
|
||||||
|
res = ATinsert(res,
|
||||||
|
ATmake("Call(<term>, <term>)", function, *i));
|
||||||
|
|
||||||
|
return ATmake("List(<term>)", ATreverse(res));
|
||||||
|
}
|
||||||
|
|
|
@ -34,5 +34,13 @@ Expr primNull(EvalState & state);
|
||||||
/* Determine whether the argument is the null value. */
|
/* Determine whether the argument is the null value. */
|
||||||
Expr primIsNull(EvalState & state, Expr arg);
|
Expr primIsNull(EvalState & state, Expr arg);
|
||||||
|
|
||||||
|
/* Return the current time. !!! hack, impure - although due to
|
||||||
|
memoization of evaluation results this should always yield the same
|
||||||
|
value for a particular run of the program. */
|
||||||
|
Expr primCurTime(EvalState & state);
|
||||||
|
|
||||||
|
/* Apply a function to each element of a list. */
|
||||||
|
Expr primMap(EvalState & state, Expr arg);
|
||||||
|
|
||||||
|
|
||||||
#endif /* !__PRIMOPS_H */
|
#endif /* !__PRIMOPS_H */
|
||||||
|
|
Loading…
Reference in a new issue