* 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:
Eelco Dolstra 2005-05-02 15:25:28 +00:00
parent 02f2da0142
commit 36fb29f8f0
22 changed files with 347 additions and 0 deletions

View 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;
};
}

View file

@ -0,0 +1 @@
import test/default.nix

View 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];
}

View file

@ -0,0 +1,6 @@
[ (import ./trivial)
(import ./simple-header)
(import ./not-so-simple-header)
(import ./not-so-simple-header-auto)
(import ./aterm)
]

View file

@ -0,0 +1 @@
#define WHAT "World"

View 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];
}

View file

@ -0,0 +1,3 @@
#define HELLO "Hello"
#include "../../bar/hello.h"

View file

@ -0,0 +1,9 @@
#include <stdio.h>
#include "fnord/indirect.h"
int main(int argc, char * * argv)
{
printf(HELLO " " WHAT "\n");
return 0;
}

View file

@ -0,0 +1 @@
#define WHAT "World"

View 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];
}

View file

@ -0,0 +1,3 @@
#define HELLO "Hello"
#include "../../bar/hello.h"

View file

@ -0,0 +1,9 @@
#include <stdio.h>
#include "fnord/indirect.h"
int main(int argc, char * * argv)
{
printf(HELLO " " WHAT "\n");
return 0;
}

View 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];
}

View file

@ -0,0 +1,9 @@
#include <stdio.h>
#include "hello.h"
int main(int argc, char * * argv)
{
printf("Hello " WHAT "\n");
return 0;
}

View file

@ -0,0 +1 @@
#define WHAT "World"

View file

@ -0,0 +1,8 @@
let {
inherit (import ../../lib) compileC link;
hello = link {objects = compileC {main = ./hello.c;};};
body = [hello];
}

View 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
View 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
View 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
View 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
View 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
View 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