From 92751409f7e9c403cbfeb503cc494279c712c9ab Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sat, 29 Oct 2016 13:28:03 -0700 Subject: Provide mechanism to track library dependencies Now, ar/lib rules can list static libraries or other .d files. These (as well as the target library) are written to a file called $lib.d. link/exe rules can list these .d files, causing them to be flattened into an RSP file and appear on the command line as @$rsp. The rule to generate the dependency list files depends on the libraries they contain, so they also act as a stamp file for the dependencies. This gives us dependency management for free. --- ninja.rc | 26 ++++++++++++++++++++++---- rules.ninja | 5 +++++ scripts/rsp.awk | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 scripts/rsp.awk diff --git a/ninja.rc b/ninja.rc index 0733e2d3..d1f3550b 100644 --- a/ninja.rc +++ b/ninja.rc @@ -74,24 +74,42 @@ fn cc { } fn link { - out='$outdir'/$1 objs=() { + out='$outdir'/$1 objs=() deps=() { shift for(obj in $*) { if(! ~ $obj '$'*) obj='$outdir'/$obj - objs=($objs $obj) + switch($obj) { + case *.d + deps=($deps $obj) + case * + objs=($objs $obj) + } + } + if(! ~ $#deps 0) { + build $out.rsp awk $deps '|' scripts/rsp.awk ; with expr '-f scripts/rsp.awk' + objs=($objs '|' $out.rsp) } build $out link $objs + if(! ~ $#deps 0) + with ldlibs @$out.rsp + status=() } } fn ar { - out='$outdir'/$1 objs=() { + out='$outdir'/$1 objs=() deps=() { shift for(obj in $*) { if(! ~ $obj '$'*) obj='$outdir'/$obj - objs=($objs $obj) + switch($obj) { + case *.[ad] + deps=($deps $obj) + case * + objs=($objs $obj) + } } build $out ar $objs + build $out.d lines $out $deps } } diff --git a/rules.ninja b/rules.ninja index 45821074..6ab2b0da 100644 --- a/rules.ninja +++ b/rules.ninja @@ -17,6 +17,11 @@ rule link rule ar command = rm -f $out && $ar crs $out $in +rule lines + command = ln -f $rspfile $out + rspfile = $out.tmp + rspfile_content = $in_newline + rule nasm command = nasm $nasmflags -o $out $in diff --git a/scripts/rsp.awk b/scripts/rsp.awk new file mode 100644 index 00000000..d157e249 --- /dev/null +++ b/scripts/rsp.awk @@ -0,0 +1,34 @@ +function line() { + if (match($0, /\.d$/)) + read($0) + else + libs[++n] = $0 +} + +function read(name) { + for (;;) { + ret = getline < name + if (ret < 0) { + print "failed to read line from " name > "/proc/self/fd/2" + exit(1) + } + if (ret == 0) + break + line() + } + close(name) +} + +{line()} + +END { + for (i = n; i > 0; --i) { + lib = libs[i] + if (lib in seen) + continue + seen[lib] = 1 + uniq[++m] = lib + } + for (i = m; i > 0; --i) + print uniq[i] +} -- cgit v1.2.3