Skip to content

Commit 693f88e

Browse files
authored
Merge ec0f4a5 into 36ee76d
2 parents 36ee76d + ec0f4a5 commit 693f88e

File tree

12 files changed

+287
-32
lines changed

12 files changed

+287
-32
lines changed

‎Makefile.am‎

Lines changed: 224 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,117 @@
99
@NUT_AM_MAKE_CAN_EXPORT@@NUT_AM_EXPORT_CCACHE_PATH@export CCACHE_PATH=@CCACHE_PATH@
1010
@NUT_AM_MAKE_CAN_EXPORT@@NUT_AM_EXPORT_CCACHE_PATH@export PATH=@PATH_DURING_CONFIGURE@
1111

12-
# First target often defines default behavior: all
13-
# We follow up with another pass to `make doc` because our wild recipes
14-
# sometimes preclude generating all of them on the first pass (FIXME!)
15-
# missing e.g. PDF and HTML which then pop up in `make check` footprint,
16-
# or misses a .prep-src-docs stage needed to pattern-make man page files
17-
# with some "make" implementations...
18-
all all-am-local all-local: all-recursive
19-
+@$(MAKE) $(AM_MAKEFLAGS) doc
20-
+@$(MAKE) $(AM_MAKEFLAGS) doc
21-
2212
# include directory for aclocal
2313
ACLOCAL_AMFLAGS = -I m4
2414

