From 0920fe3038d7653e674630b3c7900b86f37c018d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 6 Jul 2004 13:45:14 +0000 Subject: [PATCH] * Deal with directory components in header file references (e.g., `#include "foo/../bar/bla.h"') by building an appropriate tree of symlinks. --- examples/default.nix | 1 + examples/not-so-simple-header/bar/hello.h | 1 + examples/not-so-simple-header/default.nix | 14 ++++ .../not-so-simple-header/foo/fnord/indirect.h | 3 + examples/not-so-simple-header/foo/hello.c | 9 +++ lib/compile-c.sh | 66 +++++++++++++++++-- 6 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 examples/not-so-simple-header/bar/hello.h create mode 100644 examples/not-so-simple-header/default.nix create mode 100644 examples/not-so-simple-header/foo/fnord/indirect.h create mode 100644 examples/not-so-simple-header/foo/hello.c diff --git a/examples/default.nix b/examples/default.nix index 17144a255..cbeaa8bf9 100644 --- a/examples/default.nix +++ b/examples/default.nix @@ -1,3 +1,4 @@ [ (import ./trivial) (import ./simple-header) + (import ./not-so-simple-header) ] \ No newline at end of file diff --git a/examples/not-so-simple-header/bar/hello.h b/examples/not-so-simple-header/bar/hello.h new file mode 100644 index 000000000..4595fad98 --- /dev/null +++ b/examples/not-so-simple-header/bar/hello.h @@ -0,0 +1 @@ +#define WHAT "World" diff --git a/examples/not-so-simple-header/default.nix b/examples/not-so-simple-header/default.nix new file mode 100644 index 000000000..ad7470f81 --- /dev/null +++ b/examples/not-so-simple-header/default.nix @@ -0,0 +1,14 @@ +let { + + inherit (import ../../lib) compileC link; + + hello = link {objects = compileC { + main = ./foo/hello.c; + localIncludes = [ + [./foo/fnord/indirect.h "fnord/indirect.h"] + [./bar/hello.h "fnord/../../bar/hello.h"] + ]; + };}; + + body = [hello]; +} diff --git a/examples/not-so-simple-header/foo/fnord/indirect.h b/examples/not-so-simple-header/foo/fnord/indirect.h new file mode 100644 index 000000000..2fde1e26c --- /dev/null +++ b/examples/not-so-simple-header/foo/fnord/indirect.h @@ -0,0 +1,3 @@ +#define HELLO "Hello" + +#include "../../bar/hello.h" diff --git a/examples/not-so-simple-header/foo/hello.c b/examples/not-so-simple-header/foo/hello.c new file mode 100644 index 000000000..7d5b402ce --- /dev/null +++ b/examples/not-so-simple-header/foo/hello.c @@ -0,0 +1,9 @@ +#include + +#include "fnord/indirect.h" + +int main(int argc, char * * argv) +{ + printf(HELLO " " WHAT "\n"); + return 0; +} diff --git a/lib/compile-c.sh b/lib/compile-c.sh index 701c16048..71c67f744 100644 --- a/lib/compile-c.sh +++ b/lib/compile-c.sh @@ -1,18 +1,70 @@ . $stdenv/setup mainName=$(basename $main | cut -c34-) -ln -s $main $mainName 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 -while test $n -lt ${#localIncludes[*]}; do - source=${localIncludes[n]} - target=${localIncludes[$((n+1))]} - ln -s $source $target - n=$((n + 2)) +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. +ln -s $main $prefix$mainName + mkdir $out -gcc -Wall -c $mainName -o $out/$mainName.o +gcc -Wall -c $prefix$mainName -o $out/$mainName.o