• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014-2024 The Khronos Group Inc.
2#
3# SPDX-License-Identifier: Apache-2.0
4
5# Vulkan Specification makefile
6#
7# To build the spec with a specific version included, set the
8# $(VERSIONS) variable on the make command line to a space-separated
9# list of version names (e.g. VK_VERSION_1_3) *including all previous
10# versions of the API* (e.g. VK_VERSION_1_1 must also include
11# VK_VERSION_1_0 and VKSC_VERSION_1_0 must also include VK_VERSION_1_2,
12# VK_VERSION_1_1 & VK_VERSION_1_0). $(VERSIONS) is converted into generator
13# script arguments $(VERSIONOPTIONS) and into $(ATTRIBFILE)
14#
15# To build the specification / reference pages (refpages) with optional
16# extensions included, set the $(EXTENSIONS) variable on the make
17# command line to a space-separated list of extension names.
18# $(EXTENSIONS) is converted into generator script
19# arguments $(EXTOPTIONS) and into $(ATTRIBFILE)
20
21# If a recipe fails, delete its target file. Without this cleanup, the leftover
22# file from the failed recipe can falsely satisfy dependencies on subsequent
23# runs of `make`.
24.DELETE_ON_ERROR:
25
26# Support building both Vulkan and Vulkan SC APIs
27# Allow the API to be overridden by the VULKAN_API environment variable
28# supported options are 'vulkan' and 'vulkansc' or unset
29# default to 'vulkan'
30VULKAN_API ?= vulkan
31ifeq ($(VULKAN_API),vulkan)
32VERSIONS := VK_VERSION_1_0 VK_VERSION_1_1 VK_VERSION_1_2 VK_VERSION_1_3
33else
34VERSIONS := VK_VERSION_1_0 VK_VERSION_1_1 VK_VERSION_1_2 VKSC_VERSION_1_0
35endif
36VERSIONOPTIONS := $(foreach version,$(VERSIONS),-feature $(version))
37
38EXTS := $(sort $(EXTENSIONS) $(DIFFEXTENSIONS))
39EXTOPTIONS := $(foreach ext,$(EXTS),-extension $(ext))
40
41# APITITLE can be set to extra text to append to the document title,
42# normally used when building with extensions included.
43APITITLE =
44
45# IMAGEOPTS is normally set to generate inline SVG images, but can be
46# overridden to an empty string, since the inline option does not work
47# well with our HTML diffs.
48IMAGEOPTS = inline
49
50# The default 'all' target builds the following sub-targets:
51#  html - HTML single-page API specification
52#  pdf - PDF single-page API specification
53#  styleguide - HTML5 single-page "Documentation and Extensions" guide
54#  registry - HTML5 single-page XML Registry Schema documentation
55#  manhtml - HTML5 single-page reference guide - NOT SUPPORTED
56#  manpdf - PDF reference guide - NOT SUPPORTED
57#  manhtmlpages - HTML5 separate per-feature refpages
58#  allchecks - checks for style guide compliance, XML consistency,
59#   internal link validity, and other easy to catch errors.
60
61all: alldocs allchecks
62
63alldocs: allspecs allman proposals
64
65allspecs: html pdf styleguide registry
66
67allman: manhtmlpages
68
69# Invokes all the automated checks, but CHECK_XREFS can be set to empty
70# on the command line to avoid building an HTML spec target.
71CHECK_XREFS = check-xrefs
72ifeq ($(VULKAN_API),vulkansc)
73CHECK_XREFS =
74endif
75allchecks: check-copyright-dates \
76    check-contractions \
77    check-spelling \
78    check-writing \
79    check-bullets \
80    check-reflow \
81    check-links \
82    check-consistency \
83    check-undefined \
84    check-txtfiles \
85    $(CHECK_XREFS)
86
87QUIET	 ?= @
88VERYQUIET?= @
89PYTHON	 ?= python3
90ASCIIDOC ?= asciidoctor
91RUBY	 = ruby
92NODEJS	 = node
93PATCH	 = patch
94RM	 = rm -f
95RMRF	 = rm -rf
96MKDIR	 = mkdir -p
97CP	 = cp
98ECHO	 = echo
99
100# Where the repo root is
101ROOTDIR        = $(CURDIR)
102# Where the spec files are
103SPECDIR        = $(CURDIR)
104
105# Path to scripts used in generation
106SCRIPTS  = $(ROOTDIR)/scripts
107# Path to configs and asciidoc extensions used in generation
108CONFIGS  = $(ROOTDIR)/config
109
110# Target directories for output files
111# HTMLDIR - 'html' target
112# PDFDIR - 'pdf' target
113OUTDIR	  = $(GENERATED)/out
114HTMLDIR   = $(OUTDIR)/html
115VUDIR	  = $(OUTDIR)/validation
116PDFDIR	  = $(OUTDIR)/pdf
117PROPOSALDIR = $(OUTDIR)/proposals
118JSAPIMAP  = $(GENERATED)/apimap.cjs
119PYAPIMAP  = $(GENERATED)/apimap.py
120RBAPIMAP  = $(GENERATED)/apimap.rb
121
122# PDF Equations are written to SVGs, this dictates the location to store those files (temporary)
123PDFMATHDIR = $(OUTDIR)/equations_temp
124
125# Set VERBOSE to -v to see what asciidoc is doing.
126VERBOSE =
127
128# asciidoc attributes to set (defaults are usually OK)
129# NOTEOPTS sets options controlling which NOTEs are generated
130# PATCHVERSION must equal VK_HEADER_VERSION from vk.xml
131# SCPATCHVERSION is specific to the Vulkan SC spec
132# ATTRIBOPTS sets the API revision and enables KaTeX generation
133# EXTRAATTRIBS sets additional attributes, if passed to make
134# ADOCMISCOPTS miscellaneous options controlling error behavior, etc.
135# ADOCEXTS asciidoctor extensions to load
136# ADOCOPTS options for asciidoc->HTML5 output
137
138NOTEOPTS     = -a editing-notes -a implementation-guide
139PATCHVERSION = 275
140BASEOPTS     =
141
142ifneq (,$(findstring VKSC_VERSION_1_0,$(VERSIONS)))
143VKSPECREVISION := 1.2.$(PATCHVERSION)
144SCPATCHVERSION = 14
145SPECREVISION = 1.0.$(SCPATCHVERSION)
146BASEOPTS = -a baserevnumber="$(VKSPECREVISION)"
147else
148
149ifneq (,$(findstring VK_VERSION_1_3,$(VERSIONS)))
150SPECMINOR = 3
151else
152ifneq (,$(findstring VK_VERSION_1_2,$(VERSIONS)))
153SPECMINOR = 2
154else
155ifneq (,$(findstring VK_VERSION_1_1,$(VERSIONS)))
156SPECMINOR = 1
157else
158SPECMINOR = 0
159endif
160endif
161endif
162
163SPECREVISION = 1.$(SPECMINOR).$(PATCHVERSION)
164endif
165
166# Spell out ISO 8601 format as not all date commands support --rfc-3339
167SPECDATE     = $(shell echo `date -u "+%Y-%m-%d %TZ"`)
168
169# Generate Asciidoc attributes for spec remark
170# Could use `git log -1 --format="%cd"` to get branch commit date
171# This used to be a dependency in the spec html/pdf targets,
172# but that is likely to lead to merge conflicts. Just regenerate
173# when pushing a new spec for review to the sandbox.
174# The dependency on HEAD is per the suggestion in
175# http://neugierig.org/software/blog/2014/11/binary-revisions.html
176SPECREMARK = from git branch: $(shell echo `git symbolic-ref --short HEAD 2> /dev/null || echo Git branch not available`) \
177	     commit: $(shell echo `git log -1 --format="%H" 2> /dev/null || echo Git commit not available`)
178
179# Some of the attributes used in building all spec documents:
180#   chapters - absolute path to chapter sources
181#   appendices - absolute path to appendix sources
182#   proposals - absolute path to proposal sources
183#   images - absolute path to images
184#   generated - absolute path to generated sources
185#   refprefix - controls which generated extension metafiles are
186#	included at build time. Must be empty for specification,
187#	'refprefix.' for refpages (see ADOCREFOPTS below).
188ATTRIBOPTS   = -a revnumber="$(SPECREVISION)" $(BASEOPTS) \
189	       -a revdate="$(SPECDATE)" \
190	       -a revremark="$(SPECREMARK)" \
191	       -a apititle="$(APITITLE)" \
192	       -a stem=latexmath \
193	       -a imageopts="$(IMAGEOPTS)" \
194	       -a config=$(ROOTDIR)/config \
195	       -a appendices=$(SPECDIR)/appendices \
196	       -a proposals=$(SPECDIR)/proposals \
197	       -a chapters=$(SPECDIR)/chapters \
198	       -a images=$(IMAGEPATH) \
199	       -a generated=$(GENERATED) \
200	       -a refprefix \
201	       $(EXTRAATTRIBS)
202ADOCMISCOPTS = --failure-level ERROR
203# Non target-specific Asciidoctor extensions and options
204# Look in $(GENERATED) for explicitly required non-extension Ruby, such
205# as apimap.rb
206ADOCEXTS     = -I$(GENERATED) \
207	       -r $(CONFIGS)/spec-macros.rb \
208	       -r $(CONFIGS)/open_listing_block.rb \
209	       -r $(CONFIGS)/ifdef-mismatch.rb
210ADOCOPTS     = -d book $(ADOCMISCOPTS) $(ATTRIBOPTS) $(NOTEOPTS) $(VERBOSE) $(ADOCEXTS)
211
212# HTML target-specific Asciidoctor extensions and options
213ADOCHTMLEXTS = -r $(CONFIGS)/katex_replace.rb \
214	       -r $(CONFIGS)/loadable_html.rb \
215	       -r $(CONFIGS)/vuid-expander.rb \
216	       -r $(CONFIGS)/rouge-extend-css.rb \
217	       -r $(CONFIGS)/genanchorlinks.rb
218
219# ADOCHTMLOPTS relies on the relative runtime path from the output HTML
220# file to the katex scripts being set with KATEXDIR. This is overridden
221# by some targets.
222# KaTeX source is copied from KATEXSRCDIR in the repository to
223# KATEXINSTDIR in the output directory.
224# KATEXDIR is the relative path from a target to KATEXINSTDIR, since
225# that is coded into CSS, and set separately for each HTML target.
226# ADOCHTMLOPTS also relies on the absolute build-time path to the
227# 'stylesdir' containing our custom CSS.
228KATEXSRCDIR  = $(ROOTDIR)/katex
229KATEXINSTDIR = $(OUTDIR)/katex
230ADOCHTMLOPTS = $(ADOCHTMLEXTS) -a katexpath=$(KATEXDIR) \
231	       -a stylesheet=khronos.css \
232	       -a stylesdir=$(ROOTDIR)/config \
233	       -a sectanchors
234
235# PDF target-specific Asciidoctor extensions and options
236ADOCPDFEXTS  = -r asciidoctor-pdf \
237	       -r asciidoctor-mathematical \
238	       -r $(CONFIGS)/asciidoctor-mathematical-ext.rb \
239	       -r $(CONFIGS)/vuid-expander.rb
240ADOCPDFOPTS  = $(ADOCPDFEXTS) -a mathematical-format=svg \
241	       -a imagesoutdir=$(PDFMATHDIR) \
242	       -a pdf-fontsdir=$(CONFIGS)/fonts,GEM_FONTS_DIR \
243	       -a pdf-stylesdir=$(CONFIGS)/themes -a pdf-style=pdf
244
245# Valid usage-specific Asciidoctor extensions and options
246ADOCVUEXTS = -r $(CONFIGS)/vu-to-json.rb -r $(CONFIGS)/quiet-include-failure.rb
247# {vuprefix} precedes some anchors which are otherwise encountered twice
248# by the validusage extractor.
249# {attribute-missing} overrides the global setting, since the extractor
250# reports a lot of false-flag warnings otherwise.
251ADOCVUOPTS = $(ADOCVUEXTS) -a vuprefix=vu- -a attribute-missing=skip
252
253.PHONY: directories
254
255# Images used by the spec. These are included in generated HTML now.
256IMAGEPATH = $(SPECDIR)/images
257SVGFILES  = $(wildcard $(IMAGEPATH)/*.svg)
258
259# Top-level spec source file
260SPECSRC        = $(SPECDIR)/vkspec.adoc
261# Static files making up sections of the API spec.
262SPECFILES = $(wildcard $(SPECDIR)/chapters/[A-Za-z]*.adoc $(SPECDIR)/chapters/*/[A-Za-z]*.adoc $(SPECDIR)/appendices/[A-Za-z]*.adoc)
263# Shorthand for where different types generated files go.
264# All can be relocated by overriding GENERATED in the make invocation.
265GENERATED      = $(CURDIR)/gen
266REFPATH        = $(GENERATED)/refpage
267APIPATH        = $(GENERATED)/api
268VALIDITYPATH   = $(GENERATED)/validity
269HOSTSYNCPATH   = $(GENERATED)/hostsynctable
270METAPATH       = $(GENERATED)/meta
271INTERFACEPATH  = $(GENERATED)/interfaces
272SPIRVCAPPATH   = $(GENERATED)/spirvcap
273FORMATSPATH    = $(GENERATED)/formats
274SYNCPATH       = $(GENERATED)/sync
275PROPOSALPATH   = $(SPECDIR)/proposals
276# timeMarker is a proxy target created when many generated files are
277# made at once
278APIDEPEND      = $(APIPATH)/timeMarker
279VALIDITYDEPEND = $(VALIDITYPATH)/timeMarker
280HOSTSYNCDEPEND = $(HOSTSYNCPATH)/timeMarker
281METADEPEND     = $(METAPATH)/timeMarker
282INTERFACEDEPEND = $(INTERFACEPATH)/timeMarker
283SPIRVCAPDEPEND = $(SPIRVCAPPATH)/timeMarker
284FORMATSDEPEND = $(FORMATSPATH)/timeMarker
285SYNCDEPEND = $(SYNCPATH)/timeMarker
286RUBYDEPEND     = $(RBAPIMAP)
287ATTRIBFILE     = $(GENERATED)/specattribs.adoc
288# All generated dependencies
289GENDEPENDS     = $(APIDEPEND) $(VALIDITYDEPEND) $(HOSTSYNCDEPEND) $(METADEPEND) $(INTERFACEDEPEND) $(SPIRVCAPDEPEND) $(FORMATSDEPEND) $(SYNCDEPEND) $(RUBYDEPEND) $(ATTRIBFILE)
290# All non-format-specific dependencies
291COMMONDOCS     = $(SPECFILES) $(GENDEPENDS)
292
293# Script to translate math on build time
294TRANSLATEMATH = $(NODEJS) $(SCRIPTS)/translate_math.js $(KATEXSRCDIR)/katex.min.js
295
296# Install katex in KATEXINSTDIR ($(OUTDIR)/katex) to be shared by all
297# HTML targets.
298# We currently only need the css and fonts, but copy all of KATEXSRCDIR anyway.
299$(KATEXINSTDIR): $(KATEXSRCDIR)
300	$(QUIET)$(MKDIR) $(KATEXINSTDIR)
301	$(QUIET)$(RMRF)  $(KATEXINSTDIR)
302	$(QUIET)$(CP) -rf $(KATEXSRCDIR) $(KATEXINSTDIR)
303
304# Spec targets
305# There is some complexity to try and avoid short virtual targets like 'html'
306# causing specs to *always* be regenerated.
307
308CHUNKER = $(SCRIPTS)/asciidoctor-chunker/asciidoctor-chunker.js
309CHUNKINDEX = $(CONFIGS)/chunkindex
310# Only the $(CHUNKER) step is required unless the search index is to be
311# generated and incorporated into the chunked spec.
312#
313# Dropped $(QUIET) for now
314# Should set NODE_PATH=/usr/local/lib/node_modules or wherever, outside Makefile
315# Copying chunked.js into target avoids a warning from the chunker
316chunked: $(HTMLDIR)/vkspec.html $(SPECSRC) $(COMMONDOCS)
317	$(QUIET)$(CHUNKINDEX)/addscripts.sh $(HTMLDIR)/vkspec.html $(HTMLDIR)/prechunked.html
318	$(QUIET)$(CP) $(CHUNKINDEX)/chunked.css $(CHUNKINDEX)/chunked.js \
319	    $(CHUNKINDEX)/lunr.js $(HTMLDIR)
320	$(QUIET)$(NODEJS) $(CHUNKER) $(HTMLDIR)/prechunked.html -o $(HTMLDIR)
321	$(QUIET)$(RM) $(HTMLDIR)/prechunked.html
322	$(QUIET)$(RUBY) $(CHUNKINDEX)/generate-index.rb $(HTMLDIR)/chap*html | \
323	    $(NODEJS) $(CHUNKINDEX)/build-index.js > $(HTMLDIR)/search.index.js
324
325# This is a temporary target while the new chunker is pre-release.
326# Eventually we will either pull the chunker into CI, or permanently
327# store a copy of the short JavaScript chunker in this repository.
328CHUNKERVERSION = asciidoctor-chunker_v1.0.0
329CHUNKURL = https://github.com/wshito/asciidoctor-chunker/releases/download/v1.0.0/$(CHUNKERVERSION).zip
330getchunker:
331	wget $(CHUNKURL) -O $(CHUNKERVERSION).zip
332	unzip $(CHUNKERVERSION).zip
333	mv $(CHUNKERVERSION)/* scripts/asciidoctor-chunker/
334	$(RMRF) $(CHUNKERVERSION).zip $(CHUNKERVERSION)
335
336html: $(HTMLDIR)/vkspec.html $(SPECSRC) $(COMMONDOCS)
337
338$(HTMLDIR)/vkspec.html: KATEXDIR = ../katex
339$(HTMLDIR)/vkspec.html: $(SPECSRC) $(COMMONDOCS) $(KATEXINSTDIR)
340	$(QUIET)$(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) -o $@ $(SPECSRC)
341	$(QUIET)$(TRANSLATEMATH) $@
342
343diff_html: $(HTMLDIR)/diff.html $(SPECSRC) $(COMMONDOCS)
344
345$(HTMLDIR)/diff.html: KATEXDIR = ../katex
346$(HTMLDIR)/diff.html: $(SPECSRC) $(COMMONDOCS) $(KATEXINSTDIR)
347	$(QUIET)$(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) \
348	    -a diff_extensions="$(DIFFEXTENSIONS)" \
349	    -r $(CONFIGS)/extension-highlighter.rb --trace \
350	    -o $@ $(SPECSRC)
351	$(QUIET)$(TRANSLATEMATH) $@
352
353# PDF optimizer - usage $(OPTIMIZEPDF) in.pdf out.pdf
354# OPTIMIZEPDFOPTS=--compress-pages is slightly better, but much slower
355OPTIMIZEPDF = hexapdf optimize $(OPTIMIZEPDFOPTS)
356
357pdf: $(PDFDIR)/vkspec.pdf $(SPECSRC) $(COMMONDOCS)
358
359$(PDFDIR)/vkspec.pdf: $(SPECSRC) $(COMMONDOCS)
360	$(QUIET)$(MKDIR) $(PDFDIR)
361	$(QUIET)$(MKDIR) $(PDFMATHDIR)
362	$(QUIET)$(ASCIIDOC) -b pdf $(ADOCOPTS) $(ADOCPDFOPTS) -o $@ $(SPECSRC)
363	$(QUIET)$(OPTIMIZEPDF) $@ $@.out.pdf && mv $@.out.pdf $@
364	$(QUIET)$(RMRF) $(PDFMATHDIR)
365
366validusage: $(VUDIR)/validusage.json $(SPECSRC) $(COMMONDOCS)
367
368$(VUDIR)/validusage.json: $(SPECSRC) $(COMMONDOCS)
369	$(QUIET)$(MKDIR) $(VUDIR)
370	$(QUIET)$(ASCIIDOC) $(ADOCOPTS) $(ADOCVUOPTS) --trace \
371	    -a json_output=$@ -o $@ $(SPECSRC)
372
373# Vulkan Documentation and Extensions, a.k.a. "Style Guide" documentation
374
375STYLESRC = styleguide.adoc
376STYLEFILES = $(wildcard $(SPECDIR)/style/[A-Za-z]*.adoc)
377
378styleguide: $(OUTDIR)/styleguide.html
379
380$(OUTDIR)/styleguide.html: KATEXDIR = katex
381$(OUTDIR)/styleguide.html: $(STYLESRC) $(STYLEFILES) $(GENDEPENDS) $(KATEXINSTDIR)
382	$(QUIET)$(MKDIR) $(OUTDIR)
383	$(QUIET)$(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) -o $@ $(STYLESRC)
384	$(QUIET)$(TRANSLATEMATH) $@
385
386
387# Vulkan API Registry (XML Schema) documentation
388# Currently does not use latexmath / KaTeX
389
390REGSRC = registry.adoc
391
392registry: $(OUTDIR)/registry.html
393
394$(OUTDIR)/registry.html: KATEXDIR = katex
395$(OUTDIR)/registry.html: $(REGSRC) $(GENDEPENDS)
396	$(QUIET)$(MKDIR) $(OUTDIR)
397	$(QUIET)$(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) -o $@ $(REGSRC)
398	$(QUIET)$(TRANSLATEMATH) $@
399
400# Build proposal documents
401PROPOSALSOURCES   = $(filter-out $(PROPOSALPATH)/template.adoc, $(wildcard $(PROPOSALPATH)/*.adoc))
402PROPOSALDOCS	  = $(PROPOSALSOURCES:$(PROPOSALPATH)/%.adoc=$(PROPOSALDIR)/%.html)
403proposals: $(PROPOSALDOCS) $(PROPOSALSOURCES)
404
405# Proposal documents are built outside of the main specification
406$(PROPOSALDIR)/%.html: $(PROPOSALPATH)/%.adoc
407	$(QUIET)$(ASCIIDOC) --failure-level ERROR -b html5 -o $@ $<
408	$(QUIET) if egrep -q '\\[([]' $@ ; then \
409	    $(TRANSLATEMATH) $@ ; \
410	fi
411
412# Reflow text in spec sources
413REFLOW = $(SCRIPTS)/reflow.py
414REFLOWOPTS = -overwrite
415
416reflow:
417	$(QUIET) echo "Warning: please verify the spec outputs build without changes!"
418	$(PYTHON) $(REFLOW) $(REFLOWOPTS) $(SPECSRC) $(SPECFILES) $(STYLESRC) $(STYLEFILES)
419
420# Automated markup and consistency checks, invoked by 'allchecks' and
421# 'ci-allchecks' targets or individually.
422
423# Look for disallowed contractions
424CHECK_CONTRACTIONS = git grep -i -F -f $(ROOTDIR)/config/CI/contractions | egrep -v -E -f $(ROOTDIR)/config/CI/contractions-allowed
425check-contractions:
426	if test `$(CHECK_CONTRACTIONS) | wc -l` != 0 ; then \
427	    echo "Contractions found that are not allowed:" ; \
428	    $(CHECK_CONTRACTIONS) ; \
429	    exit 1 ; \
430	fi
431
432# Look for typos and suggest fixes
433CODESPELL = codespell --config $(ROOTDIR)/config/CI/codespellrc -S '*.js' -S './antora*/*' -S 'ERRS*,*.pdf,*.html'
434check-spelling:
435	if ! $(CODESPELL) > /dev/null ; then \
436	    echo "Found probable misspellings. Corrections can be added to config/CI/codespell-allowed:" ; \
437	    $(CODESPELL) ; \
438	    exit 1 ; \
439	fi
440
441# Look for old or unpreferred language in specification language.
442# This mostly helps when we make global changes that also need to be
443# made in outstanding extension branches for new text.
444CHECK_WRITING = git grep -E -f $(ROOTDIR)/config/CI/writing $(SPECDIR)/registry.adoc $(SPECDIR)/vkspec.adoc $(SPECDIR)/chapters $(SPECDIR)/appendices
445check-writing:
446	if test `$(CHECK_WRITING) | wc -l` != 0 ; then \
447	    echo "Found old style writing. Please refer to the style guide or similar language in current main branch for fixes:" ; \
448	    $(CHECK_WRITING) ; \
449	    exit 1 ; \
450	fi
451
452# Look for bullet list items not preceded by exactly two spaces, per styleguide
453CHECK_BULLETS = git grep -E '^( |   +)[-*]+ ' $(SPECDIR)/chapters $(SPECDIR)/appendices $(SPECDIR)/style $(SPECDIR)/[a-z]*.adoc
454check-bullets:
455	if test `$(CHECK_BULLETS) | wc -l` != 0 ; then \
456	    echo "Bullet list item found not preceded by exactly two spaces:" ; \
457	    $(CHECK_BULLETS) ; \
458	    exit 1 ; \
459	fi
460
461# Look for asciidoctor conditionals inside VU statements; and for
462# duplicated VUID numbers, but only in spec sources.
463check-reflow:
464	$(PYTHON) $(SCRIPTS)/reflow.py -nowrite -noflow -check FAIL -checkVUID FAIL $(SPECFILES)
465
466# Look for files whose Khronos copyright has not been updated to the
467# current year
468DATE_YEAR = $(shell date +%Y)
469CHECK_DATES = git grep -z -l 'Copyright.*The Khronos' | xargs -0 git grep -L 'Copyright.*$(DATE_YEAR).*The Khronos'
470check-copyright-dates:
471	if test `$(CHECK_DATES) | wc -l` != 0 ; then \
472	    echo "Files with out-of-date Khronos copyrights (must be updated to $(DATE_YEAR):" ; \
473	    $(CHECK_DATES) ; \
474	    exit 1 ; \
475	 fi
476
477# Look for proper use of custom markup macros
478#   --ignore_count 0 can be incremented if there are unfixable errors
479check-links:
480	$(PYTHON) $(SCRIPTS)/check_spec_links.py -Werror --ignore_count 0
481
482# Perform XML consistency checks
483# Use '-warn' option to display warnings as well as errors
484check-consistency:
485	$(PYTHON) $(SCRIPTS)/xml_consistency.py
486
487# Looks for untagged use of 'undefined' in spec sources
488check-undefined:
489	$(SCRIPTS)/ci/check_undefined
490
491# Look for '.txt' files, which should almost all be .adoc now
492CHECK_TXTFILES = find . -name '*.txt' | egrep -v -E -f $(ROOTDIR)/config/CI/txt-files-allowed
493check-txtfiles:
494	if test `$(CHECK_TXTFILES) | wc -l` != 0 ; then \
495	    echo "*.txt files found that are not allowed (use .adoc):" ; \
496	    $(CHECK_TXTFILES) ; \
497	    exit 1 ; \
498	fi
499
500# Check for valid xrefs in the output html
501check-xrefs: $(HTMLDIR)/vkspec.html
502	$(SCRIPTS)/check_html_xrefs.py $(HTMLDIR)/vkspec.html
503
504# Clean generated and output files
505
506clean: clean_html clean_pdf clean_man clean_generated clean_validusage
507
508clean_html:
509	$(QUIET)$(RMRF) $(HTMLDIR) $(OUTDIR)/katex
510	$(QUIET)$(RM) $(OUTDIR)/apispec.html $(OUTDIR)/styleguide.html \
511	    $(OUTDIR)/registry.html
512
513clean_pdf:
514	$(QUIET)$(RMRF) $(PDFDIR) $(OUTDIR)/apispec.pdf
515
516clean_man:
517	$(QUIET)$(RMRF) $(MANHTMLDIR)
518
519# Generated directories and files to remove
520CLEAN_GEN_PATHS = \
521    $(APIPATH) \
522    $(HOSTSYNCPATH) \
523    $(VALIDITYPATH) \
524    $(METAPATH) \
525    $(INTERFACEPATH) \
526    $(SPIRVCAPPATH) \
527    $(FORMATSPATH) \
528    $(SYNCPATH) \
529    $(REFPATH) \
530    $(GENERATED)/include \
531    $(GENERATED)/__pycache__ \
532    $(PDFMATHDIR) \
533    $(JSAPIMAP) \
534    $(PYAPIMAP) \
535    $(RBAPIMAP) \
536    $(ATTRIBFILE)
537
538clean_generated:
539	$(QUIET)$(RMRF) $(CLEAN_GEN_PATHS)
540
541clean_validusage:
542	$(QUIET)$(RM) $(VUDIR)/validusage.json
543
544
545# Generated refpage sources. For now, always build all refpages.
546MANSOURCES   = $(filter-out $(REFPATH)/apispec.adoc, $(wildcard $(REFPATH)/*.adoc))
547
548# Generation of refpage asciidoctor sources by extraction from the
549# specification(s).
550#
551# Should have a proper dependency causing the man page sources to be
552# generated by running genRef (once), but adding $(MANSOURCES) to the
553# targets causes genRef to run once/target.
554#
555# Should pass in $(EXTOPTIONS) to determine which pages to generate.
556# For now, all core and extension refpages are extracted by genRef.py.
557GENREF = $(SCRIPTS)/genRef.py
558LOGFILE = $(REFPATH)/refpage.log
559refpages: $(REFPATH)/apispec.adoc
560$(REFPATH)/apispec.adoc: $(SPECFILES) $(GENREF) $(SCRIPTS)/reflib.py $(PYAPIMAP)
561	$(QUIET)$(MKDIR) $(REFPATH)
562	$(PYTHON) $(GENREF) -genpath $(GENERATED) -basedir $(REFPATH) \
563	    -log $(LOGFILE) -extpath $(SPECDIR)/appendices \
564	    $(EXTOPTIONS) $(SPECFILES)
565
566# These targets are HTML5 refpages
567#
568# The recursive $(MAKE) is an apparently unavoidable hack, since the
569# actual list of man page sources is not known until after
570# $(REFPATH)/apispec.adoc is generated. $(GENDEPENDS) is generated before
571# running the recursive make, so it does not trigger twice
572# $(SUBMAKEOPTIONS) suppresses the redundant "Entering / leaving"
573# messages make normally prints out, similarly to suppressing make
574# command output logging in the individual refpage actions below.
575SUBMAKEOPTIONS = --no-print-directory
576manhtmlpages: $(REFPATH)/apispec.adoc $(GENDEPENDS)
577	$(QUIET) echo "manhtmlpages: building HTML refpages with these options:"
578	$(QUIET) echo $(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) \
579	    $(ADOCREFOPTS) -d manpage -o REFPAGE.html REFPAGE.adoc
580	$(MAKE) $(SUBMAKEOPTIONS) -e buildmanpages
581
582# Build the individual refpages, then the symbolic links from aliases
583MANHTMLDIR  = $(OUTDIR)/man/html
584MANHTML     = $(MANSOURCES:$(REFPATH)/%.adoc=$(MANHTMLDIR)/%.html)
585buildmanpages: $(MANHTML)
586	$(MAKE) $(SUBMAKEOPTIONS) -e manaliases
587
588# Asciidoctor options to build refpages
589#
590# ADOCREFOPTS *must* be placed after ADOCOPTS in the command line, so
591# that it can override spec attribute values.
592#
593# cross-file-links makes custom macros link to other refpages
594# refprefix includes the refpage (not spec) extension metadata.
595# isrefpage is for refpage-specific content
596# html_spec_relative is where to find the full specification
597ADOCREFOPTS = -a cross-file-links -a refprefix='refpage.' -a isrefpage \
598	      -a html_spec_relative='../../html/vkspec.html'
599
600# The refpage build process normally generates far too much output, so
601# use VERYQUIET instead of QUIET
602# Running translate_math.js on every refpage is slow and most of them
603# do not contain math, so do a quick search for latexmath delimiters.
604$(MANHTMLDIR)/%.html: KATEXDIR = ../../katex
605$(MANHTMLDIR)/%.html: $(REFPATH)/%.adoc $(GENDEPENDS) $(KATEXINSTDIR)
606	$(VERYQUIET)echo "Building $@ from $< using default options"
607	$(VERYQUIET)$(MKDIR) $(MANHTMLDIR)
608	$(VERYQUIET)$(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) $(ADOCREFOPTS) \
609	    -d manpage -o $@ $<
610	$(VERYQUIET)if egrep -q '\\[([]' $@ ; then \
611	    $(TRANSLATEMATH) $@ ; \
612	fi
613
614# The 'manhtml' and 'manpdf' targets are NO LONGER SUPPORTED by Khronos.
615# They generate HTML5 and PDF single-file versions of the refpages.
616# The generated refpage sources are included by $(REFPATH)/apispec.adoc,
617# and are always generated along with that file. Therefore there is no
618# need for a recursive $(MAKE) or a $(MANHTML) dependency, unlike the
619# manhtmlpages target.
620
621manpdf: $(OUTDIR)/apispec.pdf
622
623$(OUTDIR)/apispec.pdf: $(SPECVERSION) $(REFPATH)/apispec.adoc $(SVGFILES) $(GENDEPENDS)
624	$(QUIET)$(MKDIR) $(OUTDIR)
625	$(QUIET)$(MKDIR) $(PDFMATHDIR)
626	$(QUIET)$(ASCIIDOC) -b pdf -a html_spec_relative='html/vkspec.html' \
627	    $(ADOCOPTS) $(ADOCPDFOPTS) -o $@ $(REFPATH)/apispec.adoc
628	$(QUIET)$(OPTIMIZEPDF) $@ $@.out.pdf && mv $@.out.pdf $@
629
630manhtml: $(OUTDIR)/apispec.html
631
632$(OUTDIR)/apispec.html: KATEXDIR = katex
633$(OUTDIR)/apispec.html: ADOCMISCOPTS =
634$(OUTDIR)/apispec.html: $(SPECVERSION) $(REFPATH)/apispec.adoc $(SVGFILES) $(GENDEPENDS) $(KATEXINSTDIR)
635	$(QUIET)$(MKDIR) $(OUTDIR)
636	$(QUIET)$(ASCIIDOC) -b html5 -a html_spec_relative='html/vkspec.html' \
637	    $(ADOCOPTS) $(ADOCHTMLOPTS) -o $@ $(REFPATH)/apispec.adoc
638	$(QUIET)$(TRANSLATEMATH) $@
639
640# Create links for refpage aliases
641
642MAKEMANALIASES = $(SCRIPTS)/makemanaliases.py
643manaliases: $(PYAPIMAP)
644	$(PYTHON) $(MAKEMANALIASES) -genpath $(GENERATED) -refdir $(MANHTMLDIR)
645
646# Targets generated from the XML and registry processing scripts
647#   $(PYAPIMAP) (apimap.py) - Python encoding of the registry
648# The $(...DEPEND) targets are files named 'timeMarker' in generated
649# target directories. They serve as proxies for the multiple generated
650# files written for each target:
651#   apiinc / proxy $(APIDEPEND) - API interface include files in $(APIPATH)
652#   hostsyncinc / proxy $(HOSTSYNCDEPEND) - host sync table include files in $(HOSTSYNCPATH)
653#   validinc / proxy $(VALIDITYDEPEND) - API validity include files in $(VALIDITYPATH)
654#   extinc / proxy $(METADEPEND) - extension appendix metadata include files in $(METAPATH)
655#
656# $(VERSIONOPTIONS) specifies the core API versions which are included
657# in these targets, and is set above based on $(VERSIONS)
658#
659# $(EXTOPTIONS) specifies the extensions which are included in these
660# targets, and is set above based on $(EXTENSIONS).
661#
662# $(GENVKEXTRA) are extra options that can be passed to genvk.py, e.g.
663# '-diag diag'
664
665REGISTRY   = $(ROOTDIR)/xml
666VKXML	   = $(REGISTRY)/vk.xml
667GENVK	   = $(SCRIPTS)/genvk.py
668GENVKOPTS  = $(VERSIONOPTIONS) $(EXTOPTIONS) $(GENVKEXTRA) -registry $(VKXML)
669GENVKEXTRA =
670
671scriptapi: jsapi pyapi rubyapi
672
673jsapi $(JSAPIMAP): $(VKXML) $(GENVK)
674	$(QUIET)$(MKDIR) $(GENERATED)
675	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(GENERATED) apimap.cjs
676
677pyapi $(PYAPIMAP): $(VKXML) $(GENVK)
678	$(QUIET)$(MKDIR) $(GENERATED)
679	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(GENERATED) apimap.py
680
681rubyapi $(RBAPIMAP): $(VKXML) $(GENVK)
682	$(QUIET)$(MKDIR) $(GENERATED)
683	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(GENERATED) apimap.rb
684
685apiinc: $(APIDEPEND)
686
687$(APIDEPEND): $(VKXML) $(GENVK) $(PYAPIMAP)
688	$(QUIET)$(MKDIR) $(APIPATH)
689	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(APIPATH) -genpath $(GENERATED) apiinc
690
691hostsyncinc: $(HOSTSYNCDEPEND)
692
693$(HOSTSYNCDEPEND): $(VKXML) $(GENVK)
694	$(QUIET)$(MKDIR) $(HOSTSYNCPATH)
695	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(HOSTSYNCPATH) hostsyncinc
696
697validinc: $(VALIDITYDEPEND)
698
699$(VALIDITYDEPEND): $(VKXML) $(GENVK)
700	$(QUIET)$(MKDIR) $(VALIDITYPATH)
701	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(VALIDITYPATH) validinc
702
703extinc: $(METAPATH)/timeMarker
704
705$(METADEPEND): $(VKXML) $(GENVK)
706	$(QUIET)$(MKDIR) $(METAPATH)
707	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(METAPATH) extinc
708
709interfaceinc: $(INTERFACEPATH)/timeMarker
710
711$(INTERFACEDEPEND): $(VKXML) $(GENVK)
712	$(QUIET)$(MKDIR) $(INTERFACEPATH)
713	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(INTERFACEPATH) interfaceinc
714
715# This generates a single file, so SPIRVCAPDEPEND is the full path to
716# the file, rather than to a timeMarker in the same directory.
717spirvcapinc: $(SPIRVCAPDEPEND)
718
719$(SPIRVCAPDEPEND): $(VKXML) $(GENVK)
720	$(QUIET)$(MKDIR) $(SPIRVCAPPATH)
721	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(SPIRVCAPPATH) spirvcapinc
722
723# This generates a single file, so FORMATSDEPEND is the full path to
724# the file, rather than to a timeMarker in the same directory.
725formatsinc: $(FORMATSDEPEND)
726
727$(FORMATSDEPEND): $(VKXML) $(GENVK)
728	$(QUIET)$(MKDIR) $(FORMATSPATH)
729	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(FORMATSPATH) formatsinc
730
731# This generates a single file, so FORMATSDEPEND is the full path to
732# the file, rather than to a timeMarker in the same directory.
733syncinc: $(SYNCDEPEND)
734
735$(SYNCDEPEND): $(VKXML) $(GENVK)
736	$(QUIET)$(MKDIR) $(SYNCPATH)
737	$(QUIET)$(PYTHON) $(GENVK) $(GENVKOPTS) -o $(SYNCPATH) syncinc
738
739# This generates a single file containing asciidoc attributes for each
740# core version and extension in the spec being built.
741# For use with Antora, it also includes a couple of document attributes
742# otherwise passed on the asciidoctor command line.
743# These should not use the asciidoctor attribute names (e.g. revnumber,
744# revdate), so use the Makefile variable names instead (e.g.
745# SPECREVISION, SPECDATE).
746
747attribs: $(ATTRIBFILE)
748
749$(ATTRIBFILE):
750	$(QUIET)for attrib in $(VERSIONS) $(EXTS) ; do \
751	    echo ":$${attrib}:" ; \
752	done > $@
753	$(QUIET)(echo ":SPECREVISION: $(SPECREVISION)" ; \
754		 echo ":SPECDATE: $(SPECDATE)" ; \
755		 echo ":SPECREMARK: $(SPECREMARK)" ; \
756		 echo ":APITITLE: $(APITITLE)") >> $@
757
758# Debugging aid - generate all files from registry XML
759generated: $(PYAPIMAP) $(GENDEPENDS)
760