25-
# subdirectories to build and distribute. The order matters, as
26-
# several subdirectories depend on stuff in "common" or tools being built first
27-
SUBDIRS = include common clients conf data docs drivers tools \
28-
lib scripts server tests
15+
# Autotools' SUBDIRS (our values are listed below) allow for powerful recursive
16+
# recipe automation, with one notable weakness: the dirs are processed in a
17+
# loop sequentially, even in parallel builds (each such sub-make is parallel
18+
# then). In our case, the HTML/PDF render of ChangeLog can take a minute of
19+
# work in "docs" while we are not building anything in other dirs. On the up
20+
# side, that approach does allow for dirs with dependencies to get built first
21+
# deterministically. For more details search for "am__recursive_targets" in the
22+
# generated Makefile.
23+
#
24+
# The commonly suggested way out of this predicament is to consolidate numerous
25+
# Makefile.am recipes into one, which alone properly defines all the needed
26+
# interdependecies that are "known" to one instance of the `make` process.
27+
# This however loses the ability to quickly e.g. `cd tests && make check`, so
28+
# the next layer is to re-introduce Makefiles in sub-directories that define
29+
# a few popular targets to perform via the one big top-level Makefile.
30+
#
31+
# Our approach here is to merge the two solutions: do use SUBDIRS the way
32+
# autotools handle them for the hordes of `*-recursive` targets for us, but
33+
# define more explicitly the targets for hot code paths (all, check) so that
34+
# they can run first for certain different directories (in parallel if asked
35+
# to) with "knowledge" of dependencies, and then a bit wastefully maybe re-run
36+
# those directories via autotools integration. They should be quick no-ops by
37+
# then in the anticipated common use-cases.
38+
#
39+
# List of source subdirectories to build and distribute, used to spawn automake
40+
# (alas sequential) target recipes. The order matters, as several subdirectories
41+
# depend on stuff in "common" or tools being built first!
42+
SUBDIRS = include common clients conf data drivers tools \
43+
lib scripts server tests docs
44+
45+
# Note: not generated from SUBDIRS, because not all are recursive:
46+
SUBDIRS_ALL_RECURSIVE = \
47+
all/include \
48+
all/common \
49+
all/clients \
50+
all/conf \
51+
all-recursive/data \
52+
all/docs/man \
53+
all/docs \
54+
all-recursive/docs \
55+
all/drivers \
56+
all/tools/nut-scanner \
57+
all/tools/nutconf \
58+
all-recursive/tools \
59+
all/lib \
60+
all-recursive/scripts \
61+
all/server \
62+
all/tests/NIT \
63+
all-recursive/tests
64+
65+
# Library creation happens in a number of subdirectories, may be optional
66+
# (e.g. C++ ones are not built without a suitable compiler and enablement).
67+
# List maintenance is aided by this query:
68+
# git grep -E 'LTLIBRARIES' '*.am'
69+
SUBDIRS_ALL_LIBS_LOCAL = \
70+
all-libs-local/clients \
71+
all-libs-local/common \
72+
all-libs-local/drivers \
73+
all-libs-local/tests \
74+
all-libs-local/tools/nut-scanner
75+
76+
# First target often defines default behavior, and in automake is always at least:
77+
# all: all-recursive
78+
# with maybe custom dependencies of "all:" from a Makefile.am tacked on too
79+
# (which used to cause us a lot of headache, building same things twice at
80+
# the same time).
81+
82+
#all all-recursive all-am-local all-local: all-fanout-maybe
83+
all-recursive: all-fanout-maybe
84+
85+
# Run the standard build if going sequential (or with unknown MAKEFLAGS),
86+
# or fanout if parallel (presuming GNU/BSD/Sun make at least):
87+
all-fanout-maybe:
88+
+@if [ x"$(NUT_MAKE_SKIP_FANOUT)" = xtrue ] ; then \
89+
echo " SUBDIR-MAKE $@: skip optimization for parallel make - NUT_MAKE_SKIP_FANOUT is set" ; exit 0 ; \
90+
fi ; \
91+
case "-$(MAKEFLAGS) $(AM_MAKEFLAGS)" in \
92+
*-j|*-j" "*|*-{j,l}{0,1,2,3,4,5,6,7,8,9}*|*-[jl][0123456789]*|*{-l,--jobs,--load-average,--max-load}" "{-,0,1,2,3,4,5,6,7,8,9}*|*--jobserver*|*--jobs" "[0123456789]*|*--load-average" "[0123456789]*|*--max-load" "[0123456789]*) \
93+
echo " SUBDIR-MAKE $@: implement optimization for parallel make as 'make all-fanout-subdirs'" ; \
94+
$(MAKE) $(AM_MAKEFLAGS) all-fanout-subdirs ;; \
95+
*) echo " SUBDIR-MAKE $@: skip optimization for parallel make - we seem to run sequentially now, seen MAKEFLAGS='$(MAKEFLAGS)' AM_MAKEFLAGS='$(AM_MAKEFLAGS)'" ;; \
96+
esac
97+
98+
# We start with a pass to `make all` in `common` dir because our wild recipes
99+
# (with other subdirs ensuring the libraries they need have been built) can
100+
# sometimes cause parallel compilation and library generation for same files
101+
# driven by different make processes that do not know they aim for same goal,
102+
# with some "make" implementations...
103+
# Just in case we followed up with "make doc", since our wild recipes could end
104+
# up writing into same files and so corrupting them (fixes applied, but...)
105+
106+
# FIXME: Alas, we still tend to step on our toes when making everything at
107+
# once from scratch, so still do benefit from pre-making the libraries:
108+
all-fanout-staged:
109+
+$(MAKE) $(AM_MAKEFLAGS) all/include
110+
+$(MAKE) $(AM_MAKEFLAGS) all/common
111+
+$(MAKE) $(AM_MAKEFLAGS) all-fanout-libs
112+
+$(MAKE) $(AM_MAKEFLAGS) all-fanout-subdirs
113+
114+
all-fanout-subdirs: $(SUBDIRS_ALL_RECURSIVE)
115+
116+
all-fanout-libs all-libs-local: $(SUBDIRS_ALL_LIBS_LOCAL)
117+
118+
#all all-am-local all-local:
119+
# +@cd common && $(MAKE) $(AM_MAKEFLAGS) all
120+
# +@$(MAKE) $(AM_MAKEFLAGS) all-recursive
121+
# +@$(MAKE) $(AM_MAKEFLAGS) doc
122+
# +@$(MAKE) $(AM_MAKEFLAGS) doc
29123

30124
bindir = @bindir@
31125
sbindir = @sbindir@
@@ -58,6 +152,122 @@ if KEEP_NUT_REPORT
58152
nodist_data_DATA = config.nut_report_feature.log
59153
endif
60154

