aboutsummaryrefslogtreecommitdiff
path: root/make/lib
diff options
context:
space:
mode:
Diffstat (limited to 'make/lib')
-rw-r--r--make/lib/compile-c.sh73
-rw-r--r--make/lib/default.nix59
-rw-r--r--make/lib/find-includes.sh20
-rw-r--r--make/lib/link.sh21
-rw-r--r--make/lib/make-library.sh28
5 files changed, 201 insertions, 0 deletions
diff --git a/make/lib/compile-c.sh b/make/lib/compile-c.sh
new file mode 100644
index 000000000..3558dd89e
--- /dev/null
+++ b/make/lib/compile-c.sh
@@ -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
diff --git a/make/lib/default.nix b/make/lib/default.nix
new file mode 100644
index 000000000..a5059252d
--- /dev/null
+++ b/make/lib/default.nix
@@ -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;
+ };
+
+}
diff --git a/make/lib/find-includes.sh b/make/lib/find-includes.sh
new file mode 100644
index 000000000..4824207c2
--- /dev/null
+++ b/make/lib/find-includes.sh
@@ -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
diff --git a/make/lib/link.sh b/make/lib/link.sh
new file mode 100644
index 000000000..a48f750f4
--- /dev/null
+++ b/make/lib/link.sh
@@ -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
diff --git a/make/lib/make-library.sh b/make/lib/make-library.sh
new file mode 100644
index 000000000..a486a7bf7
--- /dev/null
+++ b/make/lib/make-library.sh
@@ -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
+
+