Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 49 additions & 10 deletions docs/src/Submakefile
Original file line number Diff line number Diff line change
Expand Up @@ -1088,21 +1088,29 @@ $(DOC_OUT_HTML)/en/pdf/LinuxCNC_Manual_Pages_en.pdf: objects/LinuxCNC_Manual_Pag
|| (X=$$?; rm -f $@ $@.raw; exit $$X)
@test -f $@

# Target a page's include:: and image: prerequisites hang off. A page is
# consumed by its .html; a Master document has no HTML, only the PDF that
# pulls its chapters in, and the English ones render into objects/. Not
# derivable from the source path, so asciideps is told.
EN_DEP_TARGET = $(if $(filter Master_%,$*),objects/$*.pdf,$(DOC_OUT_ADOC)/en/$*.html)

depends/%.d: $(DOC_OUT_ADOC)/en/%.adoc $(DOC_SRCDIR)/asciideps .include-stamp | stage-en
$(ECHO) Depending $<
@mkdir -p $(dir $@)
$(Q)$(DOC_SRCDIR)/asciideps $< > $@.tmp
$(Q)$(DOC_SRCDIR)/asciideps $< $(EN_DEP_TARGET) > $@.tmp
@mv $@.tmp $@

# Translated .adoc lives in $(DOC_OUT_ADOC)/<lang>/; same recipe, just a
# different source dir so the per-language depends/<lang>/X.d targets
# resolve. The pattern only matches paths starting with a known language
# tag, so the English depends/%.d above wins for non-translated entries.
# Translated Master PDFs render beside their source, so unlike English the
# target is the sibling .pdf.
define TRANSLATED_DEP_RULE
depends/$(1)/%.d: $(DOC_OUT_ADOC)/$(1)/%.adoc $(DOC_SRCDIR)/asciideps .include-stamp | stage-en
$$(ECHO) Depending $$<
@mkdir -p $$(dir $$@)
$$(Q)$$(DOC_SRCDIR)/asciideps $$< > $$@.tmp
$$(Q)$$(DOC_SRCDIR)/asciideps $$< $$(if $$(filter Master_%,$$*),$(DOC_OUT_ADOC)/$(1)/$$*.pdf,$(DOC_OUT_ADOC)/$(1)/$$*.html) > $$@.tmp
@mv $$@.tmp $$@
endef
$(foreach L,$(LANGUAGES),$(eval $(call TRANSLATED_DEP_RULE,$(L))))
Expand Down Expand Up @@ -1191,14 +1199,19 @@ $(foreach L,$(LANGUAGES),$(eval $(call HTML_COPY_RULE,$(L))))
# has no work to do (filter-out yields empty) so we skip the dep too. HTML
# image placement is no longer done here: the image_resolver rewrites HTML src
# to the shared pool and .html-images-stamp materialises it.
#
# Matched anywhere on the line, like asciideps, so both see the same set.
# Anchored at the start it missed the 39 inline refs, leaving those images
# out of the translated PDFs that embed them from here. Keyed on the macro
# shape, or prose mentioning image:: is taken for a path and the copy fails.
ifeq ($(BUILD_DOCS_TRANSLATED),yes)
ADOC_IMAGES_STAMP_DEPS := $(DOC_DIR)/.translateddocs-stamp
endif
.adoc-images-stamp: $(ADOC_IMAGES_STAMP_DEPS) $(addprefix $(DOC_OUT_ADOC)/, $(filter-out $(DOC_SRCS_EN), $(DOC_SRCS)))
set -e; for ADOC_FILE in $(addprefix $(DOC_OUT_ADOC)/, $(filter-out $(DOC_SRCS_EN), $(DOC_SRCS))); do \
ADOC_DIR=$$(echo $$(dirname $$ADOC_FILE) | sed s%$(DOC_OUT_ADOC)/%% ); \
echo Processing $$ADOC_FILE, dir $$ADOC_DIR; \
for IMAGE_FILE in $$(grep -E ^image:[^[:space:]] $$ADOC_FILE | sed -E "s/image:+([^[]+)\[/\nimage:\1\n/g" | grep image: | cut -d: -f2-); do \
for IMAGE_FILE in $$(grep -v '^[[:space:]]*//' $$ADOC_FILE | grep -oE 'image::?[^[:space:][]+\[' | sed -E 's/^image::?//; s/\[$$//'); do \
IMAGE_DIR=$$(dirname $$IMAGE_FILE); \
IMAGE_PATH=$$(echo $(DOC_SRCDIR)/$$ADOC_DIR/$$IMAGE_FILE | sed -E 's%/src/($(LANGUAGES_MATCH))/%/src/%'); \
if [ ! -e $$IMAGE_PATH ] ; then \
Expand All @@ -1214,6 +1227,24 @@ endif
done; \
done > $@.new && mv $@.new $@

# Same staging, one file at a time. The dependency files name these images,
# so a clean -j build reaches one before the bulk pass has written it and
# falls through to the "Required image file" error at the end of this file.
# Source lookup as above: the English original, else the English build tree
# for images generated there, such as the .dot-rendered SVGs.
ifeq ($(BUILD_DOCS_TRANSLATED),yes)
define TRANSLATED_IMAGE_RULE
$(DOC_OUT_ADOC)/$(1)/%.$(2): | $(DOC_DIR)/.translateddocs-stamp
@mkdir -p $$(@D)
$$(Q)S=$(DOC_SRCDIR)/$$*.$(2); \
[ -e "$$$$S" ] || S=$(DOC_OUT_ADOC)/en/$$*.$(2); \
cp -f "$$$$S" $$@
endef
$(foreach L,$(LANGUAGES), \
$(foreach E,png jpg jpeg gif svg, \
$(eval $(call TRANSLATED_IMAGE_RULE,$(L),$(E)))))
endif