155+
# Not too different from automake generated recursive rules at first sight,
156+
# but here we do not loop all subdirs sequentially - instead, a sub-make
157+
# (maybe parallel itself and with parallel flags passed) with a certain
158+
# target in specified dir is the goal, all as separate targets for this
159+
# level's Makefile:
160+
SUBDIR_TGT_RULE = ( \
161+
TGT="`echo '$@' | awk -F/ '{print $$1}'`" ; \
162+
DIR="`echo '$@' | sed 's,^[^/]*/,,'`" ; \
163+
echo " SUBDIR-MAKE STARTING: 'make $$TGT' in $$DIR ..." ; \
164+
cd "$(abs_builddir)/$${DIR}" && \
165+
$(MAKE) $(AM_MAKEFLAGS) "$${TGT}" || { RES=$$?; echo " SUBDIR-MAKE FAILURE: 'make $$TGT' in $$DIR" >&2 ; exit $$RES ; } ; \
166+
echo " SUBDIR-MAKE SUCCESS: 'make $$TGT' in $$DIR" ; \
167+
)
168+
169+
# A way to quickly handle SUBDIRS_ALL_LIBS_LOCAL as dependency for all others
170+
# (aka `make all-libs-local` also in root dir):
171+
all-libs-local/common: all/include
172+
+@$(SUBDIR_TGT_RULE)
173+
174+
all-libs-local/clients: all-libs-local/common
175+
+@$(SUBDIR_TGT_RULE)
176+
177+
all-libs-local/drivers: all-libs-local/common
178+
+@$(SUBDIR_TGT_RULE)
179+
180+
all-libs-local/tests: all-libs-local/common
181+
+@$(SUBDIR_TGT_RULE)
182+
183+
all-libs-local/tools/nut-scanner: all-libs-local/drivers all-libs-local/clients
184+
+@$(SUBDIR_TGT_RULE)
185+
186+
# Handle all SUBDIRS_ALL_RECURSIVE in a way that dependencies can be specified,
187+
# and portably to different make program implementations. Note we may revisit
188+
# some dirs via "all-recursive" of a parent after "all" in them first, but it is
189+
# expected to be a quick no-op (beneficial overall in parallel make situation).
190+
# NOTE: "lib" dir only delivers pkg-config metadata or legacy scripts for any
191+
# third-party development to integrate with NUT libs, no library recipes there.
192+
193+
all/include \
194+
all/conf \
195+
all/docs/man \
196+
all/lib \
197+
all-recursive/data:
198+
+@$(SUBDIR_TGT_RULE)
199+
200+
all/docs:
201+
+@DOCS_NO_MAN=true; export DOCS_NO_MAN; $(SUBDIR_TGT_RULE)
202+
203+
all-recursive/docs: all/docs all/docs/man
204+
+@$(SUBDIR_TGT_RULE)
205+
206+
# Dependencies below are dictated by who needs whose library from another dir
207+
# (generated by a sub-make there, so we pre-emptively ensure it exists to avoid
208+
# conflicts of several make's writing to same files). Aided by this query:
209+
# git grep -E '/[^ ]*\.la([ :]|$)' '*.am'
210+
# It does help to spell out all dependencies, even if transitive, to ensure
211+
# that the top-level make completes needed (all-libs*) targets before drilling.
212+
all/common: all/include all-libs-local/common
213+
+@$(SUBDIR_TGT_RULE)
214+
215+
all/clients: all/common all-libs-local/clients
216+
+@$(SUBDIR_TGT_RULE)
217+
218+
# only libupsclient is needed for dummy-ups,
219+
# but we do wholesale subdir all-libs-local at the moment...
220+
if SOME_DRIVERS
221+
all/drivers: all-libs-local/clients all-libs-local/common
222+
+@$(SUBDIR_TGT_RULE)
223+
else !SOME_DRIVERS
224+
dummy-ups/drivers: all-libs-local/clients all-libs-local/common
225+
+@$(SUBDIR_TGT_RULE)
226+
227+
all/drivers: dummy-ups/drivers all/common all-libs-local/drivers
228+
+@$(SUBDIR_TGT_RULE)
229+
endif !SOME_DRIVERS
230+
231+
all/server: all-libs-local/common
232+
+@$(SUBDIR_TGT_RULE)
233+
234+
all/tools/nut-scanner: all-libs-local/tools/nut-scanner all-libs-local/drivers all-libs-local/common
235+
+@$(SUBDIR_TGT_RULE)
236+
237+
# only libnutscan is needed for nutconf,
238+
# but we do wholesale subdir all-libs-local at the moment...
239+
all/tools/nutconf: all-libs-local/tools/nut-scanner all-libs-local/common
240+
+@$(SUBDIR_TGT_RULE)
241+
242+
all-recursive/tools: all/tools/nutconf all/tools/nut-scanner
243+
+@$(SUBDIR_TGT_RULE)
244+
245+
# At least prereqs for NIT, maybe for certain compiled tests too:
246+
all/tests/NIT: all/clients all/server all/drivers all-recursive/tools all-recursive/data
247+
+@$(SUBDIR_TGT_RULE)
248+
249+
all/tests: all-libs-local/tests all-libs-local/drivers all-libs-local/common all-libs-local/clients
250+
+@$(SUBDIR_TGT_RULE)
251+
252+
all-recursive/tests: all/tests/NIT all/tests
253+
+@$(SUBDIR_TGT_RULE)
254+
255+
if HAVE_MINGW_RESGEN
256+
if HAVE_WINDOWS
257+
all/scripts/Windows: all-libs-local/common
258+
+@$(SUBDIR_TGT_RULE)
259+
else !HAVE_WINDOWS
260+
all/scripts/Windows:
261+
+@$(SUBDIR_TGT_RULE)
262+
endif !HAVE_WINDOWS
263+
else !HAVE_MINGW_RESGEN
264+
all/scripts/Windows:
265+
+@$(SUBDIR_TGT_RULE)
266+
endif !HAVE_MINGW_RESGEN
267+
268+
all-recursive/scripts: all/scripts/Windows
269+
+@$(SUBDIR_TGT_RULE)
270+
61271
# ----------------------------------------------------------------------
62272
# flags to pass to ./configure when calling "make distcheck" and "make
63273
# distcheck-light". Try to check as many features as possible! Also

