Add build utility commands

* `build` is an alias which on first use invokes `build-dir --build` to
  select a build directory, reconfigure the `build` alias, and invoke
  the `build` alias on the selected build directory.
* `debug` is an alias to the installed system native debugger.
* `build-dir` is a function to select a build directory by reconfiguring
  the `build` alias, it detects `build.ninja` or `Makefile` in the build
  directory and selects the appropriate `ninja` or `make` command.
  Depends on the `build-dir.py` Python script which uses the `pick`
  package to interactively select the build directory.
* `build-run` is a function which builds the specified target then
  attempts to run it, making the assumption it resides in the `bin`
  subdirectory of the build directory.
* `build-debug` is a function which build the specified tared then
  attempts to debug it using the system native debugger, making the
  assumption it resides in the `bin` subdirectory of the build
  directory.
This commit is contained in:
Kenneth Benzie 2018-04-29 22:55:35 +01:00
parent e9993b0874
commit b12dcfe243
4 changed files with 121 additions and 0 deletions

View File

@ -20,4 +20,6 @@
- https://github.com/zsh-users/zsh-autosuggestions.git
- https://github.com/zsh-users/zsh-history-substring-search.git
- https://github.com/zsh-users/zsh-syntax-highlighting.git
- pip:
- --user pick
- message: zsh will be the default prompt after next login

46
build/build-dir.py Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env python
"""The pick_build_dir command selects a build directory
The pick_build_dir command scans the current directory for directories starting
with ``build`` and prompts the user to select one from the list.
"""
from __future__ import print_function
from argparse import ArgumentParser
from os import listdir
from os.path import curdir, isdir
from sys import stderr
from pick import Picker
def main():
"""Main entry point to build-dir.py script."""
parser = ArgumentParser()
parser.add_argument('output')
parser.add_argument('--default', action='store_true')
args = parser.parse_args()
directories = []
for directory in listdir(curdir):
if isdir(directory) and directory.startswith('build'):
directories.append(directory)
if len(directories) == 0:
print('no build directories found', file=stderr)
exit(1)
build_dirs = sorted(directories)
if args.default:
build_dir = build_dirs[0]
else:
picker = Picker(build_dirs, 'Select a build directory:')
picker.register_custom_handler(ord(''), lambda _: exit(1))
build_dir, _ = picker.start()
with open(args.output, 'w') as output:
output.write(build_dir)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
exit(130)

72
build/build.plugin.zsh Normal file
View File

@ -0,0 +1,72 @@
# A collection of commands to make it easier to build projects.
# Default `build` alias to select a `build-dir` then invoke a build, using an
# alias means the configured build command's completion works out of the box.
alias build="build-dir --build"
# Detect installed debugger and set the `debug` alias to debug a program with
# command line arguments.
if [ `uname` = Linux ]; then
if which cgdb &> /dev/null; then
alias debug='cgdb --args'
elif which gdb &> /dev/null; then
alias debug='gdb --args'
fi
elif [ `uname` = Darwin ]; then
which lldb &> /dev/null && \
alias debug='lldb --'
fi
# Store the path to `build-dir.py`, using `${0:a:h}` does not work in a
# function because it will result in `pwd` not this scripts directory.
_build_dir_py=${0:a:h}/build-dir.py
# Interactively choose a `~build` directory for `build` to build.
# TODO: Support arguments:
# * [x] [-h,--help] - show this help message and exit
# * [x] [--build] - execute the build commend
# * [ ] <dir> - start in another directory, not `pwd`
build-dir() {
# Get a unique filename to store the chosen build directory in.
[ `uname` = Darwin ] && local file=`mktemp` || local file=`tempfile`
# Prompt user to choose a build directory.
python $_build_dir_py $file;
local error=$?
# If the file exists, read the build directory from it, then delete it.
[ -f $file ] && build_dir=$PWD/`cat $file`; rm $file
# If choosing a build directory failed, return that error.
[[ "$error" = "0" ]] || return $error
# If `build.ninja` exists in alias `ninja`, return.
[ -f $build_dir/build.ninja ] && \
local build="ninja -C $build_dir"
# If `Makefile` exists in alias `make`, return.
if [ -f $build_dir/Makefile ]; then
[ `uname` = Darwin ] && \
local cpu_count=`sysctl -n hw.ncpu` ||
local cpu_count=`grep -c '^processor' /proc/cpuinfo`
local build="make -j $cpu_count -C $build_dir"
fi
# If the build variable is not defined the command could not be determined.
if [ -z $build ]; then
# TODO: Prompt user to choose a build command?
echo "could not determine build command"
return 1
fi
# Redefine the `build` alias and update the `~build` hash directory.
alias build="$build"
hash -d build=$build_dir
# If `--build` is specified then evaluate the command.
[[ "$1" = "--build" ]] && eval $build || true
}
# Build then run a target residing in `$build_dir/bin`.
build-run() {
local target=$1; shift 1
build $target && $build_dir/bin/$target $*
}
# Build then debug a target residing in `$build_dir/bin`.
build-debug() {
local target=$1; shift 1
build $target && debug $build_dir/bin/$target $*
}

1
zshrc
View File

@ -13,6 +13,7 @@ source-plugin zsh-autosuggestions
source-plugin zsh-history-substring-search
source-plugin zsh-syntax-highlighting
source-plugin autoenv
source-plugin build
# Disable non end-of-line autosuggest accept widgets
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(end-of-line vi-end-of-line)