Initial commit of english_knight. - english_knight - A ninja replacement. | |
git clone git://bitreich.org/english_knight git://enlrupgkhuxnvlhsf6lc3fziv5h2h… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit 6a9c9e7385c6976e2297bcc743abde34a0eceb99 | |
Author: Christoph Lohmann <[email protected]> | |
Date: Sun, 10 Apr 2022 19:27:37 +0200 | |
Initial commit of english_knight. | |
A ninja replacement. | |
Diffstat: | |
A LICENSE | 2 ++ | |
A README.md | 33 +++++++++++++++++++++++++++++… | |
A english_knight | 231 +++++++++++++++++++++++++++++… | |
3 files changed, 266 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/LICENSE b/LICENSE | |
@@ -0,0 +1,2 @@ | |
+This content is in public domain. | |
+ | |
diff --git a/README.md b/README.md | |
@@ -0,0 +1,33 @@ | |
+# English Knight | |
+ | |
+Are you #french? | |
+gopher://bitreich.org/9/memecache/french.mkv | |
+ | |
+Just a question. | |
+ | |
+The topic is about replacing ninjas. Have you ever thought of not being a | |
+ninja, but some english knight? | |
+ | |
+Here is your chance. | |
+ | |
+## Let's start. | |
+ | |
+Just run | |
+ | |
+ ./english_knight | |
+ | |
+and you will see the light. | |
+ | |
+## Got Problems? | |
+ | |
+Be a #black-knight. | |
+gopher://bitreich.org/9/memecache/black-knight.mp4 | |
+ | |
+Fight for the glory of the good old ways! | |
+ | |
+In case you get stuck, use the #holy-hand-grenade and retry. | |
+gopher://bitreich.org/9/memecache/holy-hand-grenade.mkv | |
+ | |
+ | |
+Have fun! | |
+ | |
diff --git a/english_knight b/english_knight | |
@@ -0,0 +1,231 @@ | |
+#!/bin/sh | |
+ | |
+cat <<EOF | |
+#[1]Seninha's notes | |
+ | |
+ A Template for Portable Idiomatic Makefiles | |
+ | |
+[2]seninha.org | |
+2022-04-07 | |
+ | |
+In this post, I present the template I use to write portable, idiomatic | |
+Makefiles for building C programs. | |
+ | |
+I use ${MYVAR}, with curly braces, rather than $(MYVAR), with parentheses, but | |
+both notations are supported. In this document I identify two different people: | |
+the developer or Makefile author, who writes the Makefile; and the user or | |
+package maintainer, who defines the proper variables and run make(1). | |
+ | |
+The Project Files | |
+ | |
+There are several files involved in the building process: the target files to … | |
+built, the source files, and the intermediate files. They may be referenced | |
+several times by different rules, so it is a good practice to name them with | |
+variables. Suppose we're building a program called myprog composed of three | |
+modules. These are the variables to be defined: | |
+PROG = myprog | |
+SRCS = main.c parse.c util.c | |
+OBJS = main.o parse.o util.o | |
+ | |
+The varialbe PROG is the final file; SRCS lists the source files; and OBJS lis… | |
+the intermediate, object files. Note that both the list of source files and of | |
+object files are almost equal, differing only by the extension of the files. | |
+POSIX make(1) has a notation for changing the ending of each word in a variabl… | |
+In order to avoid repeating ourselves, we can use this notation to define | |
+${OBJS}. | |
+PROG = myprog | |
+SRCS = main.c parse.c util.c | |
+OBJS = ${SRCS:.c=.o} | |
+ | |
+We want to build our program when we call make without any arguments. To do | |
+this, the first target should be ${PROG} itself. However, it is a common | |
+practice to use the target all to build the final files. So the first target is | |
+all, which just has ${PROG} as prerequisite. | |
+all: ${PROG} | |
+ | |
+Next we need to declare the dependencies between the program modules. This is | |
+done with rules without commands. | |
+main.o: parse.h util.h | |
+parse.o: parse.h util.h | |
+util.o: util.h | |
+ | |
+The Compilation Rules | |
+ | |
+The compilation process is split in two parts: generate the object files from | |
+the source files, and generate the program from the object files. So we need t… | |
+rules. | |
+ | |
+The following rule builds object files (.o) from source files (.c). The .c.o is | |
+a inference rule that declare each .c file to be the prerequisite of a | |
+homonymous .o file. This notation is defined by POSIX and is, therefore, | |
+portable (different from the %.o: %.c rule, which is a GNU extension). In the | |
+command of an inference rule (and only in the command of an inference rule), t… | |
+$< variable evaluates to the prerequisite file. | |
+.c.o: | |
+ ${CC} -I/usr/X11R6/include ${CFLAGS} ${CPPFLAGS} -c $< | |
+ | |
+We use the variable ${CC} to expand to the proper C compiler command. This | |
+variable is set by default to the proper command. We should use this variable | |
+rather than hardcoding it to gcc, for example. | |
+ | |
+The variables ${CFLAGS} and ${CPPFLAGS} contains options that the user or | |
+package maintainer wants to pass to the compiler or preprocessor. It is a bad | |
+practice to define those variables in a Makefile; let the user (or package | |
+maintainer) define them. Any option that must be passed to the compiler (such … | |
+-I/usr/X11R6/include above) should be passed before those variables. If the | |
+Makefile author, for example, define ${CFLAGS} to -I/usr/X11R6/include, either | |
+this value may override the values set by the user, or the values set by the | |
+user may shadow the option set by the Makefile author. | |
+ | |
+The following rule links all object files into the program. We define ${OBJS} … | |
+be the prerequisites of ${PROG}. The $@ variable evaluates to the target file | |
+(${PROG} in our case). Since this is not an inference rule, the $< variable | |
+cannot be used; we must write ${OBJS} both in the rule and in the command. | |
+${PROG}: ${OBJS} | |
+ ${CC} -o $@ ${OBJS} -L/usr/X11R6/lib -lX11 ${LDFLAGS} | |
+ | |
+The variable ${LDFLAGS} contains options that the user or package maintainer | |
+wants to pass to the linker. Again, it is a bad practice to define it in the | |
+Makefile. The options -L/usr/X11R6/lib and -lX11 are passed before this variab… | |
+(so the user can override or increment them if necessary). | |
+ | |
+The Installation rules | |
+ | |
+Your Makefile may include rules for installing the final files in the system. … | |
+this example, two files are installed, ${PROG} (the final, compiled program), | |
+and ${PROG}.1 (the manpage, named as the program followed by .1). The following | |
+rule performs the installation. | |
+PREFIX = /usr/local | |
+MANPREFIX = ${PREFIX}/share/man | |
+ | |
+install: all | |
+ mkdir -p ${DESTDIR}${PREFIX}/bin | |
+ mkdir -p ${DESTDIR}${MANPREFIX}/man1 | |
+ install -m 755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG} | |
+ install -m 644 ${PROG}.1 ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
+ | |
+Before installing, the program should have been built; therefore all must be a | |
+prerequisite for install. | |
+ | |
+The user or package maintainer can set the variable ${DESTDIR} to specify a | |
+different installation destination. This variable must be prepended to each | |
+installation path; and the Makefile author should not define it (it is left to | |
+the user or package maintainer to define it). Note that there is no bar | |
+separating ${DESTDIR} from what follows, because the ${PREFIX} and ${MANPREFIX} | |
+variables should already begin with a bar. | |
+ | |
+The Makefile author, however, is expected to define two variables pointing to | |
+installation prefixes: ${PREFIX}, pointing to the general installation prefix; | |
+and ${MANPREFIX}, pointing to the manual page installation prefix. There are | |
+other commonly defined prefixes, such as ${bindir}, set to ${PREFIX}/bin. The | |
+user or package maintainer can then invoke make(1) with those variables assign… | |
+to different prefixes. On most GNU/Linux systems, for example, ${PREFIX} is | |
+assigned to /usr; and on OpenBSD, ${MANPREFIX} is assigned to ${PREFIX}/man | |
+(without the share/ part). | |
+ | |
+The variables ${PREFIX} and ${MANPREFIX} are not automatically assigned, but | |
+they can be changed by the user or package maintainer. These variables are | |
+commonly assigned in the Makefile by the Makefile author with the ?= operator, | |
+which assign them only if not already defined, rather than with the common = | |
+operator. Thus, the values of these variables can be inherited from the | |
+environment, and the user need not have to assign them on each invocation. This | |
+operator is a non-POSIX extension, however, although supported by both GNU and | |
+BSD make implementations. | |
+ | |
+Looking back at the installation commands, we first use mkdir(1) to create the | |
+destination directories, and then use install(1) to install them. We could | |
+simply call install with the -D flag, which automatically creates the | |
+destination directories if necessary. However, this option is an extension and | |
+is not supported by some implementations (such as FreeBSD's). Remember to | |
+install each file with its proper permission modes with the -m option. | |
+ | |
+The Makefile author can also create a uninstallation rule, which simply remove | |
+the files from their destination directories. | |
+uninstall: | |
+ rm ${DESTDIR}${PREFIX}/bin/${PROG} | |
+ rm ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
+ | |
+The Cleaning Rule | |
+ | |
+The Makefile author can define a rule to clean the build directory and revert … | |
+to its original state. Such rule is commonly called clean. It removes the | |
+intermediate object files and the final files. As convenience, for the develop… | |
+to clean the build directory from core files that may be created by the system | |
+during the development, the clean rule can also delete .core files. | |
+clean: | |
+ -rm -f ${OBJS} ${PROG} ${PROG:=.core} | |
+ | |
+Note that the command of this rule begins with an hyphen -. This causes make to | |
+not return error (non-zero) exit status when the command fails. This is handy, | |
+for cleaning an already cleaned build directory to not print errors. | |
+ | |
+The Phony Targets | |
+ | |
+In a Makefile, some rules specify “virtual” targets which do not correspon… | |
+any file to be created. These are the “phony” targets. The .PHONY special … | |
+is used to mark its prerequisites as phony targets. In our Makefile, we have | |
+four phony targets: all, install, uninstall, and clean. | |
+.PHONY: all clean install uninstall | |
+ | |
+The Makefile | |
+ | |
+In the end, our Makefile should look like this: | |
+PROG = myprog | |
+SRCS = main.c util.c | |
+OBJS = ${SRCS:.c=.o} | |
+ | |
+PREFIX = /usr/local | |
+MANPREFIX = ${PREFIX}/share/man | |
+ | |
+all: ${PROG} | |
+ | |
+main.o: parse.h util.h | |
+parse.o: parse.h util.h | |
+util.o: util.h | |
+ | |
+.c.o: | |
+ ${CC} -I/usr/X11R6/include ${CFLAGS} ${CPPFLAGS} -c $< | |
+ | |
+${PROG}: ${OBJS} | |
+ ${CC} -o $@ ${OBJS} -L/usr/X11R6/lib -lX11 ${LDFLAGS} | |
+ | |
+install: all | |
+ mkdir -p ${DESTDIR}${PREFIX}/bin | |
+ mkdir -p ${DESTDIR}${MANPREFIX}/man1 | |
+ install -m 755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG} | |
+ install -m 644 ${PROG}.1 ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
+ | |
+uninstall: | |
+ rm ${DESTDIR}${PREFIX}/bin/${PROG} | |
+ rm ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
+ | |
+clean: | |
+ -rm -f ${OBJS} ${PROG} ${PROG:=.core} | |
+ | |
+.PHONY: all clean install uninstall | |
+ | |
+tl;dr | |
+ | |
+ * Define variables for the final files to be built, the source files, and the | |
+intermediate object files created by the building process. Those are commonly | |
+named ${PROG}, ${SRCS} and ${OBJS}, respectively. | |
+ * Include in the Makefile, but do not assign them, the variables ${CFLAGS}, | |
+${CPPFLAGS}, ${LDFLAGS} and ${DESTDIR}. They should be assigned by the user or | |
+package maintainer. | |
+ * Evaluate the flag variables (${CFLAGS}, ${CPPFLAGS}, and ${LDFLAGS}) after | |
+any hardcoded flag, so the user or package maintainer can override it. | |
+ * Include the all and clean phony targets. Optionally include install and | |
+uninstall phony targets. Always mark them as .PHONY. | |
+ * Do not use $< on anything but on the command of inference rules. | |
+ * Do not use -D with install(1). | |
+ * Do not call c99 or gcc manually. Call the command set in ${CC} instead. | |
+ * Assign ${PREFIX} and ${MANPREFIX} to the proper installation prefixes. You | |
+can assign them with the ?= operator for the user convenience, but this | |
+assignment operatior is not portable, although commonly supported. | |
+ | |
+References | |
+ | |
+ 1. file:///feed.xml | |
+ 2. https://seninha.org/ | |
+EOF | |
+ |