Initial commit. - bitreich-style - Style guide for programmers. HTML git clone git://bitreich.org/bitreich-style DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit 040830cabbba670cfbac39d214fe274d7c10b88d HTML Author: Christoph Lohmann <20h@r-36.net> Date: Wed, 10 Jun 2020 14:26:06 +0200 Initial commit. Diffstat: A LICENSE | 16 ++++++++++++++++ A Principles.md | 58 ++++++++++++++++++++++++++++++ A README.md | 23 +++++++++++++++++++++++ A c/makefile-guideline.txt | 272 +++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+), 0 deletions(-) --- DIR diff --git a/LICENSE b/LICENSE @@ -0,0 +1,16 @@ +ISC License + +Copyright (c) 2020 Christoph Lohmann <20h@r-36.net> +Copyright (c) 2020 Hiltjo Posthuma <hiltjo@codemadness.org> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. DIR diff --git a/Principles.md b/Principles.md @@ -0,0 +1,58 @@ +# Principles + +Please first see the Bitreich Manifesto at + + gopher://bitreich.org/0/documents/bitreich-manifesto.md + + +## KISP – Keep It Simple Perfect + +* Make a project do one thing well. +* A project can be done, does not need change just because. + +## Commandline Interfaces + +* Always add a commandline interface so advanced users can script your +application and thus have more fun using it. + +## When Possible Use GPLv3 + +* Use which license you like, but think of the future, when people might +use your software in war or other inhumane things. A life of open source +is not just about the CV and getting a Google job with a small home, bad +sex in marriage and a dog. + +## Users are Programmers + +* First think of the programmers who might want to change your +application, help you, find bugs you have not spotted because you made +the application. Make this as simple as possible to contribute. +* Some ugly website which requires Gigabytes of RAM and big hardware is +not a simple access and will only make your own brain in the long run +fluid. +* Always add a Makefile using common methodologies and commands so +people can easily build your software. Do not make a build framework for +every new project. Make(1) knows most things needed, you may not have +read the documentation properly. + +## Straightforward Documentation + +* When compiling software you realize, that people are using all kind of +bloated tools to generate documentation. Please do not be like that. +Think of all the people having to compile this to get your application. +Use what is more descriptive and easy to use: Man pages, a text or the +source. + +## Applications Can Be Done + +* If your application does what it should do, but suddenly you have a +new big idea, make a new project, do not push the old one. There are old +users who do not think the same as you. + +## Freedom Of Language + +* Use whatever language you like. +* Think of the dependencies. If you use slow to compile languages, you +will waste hours of lifetime of others. Do not be an asshole to those +people. + DIR diff --git a/README.md b/README.md @@ -0,0 +1,23 @@ +# Bitreich Style + +## Description + +This repository's purpose is to document style, simple tutorials on how +to start projects, hints for new developers on how packagers or other +developers think. Overall it is to make open source a nicer place, which +does not get ugly over time or slower due to people just adding what +they found on stackoverflow over eachother because they never learned +the basics. + +## Bugs / Hints + +Send bugs / hints to + + Christoph Lohmann <20h@r-36.net> + +or on #bitreich-en on Freenode. + + + +Have fun! + DIR diff --git a/c/makefile-guideline.txt b/c/makefile-guideline.txt @@ -0,0 +1,272 @@ +Title: Guidelins for writing simple portable Makefiles + + +This page describes some guidelines and good practises for writing simple +portable POSIX Makefiles. It assumes a basic level of understanding in writing +Makefiles already. It will focus on projects that use the C programming +language. + +make is used because it has been around for a long time, it is available on +many systems, it is a POSIX standard and it has proven to work well for most +projects. + + +Targets +------- + +The following targets should be defined in the Makefile: + +* all or the "default": build the project. +* clean: clean files used by compilation, such as: object files, compiled + binaries. +* install: install the build project. +* uninstall (optional): uninstall the project. +* dist (optional): create a source tarball of the project intended as + redistribution for source packages. +* tests (optional): run unit tests. + + +Portability +----------- + +Do not use GNUisms in Makefiles. Testing with different make implementations +like BSD make which mostly respect POSIX is very useful. Use POSIX Makefile +rules: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html + + +Variables +--------- + +It is recommended to respect the following commonly-used variables. + +* $DESTDIR: for the install targets make use of the $DESTDIR variable. This + make it simpler to install the package to an other location and make binary + packages. It is the prefix destination directory to install to (before $PREFIX). + It should be unset by default. + +* $PREFIX: this specifies the prefix location to install to, it should be + "/usr/local" by default since this is most commonly used for ports. + +* $MANPREFIX or $MANDIR: + * Distributions can use different locations for man pages for ports or in general. + * Some distributions package documentation in a separate package (project-doc). + +Specifying compiler and linker flags: + +* $CC, $CFLAGS, $LDFLAGS, $CPPFLAGS: make sure to respect the default set flags + as specified in POSIX: https://pubs.opengroup.org/onlinepubs/9699919799/ + under the section "Default rules". This make it easier for the ports build system + to use the set variables and not having to patch the Makefile in some way. +* $CFLAGS: do not hard-code optimization flags like (-O2) or diagnostic flags such as + -Wall, -Wextra, -pedantic. Of course do not specify unportable compiler flags. +* $LDFLAGS: do not hard-code linker flags like -s (symbol stripping) or -g, -static + or such flags. +* Libraries: using separate variables for compile and link per library (for + example libpng, libjpeg) can be useful for building in ports. + For example a variable LIBPNG_CFLAGS, LIBPNG_LDFLAGS for the header files or + library location. + + +Considerations +-------------- + +* It is not recommended to suppress compilation output with the @ prefix (for + example to make output look nicer aligned). The verbose output is very useful + for debugging and suppressing it only adds debugging abstractions. + +* Try to use a single-file Makefile for atleast small projects. If needed some + configuration could be included from the Makefile: config.mk. Keep in mind + reducing abstractions will increase readability and debugability. Package + maintainers/porters do not want to have to relearn a new system for each + software package. + +* As specified above different systems can use different locations for certain + things like man pages, X11 header files and libraries and ports installation. + + Examples: + * X11: commonly uses /usr/X11R6 on BSD-like platforms. + * Man page directories: on OpenBSD: /usr/local/man. + +Testing on many different systems is useful! For example: Linux, OpenBSD, NetBSD. + + +Examples +-------- + +Below is an example of a project json2tsv Makefile. It is line-numbered and +below are some added remarks why things are done the way they are. + + 1 .POSIX: + +Specify POSIX compatibility: "To receive exactly the behavior described in this +section, the user shall ensure that a portable makefile shall: Include the +special target .POSIX" + + 2 + 3 NAME = json2tsv + 4 VERSION = 0.5 + 5 + +Define a name and version variable of the project which can be reused, for +example for the dist tarball. + + 6 # paths + 7 PREFIX = /usr/local + 8 MANPREFIX = ${PREFIX}/man + 9 DOCPREFIX = ${PREFIX}/share/doc/${NAME} + 10 + +Specify default sane paths. + + 11 RANLIB = ranlib + 12 + +This variable is not specified by default in POSIX. It is commonly "ranlib", +but can be overwritten. + + 13 BIN = ${NAME} + +In this case it's simple: the binary is the program name. + + 14 SRC = ${BIN:=.c} + +C source files, so just json2tsv.c here. + + 15 HDR = json.h + +Header files. + + 16 MAN1 = ${BIN:=.1} + +Man section 1 pages. + + 17 DOC = \ + 18 LICENSE\ + 19 README + 20 + +Other documentation and license files. + + 21 LIBJSON = libjson.a + 22 LIBJSONSRC = json.c + 23 LIBJSONOBJ = ${LIBJSONSRC:.c=.o} + 24 + 25 LIB = ${LIBJSON} + 26 + +Build the json.c file as a local reusable linkable library (libjson.a). + + 27 all: ${BIN} + 28 + +The default build rule: build the binary. + + 29 ${BIN}: ${LIB} ${@:=.o} + 30 + +The binary depends on the own libjson library and object files. + + 31 OBJ = ${SRC:.c=.o} ${LIBJSONOBJ} + 32 + +The object files are all C source-code substituted to from .c to .o and the +local libjson library files, so: json2tsv.o json.o + + 33 ${OBJ}: ${HDR} + 34 + +Ensure the object files are recompiled if the header file contents change. + + 35 .o: + 36 ${CC} ${LDFLAGS} -o $@ $< ${LIB} + +Linking, use the system specified LDFLAGS. + + 37 + 38 .c.o: + 39 ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ -c $< + +Compiling, use the system specified CFLAGS and CPPFLAGS. + + 40 + 41 ${LIBJSON}: ${LIBJSONOBJ} + 42 ${AR} rc $@ $? + 43 ${RANLIB} $@ + 44 + +Create an archive of the libjson object files. Note that ar -s is an extension +so ranlib is called as a separate command. It is also useful to be specified +separately for cross-compiling. + + 45 dist: + 46 rm -rf "${NAME}-${VERSION}" + 47 mkdir -p "${NAME}-${VERSION}" + 48 cp -f ${MAN1} ${DOC} ${HDR} \ + 49 ${SRC} ${LIBJSONSRC} Makefile "${NAME}-${VERSION}" + +Use the -f (force) options for rm to make sure to not return an error in-case +of failure. For cp it ensures to overwrite the file even if it is busy. For +mkdir the -p flag is used to create all intermediary directories and to not +return an error if the directory already exists. + + 50 # make tarball + 51 tar -cf - "${NAME}-${VERSION}" | gzip -c > "${NAME}-${VERSION}.tar.gz" + +Make a tarball. gzip from stdin is used for portability (tar -z is non-POSIX). +https://pubs.opengroup.org/onlinepubs/007908799/xcu/tar.html + + 52 rm -rf "${NAME}-${VERSION}" + 53 + + 54 clean: + 55 rm -f ${BIN} ${OBJ} ${LIB} + +Remove the binary, object files and the local archive library (.a) file. + + 56 + 57 install: all + 58 # installing executable files. + 59 mkdir -p "${DESTDIR}${PREFIX}/bin" + 60 cp -f ${BIN} "${DESTDIR}${PREFIX}/bin" + +For cp it ensures to overwrite the file even if it is installed already and +busy as a process. + + 61 for f in ${BIN}; do chmod 755 "${DESTDIR}${PREFIX}/bin/$$f"; done + 62 # installing example files. + 63 mkdir -p "${DESTDIR}${DOCPREFIX}" + 64 cp -f README "${DESTDIR}${DOCPREFIX}" + 65 # installing manual pages for general commands: section 1. + 66 mkdir -p "${DESTDIR}${MANPREFIX}/man1" + 67 cp -f ${MAN1} "${DESTDIR}${MANPREFIX}/man1" + 68 for m in ${MAN1}; do chmod 644 "${DESTDIR}${MANPREFIX}/man1/$$m"; done + 69 + +Explicitly sets permissions for executable files and for documentation. + + 70 uninstall: + 71 # removing executable files. + 72 for f in ${BIN}; do rm -f "${DESTDIR}${PREFIX}/bin/$$f"; done + 73 # removing example files. + 74 rm -f "${DESTDIR}${DOCPREFIX}/README" + + 75 -rmdir "${DESTDIR}${DOCPREFIX}" + +Try to remove the doc directory, but if it is shared by other packages and +rmdir returns an error code then that is ok and make still proceeds. + + 76 # removing manual pages. + 77 for m in ${MAN1}; do rm -f "${DESTDIR}${MANPREFIX}/man1/$$m"; done + 78 + 79 .PHONY: all clean dist install uninstall + + + + +TODO + +References: +- https://www.gnu.org/prep/standards/standards.html#DESTDIR +- https://nullprogram.com/blog/2017/08/20/ + +- https://www.openbsd.org/faq/ports/