#!/usr/bin/python
##
# build-test.py [--verbose]
#
# reads the output of exiv2 -v -V and inspects it for sanity
# inspect run-library libraries platform/compiler/{debug|release}{shared|static}
# TODO: 1 report loaded libraries that we didn't expect
# 2 mingw support
##
import os
import sys
import subprocess
##
# print error msg and terminate
def error(msg):
print '***',msg,'***'
sys.exit(1)
##
# run a command and return output string
def runCommand(command):
##
# don't use check_output
# this is 2.7 feature.
# not available on cygwin's default python 2.6.8 interpreter
# result=subprocess.check_output( command.split(' '))
##
result =subprocess.Popen(command.split(' '), stdout=subprocess.PIPE).communicate()[0]
# ensure lines are \n terminated (remove \r bytes)
return result.replace('\r\n', '\n').replace('\r', '\n')
##
# process the version information dictionary
def platform(dict):
verbose=dict.has_key('verbose')
for k in sorted(dict.keys()):
v=dict[k]
if type(v)==type([]):
v='['+str(len(v))+']'
if verbose:
print "%-20s -> %s" % (k,v)
##
# search dict for an array of libraries
def expect(dict,expects):
verbose=dict.has_key('verbose')
libs=dict['library']
E={};
for e in expects:
e=e.lower().replace('-','.') # cygwin uses '-' in versioning
e=e.split('.')[0]
if verbose:
print 'expect library',e
E[e]=0
for lib in libs:
lib=lib.lower().replace('\\','/') # cygwin uses '\' in pathnames
lib=lib.replace('-','.')
lib=os.path.basename(lib).split('.')[0]
if E.has_key(lib):
E[lib]=E[lib]+1
if verbose:
print 'found library',lib
for e in E.keys():
if E[e]==0:
error( "expected library '%s' not found" % e )
##
def apple(dict):
expects= [ 'libSystem.B.dylib'
, 'libexpat.1.dylib'
, 'libz.1.dylib'
, 'libiconv.2.dylib'
, 'libdyld.dylib'
, 'libc++.1.dylib'
# , 'libstdc++.6.dylib' # I suspect this is only with GCC (Xcode4 and earlier)
] ;
# which version of MacOS-X ?
os_major=int(os.uname()[2].split('.')[0])
os_minor=int(os.uname()[2].split('.')[1])
NC=13;ML=12;LION=11;SL=10;LEO=9;
if dict['dll']:
expects.append('libexiv2.12.dylib')
## Mountain Lion
if os_major==ML and dict['dll']:
expects.append('libexiv2.12.dylib')
expects.append('libSystem.B.dylib')
expects.append('libexpat.1.dylib')
expects.append('libz.1.dylib')
expects.append('libiconv.2.dylib')
expects.append('libstdc++.6.dylib')
expects.append('libdyld.dylib')
expects.append('libc++.1.dylib')
expect(dict,expects)
expect_bits = 32 if os_major==LEO else 64
if expect_bits != dict['bits']:
error('*** expected %d bit build ***' % expect_bits)
##
def linux(dict):
expects = [ 'libdl.so.2'
, 'libexiv2.so.12'
, 'libstdc++.so.6'
, 'libm.so.6'
, 'libgcc_s.so.1'
, 'libc.so.6'
, 'libz.so.1'
, 'libexpat.so.1'
]
expect(dict,expects)
##
def windows(dict):
expects = [ 'ntdll.dll'
, 'kernel32.dll'
, 'kernelbase.dll'
, 'psapi.dll'
];
if dict['dll']:
dll='d.dll' if dict['debug'] else '.dll'
expects.append( 'exiv2' + dll )
expects.append( 'zlib1' + dll )
expects.append('libexpat.dll' )
# c run time libraries
# 2003=71, 2005=80, 2008=90, 2010=100
v=int( float(dict['version'])*10 )
expects.append('msvcr%d%s' % (v,dll) )
expects.append('msvcp%d%s' % (v,dll) )
expect(dict,expects)
##
def cygwin(dict):
expects = [ 'ntdll.dll'
, 'kernel32.dll'
, 'kernelbase.dll'
, 'cygexiv2-12.dll'
, 'cygwin1.dll'
, 'cyggcc_s-1.dll'
, 'cygstdc++-6.dll'
, 'psapi.dll'
, 'cygexpat-1.dll'
, 'cygiconv-2.dll'
, 'cygintl-8.dll'
];
expect(dict,expects)
##
def mingw(dict):
error("can't test platform mingw")
##
def unknown(dict):
error("can't test platform unknown")
##
def main(args):
this=os.path.abspath(args[0])
##
# find the exiv2 executable
exiv2='exiv2'
if os.environ.has_key('EXIV2_BINDIR'):
exiv2=os.path.abspath(os.path.join(os.environ['EXIV2_BINDIR'],exiv2))
else:
exiv2=os.path.join(os.path.dirname(this),'../bin',exiv2)
##
# collect the version dictionary from exiv2
dict={}
verbose=False
for arg in args:
if arg == '--verbose':
verbose=True
dict['verbose']=True
if os.path.exists(exiv2):
output = runCommand(exiv2 + ' -v -V')
if verbose:
print output
lines = output.split('\n')
for l in lines:
kv=l.split('=')
if len(kv)==2:
k=kv[0]
v=kv[1]
if not dict.has_key(k):
dict[k]=[]
dict[k].append(v)
# flatten value arrays of length 1
for k in dict.keys():
if type(dict[k])==type([]):
if len(dict[k])==1:
dict[k]=dict[k][0]
# convert numeric strings to ints
debug='debug'
dll='dll'
bits='bits'
dict[dll ] = int(dict[dll])
dict[debug] = int(dict[debug])
dict[bits ] = int(dict[bits])
##
# analyse the version dictionary
platform(dict)
eval(dict['platform']+'(dict)')
##
# report
v='Release' if dict[debug]==0 else 'Debug'
d='DLL' if dict[dll ]==0 else ''
print "build %dbit %-8s %-12s looks good" % (dict[bits],dict['platform'],v+d)
else:
error("exiv2 not found!")
if __name__ == '__main__':
main(sys.argv)
# That's all Folks!
##