From 6d81387ea11293f04128ea0279e5bc54dafe0860 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Sat, 13 Apr 2024 23:23:21 -0500 Subject: Add COPYING and README --- COPYING | 26 ++++++++++++ README | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 COPYING create mode 100644 README diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d745fba --- /dev/null +++ b/COPYING @@ -0,0 +1,26 @@ +Copyright (C) Case Duckworth + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..93f1b6b --- /dev/null +++ b/README @@ -0,0 +1,142 @@ +ok : a minimal build system in posix sh + +ok is a minimal build system that's kinda like make in that you plop a file +describing your build in your project's folder, then run a system command that +reads the file and builds the project. it's written in posix sh and is designed +to be strictly more expressive than posix make, which is awful. + +[[ INSTALLING ]] + +ok is just a shell script, so you can mv or cp it to your $PATH. It requires a +somewhat-modern posix-compliant shell (i am not going to figure out what +"somewhat-modern" means), as well as the following utilities: + +- sed +- grep +- cut + +if you don't have these, congratulations! You are really doing something +interesting with your system. + +[[ USING OK ]] + +If the project you're hacking on has an okfile (by default, ./ok), you can just +run ok and it'll do whatever the author made the default target. You can also +run ok with the following flags: + +- -h shows a help message, then exits +- -q runs ok in "quiet" mode; that is, no messages are printed +- -x runs ok with "set -x" turned on; this is a shell feature + that might help you debug some weirdness +- -n runs ok in "dry-run" mode; that is, no recipes are run +- -B run all targets as if they were "new," like make -B +- -f FILE use FILE as the okfile instead of ./ok +- -C DIR change to DIR before doing anything, like make -C + +ok -h will also print the targets it's found in the okfile, along with +explanatory comments provided on the target's first lines. See the example +provided below for an idea. + +[[ WRITING OKFILES ]] + +of course, the real part of using ok is writing the okfile. This section +describes the format of that file, which is a shell script sourced by ok, to +help you write good okfiles for your own projects. + +an okfile is simply a shell script where every function defined is a target. +The first function in the script is the default target that runs if no target is +specified. ok has a few utility functions to make writing targets easier: + +- ok : print, then run the command given after it on the command line. if -q + has been passed, suppress printing; if -n has been passed, suppress + running. if the command fails, ok will exit with 100 + the command's + exit code. + +- dep : define a dependency on the targets specified as arguments. the + dependencies will be run in the order of the command line before + continuing with the current recipe. + +- fr : define a series of file rules. See the next section for a description of + these. + +- allfiles : print all the files defined in the fr call. + +[[ FILE RULES (FR) ]] + +while writing shell functions is fine and dandy to simulate make's .PHONY rules, +it does nothing for the main use of make: generating files from other files. +The solution i landed on for ok was the fr function, which is short for file +rules. This section describes the format of fr's input, as well as suggestions +for use. + +fr reads lines from standard input, processes them, and outputs them to an +frfile in the current directory (which can be safely deleted, and is in fact +rebuilt on every invocation). I recommend using a heredoc for building the file +rules, since that allows free-form text as well as programmatic rule generation +(something make does not do). + +each line fr reads will be parsed as a TARGET, a JOB, and the JOB's DEPS. The +TARGET is the target file to build, JOB is the job to run to build that file, +and DEPS are all the dependencies of TARGET. + +DEPS can include both build and order dependencies. Build dependencies are +appended to JOB as arguments, while order dependencies merely force TARGET to be +built if it's newer than them. TODO: THERE IS A BUG IN THIS IMPLEMENTATION. +ORDER DEPENDENCIES ARE CURRENTLY IGNORED. + +JOB should be a function defined in the okfile or a one-word command, since fr +doesn't do any special $IFS magic. I recommend creating an ok function that +encapsulates JOB's logic and including that in the fr block. + +[[ FR EXAMPLE ]] + +since fr is possibly the most complex thing to understand for ok, here is an +example. This okfile is how i build a simple 'hello, world' program in C[1]: + +---------------------------------------------->8 +for c in *.c +do echo "${c%.c}" build "$c" +done | fr + +: "${CC:=cc}" + +default() { dep allfiles; } + +build() { # build an executable from a c source file + ok "$CC" "$1" -o "$TARGET" +} +8<---------------------------------------------- + +as you can see, providing a heredoc to fr's input means i can build up the flies +i want to build dynamically, rather than having to update the okfile every time. +This fr invocation produces the following file[2]: + +---------------------------------------------->8 +hello ok build hello.c +8<---------------------------------------------- + +in this simple example, i could've written this just as well: + +---------------------------------------------->8 +fr<<.. +hello build hello.c +.. +8<---------------------------------------------- + +you can depend on all files that need building using the 'allfiles' target, so +it's a good idea to put a 'dep allfiles' somewhere in your build functions. you +can see it above in the 'default' rule. + +[[ COPYING AND CONTRIBUTING ]] + +ok is distributed under a standard BSD 3-clause license. Contributions are +welcome; feel free to email me[3] with feedback, questions, or patches. + +[[ INSPIRATION ]] + +thanks to akkartik, whose basic-build[4] gave me the inspiration for ok. + +[1] https://www.helloworldin.com/c.html, e.g. +[2] https://www.acdw.net/.fr +[3] mailto:git@acdw.net +[4] https://git.sr.ht/~akkartik/basic-build \ No newline at end of file -- cgit 1.4.1-21-gabe81