* Merge remaining stuff from the nix-make branch.
* Add support for the creation of shared libraries to `compileC', `link', and `makeLibrary'. * Enable the ATerm library to be made into a shared library.
This commit is contained in:
parent
02f2da0142
commit
36fb29f8f0
34
make/examples/aterm/aterm/default.nix
Normal file
34
make/examples/aterm/aterm/default.nix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{sharedLib ? true}:
|
||||||
|
|
||||||
|
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";
|
||||||
|
forSharedLib = sharedLib;
|
||||||
|
};
|
||||||
|
|
||||||
|
libATerm = makeLibrary {
|
||||||
|
libraryName = "ATerm";
|
||||||
|
objects = map compile sources;
|
||||||
|
inherit sharedLib;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
1
make/examples/aterm/default.nix
Normal file
1
make/examples/aterm/default.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import test/default.nix
|
18
make/examples/aterm/test/default.nix
Normal file
18
make/examples/aterm/test/default.nix
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
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;};
|
||||||
|
|
||||||
|
primes = link {objects = compile ./primes.c; libraries = libATerm;};
|
||||||
|
|
||||||
|
body = [fib primes];
|
||||||
|
}
|
6
make/examples/default.nix
Normal file
6
make/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
make/examples/not-so-simple-header-auto/bar/hello.h
Normal file
1
make/examples/not-so-simple-header-auto/bar/hello.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#define WHAT "World"
|
11
make/examples/not-so-simple-header-auto/default.nix
Normal file
11
make/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];
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
#define HELLO "Hello"
|
||||||
|
|
||||||
|
#include "../../bar/hello.h"
|
9
make/examples/not-so-simple-header-auto/foo/hello.c
Normal file
9
make/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
make/examples/not-so-simple-header/bar/hello.h
Normal file
1
make/examples/not-so-simple-header/bar/hello.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#define WHAT "World"
|
14
make/examples/not-so-simple-header/default.nix
Normal file
14
make/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
make/examples/not-so-simple-header/foo/fnord/indirect.h
Normal file
3
make/examples/not-so-simple-header/foo/fnord/indirect.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define HELLO "Hello"
|
||||||
|
|
||||||
|
#include "../../bar/hello.h"
|
9
make/examples/not-so-simple-header/foo/hello.c
Normal file
9
make/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
make/examples/simple-header/default.nix
Normal file
11
make/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
make/examples/simple-header/hello.c
Normal file
9
make/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
make/examples/simple-header/hello.h
Normal file
1
make/examples/simple-header/hello.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#define WHAT "World"
|
8
make/examples/trivial/default.nix
Normal file
8
make/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
make/examples/trivial/hello.c
Normal file
7
make/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
make/lib/compile-c.sh
Normal file
73
make/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 -sf $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
|
59
make/lib/default.nix
Normal file
59
make/lib/default.nix
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
rec {
|
||||||
|
|
||||||
|
# Should point at your Nixpkgs installation.
|
||||||
|
pkgPath = ./pkgs;
|
||||||
|
|
||||||
|
pkgs = import (pkgPath + /system/all-packages.nix) {};
|
||||||
|
|
||||||
|
stdenv = pkgs.stdenv;
|
||||||
|
|
||||||
|
|
||||||
|
compileC = {main, localIncludes ? [], cFlags ? "", forSharedLib ? false}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "compile-c";
|
||||||
|
builder = ./compile-c.sh;
|
||||||
|
localIncludes =
|
||||||
|
if localIncludes == "auto" then
|
||||||
|
import (findIncludes {
|
||||||
|
main = toString main;
|
||||||
|
hack = __currentTime;
|
||||||
|
inherit cFlags;
|
||||||
|
})
|
||||||
|
else
|
||||||
|
localIncludes;
|
||||||
|
inherit main;
|
||||||
|
cFlags = [
|
||||||
|
cFlags
|
||||||
|
(if forSharedLib then ["-fpic"] else [])
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 ? [], sharedLib ? false}:
|
||||||
|
# assert sharedLib -> fold (obj: x: assert obj.sharedLib && x) false objects
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "library";
|
||||||
|
builder = ./make-library.sh;
|
||||||
|
inherit objects libraryName sharedLib;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
20
make/lib/find-includes.sh
Normal file
20
make/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
|
21
make/lib/link.sh
Normal file
21
make/lib/link.sh
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
. $stdenv/setup
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
objs=
|
||||||
|
for i in $objects; do
|
||||||
|
obj=$(echo $i/*.o)
|
||||||
|
objs="$objs $obj"
|
||||||
|
done
|
||||||
|
|
||||||
|
libs=
|
||||||
|
for i in $libraries; do
|
||||||
|
lib=$(echo $i/*.a; echo $i/*.so)
|
||||||
|
name=$(echo $(basename $lib) | sed -e 's/^lib//' -e 's/.a$//' -e 's/.so$//')
|
||||||
|
libs="$libs -L$(dirname $lib) -l$name"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "linking object files into \`$programName'..."
|
||||||
|
|
||||||
|
mkdir $out
|
||||||
|
gcc -o $out/$programName $objs $libs
|
28
make/lib/make-library.sh
Normal file
28
make/lib/make-library.sh
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
. $stdenv/setup
|
||||||
|
|
||||||
|
objs=
|
||||||
|
for i in $objects; do
|
||||||
|
obj=$(echo $i/*.o)
|
||||||
|
objs="$objs $obj"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "archiving object files into library \`$libraryName'..."
|
||||||
|
|
||||||
|
ensureDir $out
|
||||||
|
|
||||||
|
if test -z "$sharedLib"; then
|
||||||
|
|
||||||
|
outPath=$out/lib${libraryName}.a
|
||||||
|
|
||||||
|
ar crs $outPath $objs
|
||||||
|
ranlib $outPath
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
outPath=$out/lib${libraryName}.so
|
||||||
|
|
||||||
|
gcc -shared -o $outPath $objs
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue