diff options
author | Case Duckworth | 2024-04-13 23:23:21 -0500 |
---|---|---|
committer | Case Duckworth | 2024-04-13 23:23:21 -0500 |
commit | 6d81387ea11293f04128ea0279e5bc54dafe0860 (patch) | |
tree | 26543a5b1ebc7b0b24f6859c6c69b71e639fc575 /README | |
parent | Removed first version (diff) | |
download | ok-6d81387ea11293f04128ea0279e5bc54dafe0860.tar.gz ok-6d81387ea11293f04128ea0279e5bc54dafe0860.zip |
Add COPYING and README
Diffstat (limited to 'README')
-rw-r--r-- | README | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/README b/README new file mode 100644 index 0000000..93f1b6b --- /dev/null +++ b/README | |||
@@ -0,0 +1,142 @@ | |||
1 | ok : a minimal build system in posix sh | ||
2 | |||
3 | ok is a minimal build system that's kinda like make in that you plop a file | ||
4 | describing your build in your project's folder, then run a system command that | ||
5 | reads the file and builds the project. it's written in posix sh and is designed | ||
6 | to be strictly more expressive than posix make, which is awful. | ||
7 | |||
8 | [[ INSTALLING ]] | ||
9 | |||
10 | ok is just a shell script, so you can mv or cp it to your $PATH. It requires a | ||
11 | somewhat-modern posix-compliant shell (i am not going to figure out what | ||
12 | "somewhat-modern" means), as well as the following utilities: | ||
13 | |||
14 | - sed | ||
15 | - grep | ||
16 | - cut | ||
17 | |||
18 | if you don't have these, congratulations! You are really doing something | ||
19 | interesting with your system. | ||
20 | |||
21 | [[ USING OK ]] | ||
22 | |||
23 | If the project you're hacking on has an okfile (by default, ./ok), you can just | ||
24 | run ok and it'll do whatever the author made the default target. You can also | ||
25 | run ok with the following flags: | ||
26 | |||
27 | - -h shows a help message, then exits | ||
28 | - -q runs ok in "quiet" mode; that is, no messages are printed | ||
29 | - -x runs ok with "set -x" turned on; this is a shell feature | ||
30 | that might help you debug some weirdness | ||
31 | - -n runs ok in "dry-run" mode; that is, no recipes are run | ||
32 | - -B run all targets as if they were "new," like make -B | ||
33 | - -f FILE use FILE as the okfile instead of ./ok | ||
34 | - -C DIR change to DIR before doing anything, like make -C | ||
35 | |||
36 | ok -h will also print the targets it's found in the okfile, along with | ||
37 | explanatory comments provided on the target's first lines. See the example | ||
38 | provided below for an idea. | ||
39 | |||
40 | [[ WRITING OKFILES ]] | ||
41 | |||
42 | of course, the real part of using ok is writing the okfile. This section | ||
43 | describes the format of that file, which is a shell script sourced by ok, to | ||
44 | help you write good okfiles for your own projects. | ||
45 | |||
46 | an okfile is simply a shell script where every function defined is a target. | ||
47 | The first function in the script is the default target that runs if no target is | ||
48 | specified. ok has a few utility functions to make writing targets easier: | ||
49 | |||
50 | - ok : print, then run the command given after it on the command line. if -q | ||
51 | has been passed, suppress printing; if -n has been passed, suppress | ||
52 | running. if the command fails, ok will exit with 100 + the command's | ||
53 | exit code. | ||
54 | |||
55 | - dep : define a dependency on the targets specified as arguments. the | ||
56 | dependencies will be run in the order of the command line before | ||
57 | continuing with the current recipe. | ||
58 | |||
59 | - fr : define a series of file rules. See the next section for a description of | ||
60 | these. | ||
61 | |||
62 | - allfiles : print all the files defined in the fr call. | ||
63 | |||
64 | [[ FILE RULES (FR) ]] | ||
65 | |||
66 | while writing shell functions is fine and dandy to simulate make's .PHONY rules, | ||
67 | it does nothing for the main use of make: generating files from other files. | ||
68 | The solution i landed on for ok was the fr function, which is short for file | ||
69 | rules. This section describes the format of fr's input, as well as suggestions | ||
70 | for use. | ||
71 | |||
72 | fr reads lines from standard input, processes them, and outputs them to an | ||
73 | frfile in the current directory (which can be safely deleted, and is in fact | ||
74 | rebuilt on every invocation). I recommend using a heredoc for building the file | ||
75 | rules, since that allows free-form text as well as programmatic rule generation | ||
76 | (something make does not do). | ||
77 | |||
78 | each line fr reads will be parsed as a TARGET, a JOB, and the JOB's DEPS. The | ||
79 | TARGET is the target file to build, JOB is the job to run to build that file, | ||
80 | and DEPS are all the dependencies of TARGET. | ||
81 | |||
82 | DEPS can include both build and order dependencies. Build dependencies are | ||
83 | appended to JOB as arguments, while order dependencies merely force TARGET to be | ||
84 | built if it's newer than them. TODO: THERE IS A BUG IN THIS IMPLEMENTATION. | ||
85 | ORDER DEPENDENCIES ARE CURRENTLY IGNORED. | ||
86 | |||
87 | JOB should be a function defined in the okfile or a one-word command, since fr | ||
88 | doesn't do any special $IFS magic. I recommend creating an ok function that | ||
89 | encapsulates JOB's logic and including that in the fr block. | ||
90 | |||
91 | [[ FR EXAMPLE ]] | ||
92 | |||
93 | since fr is possibly the most complex thing to understand for ok, here is an | ||
94 | example. This okfile is how i build a simple 'hello, world' program in C[1]: | ||
95 | |||
96 | ---------------------------------------------->8 | ||
97 | for c in *.c | ||
98 | do echo "${c%.c}" build "$c" | ||
99 | done | fr | ||
100 | |||
101 | : "${CC:=cc}" | ||
102 | |||
103 | default() { dep allfiles; } | ||
104 | |||
105 | build() { # build an executable from a c source file | ||
106 | ok "$CC" "$1" -o "$TARGET" | ||
107 | } | ||
108 | 8<---------------------------------------------- | ||
109 | |||
110 | as you can see, providing a heredoc to fr's input means i can build up the flies | ||
111 | i want to build dynamically, rather than having to update the okfile every time. | ||
112 | This fr invocation produces the following file[2]: | ||
113 | |||
114 | ---------------------------------------------->8 | ||
115 | hello ok build hello.c | ||
116 | 8<---------------------------------------------- | ||
117 | |||
118 | in this simple example, i could've written this just as well: | ||
119 | |||
120 | ---------------------------------------------->8 | ||
121 | fr<<.. | ||
122 | hello build hello.c | ||
123 | .. | ||
124 | 8<---------------------------------------------- | ||
125 | |||
126 | you can depend on all files that need building using the 'allfiles' target, so | ||
127 | it's a good idea to put a 'dep allfiles' somewhere in your build functions. you | ||
128 | can see it above in the 'default' rule. | ||
129 | |||
130 | [[ COPYING AND CONTRIBUTING ]] | ||
131 | |||
132 | ok is distributed under a standard BSD 3-clause license. Contributions are | ||
133 | welcome; feel free to email me[3] with feedback, questions, or patches. | ||
134 | |||
135 | [[ INSPIRATION ]] | ||
136 | |||
137 | thanks to akkartik, whose basic-build[4] gave me the inspiration for ok. | ||
138 | |||
139 | [1] https://www.helloworldin.com/c.html, e.g. | ||
140 | [2] https://www.acdw.net/.fr | ||
141 | [3] mailto:git@acdw.net | ||
142 | [4] https://git.sr.ht/~akkartik/basic-build \ No newline at end of file | ||