firmware-base/vendor/sming/Sming/docs/Makefile
2026-01-28 16:42:43 +01:00

295 lines
9.4 KiB
Makefile

# Makefile for Sphinx documentation
#
# Don't bother with implicit checks
.SUFFIXES:
SHELL = /bin/bash
AWK ?= POSIXLY_CORRECT= awk
SMINGDIR := ..
override SMING_HOME := $(SMINGDIR)/Sming
override SMING_ARCH := Host
include $(SMING_HOME)/util.mk
# You can set these variables from the command line, and also from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
ARCH_BASE := $(SMING_HOME)/Arch/$(SMING_ARCH)
BUILD_TYPE := release
OUT_BASE := out/$(SMING_ARCH)/$(BUILD_TYPE)
BUILD_BASE = $(OUT_BASE)/build
# Components can detect when docs are being built
MAKE_DOCS := 1
# Documentation is copied into this directory so it gets pulled into build
SOURCE_INCDIR := $(SOURCEDIR)/_inc
# Define anything required to get all optional code included
include defines.mk
define Sphinx
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
endef
# $1 -> Directories to look for README and image files
define FindSourceFiles
$(foreach d,$1,$(wildcard $d/*.rst $d/README.md $d/*.svg $d/*.png $d/*.jpg))
endef
# Translate a source path into the corresponding INCDIR location
# $1 -> Path(s) to source file in code tree
define GetIncPath
$(patsubst $(SMINGDIR)/%,$(SOURCE_INCDIR)/%,$1)
endef
# Translate a source path into the corresponding document link path
# $1 -> Path(s) to source file in code tree
define GetDocPath
$(patsubst $(SMINGDIR)/%,/_inc/%,$1)
endef
# Put it first so that "make" without argument is like "make help".
.PHONY: help
help:
$(call Sphinx)
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
.PHONY: html singlehtml latex
html singlehtml latex:
$(call Sphinx)
.PHONY: latexpdf
latexpdf: latex
@echo "Running LaTeX files through pdflatex..."
$(Q) $(MAKE) -C $(BUILDDIR)/latex all-pdf
# Non-component locations to copy docs from
SOURCE_DIRS := \
$(SMINGDIR)/docs \
$(call ListSubDirs,$(SMING_HOME)/Arch)
# List of documentation files to be included from source tree
SOURCE_FILES := \
$(SMINGDIR)/CONTRIBUTING.md \
$(call FindSourceFiles,$(SOURCE_DIRS))
# Additional paths for doxygen
DOXYGEN_INPUT := api.dox
# Paths containing files to be pre-processed but not included in output
DOXYGEN_INCLUDE_PATH :=
DOXYGEN_PREDEFINED := \
__cplusplus \
IRAM_ATTR= \
ICACHE_FLASH= \
ICACHE_FLASH_ATTR= \
__forceinline= \
__attribute__((packed))= \
SMING_DEPRECATED= \
SMING_ARCH=$(SMING_ARCH) \
ARCH_HOST=1
# Each sample, library and Component MUST have a README.rst or README.md file
# This is a list of directories where such files may exist
# If a component.mk file exists, then it is parsed and any dependencies handled
COMPONENT_ROOT_DIRS := \
$(wildcard $(SMING_HOME)/Arch/*/Components) \
$(SMING_HOME)/Components \
$(SMING_HOME)/Libraries \
$(SMINGDIR)/samples
# All directories where a README file should/must exist, and where a component.mk file could exist
COMPONENT_DIRS := $(SMING_HOME) $(call ListSubDirs,$(COMPONENT_ROOT_DIRS))
COMPONENT_SAMPLES := $(wildcard $(addsuffix /samples/*/component.mk,$(COMPONENT_DIRS)))
COMPONENT_DIRS += $(COMPONENT_SAMPLES:/component.mk=)
# Fetch a list of URLs once rather than invoking shell each time we need a lookup
SUBMODULE_URLS := $(shell $(AWK) '/path = .*/ { path = $$3 } /url = .*/ { printf "%s=%s ", path, $$3 } ' $(SMINGDIR)/.gitmodules)
# Lookup the URL for a submodule given its path
# $1 -> path
define GetSubmoduleURL
$(subst $1=,,$(filter $1=%,$(SUBMODULE_URLS)))
endef
# If a Sphinx 'include' directive starts with '/' that's the source directory, so we need a path relative to that
GetIncludePath = /../$(SMINGDIR)/$(patsubst $(abspath $(SMINGDIR))/%,%,$(abspath $1))
# For Windows, Sphinx has a problem with the /c/ style drives and wants c:/ instead
ifeq ($(OS),Windows_NT)
DRIVE := $(firstword $(subst /, ,$(CURDIR)))
GetMdIncludePath = $(DRIVE):/$(subst /$(DRIVE)/,,$(abspath $1))
else
GetMdIncludePath = $(abspath $1)
endif
# $1 -> Path to a Component, sample or Library
define GetComponentType
$(if $(findstring /samples/,$1),Sample,$(if $(findstring /Libraries/,$1),Library,Component))
endef
include index.mk
# Used to escape generated text so it can be handled as a single line
define NewLine
endef
# This macro sets the default component variables before including the (optional) component.mk file.
# $1 -> name
# $2 -> path
define ParseComponent
$(if $V,$(info -- Parsing $2))
ARCHLIST := $(subst /, ,$(patsubst $(SMING_HOME)/Arch/%,%,$2))
ARCH_SOC := $$(ARCH_$$(firstword $$(ARCHLIST))_SOC)
COMPONENT_SUBMODULES :=
COMPONENT_DOCFILES :=
COMPONENT_DOXYGEN_INPUT :=
COMPONENT_DOXYGEN_INCLUDE :=
COMPONENT_DOXYGEN_PREDEFINED :=
COMPONENT_SOC := $$(if $$(ARCH_SOC),$$(ARCH_SOC),*)
# Process any component.mk file (optional)
COMPONENT_RULE := __no_build__
COMPONENT_NAME := $1
COMPONENT_PATH := $2
COMPONENT_VARS :=
COMPONENT_RELINK_VARS :=
CONFIG_VARS :=
RELINK_VARS :=
CACHE_VARS :=
DEBUG_VARS :=
COMPONENT_DEPENDS :=
ARDUINO_LIBRARIES :=
COMPONENT_BUILD_BASE := $(BUILD_BASE)/$1
COMPONENT_BUILD_DIR := $(BUILD_BASE)/$1
include defines.mk
-include $2/component.mk
CMP_$2_SOC := $$(filter $$(subst *,%,$$(COMPONENT_SOC)),$(AVAILABLE_SOCS))
CMP_$2_VARS := $$(sort $$(COMPONENT_VARS))
CMP_$2_LIBRARIES := $$(ARDUINO_LIBRARIES)
CMP_$2_SUBMODULES := $$(COMPONENT_SUBMODULES)
CMP_$2_DIRS := $2 $$(addprefix $2/,$$(COMPONENT_SUBMODULES))
CMP_$2_FILES := \
$$(call FindSourceFiles,$$(CMP_$2_DIRS)) \
$$(wildcard $$(addprefix $2/,$$(COMPONENT_DOCFILES)))
CMP_$2_README := $$(filter $2/README.%,$$(CMP_$2_FILES))
CMP_$2_FILES := $$(filter-out $$(CMP_$2_README),$$(CMP_$2_FILES))
SOURCE_FILES += $$(CMP_$2_FILES)
#
DOXYGEN_INPUT += $$(addprefix $2/,$$(COMPONENT_DOXYGEN_INPUT))
DOXYGEN_INCLUDE_PATH += $$(addprefix $2/,$$(COMPONENT_DOXYGEN_INCLUDE))
DOXYGEN_PREDEFINED += $$(COMPONENT_DOXYGEN_PREDEFINED)
#
COMPONENT_ENVVARS := $$(sort $$(COMPONENT_VARS) $$(COMPONENT_RELINK_VARS) $$(CONFIG_VARS) $$(RELINK_VARS) $$(CACHE_VARS) $$(DEBUG_VARS))
CMP_$2_ENVVARS := $$(COMPONENT_ENVVARS)
$$(foreach c,$$(COMPONENT_DEPENDS) $$(ARDUINO_LIBRARIES),$$(eval CMP_$$c_XREF += $2))
# Resolve dependencies
#
# If this is an Arch component, then match this Arch only, or **main components** (e.g. Host/heap -> malloc_count)
#
ifneq (,$(findstring /Arch/,$2))
FILTERED_DIRS := $$(filter $(dir $2)% $(SMING_HOME)/Components/%,$(COMPONENT_DIRS))
else
FILTERED_DIRS := $(COMPONENT_DIRS)
endif
CMP_$2_DEPENDS := \
$(if $(findstring /samples/,$2),$(SMING_HOME)) \
$$(foreach d,$$(foreach c,$$(COMPONENT_DEPENDS) $$(ARDUINO_LIBRARIES),$$(filter %/$$c,$$(FILTERED_DIRS))),$$d)
CMP_$2_INDEX = $$(subst $$(NewLine),\n,$$(call GenIndex,$1,$2,$(patsubst $(SMINGDIR)/%,%,$2)))
# Filter SOC dependencies
CMP_$2_UNSUPPORTED_SOC = $$(foreach d,$$(CMP_$2_DEPENDS),$$(filter-out $$(CMP_$$d_SOC),$$(AVAILABLE_SOCS)))
CMP_$2_SOC_DEPENDS = $$(filter-out $$(CMP_$2_UNSUPPORTED_SOC),$$(CMP_$2_SOC))
$$(call GetIncPath,$$(COMPONENT_PATH))/index.rst: $$(CMP_$2_README) $$(call GetIncPath,$$(CMP_$2_FILES))
ifeq ($V,1)
$$(info Creating $$@...)
endif
@echo -e '$$(CMP_$2_INDEX)' > $$@
endef # ParseComponent
$(foreach d,$(COMPONENT_DIRS),$(eval $(call ParseComponent,$(notdir $d),$d)))
SOURCE_FILE_DIRS := $(sort $(dir $(SOURCE_FILES)))
MISSING_README_DIRS := $(filter-out $(SOURCE_FILE_DIRS:/=),$(SOURCE_DIRS))
#
export DOXYGEN_INPUT
export DOXYGEN_INCLUDE_PATH
export DOXYGEN_PREDEFINED
.PHONY: clean
clean:
$(Q) rm -rf $(SOURCE_INCDIR) api $(BUILDDIR)
SOURCE_INCDIRS := $(sort $(call GetIncPath,$(COMPONENT_DIRS) $(SOURCE_FILE_DIRS)))
# Each Sample, Library or Component README.* is included directly rather than added to the toctree
SOURCE_FILES := $(filter-out $(addsuffix /README.%,$(COMPONENT_DIRS)),$(SOURCE_FILES))
SOURCE_INCFILES := $(call GetIncPath,$(SOURCE_FILES))
COMPONENT_INDEXFILES := $(addsuffix /index.rst,$(call GetIncPath,$(COMPONENT_DIRS)))
.PHONY: setup
setup: initdirs $(SOURCE_INCFILES) $(COMPONENT_INDEXFILES)
ifeq ($V,1)
$(call PrintVariable,SOURCE_DIRS)
$(call PrintVariable,SOURCE_FILES)
endif
$(if $(MISSING_README_DIRS),$(call PrintVariable,MISSING_README_DIRS))
# Copy source -> dest file
# $1 -> Source file
# $2 -> Destination file
define CopyFileTarget
$1: $2
$(Q) cp $$< $$@
endef
$(foreach f,$(SOURCE_FILES),$(eval $(call CopyFileTarget,$(call GetIncPath,$f),$f)))
.PHONY: initdirs
initdirs:
$(Q) mkdir -p $(SOURCE_INCDIRS)
.PHONY: api
api: api/xml/index.xml
#
DOXYGEN := $(shell command -v doxygen 2> /dev/null)
api/error.log:
ifndef DOXYGEN
$(error doxygen not found - not building API docs)
endif
@echo Generating Doxygen information
$(Q) mkdir -p api api/html
$(Q) doxygen 2>$@ 1>$(@D)/doxygen.log
-$(Q) rm api/html/api/*.md5 api/html/api/*.map
api/xml/index.xml: api/error.log
@echo "Undocumented:"
@echo "- Compounds: $(shell grep "Compound.*is not documented" $< | wc -l)"
@echo "- Members: $(shell grep "Member.*is not documented" $< | wc -l) "
@echo "- Parameters: $(shell grep "The following parameters of .* are not documented" $< | wc -l) "
@echo "- Symbols: $(shell grep "documented symbol.*not declared" $< | wc -l)"
@echo "Unknown:"
@echo " - Commands: $(shell grep "Found unknown command" $< | wc -l)"
@echo "Not Found:"
@echo " - Arguments: $(shell grep "argument.*not found" $< | wc -l)"
@echo " - Files: $(shell grep "included file.*not found" $< | wc -l)"
@echo " - Links: $(shell grep "link request.*could not be resolved" $< | wc -l)"