‎clients/Makefile.am‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,6 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp
180180
# the root Makefile.am takes care of that!
181181
#clean-local:
182182
# $(AM_V_at)rm -rf $(builddir)/.deps
183+
184+
# Helper for only the enabled libs to get built:
185+
all-libs-local: $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) $(EXTRA_LTLIBRARIES)

‎common/Makefile.am‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,6 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp
164164
# the root Makefile.am takes care of that!
165165
#clean-local:
166166
# $(AM_V_at)rm -rf $(builddir)/.deps
167+
168+
# Helper for only the enabled libs to get built:
169+
all-libs-local: $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) $(EXTRA_LTLIBRARIES)

‎docs/.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ nut.dict.sorted
2626
docinfo.xml.in.tmp
2727
/asciidoc-vars.conf.lastrev.tmp
2828
.prep-src-docs*
29+
/.check-pdf
30+
/.check-html-single
31+
/.check-html-chunked

‎docs/Makefile.am‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,15 @@ pdf_DATA = $(ASCIIDOC_PDFS)
215215
endif
216216

217217
# the "for" loops might better use $^ but it might be not portable
218-
check-pdf: $(ASCIIDOC_PDF)
218+
check-pdf: .check-pdf
219+
.check-pdf: $(ASCIIDOC_PDF) Makefile
219220
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
220221
for F in $(ASCIIDOC_PDF) ; do \
221222
test -s "$$F" && { file "$$F" | $(EGREP) -i 'PDF document' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
222223
done; if test -n "$$FAILED" ; then \
223224
echo "FAILED PDF sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
224225
fi; echo "PASSED PDF sanity check"; exit 0
226+
@touch $@
225227

226228
# Regarding ChangeLog check: sometimes asciidoc gives up early
227229
# (we have megabytes of text and thousands of sections here).
@@ -244,7 +246,8 @@ check-pdf: $(ASCIIDOC_PDF)
244246
# (either with different e-mails, or if different author's work
245247
# is interleaved during the day, e.g. many PRs merged, and no
246248
# CHANGELOG_REQUIRE_GROUP_BY_DATE_AUTHOR=true setting was in place.
247-
# NOTE: No dependencies, avoids (re-)generation and log messages.
249+
# NOTE: No dependencies, avoids (re-)generation and log messages
250+
# but causes re-run of the check every time.
248251
ChangeLog.html-contentchecked:
249252
@FAILED=""; \
250253
if [ -s '$(top_builddir)/ChangeLog' ] && [ -s ChangeLog.html ] ; then \
@@ -309,7 +312,8 @@ ChangeLog.html-contentchecked:
309312
fi ; \
310313
exit 1
311314

312-
check-html-single: $(ASCIIDOC_HTML_SINGLE)
315+
check-html-single: .check-html-single
316+
.check-html-single: $(ASCIIDOC_HTML_SINGLE) Makefile
313317
+@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
314318
for F in $(ASCIIDOC_HTML_SINGLE) ; do \
315319
test -s "$$F" && { file "$$F" | $(EGREP) -i '(XML|HTML.*document)' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
@@ -321,8 +325,10 @@ check-html-single: $(ASCIIDOC_HTML_SINGLE)
321325
done; if test -n "$$FAILED" ; then \
322326
echo "FAILED HTML-single sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
323327
fi; echo "PASSED HTML-single sanity check"; exit 0
328+
@touch $@
324329

325-
check-html-chunked: $(ASCIIDOC_HTML_CHUNKED)
330+
check-html-chunked: .check-html-chunked
331+
.check-html-chunked: $(ASCIIDOC_HTML_CHUNKED) Makefile
326332
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
327333
for D in $(ASCIIDOC_HTML_CHUNKED); do \
328334
for F in "$$D"/*.html ; do \
@@ -334,19 +340,25 @@ check-html-chunked: $(ASCIIDOC_HTML_CHUNKED)
334340
done; if test -n "$$FAILED" ; then \
335341
echo "FAILED HTML-chunked sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
336342
fi; echo "PASSED HTML-chunked sanity check"; exit 0
343+
@touch $@
337344

338345
# Note: usually the results from man-page check will be reported twice:
339346
# once as a SUBDIRS child makefile, and once via DOC_CHECK_LIST expansion
340347
# Note: default `make all` in the man directory caters to drivers etc.
341348
# chosen during configure script execution. The "all-man" and "all-html"
342349
# rules build everything documented.
350+
# NOTE; we rig it up with a DOCS_NO_MAN option to simplify parallel work
351+
# from top-level Makefile, while allowing legacy "cd docs && make" to
352+
# still do the right thing by default :)
343353
check-man check-man-man all-man man-man all-html html-man:
344-
+cd $(abs_top_builddir)/docs/man/ && $(MAKE) $(AM_MAKEFLAGS) -f Makefile $@
354+
+@if [ x"$(DOCS_NO_MAN)" = xtrue ] ; then echo " DOC-NOT-MAN SKIP: $@ called in docs/Makefile" ; exit 0 ; fi ; \
355+
cd $(abs_top_builddir)/docs/man/ && $(MAKE) $(AM_MAKEFLAGS) -f Makefile $@
345356

346357
man:
347-
+cd $(abs_top_builddir)/docs/man/ && $(MAKE) $(AM_MAKEFLAGS) -f Makefile all
358+
+@if [ x"$(DOCS_NO_MAN)" = xtrue ] ; then echo " DOC-NOT-MAN SKIP: $@ called in docs/Makefile" ; exit 0 ; fi ; \
359+
cd $(abs_top_builddir)/docs/man/ && $(MAKE) $(AM_MAKEFLAGS) -f Makefile all
348360

349-
CLEANFILES = *.xml *.html *.pdf *-spellchecked *-contentchecked docbook-xsl.css docinfo.xml.in.tmp
361+
CLEANFILES = *.xml *.html *.pdf *-spellchecked *-contentchecked .check-* docbook-xsl.css docinfo.xml.in.tmp
350362
CLEANFILES += $(top_builddir)/INSTALL.nut $(top_builddir)/UPGRADING $(top_builddir)/NEWS $(top_builddir)/ChangeLog.adoc $(top_builddir)/README
351363
CLEANFILES += $(top_builddir)/*.adoc-parsed *.adoc-parsed
352364

‎docs/man/.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@
1111
/tmp/
1212
/linkman-driver-names.txt
1313
/linkman-drivertool-names.txt
14+
/.check-html-man
15+
/.check-man-pages
16+
/.check-man-txt

0 commit comments

Comments
 (0)