# Relative path from this html target back to $(DOC_OUT_HTML)/, used to
# point the lcnc-overrides.css <link> in docinfo.html at the right place.
# Every output now lives under a $(DOC_OUT_HTML)/<lang>/ subtree, so depth
Expand Down Expand Up @@ -1282,24 +1313,32 @@ endef
# components_gen.adoc generates straight into build/adoc/en/hal; svgs_made_from_dots
# runs first.
#
# One rule per staged file, not a bulk find|tar behind a stamp with the staged copies hanging off it order-only.
# make stats a prerequisite once per run and re-stats it only if it decided to remake it, and an order-only edge never triggers a remake.
# A bulk copy that rewrote the staged .adoc mid-run was therefore invisible to the renderer, which had already compared the .html against the pre-copy mtime, so editing a page took two `make` runs to reach the HTML: the first re-staged, the second rendered.
# With a real recipe per file make knows the staged copy changed and the render fires in the same run.
# One rule per staged file, not a bulk copy behind a stamp with the staged
# copies hanging off it order-only. make stats a prerequisite once per run
# and re-stats it only if it decided to remake it, which an order-only edge
# never triggers, so a bulk copy rewriting the staged .adoc mid-run stayed
# invisible and editing a page took two `make` runs to reach the HTML.
EN_STAGE_TYPES := -name '*.adoc' -o -name '*.png' -o -name '*.jpg' -o -name '*.jpeg' -o -name '*.gif' -o -name '*.svg' -o -name '*.py'
EN_STAGE_SRCS := $(shell find $(DOC_SRCDIR) \( $(EN_STAGE_TYPES) \))
EN_STAGED := $(patsubst $(DOC_SRCDIR)/%,$(DOC_OUT_ADOC)/en/%,$(EN_STAGE_SRCS))

# cp -p keeps the source mtime to the nanosecond; tar rounded it down to the whole second, which could leave a staged copy a fraction older than a .html rendered from it in the same second and lose that edit entirely.
# cp -p keeps the source mtime to the nanosecond. tar rounded down to the
# whole second, which could leave a staged copy a shade older than a .html
# rendered from it in that same second and lose the edit.
$(EN_STAGED): $(DOC_OUT_ADOC)/en/%: $(DOC_SRCDIR)/% | svgs_made_from_dots
@mkdir -p $(@D)
$(Q)cp -p $< $@

# Stage the whole set before anything reads it, the way the bulk copy did. On-demand staging is not enough: asciidoctor resolves include:: and image: against the staged tree at render time, and asciideps recurses into included files there, but only a fraction of those are make prerequisites. Leave it to demand and a partial like hal/halshow.adoc never lands, so the page that includes it renders an "Unresolved directive" placeholder instead of its content.
# Stage the whole set up front, as the bulk copy did. On demand is not
# enough: asciidoctor resolves include:: and image: against this tree at
# render time and asciideps recurses into it, yet few of those files are make
# prerequisites. Left to demand, a partial like hal/halshow.adoc never lands
# and the page including it renders an "Unresolved directive" placeholder.
.PHONY: stage-en
stage-en: $(EN_STAGED)

# Staged files are used only as prerequisites: mark .SECONDARY so make does not delete them as intermediates mid -j build (like the .SECONDARY above).
# Staged files are used only as prerequisites: mark .SECONDARY so make does
# not delete them as intermediates mid -j build (like the .SECONDARY above).
.SECONDARY: $(EN_STAGED)

# English now renders from build/adoc/en, the same model as the translations.
Expand Down
30 changes: 22 additions & 8 deletions docs/src/asciideps
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@

set -e

test -z "$1" && exit 0
test -f "$1" || exit 1
# usage: asciideps SOURCE.adoc [TARGET...]
#
# Emit a make rule hanging SOURCE's include:: and image: prerequisites off
# TARGET. The caller names the target because it is not derivable from the
# source path: a Master document has no .html and its English PDF lands in
# objects/. Defaults to the source stem, for a standalone run.
SRC=$1
[ -z "$SRC" ] && exit 0
[ -f "$SRC" ] || { echo "asciideps: '$SRC' not a file" >&2; exit 1; }
shift
Comment thread
grandixximo marked this conversation as resolved.
TARGETS="$*"
[ -n "$TARGETS" ] || TARGETS="${SRC%.adoc}.html"

includestack=( )

Expand Down Expand Up @@ -31,15 +41,19 @@ includes () {

images() {
DIR=$(dirname "$1")
sed -ne "s|^.*image:\{1,2\}\([^[]*\)\[.*\].*$|$DIR/\1|p" "$1" | tr '\n' ' '
# Drop line comments first: the macro is matched anywhere on the line to
# catch inline refs, which otherwise also matches a commented-out one.
# That is no dependency, and requiring it breaks the build once the file
# it names is removed.
grep -v '^[[:space:]]*//' "$1" \
| sed -ne "s|^.*image:\{1,2\}\([^[]*\)\[.*\].*$|$DIR/\1|p" \
| tr '\n' ' '
}

INCLUDES=$(includes "$1" | tr '\n' ' ')
IMAGES=$(images "$1")
INCLUDES=$(includes "$SRC" | tr '\n' ' ')
IMAGES=$(images "$SRC")
for f in $INCLUDES; do
IMAGES="$IMAGES $(images "$f")"
done

echo "${1%%.txt}.dep: $INCLUDES"
echo "${1%%.txt}.html: $INCLUDES $IMAGES"
echo "${1%%.txt}.pdf: $INCLUDES $IMAGES"
echo "$TARGETS: $INCLUDES $IMAGES"
Loading