Quieten build & ensure API build scripts exit with non-zero status

The current API build scripts will continue and exit with a zero
status even if they find problems. This has been the cause of many
build problems, or hidden build errors, in the past. Change the
scripts so they always exit with a non-zero status for any problems
they do not understand. Also turn off all debug output by default
so they respect $(AM_V_GEN)

* docs/Makefile.am: Use $(AM_V_GEN) for API/HTML scripts
* docs/apibuild.py, python/generator.py: Exit with non-zero status
  if problems are found. Also be silent, not outputting any debug
  messages.
* src/Makefile.am: Use $(AM_V_GEN) for ESX generator
* python/Makefile.am: Tweak rule
This commit is contained in:
Daniel P. Berrange 2011-05-12 11:19:42 +01:00
parent fff9d71a65
commit 8665f85523
5 changed files with 72 additions and 56 deletions

View File

@ -153,21 +153,18 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in
html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in
-@if [ -x $(XSLTPROC) ] ; then \ $(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
echo "Rebuilding the HTML pages from the XML API" ; \
$(XSLTPROC) --nonet -o $(srcdir)/ \ $(XSLTPROC) --nonet -o $(srcdir)/ \
$(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi $(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi ; \
-@if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \
if $(XMLCATALOG) '$(XML_CATALOG_FILE)' "-//W3C//DTD XHTML 1.0 Strict//EN" \ if $(XMLCATALOG) '$(XML_CATALOG_FILE)' "-//W3C//DTD XHTML 1.0 Strict//EN" \
> /dev/null ; then \ > /dev/null ; then \
echo "Validating the resulting XHTML pages" ; \
SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \ SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \
$(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html ; \ $(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html ; \
else echo "missing XHTML1 DTD" ; fi ; fi else echo "missing XHTML1 DTD" ; fi ; fi
$(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl) $(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl)
-@echo Rebuilding devhelp files $(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
-@if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \ $(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \
$(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi $(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi

View File

@ -11,7 +11,9 @@ import os, sys
import string import string
import glob import glob
debug=0 quiet=True
warnings=0
debug=False
debugsym=None debugsym=None
# #
@ -95,7 +97,7 @@ class identifier:
self.conditionals = None self.conditionals = None
else: else:
self.conditionals = conditionals[:] self.conditionals = conditionals[:]
if self.name == debugsym: if self.name == debugsym and not quiet:
print "=> define %s : %s" % (debugsym, (module, type, info, print "=> define %s : %s" % (debugsym, (module, type, info,
extra, conditionals)) extra, conditionals))
@ -155,7 +157,7 @@ class identifier:
def update(self, header, module, type = None, info = None, extra=None, def update(self, header, module, type = None, info = None, extra=None,
conditionals=None): conditionals=None):
if self.name == debugsym: if self.name == debugsym and not quiet:
print "=> update %s : %s" % (debugsym, (module, type, info, print "=> update %s : %s" % (debugsym, (module, type, info,
extra, conditionals)) extra, conditionals))
if header != None and self.header == None: if header != None and self.header == None:
@ -203,7 +205,7 @@ class index:
if d != None and name != None and type != None: if d != None and name != None and type != None:
self.references[name] = d self.references[name] = d
if name == debugsym: if name == debugsym and not quiet:
print "New ref: %s" % (d) print "New ref: %s" % (d)
return d return d
@ -244,9 +246,9 @@ class index:
elif type == "macro": elif type == "macro":
self.macros[name] = d self.macros[name] = d
else: else:
print "Unable to register type ", type self.warning("Unable to register type ", type)
if name == debugsym: if name == debugsym and not quiet:
print "New symbol: %s" % (d) print "New symbol: %s" % (d)
return d return d
@ -260,8 +262,8 @@ class index:
if self.macros.has_key(id): if self.macros.has_key(id):
del self.macros[id] del self.macros[id]
if self.functions.has_key(id): if self.functions.has_key(id):
print "function %s from %s redeclared in %s" % ( self.warning("function %s from %s redeclared in %s" % (
id, self.functions[id].header, idx.functions[id].header) id, self.functions[id].header, idx.functions[id].header))
else: else:
self.functions[id] = idx.functions[id] self.functions[id] = idx.functions[id]
self.identifiers[id] = idx.functions[id] self.identifiers[id] = idx.functions[id]
@ -273,15 +275,15 @@ class index:
if self.macros.has_key(id): if self.macros.has_key(id):
del self.macros[id] del self.macros[id]
if self.variables.has_key(id): if self.variables.has_key(id):
print "variable %s from %s redeclared in %s" % ( self.warning("variable %s from %s redeclared in %s" % (
id, self.variables[id].header, idx.variables[id].header) id, self.variables[id].header, idx.variables[id].header))
else: else:
self.variables[id] = idx.variables[id] self.variables[id] = idx.variables[id]
self.identifiers[id] = idx.variables[id] self.identifiers[id] = idx.variables[id]
for id in idx.structs.keys(): for id in idx.structs.keys():
if self.structs.has_key(id): if self.structs.has_key(id):
print "struct %s from %s redeclared in %s" % ( self.warning("struct %s from %s redeclared in %s" % (
id, self.structs[id].header, idx.structs[id].header) id, self.structs[id].header, idx.structs[id].header))
else: else:
self.structs[id] = idx.structs[id] self.structs[id] = idx.structs[id]
self.identifiers[id] = idx.structs[id] self.identifiers[id] = idx.structs[id]
@ -294,8 +296,8 @@ class index:
self.identifiers[id] = idx.unions[id] self.identifiers[id] = idx.unions[id]
for id in idx.typedefs.keys(): for id in idx.typedefs.keys():
if self.typedefs.has_key(id): if self.typedefs.has_key(id):
print "typedef %s from %s redeclared in %s" % ( self.warning("typedef %s from %s redeclared in %s" % (
id, self.typedefs[id].header, idx.typedefs[id].header) id, self.typedefs[id].header, idx.typedefs[id].header))
else: else:
self.typedefs[id] = idx.typedefs[id] self.typedefs[id] = idx.typedefs[id]
self.identifiers[id] = idx.typedefs[id] self.identifiers[id] = idx.typedefs[id]
@ -311,15 +313,15 @@ class index:
if self.enums.has_key(id): if self.enums.has_key(id):
continue continue
if self.macros.has_key(id): if self.macros.has_key(id):
print "macro %s from %s redeclared in %s" % ( self.warning("macro %s from %s redeclared in %s" % (
id, self.macros[id].header, idx.macros[id].header) id, self.macros[id].header, idx.macros[id].header))
else: else:
self.macros[id] = idx.macros[id] self.macros[id] = idx.macros[id]
self.identifiers[id] = idx.macros[id] self.identifiers[id] = idx.macros[id]
for id in idx.enums.keys(): for id in idx.enums.keys():
if self.enums.has_key(id): if self.enums.has_key(id):
print "enum %s from %s redeclared in %s" % ( self.warning("enum %s from %s redeclared in %s" % (
id, self.enums[id].header, idx.enums[id].header) id, self.enums[id].header, idx.enums[id].header))
else: else:
self.enums[id] = idx.enums[id] self.enums[id] = idx.enums[id]
self.identifiers[id] = idx.enums[id] self.identifiers[id] = idx.enums[id]
@ -330,10 +332,10 @@ class index:
# check that function condition agrees with header # check that function condition agrees with header
if idx.functions[id].conditionals != \ if idx.functions[id].conditionals != \
self.functions[id].conditionals: self.functions[id].conditionals:
print "Header condition differs from Function for %s:" \ self.warning("Header condition differs from Function for %s:" \
% id % id)
print " H: %s" % self.functions[id].conditionals self.warning(" H: %s" % self.functions[id].conditionals)
print " C: %s" % idx.functions[id].conditionals self.warning(" C: %s" % idx.functions[id].conditionals)
up = idx.functions[id] up = idx.functions[id]
self.functions[id].update(None, up.module, up.type, up.info, up.extra) self.functions[id].update(None, up.module, up.type, up.info, up.extra)
# else: # else:
@ -356,12 +358,13 @@ class index:
def analyze(self): def analyze(self):
self.analyze_dict("functions", self.functions) if not quiet:
self.analyze_dict("variables", self.variables) self.analyze_dict("functions", self.functions)
self.analyze_dict("structs", self.structs) self.analyze_dict("variables", self.variables)
self.analyze_dict("unions", self.unions) self.analyze_dict("structs", self.structs)
self.analyze_dict("typedefs", self.typedefs) self.analyze_dict("unions", self.unions)
self.analyze_dict("macros", self.macros) self.analyze_dict("typedefs", self.typedefs)
self.analyze_dict("macros", self.macros)
class CLexer: class CLexer:
"""A lexer for the C language, tokenize the input by reading and """A lexer for the C language, tokenize the input by reading and
@ -621,6 +624,8 @@ class CParser:
info, extra, self.conditionals) info, extra, self.conditionals)
def warning(self, msg): def warning(self, msg):
global warnings
warnings = warnings + 1
if self.no_error: if self.no_error:
return return
print msg print msg
@ -1802,7 +1807,8 @@ class CParser:
return token return token
def parse(self): def parse(self):
self.warning("Parsing %s" % (self.filename)) if not quiet:
print "Parsing %s" % (self.filename)
token = self.token() token = self.token()
while token != None: while token != None:
if token[0] == 'name': if token[0] == 'name':
@ -1869,7 +1875,8 @@ class docBuilder:
pass pass
def analyze(self): def analyze(self):
print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys())) if not quiet:
print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys()))
self.idx.analyze() self.idx.analyze()
def scanHeaders(self): def scanHeaders(self):
@ -1995,7 +2002,7 @@ class docBuilder:
else: else:
output.write(" <field name='%s' type='%s' info='%s'/>\n" % (field[1] , field[0], desc)) output.write(" <field name='%s' type='%s' info='%s'/>\n" % (field[1] , field[0], desc))
except: except:
print "Failed to serialize struct %s" % (name) self.warning("Failed to serialize struct %s" % (name))
output.write(" </struct>\n") output.write(" </struct>\n")
else: else:
output.write("/>\n"); output.write("/>\n");
@ -2023,7 +2030,7 @@ class docBuilder:
def serialize_function(self, output, name): def serialize_function(self, output, name):
id = self.idx.functions[name] id = self.idx.functions[name]
if name == debugsym: if name == debugsym and not quiet:
print "=>", id print "=>", id
output.write(" <%s name='%s' file='%s' module='%s'>\n" % (id.type, output.write(" <%s name='%s' file='%s' module='%s'>\n" % (id.type,
@ -2059,7 +2066,7 @@ class docBuilder:
output.write(" <arg name='%s' type='%s' info='%s'/>\n" % (param[1], param[0], escape(param[2]))) output.write(" <arg name='%s' type='%s' info='%s'/>\n" % (param[1], param[0], escape(param[2])))
self.indexString(name, param[2]) self.indexString(name, param[2])
except: except:
print "Failed to save function %s info: " % name, `id.info` self.warning("Failed to save function %s info: " % name, `id.info`)
output.write(" </%s>\n" % (id.type)) output.write(" </%s>\n" % (id.type))
def serialize_exports(self, output, file): def serialize_exports(self, output, file):
@ -2074,7 +2081,7 @@ class docBuilder:
escape(dict.info[data]), escape(dict.info[data]),
string.lower(data))) string.lower(data)))
except: except:
print "Header %s lacks a %s description" % (module, data) self.warning("Header %s lacks a %s description" % (module, data))
if dict.info.has_key('Description'): if dict.info.has_key('Description'):
desc = dict.info['Description'] desc = dict.info['Description']
if string.find(desc, "DEPRECATED") != -1: if string.find(desc, "DEPRECATED") != -1:
@ -2287,7 +2294,8 @@ class docBuilder:
def serialize(self): def serialize(self):
filename = "%s/%s-api.xml" % (self.path, self.name) filename = "%s/%s-api.xml" % (self.path, self.name)
print "Saving XML description %s" % (filename) if not quiet:
print "Saving XML description %s" % (filename)
output = open(filename, "w") output = open(filename, "w")
output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
output.write("<api name='%s'>\n" % self.name) output.write("<api name='%s'>\n" % self.name)
@ -2323,7 +2331,8 @@ class docBuilder:
output.close() output.close()
filename = "%s/%s-refs.xml" % (self.path, self.name) filename = "%s/%s-refs.xml" % (self.path, self.name)
print "Saving XML Cross References %s" % (filename) if not quiet:
print "Saving XML Cross References %s" % (filename)
output = open(filename, "w") output = open(filename, "w")
output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
output.write("<apirefs name='%s'>\n" % self.name) output.write("<apirefs name='%s'>\n" % self.name)
@ -2336,7 +2345,8 @@ def rebuild():
builder = None builder = None
srcdir = os.environ["srcdir"] srcdir = os.environ["srcdir"]
if glob.glob(srcdir + "/../src/libvirt.c") != [] : if glob.glob(srcdir + "/../src/libvirt.c") != [] :
print "Rebuilding API description for libvirt" if not quiet:
print "Rebuilding API description for libvirt"
dirs = [srcdir + "/../src", dirs = [srcdir + "/../src",
srcdir + "/../src/util", srcdir + "/../src/util",
srcdir + "/../include/libvirt"] srcdir + "/../include/libvirt"]
@ -2344,12 +2354,13 @@ def rebuild():
dirs.append("../include/libvirt") dirs.append("../include/libvirt")
builder = docBuilder("libvirt", srcdir, dirs, []) builder = docBuilder("libvirt", srcdir, dirs, [])
elif glob.glob("src/libvirt.c") != [] : elif glob.glob("src/libvirt.c") != [] :
print "Rebuilding API description for libvirt" if not quiet:
print "Rebuilding API description for libvirt"
builder = docBuilder("libvirt", srcdir, builder = docBuilder("libvirt", srcdir,
["src", "src/util", "include/libvirt"], ["src", "src/util", "include/libvirt"],
[]) [])
else: else:
print "rebuild() failed, unable to guess the module" self.warning("rebuild() failed, unable to guess the module")
return None return None
builder.scan() builder.scan()
builder.analyze() builder.analyze()
@ -2370,3 +2381,7 @@ if __name__ == "__main__":
parse(sys.argv[1]) parse(sys.argv[1])
else: else:
rebuild() rebuild()
if warnings > 0:
sys.exit(2)
else:
sys.exit(0)

View File

@ -53,11 +53,11 @@ GENERATED= libvirt-export.c \
libvirt.h \ libvirt.h \
libvirt.py libvirt.py
generated.stamp: $(srcdir)/$(GENERATE) $(API_DESC) $(GENERATE).stamp: $(srcdir)/$(GENERATE) $(API_DESC)
$(PYTHON) $(srcdir)/$(GENERATE) $(PYTHON) $(AM_V_GEN)$(PYTHON) $(srcdir)/$(GENERATE) $(PYTHON) && \
touch $@ touch $@
$(GENERATED): generated.stamp $(GENERATED): $(GENERATE).stamp
$(libvirtmod_la_OBJECTS): $(GENERATED) $(libvirtmod_la_OBJECTS): $(GENERATED)

View File

@ -11,6 +11,8 @@ import sys
import string import string
import re import re
quiet=True
if __name__ == "__main__": if __name__ == "__main__":
# launched as a script # launched as a script
srcPref = os.path.dirname(sys.argv[0]) srcPref = os.path.dirname(sys.argv[0])
@ -617,7 +619,8 @@ def buildStubs():
sys.exit(1) sys.exit(1)
n = len(functions.keys()) n = len(functions.keys())
print "Found %d functions in libvirt-api.xml" % (n) if not quiet:
print "Found %d functions in libvirt-api.xml" % (n)
py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject") py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
try: try:
@ -629,8 +632,8 @@ def buildStubs():
except IOError, msg: except IOError, msg:
print file, ":", msg print file, ":", msg
if not quiet:
print "Found %d functions in libvirt-override-api.xml" % ( print "Found %d functions in libvirt-override-api.xml" % (
len(functions.keys()) - n) len(functions.keys()) - n)
nb_wrap = 0 nb_wrap = 0
failed = 0 failed = 0
@ -662,20 +665,21 @@ def buildStubs():
export.close() export.close()
wrapper.close() wrapper.close()
print "Generated %d wrapper functions" % nb_wrap if not quiet:
print "Generated %d wrapper functions" % nb_wrap
if unknown_types: if unknown_types:
print "Missing type converters: " print "Missing type converters: "
for type in unknown_types.keys(): for type in unknown_types.keys():
print "%s:%d " % (type, len(unknown_types[type])), print "%s:%d " % (type, len(unknown_types[type])),
print
for f in functions_failed: for f in functions_failed:
print "ERROR: failed %s" % f print "ERROR: failed %s" % f
if failed > 0: if failed > 0:
return -1 return -1
if len(unknown_types) > 0:
return -1
return 0 return 0
####################################################################### #######################################################################

View File

@ -796,7 +796,7 @@ endif
BUILT_SOURCES += $(ESX_DRIVER_GENERATED) BUILT_SOURCES += $(ESX_DRIVER_GENERATED)
$(ESX_DRIVER_GENERATED): $(srcdir)/esx/esx_vi_generator.input $(srcdir)/esx/esx_vi_generator.py $(ESX_DRIVER_GENERATED): $(srcdir)/esx/esx_vi_generator.input $(srcdir)/esx/esx_vi_generator.py
-srcdir=$(srcdir) $(srcdir)/esx/esx_vi_generator.py $(AM_V_GEN)srcdir=$(srcdir) $(srcdir)/esx/esx_vi_generator.py
if WITH_ESX if WITH_ESX
if WITH_DRIVER_MODULES if WITH_DRIVER_MODULES