From 9cd496402453a92c4924f7f205bb22bd80202db4 Mon Sep 17 00:00:00 2001 From: crasbe Date: Sat, 15 Mar 2025 00:06:54 +0100 Subject: [PATCH 1/2] dist/tools: add doxygen as a tool for CI --- Makefile | 4 +- dist/tools/doxygen/.gitignore | 3 + dist/tools/doxygen/Makefile | 106 ++++++++++++++++++++++++++++++++++ doc/doxygen/Makefile | 36 ++++++++---- 4 files changed, 137 insertions(+), 12 deletions(-) create mode 100644 dist/tools/doxygen/.gitignore create mode 100644 dist/tools/doxygen/Makefile diff --git a/Makefile b/Makefile index b263675a80e4..dbfbfb4163ad 100644 --- a/Makefile +++ b/Makefile @@ -6,11 +6,11 @@ all: welcome @echo "" @exit 1 -doc doc-man doc-latex: +doc doc-man doc-latex doc-ci: @./dist/tools/features_yaml2mx/features_yaml2mx.py \ features.yaml \ --output-md doc/doxygen/src/feature_list.md - "$(MAKE)" -BC doc/doxygen $@ + "$(MAKE)" -C doc/doxygen $@ docclean: "$(MAKE)" -BC doc/doxygen clean diff --git a/dist/tools/doxygen/.gitignore b/dist/tools/doxygen/.gitignore new file mode 100644 index 000000000000..0c4e78613be8 --- /dev/null +++ b/dist/tools/doxygen/.gitignore @@ -0,0 +1,3 @@ +doxygen +doxygen-* +doxygen-*/ diff --git a/dist/tools/doxygen/Makefile b/dist/tools/doxygen/Makefile new file mode 100644 index 000000000000..99a92a8e9702 --- /dev/null +++ b/dist/tools/doxygen/Makefile @@ -0,0 +1,106 @@ +# This tool package is meant to be used by the `doc-ci` command +# to download and (if necessary) compile the specified Doxygen version. +# Depending on the distribution, it is quite difficult to obtain recent +# package versions. +# +# The script will try to download the binary release files for `Linux x86_64` +# systems and compile from source for every other system. +# +# The Doxygen version that will be fetched is saved in the $(PKG_VERSION) +# environment variable and has to be set by the caller. +# Accepted values for $(PKG_VERSION) are either version numbers such as +# `1.13.2` or `latest` to build the latest master source. + +PKG_NAME=doxygen +PKG_LICENSE=GPL-2.0 + +# optionally add the "clean" target to delete the binary and force a rebuild +REBUILD= + +# the PKG_VERSION is defined by the doc/doxygen/Makefile +ifeq (,$(filter clean distclean,$(MAKECMDGOALS))) + ifeq (,$(PKG_VERSION)) + $(error Doxygen version undefined!) + endif + + # If the requested and installed version mismatch, force a rebuild + # by deleting the binary. `latest` will always force a rebuild. + ifneq (,$(shell test -f $(CURDIR)/doxygen && echo exists)) + ifneq ($(PKG_VERSION),$(shell $(CURDIR)/doxygen --version | cut -d ' ' -f1)) + REBUILD=clean + endif + endif +endif + +# Try to download the binary if the platform is 'Linux x86_64' to avoid +# unnecessarily building Doxygen for CI. +ifeq (Linux x86_64,$(shell uname -m -s)) + # always build from source for the 'latest' version + ifeq (latest,$(PKG_VERSION)) + BUILD_METHOD=build_source + else + # The URL has the following format (for version 1.13.2): + # https://github.com/doxygen/doxygen/releases/download/Release_1_13_2/ + # doxygen-1.13.2.linux.bin.tar.gz + BIN_PKG_URL=https://github.com/doxygen/doxygen/releases/download/Release_ + BIN_PKG_EXT=linux.bin.tar.gz + BIN_PKG_TAR=$(PKG_NAME)-$(PKG_VERSION).$(BIN_PKG_EXT) + BIN_PKG_DOWNLOAD_URL=$(BIN_PKG_URL)$(subst .,_,$(PKG_VERSION))/$(BIN_PKG_TAR) + + BIN_AVAILABLE := $(shell curl --head --silent --fail $(BIN_PKG_DOWNLOAD_URL) \ + >/dev/null 2>&1 && echo yes || echo no) + ifeq (yes,$(BIN_AVAILABLE)) + BUILD_METHOD=download_binary + else + BUILD_METHOD=build_source + endif + endif +endif + +# fallback to building from source by default +BUILD_METHOD?=build_source + +ifeq (build_source,$(BUILD_METHOD)) + PKG_URL=https://github.com/doxygen/doxygen + PKG_EXT= +else + PKG_URL=$(BIN_PKG_URL) + PKG_EXT=$(BIN_PKG_EXT) +endif + +.PHONY: clean distclean + +all: $(CURDIR)/doxygen + +$(CURDIR)/doxygen: $(REBUILD) + @$(MAKE) $(BUILD_METHOD) + +download_binary: distclean + @echo "[INFO] Downloading Doxygen binary..." + @wget -q -O $(CURDIR)/$(BIN_PKG_TAR) $(BIN_PKG_DOWNLOAD_URL) || \ + { echo "[ERROR] Failed to download binary"; exit 1; } + @echo "[INFO] Unpacking Doxygen..." + @tar -xf $(CURDIR)/$(BIN_PKG_TAR) + @cp $(CURDIR)/$(PKG_NAME)-$(PKG_VERSION)/bin/doxygen $(CURDIR) + +build_source: distclean + @echo "[INFO] Cloning and building Doxygen from source..." + @if [ "$(PKG_VERSION)" = "latest" ]; then \ + git clone --depth=1 $(PKG_URL).git $(CURDIR)/$(PKG_NAME)-$(PKG_VERSION); \ + else \ + git ls-remote --tags $(PKG_URL).git | grep -q "refs/tags/Release_$(subst .,_,$(PKG_VERSION))$$" || \ + { echo "[ERROR] Specified version tag 'Release_$(subst .,_,$(PKG_VERSION))'" \ + "does not exist!"; exit 1; }; \ + git clone --branch Release_$(subst .,_,$(PKG_VERSION)) --depth=1 \ + $(PKG_URL).git $(CURDIR)/$(PKG_NAME); \ + fi + @cd $(CURDIR)/$(PKG_NAME)-$(PKG_VERSION) && mkdir build && cd build && \ + cmake -G "Unix Makefiles" .. && \ + $(MAKE) --no-print-directory && \ + cp bin/doxygen $(CURDIR) + +distclean:: clean + @rm -rf $(CURDIR)/$(PKG_NAME)* + +clean:: + @rm -rf $(PKG_NAME) diff --git a/doc/doxygen/Makefile b/doc/doxygen/Makefile index f367334767de..ecd1e6b46f9a 100644 --- a/doc/doxygen/Makefile +++ b/doc/doxygen/Makefile @@ -1,5 +1,7 @@ -RIOTBASE = $(shell git rev-parse --show-toplevel) -RIOTMAKE ?= $(RIOTBASE)/makefiles +RIOTBASE ?= $(shell git rev-parse --show-toplevel) +RIOTMAKE ?= $(RIOTBASE)/makefiles +RIOTTOOLS ?= $(RIOTBASE)/dist/tools + # Generate list of quoted absolute include paths. Evaluated in riot.doxyfile. export STRIP_FROM_INC_PATH_LIST=$(shell \ @@ -22,11 +24,19 @@ endif # Check that the doxygen version is not too old to avoid # certain bugs that were fixed in later revisions. Especially # Debian-based distributions tend to have very old versions. -DOXYGEN_MIN_VERSION = 1.14.0 +DOXYGEN_MIN_VERSION = 1.13.2 + +# Set the Doxygen binary if not already set +DOXYGEN ?= doxygen # Strip the commit hash that is sometimes present after the # version number. -DOXYGEN_VERSION = $(shell doxygen --version | cut -d ' ' -f1) +DOXYGEN_CUR_VERSION = $(shell $(DOXYGEN) --version | cut -d ' ' -f1) + +# for the `doc-ci` target, we can choose which Doxygen version should be built. +# If nothing has been chosen, select the minimum version. +# Valid options are `latest` and version numbers such as `1.13.2`. +DOXYGEN_VERSION ?= $(DOXYGEN_MIN_VERSION) # include color echo macros include $(RIOTMAKE)/utils/ansi.mk @@ -34,27 +44,32 @@ include $(RIOTMAKE)/color.inc.mk .PHONY: doc doc-man doc-latex doc doc-man doc-latex: $(DOCUMENTATION_FORMAT) - @if [ "`{ echo "$(DOXYGEN_MIN_VERSION)"; echo "$(DOXYGEN_VERSION)"; } | \ + @if [ "`{ echo "$(DOXYGEN_MIN_VERSION)"; echo "$(DOXYGEN_CUR_VERSION)"; } | \ sort -V | head -n1`" != "$(DOXYGEN_MIN_VERSION)" ]; then \ - $(COLOR_ECHO) "$(COLOR_RED)Warning: Doxygen version $(DOXYGEN_VERSION) is too old." \ + $(COLOR_ECHO) "$(COLOR_RED)Warning: Doxygen version $(DOXYGEN_CUR_VERSION) is too old." \ "It is recommended to use at least version $(DOXYGEN_MIN_VERSION)" \ "to avoid incorrectly formatted output.$(COLOR_RESET)"; \ fi +.PHONY: doc-ci +doc-ci: $(RIOTTOOLS)/doxygen/Makefile + @PKG_VERSION=$(DOXYGEN_VERSION) $(MAKE) -C $(RIOTTOOLS)/doxygen all --no-print-directory + @$(MAKE) -BC $(CURDIR) DOXYGEN=$(RIOTTOOLS)/doxygen/doxygen doc + # by marking html as phony we force make to re-run Doxygen even if the directory exists. .PHONY: html html: src/changelog.md src/coc.md src/governance.md - ( cat riot.doxyfile ; echo "GENERATE_HTML = yes" ) | doxygen - + ( cat riot.doxyfile ; echo "GENERATE_HTML = yes" ) | $(DOXYGEN) - @echo "" @echo "RIOT documentation successfully generated at file://$(RIOTBASE)/doc/doxygen/html/index.html" .PHONY: check check: src/changelog.md src/coc.md src/governance.md - ( cat riot.doxyfile) | doxygen - + ( cat riot.doxyfile) | $(DOXYGEN) - .PHONY: man man: src/changelog.md src/coc.md src/governance.md - ( cat riot.doxyfile ; echo "GENERATE_MAN = yes" ) | doxygen - + ( cat riot.doxyfile ; echo "GENERATE_MAN = yes" ) | $(DOXYGEN) - @echo "" @echo "RIOT documentation successfully generated at file://$(RIOTBASE)/doc/doxygen/man/man3" @@ -76,9 +91,10 @@ src/governance.md: ../../GOVERNANCE.md .PHONY: latex: src/changelog.md src/coc.md src/governance.md - ( cat riot.doxyfile ; echo "GENERATE_LATEX= yes" ) | doxygen - + ( cat riot.doxyfile ; echo "GENERATE_LATEX= yes" ) | $(DOXYGEN) - @echo "" @echo "RIOT documentation successfully generated at file://$(RIOTBASE)/doc/doxygen/latex/index.tex" clean: -@rm -rf latex man html doxygen_objdb_*.tmp doxygen_entrydb_*.tmp src/changelog.md src/coc.md src/governance.md + @$(MAKE) -C $(RIOTTOOLS)/doxygen clean From 64898cf13af16ebd36f7ea81841f3a427cf40bec Mon Sep 17 00:00:00 2001 From: crasbe Date: Sun, 23 Mar 2025 14:37:58 +0100 Subject: [PATCH 2/2] doc/doxygen: Add a check for the GraphViz dependency --- doc/doxygen/Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/doxygen/Makefile b/doc/doxygen/Makefile index ecd1e6b46f9a..48adaafe941c 100644 --- a/doc/doxygen/Makefile +++ b/doc/doxygen/Makefile @@ -43,7 +43,7 @@ include $(RIOTMAKE)/utils/ansi.mk include $(RIOTMAKE)/color.inc.mk .PHONY: doc doc-man doc-latex -doc doc-man doc-latex: $(DOCUMENTATION_FORMAT) +doc doc-man doc-latex: graphviz-check $(DOCUMENTATION_FORMAT) @if [ "`{ echo "$(DOXYGEN_MIN_VERSION)"; echo "$(DOXYGEN_CUR_VERSION)"; } | \ sort -V | head -n1`" != "$(DOXYGEN_MIN_VERSION)" ]; then \ $(COLOR_ECHO) "$(COLOR_RED)Warning: Doxygen version $(DOXYGEN_CUR_VERSION) is too old." \ @@ -51,6 +51,15 @@ doc doc-man doc-latex: $(DOCUMENTATION_FORMAT) "to avoid incorrectly formatted output.$(COLOR_RESET)"; \ fi +# GraphViz is a mandatory dependency to generate the Doxygen documentation for RIOT +.PHONY: graphviz-check +graphviz-check: + @command -v dot >/dev/null 2>&1 || { \ + $(COLOR_ECHO) "$(COLOR_RED)Error: GraphViz (dot) is not installed." \ + "GraphViz is mandatory to generate the RIOT documentation.$(COLOR_RESET)"; \ + exit 1; \ + } + .PHONY: doc-ci doc-ci: $(RIOTTOOLS)/doxygen/Makefile @PKG_VERSION=$(DOXYGEN_VERSION) $(MAKE) -C $(RIOTTOOLS)/doxygen all --no-print-directory