Top-Level Makefile¶
Read time: 4 minutes (1115 words)
The major components of this make
system are all included in the top-level
project Makefile
. That keeps this file extremely simple. All it has in it
is a few definitions to extract the project name from the current directory,
then it includes a component that detects what platform you are using.
Here is the Makefile
for this test project:
1 2 3 4 5 6 | # Modular Make - top level makefile
PROJPATH = $(PWD)
PROJNAME = $(notdir $(PROJPATH))
include $(wildcard mk/*.mk)
TARGET := $(PROJNAME)$(EXT)
|
Detecting the OS¶
In order to make this system work on any platform, I separated components of
the system into subdirectories so that components specific to each platform get
loaded when make
runs. Here is the component that figures out what system
you are using:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ifeq ($(OS), Windows_NT)
EXT = .exe
PREFIX =
RM = del
WHICH := where
PLATFORM := Windows
PROJPATH := $(CURDIR)
include $(wildcard mk/pc/*.mk)
else
EXT =
RM = rm -f
PREFIX := ./
WHICH := which
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S), Linux)
PLATFORM := Linux
include $(wildcard mk/linux/*.mk)
endif
ifeq ($(UNAME_S), Darwin)
PLATFORM := Mac
include $(wildcard mk/mac/*.mk)
endif
endif
|
Debugging the System¶
To assist in debugging the system, I found a neat way to print out all the user
defined variables in the Makefile
. Here is that code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | .DEFAULT_GOAL := all
print-%:
@echo $* = $($*)
.PHONY: debug
debug: ## display local make variables defined
@$(foreach V, $(sort $(.VARIABLES)), \
$(if $(filter-out environment% default automatic,\
$(origin $V)), \
$(warning $V = $($V) )) \
)
.PHONY: debug-all
debug-all: ## display all make variables defined
@$(foreach V, $(sort $(.VARIABLES)), \
$(warning $V = $($V) ) \
)
|
Help System¶
Finally, there is a simple help system that relies on a short Python Script. Basically, on each
make
target
line, after the dependencies, you add a comment that begins with two hash marks, then continues to the end of the line. The Python script scans all the definedMakefile
components looking for these markers, then produces a table showing what is available.help.mk¶
1 2 3 4 5 # Makefile help system .PHONY: help help: ## display help messages @python mk/pyhelp.py$(MAKEFILE_LIST)And here is the heper Python scrips
mk/pytest.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import sys import re def main(): help_re = re.compile(r"^([a-zA-Zi_-]*:).*?##(.*)$") modules = sys.argv del modules[0] for m in modules: fin = open(m,'r') lines = fin.readlines() for l in lines: m = help_re.match(l) if m: item = m.group(1).strip() defn = m.group(2).strip() print("%-20s %s" %(item,defn)) main()