-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMakefile
381 lines (348 loc) · 14.8 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
SHELL = /bin/sh
## Copyright 2015 Oliver Heimlich
##
## Copying and distribution of this file, with or without modification,
## are permitted in any medium without royalty provided the copyright
## notice and this notice are preserved. This file is offered as-is,
## without any warranty.
## This file helps the package maintainer to
## 1. run the development version
## 2. check that all tests pass
## 3. prepare the release
##
## This Makefile is _not_ meant to be portable. In order to use it, you
## have to install certain dependencies. This file is not distributed in
## the release tarball, so its dependencies must be met by developers only.
OCTAVE ?= octave
OCTAVE_CONFIG ?= octave-config
MKOCTFILE ?= mkoctfile -Wall
ZOPFLI ?= $(shell which zopfli 2> /dev/null)
PACKAGE = $(shell grep "^Name: " DESCRIPTION | cut -f2 -d" ")
VERSION = $(shell grep "^Version: " DESCRIPTION | cut -f2 -d" ")
DATE = $(shell grep "^Date: " DESCRIPTION | cut -f2 -d" ")
HG_ID = $(shell hg identify --id)
HG_DATETIME_LOCAL = $(shell hg log --rev . --template {date\|isodatesec})
HG_DATETIME_UTC = $(shell date --utc --rfc-3339=seconds --date="$(HG_DATETIME_LOCAL)")
TAR_REPRODUCIBLE_OPTIONS = --mtime="$(HG_DATETIME_UTC)" --mode=a+r,g-w,o-w --owner=root --group=root --numeric-owner
OCTAVE_REPRODUCIBLE_OPTIONS = \
--norc \
--silent \
--no-history \
--no-gui \
--eval "rand ('state', double ('reproducible')');"
OCTAVE_INSTALL_MISSING = \
$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) \
--eval "if isempty (pkg ('list', 'PKG')), \
disp (' [OCTAVE] pkg install PKG'); \
pkg install -forge -local PKG; \
endif;"
.PHONY: help
help:
@echo
@echo "Usage:"
@echo " make dist Create $(PACKAGE)-$(VERSION).tar.gz for release"
@echo " make html Create $(PACKAGE)-html.tar.gz for release"
@echo " make release Create both of the above plus md5 sums"
@echo
@echo " make install Install the release in GNU Octave"
@echo " make check Validate the package (w/o install)"
@echo " make run Run the package in GNU Octave (w/o install)"
@echo
@echo " make clean Cleanup"
@echo
.PHONY: clean
clean:
$(RM) -r .build .dist .html
##
## PART A: Produce the release tarball
##
## This happens in a temporary directory ./.dist/
##
## Generated Autotool files
CRLIBM_AUTOTOOLS_OBJ = \
src/crlibm/aclocal.m4 \
src/crlibm/configure \
src/crlibm/config.guess \
src/crlibm/config.sub \
src/crlibm/install-sh \
src/crlibm/Makefile.in \
src/crlibm/scs_lib/Makefile.in \
src/crlibm/crlibm_config.h.in \
src/crlibm/missing \
src/crlibm/INSTALL \
src/crlibm/compile
DIST_CRLIBM_AUTOTOOLS_OBJ = $(addprefix .dist/,$(CRLIBM_AUTOTOOLS_OBJ))
.dist/src/configure: src/configure.ac
@echo " [AUTOTOOLS] src/"
@mkdir -p .dist/src
@( cd .dist/src && \
ln -sf ../../src/configure.ac . && \
VERSION=$(VERSION) autoconf \
)
.NOTPARALLEL: $(DIST_CRLIBM_AUTOTOOLS_OBJ)
$(DIST_CRLIBM_AUTOTOOLS_OBJ): src/crlibm/configure.ac src/crlibm/Makefile.am src/crlibm/scs_lib/Makefile.am
@echo " [AUTOTOOLS] src/crlibm/"
@mkdir -p .dist/src/crlibm/scs_lib
@( cd .dist/src/crlibm/scs_lib && \
ln -sf ../../../../src/crlibm/scs_lib/Makefile.am . \
)
@( cd .dist/src/crlibm && \
ln -sf $(addprefix ../../../,\
src/crlibm/configure.ac \
src/crlibm/Makefile.am \
src/crlibm/AUTHORS \
src/crlibm/ChangeLog \
src/crlibm/COPYING.LIB \
src/crlibm/NEWS \
src/crlibm/README) . && \
aclocal && \
autoheader && \
automake --add-missing -c --ignore-deps && \
autoconf \
)
@touch --no-create $(DIST_CRLIBM_AUTOTOOLS_OBJ)
## Generated graphic files
IMAGE_SRC = $(filter-out %animation.svg,$(wildcard doc/image/*.svg))
IMAGE_OBJ = $(addsuffix .eps,$(IMAGE_SRC)) $(addsuffix .pdf,$(IMAGE_SRC)) $(addsuffix .png,$(IMAGE_SRC))
DIST_IMAGE_OBJ = $(addprefix .dist/,$(IMAGE_OBJ))
.dist/doc/image/%.svg.png: .dist/doc/image/%.svg.pdf
@# The output of pdftocairo has a much better quality
@# compared to the output from inkscape --export-png.
@echo " [PDFTOCAIRO] $<"
@pdftocairo -png -singlefile -transp -r 120 "$<" ".dist/doc/image/$*.svg"
.dist/doc/image/%.svg.eps: doc/image/%.svg
@mkdir -p .dist/doc/image
@echo " [INKSCAPE --export-type=eps] $<"
@inkscape --batch-process \
--export-ignore-filters \
--export-type=eps \
--export-filename="$@" \
"$<" > /dev/null
@# Make the build reproducible and remove timestamp metadata
@grep --invert-match "^%% CreationDate: " "$@" > "$@_"
@mv "$@_" "$@"
.dist/doc/image/%.svg.pdf: doc/image/%.svg
@mkdir -p .dist/doc/image
@echo " [INKSCAPE --export-type=pdf] $<"
@inkscape --batch-process \
--export-ignore-filters \
--export-type=pdf \
--export-filename="$@" \
"$<" > /dev/null
## Generated text files
TEXT_OBJ = COPYING CITATION NEWS
DIST_TEXT_OBJ = $(addprefix .dist/,$(TEXT_OBJ))
.dist/%: doc/%.texinfo
@echo " [MAKEINFO] $<"
@mkdir -p .dist
@makeinfo --plaintext -D "version $(VERSION)" -D "date $(DATE)" --output="$@" "$<"
## For the release tarball, we can take most files from version control and
## exclude:
## - .hgignore and .hgtags
## - some maintainer scripts
## - crlibm test code (it is already included in crlibm.mat
## and would take a lot of space)
## In addition, generated files are patched into the release tarball. Since
## hg and tar are very fast, we can simply recreate the tarball from scratch.
.dist/$(PACKAGE)-$(VERSION).tar: .hg/dirstate .dist/src/configure $(DIST_CRLIBM_AUTOTOOLS_OBJ) $(DIST_IMAGE_OBJ) $(DIST_TEXT_OBJ)
@echo " [HG] archive"
@hg archive --exclude ".hg*" --exclude "Makefile" --exclude "*.sh" --exclude "src/crlibm/tests" "$@"
@# Make tries to re-run automake on the target system (during installation
@# of the Octave package) if automake artefacts are older than their source
@# files. Prevent this by applying the timestamp of the source code
@# revision, which is the same that is used by “hg archive”.
@echo " [TAR --update] $@"
@tar $(TAR_REPRODUCIBLE_OPTIONS) --update --file "$@" --transform="s!^.dist/!$(PACKAGE)-$(VERSION)/!" $(wordlist 2,$(words $^),$^)
## Compress the tarball for smaller download size.
## Zopfli can create smaller files that gzip.
.PHONY: dist
dist: .dist/$(PACKAGE)-$(VERSION).tar.gz
.dist/$(PACKAGE)-$(VERSION).tar.gz: .dist/$(PACKAGE)-$(VERSION).tar
ifneq ($(ZOPFLI),)
%.gz: %
@echo " [ZOPFLI] $<"
@$(ZOPFLI) --i10 "$<"
else
%.gz: %
@echo " [GZIP] $<"
@gzip --best -f -k "$<"
@touch "$@"
endif
##
## Part B: Create HTML documentation for publication on Octave Forge
##
## Installs the package in Octave and partly happens in the user's pkg dir,
## the result is put in a temporary directory ./.html/
##
## Install the release tarball in Octave
OCTAVE_PKG_PREFIX = $(HOME)/octave
INSTALLED_PACKAGE = $(OCTAVE_PKG_PREFIX)/$(PACKAGE)-$(VERSION)/packinfo/DESCRIPTION
.PHONY: install
install: $(INSTALLED_PACKAGE)
$(INSTALLED_PACKAGE): .dist/$(PACKAGE)-$(VERSION).tar
@echo " [OCTAVE] pkg install $(PACKAGE)"
@$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) \
--eval "pkg install -local $<"
## Create HTML Documentation from scratch
.PHONY: html
html: .html/$(PACKAGE)-html.tar.gz
.html/$(PACKAGE)-html.tar.gz: $(INSTALLED_PACKAGE)
@$(subst PKG,generate_html,$(OCTAVE_INSTALL_MISSING))
@# Compile images from m-file scripts in the installed package.
@# These are not shipped in the release tarball.
@echo " [MAKE] doc/images/*.m"
@OCTAVE="$(OCTAVE) $(subst ",\",$(OCTAVE_REPRODUCIBLE_OPTIONS))" $(MAKE) --directory="$(OCTAVE_PKG_PREFIX)/$(PACKAGE)-$(VERSION)/doc" images
@# Create manual and function reference
@# - Use off-screen rendering (for demos)
@# - Specify path to package manual
@# - Use custom CSS and global version number
@# (only affects package manual, not function reference)
@echo " [OCTAVE] generate_package_html"
@$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) \
--eval "pkg load generate_html;" \
--eval "set (0, 'defaultfigurevisible', 'off');" \
--eval "options = get_html_options ('octave-forge');" \
--eval "options.package_doc = 'manual.texinfo';" \
--eval "options.package_doc_options = '-D ''version $(VERSION)'' -D octave-forge --set-customization-variable ''TOP_NODE_UP_URL ../index.html'' --set-customization-variable ''PRE_BODY_CLOSE <div id="sf_logo"><a href=\"https://sourceforge.net/\"><img width=\"120\" height=\"30\" style=\"border:0\" alt=\"Sourceforge.net Logo\" src=\"https://sourceforge.net/sflogo.php?group_id=2888&type=13\" /></a></div>'' --css-ref=manual.css';" \
--eval "generate_package_html ('$(PACKAGE)', '.html', options)"
@# Documentation will be put on a webserver,
@# where .svgz files can save bandwidth and CPU time.
@# Locally this doesn't work so well, see https://bugzilla.mozilla.org/show_bug.cgi?id=52282
@echo " [GZIP] package_doc/image/*.svg"
@( cd .html/$(PACKAGE)/package_doc/image/; \
gzip --best -f *.svg; \
rename -f 's!\.svg\.gz!.svgz!' *.svg.gz)
@echo " [SED] package_doc/*.html"
@(cd .html/$(PACKAGE)/package_doc/; \
sed -i 's!"\(image/[^"]*\.svg\)"!"\1z"!g' *.html)
@echo " [TAR --create] .html/$(PACKAGE)/"
@tar --create --auto-compress --transform="s!^.html/!!" --file "$@" .html/$(PACKAGE)/
## The release consists of the tarball from part A and the HTML documentation
## for Octave Forge. Revision numbers and hash values are used to tag and
## verify the upload.
.PHONY: release
release: .dist/$(PACKAGE)-$(VERSION).tar.gz .html/$(PACKAGE)-html.tar.gz
@echo "Source Revision: $(HG_ID)"
@( case "$(HG_ID)" in *+ ) \
echo "You have uncommitted changes!";; \
esac \
)
@md5sum $^
@echo "Upload @ https://sourceforge.net/p/octave/package-releases/new/"
@echo "The Octave Forge admins will tag this revision after publication."
##
## Part C: (Interactive) tests during development
##
## There is no need to install the package. Generated files (see part A) and
## compiled OCT files can be rebuild incrementally, which is fast. OCT files
## are compiled in a temporary directory .build, from where they can be loaded.
##
## Mirror generated .dist files for compilation in .build
.build/configure: .build/%: .dist/src/%
@mkdir -p .build
@ln -sf ../$< $@
$(patsubst src/%,.build/%,$(filter-out src/crlibm/scs_lib/%,$(CRLIBM_AUTOTOOLS_OBJ))): .build/%: .dist/src/%
@mkdir -p .build/crlibm
@ln -sf ../../$< $@
.build/crlibm/scs_lib/Makefile.in: .build/%: .dist/src/%
@mkdir -p .build/crlibm/scs_lib
@ln -sf ../../../$< $@
## If the src/Makefile changes, recompile all oct-files
$(wildcard src/*.cc): src/Makefile
@touch --no-create "$@"
## Mirror any workspace src/* files in .build and compile OCT files
OCT_COMPILED = .build/.oct
$(OCT_COMPILED): $(wildcard src/*) $(wildcard src/compatibility/*) .build/configure $(patsubst src/%,.build/%,$(CRLIBM_AUTOTOOLS_OBJ))
@mkdir -p .build/compatibility
@ln -sf $(addprefix ../,$(filter-out src/crlibm src/compatibility,$(wildcard src/*))) .build/
@ln -sf $(addprefix ../../,$(wildcard src/compatibility/*)) .build/compatibility/
@ln -sf $(addprefix ../../,$(filter-out src/crlibm/scs_lib,$(wildcard src/crlibm/*))) .build/crlibm/
@ln -sf $(addprefix ../../../,$(wildcard src/crlibm/scs_lib/*)) .build/crlibm/scs_lib/
@echo " [MAKE] src"
@OCTAVE="$(OCTAVE) $(subst ",\",$(OCTAVE_REPRODUCIBLE_OPTIONS))" OCTAVE_CONFIG="$(OCTAVE_CONFIG)" MKOCTFILE="$(MKOCTFILE)" $(MAKE) --directory=.build
@touch $@
## Octave parameters to make M files and compiled OCT files available
OCTAVE_WORKSPACE_PATH = --path "inst/" --path ".build/"
## Interactive shell with the current workspace functions in the path
.PHONY: run
run: $(OCT_COMPILED)
@$(OCTAVE) $(OCTAVE_WORKSPACE_PATH) --no-gui --silent
@echo
## Run built-in self tests (BISTs)
.PHONY: test
test: $(OCT_COMPILED)
@echo " [OCTAVE] test"
@$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) $(OCTAVE_WORKSPACE_PATH) \
--eval 'success = true;' \
--eval 'for file = {dir("./src/*.cc").name}, success &= test (file{1}, "quiet", stdout); endfor;' \
--eval 'for file = {dir("./inst/*.m").name}, success &= test (file{1}, "quiet", stdout); endfor;' \
--eval 'for file = {dir("./inst/test/*.tst").name}, success &= test (strcat ("test/", file{1}), "quiet", stdout); endfor;' \
--eval 'for file = {dir("./inst/@infsup/*.m").name}, success &= test (strcat ("@infsup/", file{1}), "quiet", stdout); endfor;' \
--eval 'for file = {dir("./inst/@infsupdec/*.m").name}, success &= test (strcat ("@infsupdec/", file{1}), "quiet", stdout); endfor;' \
--eval 'exit (not (success));'
## Validate code examples from the package manual.
## Workaround for OctSymPy issue 273, we must pre-initialize the package.
## Otherwise, it will make the doctests fail.
.PHONY: doctest-manual
doctest-manual: $(OCT_COMPILED)
@$(subst PKG,doctest,$(OCTAVE_INSTALL_MISSING))
@$(subst PKG,symbolic,$(OCTAVE_INSTALL_MISSING))
@echo " [OCTAVE] doctest doc/"
@$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) $(OCTAVE_WORKSPACE_PATH) \
--eval \
"pkg load doctest; \
pkg load symbolic; warning ('off', 'OctSymPy:function_handle:nocodegen'); sym ('x'); \
set (0, 'defaultfigurevisible', 'off'); \
warning ('off', 'backtrace'); \
makeinfo_program (cstrcat (makeinfo_program (), ' -I doc/')); \
targets = '$(shell find doc/ -name "*.texinfo")'; \
targets = strsplit (targets, ' '); \
success = doctest (targets); \
exit (!success)"
## Validate code examples from documentation strings.
.PHONY: doctest-docstrings
doctest-docstrings: $(OCT_COMPILED)
@$(subst PKG,doctest,$(OCTAVE_INSTALL_MISSING))
@echo " [OCTAVE] doctest"
@$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) $(OCTAVE_WORKSPACE_PATH) \
--eval \
"pkg load doctest; \
set (0, 'defaultfigurevisible', 'off'); \
warning ('off', 'backtrace'); \
targets = '@infsup @infsupdec $(shell find inst/ src/ -maxdepth 1 -regex ".*\\.\\(m\\|oct\\)" -printf "%f\\n" | cut -f1 -d.)'; \
targets = strsplit (targets, ' '); \
success = doctest (targets); \
exit (!success)"
.PHONY: doctest
doctest: doctest-docstrings doctest-manual
.PHONY: check-duplicates
check-duplicates: $(INSTALLED_PACKAGE)
@$(subst PKG,generate_html,$(OCTAVE_INSTALL_MISSING))
@echo " [OCTAVE] check_duplicates"
@$(OCTAVE) $(OCTAVE_REPRODUCIBLE_OPTIONS) \
--eval \
"pkg load generate_html; \
success = isempty (check_duplicates ('$(PACKAGE)', struct ('text_only', true))); \
exit (!success)"
.PHONY: check
check: doctest test check-duplicates
##
## Part D: Miscellaneous utilities
##
## GNU LilyPond graphics
## This is an exotic dependency for an Octave package, so the generated SVG
## is under version control and only gets recreated when LilyPond is installed.
LILYPOND ?= $(shell which lilypond 2> /dev/null)
ifneq ($(LILYPOND),)
doc/image/%.svg: doc/image/%.ly
@mkdir -p .build/doc/image
@echo " [LILYPOND] $<"
@# .ly -> .eps
@$(LILYPOND) --ps --output ".build/$<" --silent "$<"
@# .eps -> .pdf (with size optimizations)
@epstopdf ".build/$<.eps"
@# .pdf -> .ps (convert font glyphs to outline shapes)
@gs -q -o ".build/$<.ps" -dNOCACHE -sDEVICE=ps2write ".build/$<.pdf"
@# .ps -> .svg
@inkscape --batch-process --export-ignore-filters --export-filename="$@" --export-type=svg ".build/$<.ps"
endif