# ninja constructs fn set { var=$1 { shift printf '%s = %s\n' $var $"* } } fn with { while(! ~ $#* 0) { printf ' %s = %s\n' $1 $2 shift 2 } status=() } fn subninja { file=$1 if(! ~ $file '$'*) file='$dir'/$file echo subninja $file } fn include { echo include $* } fn rule { name=$1 { shift echo rule $name ; with command $"* } } fn build { out=$1 rule=$2 src=() { shift 2 for(src) if(~ $src '$srcdir'/*) allsrcs=($allsrcs $src) echo build $out: $rule $* } } # higher-level rules fn toolchain { set cflags '$'$1^_cflags set cxxflags '$'$1^_cxxflags set ldflags '$'$1^_ldflags include 'toolchain/$'$1'_toolchain.ninja' } fn phony { name=$1 { shift build '$dir'/$name phony $* } } fn cflags { set cflags '$cflags' $* } fn compile { rule=$1 src=$2 obj=$src.o { shift 2 if(! ~ $src '$'*) { src='$srcdir'/$src obj='$outdir'/$obj } build $obj $rule $src $* } } fn cc { compile cc $* } fn link { out='$outdir'/$1 objs=() deps=() { shift for(obj in $*) { if(! ~ $obj '$'*) obj='$outdir'/$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=() deps=() { shift for(obj in $*) { if(! ~ $obj '$'*) obj='$outdir'/$obj switch($obj) { case *.[ad] deps=($deps $obj) case * objs=($objs $obj) } } build $out ar $objs build $out.d lines $out $deps } } fn objects { rule=$1 out=$2 deps=() objs=() { shift 2 if(~ $1 -d) { deps=('||' $2) shift 2 } for(src) { switch($src) { case *.[csS] *.cc *.cpp compile cc $src $deps obj=$src.o case *.asm compile nasm $src $deps obj=$src.o case * obj=$src } objs=($objs $obj) } $rule $out $objs } } fn lib { objects ar $* } fn exe { objects link $* } fn yacc { outs='$outdir'/$1.tab.^(c h) { build $"outs yacc $2 ; with yaccflags '-d -b '$1 } } fn waylandproto { proto='$srcdir'/$1 shift build '$outdir'/$1 waylandproto $proto ; with type client-header build '$outdir'/$2 waylandproto $proto ; with type server-header build '$outdir'/$3 waylandproto $proto ; with type code cc '$outdir'/$3 '||' pkg/wayland/headers } # packaging rules fn file { ~ $#* 3 if(~ $dir . util || fs $pkg $1) { out='$builddir'/root.hash/$1 mode=`{printf %4s $3 | tr ' ' 0 | tail -c 4} build $out githash $2 '|' scripts/hash.rc '||' '$builddir'/root.stamp ; with\ args 10$mode' '$1 index_inputs=($index_inputs $out) if(! ~ $mode 0755 0644) tree_perms=($tree_perms 10$mode' '$1) } status=() } fn dir { ~ $#* 2 if(~ $dir . util || fs $pkg $1) tree_perms=($tree_perms '040'$2' '$1) status=() } fn sym { ~ $#* 2 if(~ $dir . util || fs $pkg $1) { out='$builddir/root.hash'/$1 build $out githash '|' scripts/hash.rc '||' '$builddir'/root.stamp ; with\ args 120000' '$1' '$2 index_inputs=($index_inputs $out) } status=() } fn man { srcdir='$srcdir' outdir='$outdir' if(~ $1 -d) { if(~ $2 '$'*) { srcdir=$2 outdir=$2 } if not { srcdir='$srcdir'/$2 outdir='$outdir'/$2 } shift 2 } mandir=share/man for(src) { if(~ $src [1-9]) mandir=share/man/man$src if not { if(~ $src *.gz) gz=$srcdir/$src if not { build $outdir/$src.gz gzip $srcdir/$src src=$src.gz gz=$outdir/$src } file $mandir/$src $outdir/$src 644 } } } fn fetch { # Use a phony rule and stamp file to prevent ninja from making parent # directories. build '$outdir'/fetch.stamp fetch$1 '|' '$dir'/rev shift if(! ~ $#* 0) { *=''''$*'''' with args $"* } allsrcs=`{printf %s\n $allsrcs | sort -u} if(! ~ $#allsrcs 0) build $"allsrcs phony '$outdir'/fetch.stamp status=() } status=()