diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-11-20 21:52:55 -0800 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-11-20 22:26:12 -0800 |
commit | d48a95ad5889f74777acadaeca615636f855b691 (patch) | |
tree | c9b4d8e1a246c73696506b137c12852c8f01eed8 | |
download | mk-d48a95ad5889f74777acadaeca615636f855b691.tar.gz |
Initial revision.
-rw-r--r-- | README.rst | 140 | ||||
-rw-r--r-- | c.mk | 136 | ||||
-rwxr-xr-x | configure | 42 | ||||
-rw-r--r-- | example/Makefile | 4 | ||||
-rw-r--r-- | example/hello.c | 12 | ||||
-rw-r--r-- | example/main.c | 12 | ||||
-rw-r--r-- | lexyacc.mk | 9 |
7 files changed, 355 insertions, 0 deletions
diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..ac6cbea --- /dev/null +++ b/README.rst @@ -0,0 +1,140 @@ +Makefile Templates +================== + +This contains a number of makefile templates. These Makefile +templates are as follows: + +one.mk +------ + +Builds a single target from multiple input object files. It supports the +following variables as targets: + +BIN + The name of a binary. This binary is not installed. This is + primarily useful for code generation. + +LIB + The name of a static library to build. This static library + is not installed. This is primarily convenient for breaking + your code up into smaller modules, which are linked together. + +SUB + A list of subdirectories to recurse into when building a well + known target (eg, `clean`, `install`, and so on). + +INSTBIN + The name of a binary which is installed to `$prefix/bin`. This + is the most common target which I use. + +INSTLIB + The name of a static library which is installed to `$prefix/lib`. + This makefile fragment expects the name to be in the form of + `lib$LIBNAME.a`. + +INSTHDR + A list of headers to install. The headers are copied to + `$prefix/include`. + +INSTPKG + This lists a set of pkg-config files, which are installed + to `$prefix/lib/pkgconfig`. If you are building a library + that others use, it is *highly* recommended to include a + pkg-config file for ease of use. + +INSTMAN + Installs a manpage. The manpage is expected to be named in + the form of `docname.SECT`, eg, `mycmd.1`, ad will be installed + into the appropriate directory. + +The inputs to all of the targets which are built are listed in the +`OBJ` variable, making it the central part of the makefiles. + +OBJ + This is the list of all the .o files that go into either the + library or the binary that is being constructed. + + +There are also a number of other variables that can be used to control +the way that this makefile include works: + +EXTRA + This is a list of extra targets to build when running + `make all`. These targets should be provided by you. + +PCPKGS + This contains a list of pkg-config packages that this program + depends on. The libraries and include paths will be added to the + build for the target being compiled. + +DEPS + This contains a list of local libraries that the current target + depends on, in the form `../module/libmodule.a`. These dependencies + will be built before the module that defines the dependencies. + +EXTRADEP + This is a list of extra dependencies to be added to the BIN, INSTBIN, + LIB, or INSTLIB targets. + +EXTRACLEAN + This is a list of extra files to be removed on `make clean` + +LDFLAGS + This contains the linker flags. This should only be appended to, + and not overridden. + +CFLAGS + This contains the C compiler flags. This should only be appended to, + and not overridden. + +CXXFLAGS + This contains the C++ compiler flags. This should only be appended to, + and not overridden. + +INST_ROOT + This defines the directory to install into. In this example, it + is set by ./configure + +lexyacc.mk +------ + +Augments one.mk and many.mk rules with lex and yacc rules. These +rules will take a yacc file named `input.y`, and produce `input.c` and +`input.h` from it. + +Configure +========= + +This also ships with a single, trivial script named configure. It +only supports setting the prefix, which for many of the programs I need +is enough. + +There are some examples of libraries -- for example, clang -- which do not +ship with pkg-config files, and are typically not installed to /usr/lib. For +those, code is added to the ./configure script. + +This script will automatically be run when running `make`. + +An Example +========== + +Pulled from my Myrddin code:: + + INSTBIN=6m + OBJ= \ + blob.o \ + gen.o \ + gengas.o \ + genp9.o \ + isel.o \ + locs.o \ + main.o \ + ra.o \ + peep.o \ + simp.o \ + typeinfo.o \ + + DEPS=../parse/libparse.a ../mi/libmi.a + + include ../config.mk + include ../mk/c.mk @@ -0,0 +1,136 @@ +.DEFAULT_GOAL=all +_DEPS=$(addprefix .deps/, $(OBJ:.o=.d)) + +_PCHDRS=$(shell [ -z "$(PCPKGS)" ] || pkg-config --cflags $(PCPKGS)) +_PCLIBS=$(shell [ -z "$(PCPKGS)" ] ||pkg-config --libs $(PCPKGS)) + +_LIBSRCHPATHS=$(addprefix -L, $(dir $(DEPS))) +_LIBINCPATHS=$(addprefix -I, $(dir $(DEPS))) $(_PCHDRS) +_LIBPATHS=$(addprefix -l, $(patsubst lib%.a,%,$(notdir $(DEPS)))) $(_PCLIBS) + +# yeah, I should probably remove -Werror, but it's nice for developing alone. +CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-sign-compare -Wno-array-bounds -g +CFLAGS += -MMD -MP -MF .deps/$(subst /,-,$*).d + +LIB ?= $(INSTLIB) +BIN ?= $(INSTBIN) + +# disable implicit rules. +.SUFFIXES: +.SECONDARY: +.PHONY: clean clean-gen clean-bin clean-obj clean-misc clean-backups +.PHONY: all _modversions + +all: _modversions subdirs $(BIN) $(LIB) $(EXTRA) + +$(LIB): $(OBJ) $(EXTRADEP) $(DEPS) + $(AR) -rcs $@ $(OBJ) + +$(BIN): $(OBJ) $(EXTRADEP) $(DEPS) + $(CC) -o $@ $(OBJ) $(_LIBSRCHPATHS) $(_LIBPATHS) $(LDFLAGS) + +$(DEPS): + @cd $(dir $@) && $(MAKE) + +subdirs: + @for i in $(SUB); do (\ + cd $$i && \ + $(MAKE) || \ + exit 1 \ + ) || exit 1; done + +subdirs-clean: + @for i in $(SUB); do (\ + cd $$i && \ + $(MAKE) clean|| \ + exit 1 \ + ); done + +subdirs-install: + @for i in $(SUB); do (\ + cd $$i && \ + $(MAKE) install|| \ + exit 1 \ + ); done + +clean: subdirs-clean $(EXTRACLEAN) + rm -f ${BIN} ${OBJ} ${CLEAN} ${LIB} + rm -rf .deps/ + +install: subdirs-install $(INSTBIN) $(INSTLIB) $(INSTHDR) $(INSTPKG) $(EXTRAINSTALL) + @for i in $(INSTBIN); do \ + echo install $(abspath $$i $(DESTDIR)/$(INST_ROOT)/bin); \ + mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/bin); \ + install $$i $(abspath $(DESTDIR)/$(INST_ROOT)/bin); \ + done + @for i in $(INSTLIB); do \ + echo install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/lib); \ + mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/lib); \ + install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/lib); \ + done + @for i in $(INSTHDR); do \ + echo install $$i $(abspath $(DESTDIR)/$(INST_ROOT)/include); \ + mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/include); \ + install $$i $(abspath $(DESTDIR)/$(INST_ROOT)/include); \ + done + @for i in $(INSTPKG); do \ + echo install $(abspath $$i $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig); \ + mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig); \ + install $(abspath $$i $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig); \ + done + @for i in $(INSTMAN); do \ + sect="$${i##*.}"; \ + echo install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}); \ + mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}); \ + install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}); \ + done + +subdirs-uninstall: + @for i in $(SUB); do (\ + cd $$i && \ + $(MAKE) uninstall|| \ + exit 1 \ + ); done + +uninstall: subdirs-uninstall $(EXTRAUNINSTALL) + @for i in $(INSTBIN); do \ + echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/bin/$$i); \ + rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/bin/$$i); \ + done + @for i in $(INSTLIB); do \ + echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/$$i); \ + rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/$$i); \ + done + @for i in $(INSTHDR); do \ + echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/include/$$i); \ + rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/include/$$i); \ + done + @for i in $(INSTPKG); do \ + echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig/$$i); \ + rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig/$$i); \ + done + @for i in $(INSTMAN); do \ + sect="$${i##*.}" \ + echo rm -f $$i $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}/$$i); \ + rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}/$$i); \ + done + +%.o: %.c $(GENHDR) .deps/stamp + $(CC) -c $(CFLAGS) $(_LIBINCPATHS) $< + +%.o: %.cpp $(GENHDR) .deps/stamp + $(CXX) -c $(CFLAGS) $(_LIBINCPATHS) $< + +%.o: %.cc $(GENHDR) .deps/stamp + $(CXX) -c $(CFLAGS) $(_LIBINCPATHS) $< + +.deps/stamp: + mkdir -p .deps && touch .deps/stamp + +config.mk: configure + ./configure --redo + +_modversions: + @[ -z "$(PCPKGS)" ] || pkg-config --modversion $(PCPKGS) > /dev/null + +-include $(_DEPS) diff --git a/configure b/configure new file mode 100755 index 0000000..bfa86bd --- /dev/null +++ b/configure @@ -0,0 +1,42 @@ +#!/bin/bash + +prefix="/usr/local" + +for i in `seq 300`; do + echo "Lots of output to emulate automake... ok" + echo "Lalalala twiddling thumbs... ok" + echo "Testing for things you'll never use... fail" + echo "Satisfying the fortran77 lobby... ok" + echo "Burning CPU time checking for the obvious... ok" +done +echo "Autoconf emulated successfully" + +INST_ROOT='/usr/local' + +for arg in $*; do + shift 1 + echo $* + case $arg in + "--redo" | "-r") + if [ -f ./configvar_cache ]; then + . ./configvar_cache + fi + ;; + --prefix=*) + prefix=`echo $arg | sed 's/^--prefix=//g'` + ;; + *) echo "Unrecognized argument $arg";; + esac +done + +OS=`uname` + + +echo "export INST_ROOT=$prefix" > config.mk + +echo "prefix=$prefix" > configvar_cache +cat << EOF + Building with: + prefix=$prefix +EOF + diff --git a/example/Makefile b/example/Makefile new file mode 100644 index 0000000..773eb76 --- /dev/null +++ b/example/Makefile @@ -0,0 +1,4 @@ +BIN=hello +OBJ=main.o hello.o + +include ../one.mk diff --git a/example/hello.c b/example/hello.c new file mode 100644 index 0000000..32feb10 --- /dev/null +++ b/example/hello.c @@ -0,0 +1,12 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "hello.h" + +void hello_showargs(char **args, int nargs) +{ + size_t i; + + for (i = 0; i < nargs; i++) + printf("%s\n", args[i]); +} diff --git a/example/main.c b/example/main.c new file mode 100644 index 0000000..23d37fc --- /dev/null +++ b/example/main.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +#include "hello.h" + +int main(int argc, char **argv) +{ + int i; + + printf("Hello World!\n"); + for (i = 1; i < argc; i++) + hello_showargs(argv + 1, argc - 1); +} diff --git a/lexyacc.mk b/lexyacc.mk new file mode 100644 index 0000000..c1baf61 --- /dev/null +++ b/lexyacc.mk @@ -0,0 +1,9 @@ +NOERR_FLAGS = $(subst -Werror,,$(subst -Wall,,$(CFLAGS))) + +%.o: %.y + yacc -d -o$*.c $< + $(CC) -c $(NOERR_CFLAGS) $(_LIBINCPATHS) $*.c + +%.o: %.l + flex -o$*.c $< + $(CC) -c $(NOERR_CFLAGS) $(_LIBINCPATHS) $*.c |