diff options
Diffstat (limited to 'make/lib')
-rw-r--r-- | make/lib/compile-c.sh | 73 | ||||
-rw-r--r-- | make/lib/default.nix | 59 | ||||
-rw-r--r-- | make/lib/find-includes.sh | 20 | ||||
-rw-r--r-- | make/lib/link.sh | 21 | ||||
-rw-r--r-- | make/lib/make-library.sh | 28 |
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 + + |