diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /ninja/misc | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'ninja/misc')
-rw-r--r-- | ninja/misc/bash-completion | 40 | ||||
-rw-r--r-- | ninja/misc/inherited-fds.ninja | 23 | ||||
-rw-r--r-- | ninja/misc/long-slow-build.ninja | 38 | ||||
-rwxr-xr-x | ninja/misc/measure.py | 54 | ||||
-rw-r--r-- | ninja/misc/ninja-mode.el | 42 | ||||
-rw-r--r-- | ninja/misc/ninja.vim | 81 | ||||
-rw-r--r-- | ninja/misc/ninja_syntax.py | 158 | ||||
-rwxr-xr-x | ninja/misc/ninja_syntax_test.py | 152 | ||||
-rw-r--r-- | ninja/misc/packaging/ninja.spec | 42 | ||||
-rwxr-xr-x | ninja/misc/packaging/rpmbuild.sh | 29 | ||||
-rw-r--r-- | ninja/misc/zsh-completion | 21 |
11 files changed, 680 insertions, 0 deletions
diff --git a/ninja/misc/bash-completion b/ninja/misc/bash-completion new file mode 100644 index 00000000000..2d6975b9450 --- /dev/null +++ b/ninja/misc/bash-completion @@ -0,0 +1,40 @@ +# Copyright 2011 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Add the following to your .bashrc to tab-complete ninja targets +# . path/to/ninja/misc/bash-completion + +_ninja_target() { + local cur targets dir line targets_command OPTIND + cur="${COMP_WORDS[COMP_CWORD]}" + + if [[ "$cur" == "--"* ]]; then + # there is currently only one argument that takes -- + COMPREPLY=($(compgen -P '--' -W 'version' -- "${cur:2}")) + else + dir="." + line=$(echo ${COMP_LINE} | cut -d" " -f 2-) + # filter out all non relevant arguments but keep C for dirs + while getopts C:f:j:l:k:nvd:t: opt "${line[@]}"; do + case $opt in + C) dir="$OPTARG" ;; + esac + done; + targets_command="ninja -C ${dir} -t targets all" + targets=$((${targets_command} 2>/dev/null) | awk -F: '{print $1}') + COMPREPLY=($(compgen -W "$targets" -- "$cur")) + fi + return +} +complete -F _ninja_target ninja diff --git a/ninja/misc/inherited-fds.ninja b/ninja/misc/inherited-fds.ninja new file mode 100644 index 00000000000..671155eb0b3 --- /dev/null +++ b/ninja/misc/inherited-fds.ninja @@ -0,0 +1,23 @@ +# This build file prints out a list of open file descriptors in +# Ninja subprocesses, to help verify we don't accidentally leak +# any. + +# Because one fd leak was in the code managing multiple subprocesses, +# this test brings up multiple subprocesses and then dumps the fd +# table of the last one. + +# Use like: ./ninja -f misc/inherited-fds.ninja + +rule sleep + command = sleep 10000 + +rule dump + command = sleep 1; ls -l /proc/self/fd; exit 1 + +build all: phony a b c d e + +build a: sleep +build b: sleep +build c: sleep +build d: sleep +build e: dump diff --git a/ninja/misc/long-slow-build.ninja b/ninja/misc/long-slow-build.ninja new file mode 100644 index 00000000000..46af6bafbe7 --- /dev/null +++ b/ninja/misc/long-slow-build.ninja @@ -0,0 +1,38 @@ +# An input file for running a "slow" build. +# Use like: ninja -f misc/long-slow-build.ninja all + +rule sleep + command = sleep 1 + description = SLEEP $out + +build 0: sleep README +build 1: sleep README +build 2: sleep README +build 3: sleep README +build 4: sleep README +build 5: sleep README +build 6: sleep README +build 7: sleep README +build 8: sleep README +build 9: sleep README +build 10: sleep 0 +build 11: sleep 1 +build 12: sleep 2 +build 13: sleep 3 +build 14: sleep 4 +build 15: sleep 5 +build 16: sleep 6 +build 17: sleep 7 +build 18: sleep 8 +build 19: sleep 9 +build 20: sleep 10 +build 21: sleep 11 +build 22: sleep 12 +build 23: sleep 13 +build 24: sleep 14 +build 25: sleep 15 +build 26: sleep 16 +build 27: sleep 17 +build 28: sleep 18 +build 29: sleep 19 +build all: phony 20 21 22 23 24 25 26 27 28 29 diff --git a/ninja/misc/measure.py b/ninja/misc/measure.py new file mode 100755 index 00000000000..1323fc66d12 --- /dev/null +++ b/ninja/misc/measure.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +# Copyright 2011 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""measure the runtime of a command by repeatedly running it. +""" + +import time +import subprocess +import sys + +devnull = open('/dev/null', 'w') + +def run(cmd, repeat=10): + print 'sampling:', + sys.stdout.flush() + + samples = [] + for _ in range(repeat): + start = time.time() + subprocess.call(cmd, stdout=devnull, stderr=devnull) + end = time.time() + dt = (end - start) * 1000 + print '%dms' % int(dt), + sys.stdout.flush() + samples.append(dt) + print + + # We're interested in the 'pure' runtime of the code, which is + # conceptually the smallest time we'd see if we ran it enough times + # such that it got the perfect time slices / disk cache hits. + best = min(samples) + # Also print how varied the outputs were in an attempt to make it + # more obvious if something has gone terribly wrong. + err = sum(s - best for s in samples) / float(len(samples)) + print 'estimate: %dms (mean err %.1fms)' % (best, err) + +if __name__ == '__main__': + if len(sys.argv) < 2: + print 'usage: measure.py command args...' + sys.exit(1) + run(cmd=sys.argv[1:]) diff --git a/ninja/misc/ninja-mode.el b/ninja/misc/ninja-mode.el new file mode 100644 index 00000000000..d939206de1f --- /dev/null +++ b/ninja/misc/ninja-mode.el @@ -0,0 +1,42 @@ +;; Copyright 2011 Google Inc. All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +;; Simple emacs mode for editing .ninja files. +;; Just some syntax highlighting for now. + +(setq ninja-keywords + (list + '("^#.*" . font-lock-comment-face) + (cons (concat "^" (regexp-opt '("rule" "build" "subninja" "include" + "pool" "default") + 'words)) + font-lock-keyword-face) + '("\\([[:alnum:]_]+\\) =" . (1 font-lock-variable-name-face)) + ;; Variable expansion. + '("\\($[[:alnum:]_]+\\)" . (1 font-lock-variable-name-face)) + ;; Rule names + '("rule \\([[:alnum:]_]+\\)" . (1 font-lock-function-name-face)) + )) +(define-derived-mode ninja-mode fundamental-mode "ninja" + (setq comment-start "#") + ; Pass extra "t" to turn off syntax-based fontification -- we don't want + ; quoted strings highlighted. + (setq font-lock-defaults '(ninja-keywords t)) + ) + +(provide 'ninja-mode) + +;; Run ninja-mode for files ending in .ninja. +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.ninja$" . ninja-mode)) diff --git a/ninja/misc/ninja.vim b/ninja/misc/ninja.vim new file mode 100644 index 00000000000..d8132678108 --- /dev/null +++ b/ninja/misc/ninja.vim @@ -0,0 +1,81 @@ +" ninja build file syntax. +" Language: ninja build file as described at +" http://martine.github.com/ninja/manual.html +" Version: 1.3 +" Last Change: 2013/04/16 +" Maintainer: Nicolas Weber <nicolasweber@gmx.de> +" Version 1.3 of this script is in the upstream vim repository and will be +" included in the next vim release. If you change this, please send your change +" upstream. + +" ninja lexer and parser are at +" https://github.com/martine/ninja/blob/master/src/lexer.in.cc +" https://github.com/martine/ninja/blob/master/src/manifest_parser.cc + +if exists("b:current_syntax") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +syn case match + +syn match ninjaComment /#.*/ contains=@Spell + +" Toplevel statements are the ones listed here and +" toplevel variable assignments (ident '=' value). +" lexer.in.cc, ReadToken() and manifest_parser.cc, Parse() +syn match ninjaKeyword "^build\>" +syn match ninjaKeyword "^rule\>" +syn match ninjaKeyword "^pool\>" +syn match ninjaKeyword "^default\>" +syn match ninjaKeyword "^include\>" +syn match ninjaKeyword "^subninja\>" + +" Both 'build' and 'rule' begin a variable scope that ends +" on the first line without indent. 'rule' allows only a +" limited set of magic variables, 'build' allows general +" let assignments. +" manifest_parser.cc, ParseRule() +syn region ninjaRule start="^rule" end="^\ze\S" contains=ALL transparent +syn keyword ninjaRuleCommand contained command deps depfile description generator + \ pool restat rspfile rspfile_content + +syn region ninjaPool start="^pool" end="^\ze\S" contains=ALL transparent +syn keyword ninjaPoolCommand contained depth + +" Strings are parsed as follows: +" lexer.in.cc, ReadEvalString() +" simple_varname = [a-zA-Z0-9_-]+; +" varname = [a-zA-Z0-9_.-]+; +" $$ -> $ +" $\n -> line continuation +" '$ ' -> escaped space +" $simple_varname -> variable +" ${varname} -> variable + +syn match ninjaWrapLineOperator "\$$" +syn match ninjaSimpleVar "\$[a-zA-Z0-9_-]\+" +syn match ninjaVar "\${[a-zA-Z0-9_.-]\+}" + +" operators are: +" variable assignment = +" rule definition : +" implicit dependency | +" order-only dependency || +syn match ninjaOperator "\(=\|:\||\|||\)\ze\s" + +hi def link ninjaComment Comment +hi def link ninjaKeyword Keyword +hi def link ninjaRuleCommand Statement +hi def link ninjaPoolCommand Statement +hi def link ninjaWrapLineOperator ninjaOperator +hi def link ninjaOperator Operator +hi def link ninjaSimpleVar ninjaVar +hi def link ninjaVar Identifier + +let b:current_syntax = "ninja" + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/ninja/misc/ninja_syntax.py b/ninja/misc/ninja_syntax.py new file mode 100644 index 00000000000..d69e3e49e2d --- /dev/null +++ b/ninja/misc/ninja_syntax.py @@ -0,0 +1,158 @@ +#!/usr/bin/python + +"""Python module for generating .ninja files. + +Note that this is emphatically not a required piece of Ninja; it's +just a helpful utility for build-file-generation systems that already +use Python. +""" + +import textwrap +import re + +def escape_path(word): + return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:') + +class Writer(object): + def __init__(self, output, width=78): + self.output = output + self.width = width + + def newline(self): + self.output.write('\n') + + def comment(self, text): + for line in textwrap.wrap(text, self.width - 2): + self.output.write('# ' + line + '\n') + + def variable(self, key, value, indent=0): + if value is None: + return + if isinstance(value, list): + value = ' '.join(filter(None, value)) # Filter out empty strings. + self._line('%s = %s' % (key, value), indent) + + def pool(self, name, depth): + self._line('pool %s' % name) + self.variable('depth', depth, indent=1) + + def rule(self, name, command, description=None, depfile=None, + generator=False, pool=None, restat=False, rspfile=None, + rspfile_content=None, deps=None): + self._line('rule %s' % name) + self.variable('command', command, indent=1) + if description: + self.variable('description', description, indent=1) + if depfile: + self.variable('depfile', depfile, indent=1) + if generator: + self.variable('generator', '1', indent=1) + if pool: + self.variable('pool', pool, indent=1) + if restat: + self.variable('restat', '1', indent=1) + if rspfile: + self.variable('rspfile', rspfile, indent=1) + if rspfile_content: + self.variable('rspfile_content', rspfile_content, indent=1) + if deps: + self.variable('deps', deps, indent=1) + + def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, + variables=None): + outputs = self._as_list(outputs) + all_inputs = self._as_list(inputs)[:] + out_outputs = list(map(escape_path, outputs)) + all_inputs = list(map(escape_path, all_inputs)) + + if implicit: + implicit = map(escape_path, self._as_list(implicit)) + all_inputs.append('|') + all_inputs.extend(implicit) + if order_only: + order_only = map(escape_path, self._as_list(order_only)) + all_inputs.append('||') + all_inputs.extend(order_only) + + self._line('build %s: %s' % (' '.join(out_outputs), + ' '.join([rule] + all_inputs))) + + if variables: + if isinstance(variables, dict): + iterator = iter(variables.items()) + else: + iterator = iter(variables) + + for key, val in iterator: + self.variable(key, val, indent=1) + + return outputs + + def include(self, path): + self._line('include %s' % path) + + def subninja(self, path): + self._line('subninja %s' % path) + + def default(self, paths): + self._line('default %s' % ' '.join(self._as_list(paths))) + + def _count_dollars_before_index(self, s, i): + """Returns the number of '$' characters right in front of s[i].""" + dollar_count = 0 + dollar_index = i - 1 + while dollar_index > 0 and s[dollar_index] == '$': + dollar_count += 1 + dollar_index -= 1 + return dollar_count + + def _line(self, text, indent=0): + """Write 'text' word-wrapped at self.width characters.""" + leading_space = ' ' * indent + while len(leading_space) + len(text) > self.width: + # The text is too wide; wrap if possible. + + # Find the rightmost space that would obey our width constraint and + # that's not an escaped space. + available_space = self.width - len(leading_space) - len(' $') + space = available_space + while True: + space = text.rfind(' ', 0, space) + if space < 0 or \ + self._count_dollars_before_index(text, space) % 2 == 0: + break + + if space < 0: + # No such space; just use the first unescaped space we can find. + space = available_space - 1 + while True: + space = text.find(' ', space + 1) + if space < 0 or \ + self._count_dollars_before_index(text, space) % 2 == 0: + break + if space < 0: + # Give up on breaking. + break + + self.output.write(leading_space + text[0:space] + ' $\n') + text = text[space+1:] + + # Subsequent lines are continuations, so indent them. + leading_space = ' ' * (indent+2) + + self.output.write(leading_space + text + '\n') + + def _as_list(self, input): + if input is None: + return [] + if isinstance(input, list): + return input + return [input] + + +def escape(string): + """Escape a string such that it can be embedded into a Ninja file without + further interpretation.""" + assert '\n' not in string, 'Ninja syntax does not allow newlines' + # We only have one special metacharacter: '$'. + return string.replace('$', '$$') diff --git a/ninja/misc/ninja_syntax_test.py b/ninja/misc/ninja_syntax_test.py new file mode 100755 index 00000000000..2aef7ff8307 --- /dev/null +++ b/ninja/misc/ninja_syntax_test.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python + +# Copyright 2011 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + +import ninja_syntax + +LONGWORD = 'a' * 10 +LONGWORDWITHSPACES = 'a'*5 + '$ ' + 'a'*5 +INDENT = ' ' + +class TestLineWordWrap(unittest.TestCase): + def setUp(self): + self.out = StringIO() + self.n = ninja_syntax.Writer(self.out, width=8) + + def test_single_long_word(self): + # We shouldn't wrap a single long word. + self.n._line(LONGWORD) + self.assertEqual(LONGWORD + '\n', self.out.getvalue()) + + def test_few_long_words(self): + # We should wrap a line where the second word is overlong. + self.n._line(' '.join(['x', LONGWORD, 'y'])) + self.assertEqual(' $\n'.join(['x', + INDENT + LONGWORD, + INDENT + 'y']) + '\n', + self.out.getvalue()) + + def test_short_words_indented(self): + # Test that indent is taking into acount when breaking subsequent lines. + # The second line should not be ' to tree', as that's longer than the + # test layout width of 8. + self.n._line('line_one to tree') + self.assertEqual('''\ +line_one $ + to $ + tree +''', + self.out.getvalue()) + + def test_few_long_words_indented(self): + # Check wrapping in the presence of indenting. + self.n._line(' '.join(['x', LONGWORD, 'y']), indent=1) + self.assertEqual(' $\n'.join([' ' + 'x', + ' ' + INDENT + LONGWORD, + ' ' + INDENT + 'y']) + '\n', + self.out.getvalue()) + + def test_escaped_spaces(self): + self.n._line(' '.join(['x', LONGWORDWITHSPACES, 'y'])) + self.assertEqual(' $\n'.join(['x', + INDENT + LONGWORDWITHSPACES, + INDENT + 'y']) + '\n', + self.out.getvalue()) + + def test_fit_many_words(self): + self.n = ninja_syntax.Writer(self.out, width=78) + self.n._line('command = cd ../../chrome; python ../tools/grit/grit/format/repack.py ../out/Debug/obj/chrome/chrome_dll.gen/repack/theme_resources_large.pak ../out/Debug/gen/chrome/theme_resources_large.pak', 1) + self.assertEqual('''\ + command = cd ../../chrome; python ../tools/grit/grit/format/repack.py $ + ../out/Debug/obj/chrome/chrome_dll.gen/repack/theme_resources_large.pak $ + ../out/Debug/gen/chrome/theme_resources_large.pak +''', + self.out.getvalue()) + + def test_leading_space(self): + self.n = ninja_syntax.Writer(self.out, width=14) # force wrapping + self.n.variable('foo', ['', '-bar', '-somethinglong'], 0) + self.assertEqual('''\ +foo = -bar $ + -somethinglong +''', + self.out.getvalue()) + + def test_embedded_dollar_dollar(self): + self.n = ninja_syntax.Writer(self.out, width=15) # force wrapping + self.n.variable('foo', ['a$$b', '-somethinglong'], 0) + self.assertEqual('''\ +foo = a$$b $ + -somethinglong +''', + self.out.getvalue()) + + def test_two_embedded_dollar_dollars(self): + self.n = ninja_syntax.Writer(self.out, width=17) # force wrapping + self.n.variable('foo', ['a$$b', '-somethinglong'], 0) + self.assertEqual('''\ +foo = a$$b $ + -somethinglong +''', + self.out.getvalue()) + + def test_leading_dollar_dollar(self): + self.n = ninja_syntax.Writer(self.out, width=14) # force wrapping + self.n.variable('foo', ['$$b', '-somethinglong'], 0) + self.assertEqual('''\ +foo = $$b $ + -somethinglong +''', + self.out.getvalue()) + + def test_trailing_dollar_dollar(self): + self.n = ninja_syntax.Writer(self.out, width=14) # force wrapping + self.n.variable('foo', ['a$$', '-somethinglong'], 0) + self.assertEqual('''\ +foo = a$$ $ + -somethinglong +''', + self.out.getvalue()) + +class TestBuild(unittest.TestCase): + def setUp(self): + self.out = StringIO() + self.n = ninja_syntax.Writer(self.out) + + def test_variables_dict(self): + self.n.build('out', 'cc', 'in', variables={'name': 'value'}) + self.assertEqual('''\ +build out: cc in + name = value +''', + self.out.getvalue()) + + def test_variables_list(self): + self.n.build('out', 'cc', 'in', variables=[('name', 'value')]) + self.assertEqual('''\ +build out: cc in + name = value +''', + self.out.getvalue()) + +if __name__ == '__main__': + unittest.main() diff --git a/ninja/misc/packaging/ninja.spec b/ninja/misc/packaging/ninja.spec new file mode 100644 index 00000000000..f0c46feab5a --- /dev/null +++ b/ninja/misc/packaging/ninja.spec @@ -0,0 +1,42 @@ +Summary: Ninja is a small build system with a focus on speed. +Name: ninja +Version: %{ver} +Release: %{rel}%{?dist} +Group: Development/Tools +License: Apache 2.0 +URL: https://github.com/martine/ninja +Source0: %{name}-%{version}-%{rel}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{rel} + +BuildRequires: asciidoc + +%description +Ninja is yet another build system. It takes as input the interdependencies of files (typically source code and output executables) and +orchestrates building them, quickly. + +Ninja joins a sea of other build systems. Its distinguishing goal is to be fast. It is born from my work on the Chromium browser project, +which has over 30,000 source files and whose other build systems (including one built from custom non-recursive Makefiles) can take ten +seconds to start building after changing one file. Ninja is under a second. + +%prep +%setup -q -n %{name}-%{version}-%{rel} + +%build +echo Building.. +./bootstrap.py +./ninja manual + +%install +mkdir -p %{buildroot}%{_bindir} %{buildroot}%{_docdir} +cp -p ninja %{buildroot}%{_bindir}/ + +%files +%defattr(-, root, root) +%doc COPYING README doc/manual.html +%{_bindir}/* + +%clean +rm -rf %{buildroot} + +#The changelog is built automatically from Git history +%changelog diff --git a/ninja/misc/packaging/rpmbuild.sh b/ninja/misc/packaging/rpmbuild.sh new file mode 100755 index 00000000000..9b74c6588c9 --- /dev/null +++ b/ninja/misc/packaging/rpmbuild.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +echo Building ninja RPMs.. +GITROOT=$(git rev-parse --show-toplevel) +cd $GITROOT + +VER=1.0 +REL=$(git rev-parse --short HEAD)git +RPMTOPDIR=$GITROOT/rpm-build +echo "Ver: $VER, Release: $REL" + +# Create tarball +mkdir -p $RPMTOPDIR/{SOURCES,SPECS} +git archive --format=tar --prefix=ninja-${VER}-${REL}/ HEAD | gzip -c > $RPMTOPDIR/SOURCES/ninja-${VER}-${REL}.tar.gz + +# Convert git log to RPM's ChangeLog format (shown with rpm -qp --changelog <rpm file>) +sed -e "s/%{ver}/$VER/" -e "s/%{rel}/$REL/" misc/packaging/ninja.spec > $RPMTOPDIR/SPECS/ninja.spec +git log --format="* %cd %aN%n- (%h) %s%d%n" --date=local | sed -r 's/[0-9]+:[0-9]+:[0-9]+ //' >> $RPMTOPDIR/SPECS/ninja.spec + +# Build SRC and binary RPMs +rpmbuild --quiet \ + --define "_topdir $RPMTOPDIR" \ + --define "_rpmdir $PWD" \ + --define "_srcrpmdir $PWD" \ + --define '_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm' \ + -ba $RPMTOPDIR/SPECS/ninja.spec && + +rm -rf $RPMTOPDIR && +echo Done diff --git a/ninja/misc/zsh-completion b/ninja/misc/zsh-completion new file mode 100644 index 00000000000..cd0edfbd97a --- /dev/null +++ b/ninja/misc/zsh-completion @@ -0,0 +1,21 @@ +# Copyright 2011 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Add the following to your .zshrc to tab-complete ninja targets +# . path/to/ninja/misc/zsh-completion + +_ninja() { + reply=(`(ninja -t targets all 2&>/dev/null) | awk -F: '{print $1}'`) +} +compctl -K _ninja ninja |