* 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
					
				
					 22 changed files with 347 additions and 0 deletions
				
			
		
							
								
								
									
										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…
	
	Add table
		Add a link
		
	
		Reference in a new issue