#!/usr/bin/env python3 import os import sys import uuid import optparse import datetime import platform import xml.dom.minidom def empty(): return set([]) global uid # dict: UID of every projects global project # dict: dependency sets for every project global strings # dict: Visual Studio Strings global ignore # set: projects/directories to ignore global filters # dict: patterns of filenames to be removed from the build global filter # set: patterns of filenames to be removed from the build global externlib # set: project to never filter (zlib etc) global format # str: output format global build # set: projects to be built format = '%-20s\t%s' externlib= set(['libcurl' , 'libexpat' , 'zlib' , 'libcurl' ,'libeay32' , 'ssleay32' , 'libssh' , 'openssl' ]) ignore = set(['expat' , 'expat201' , 'expat210' , 'tests' , 'testv' ,'zlib123' , 'zlib125' , 'zlib127' , 'tools' , 'exiv2lib' ]) apps = set(['exifdata' , 'exifvalue' , 'geotag' , 'xmpsample' ]) tests = set(['exifdata-test', 'conntest' , 'convert-test', 'easyaccess-test', 'exifcomment' , 'httptest' , 'iotest' , 'iptceasy' , 'iptcprint' , 'iptctest' , 'key-test' , 'largeiptc-test' , 'mmap-test' , 'path-test' , 'prevtest' , 'remotetest' , 'stringto-test' , 'taglist' , 'tiff-test' , 'utiltest' , 'werror-test' , 'write-test' , 'write2-test' , 'xmpparse' , 'xmpparser-test' ]) # always = set(['exiv2' , 'exiv2json' , 'addmoddel' , 'exifprint' , 'metacopy' ]) build=empty() ## # build dict:uid - hunt the tree for .vcproj files uid = {} for d in os.listdir('.'): if os.path.isdir(d) & (not d in ignore): for root, dirs, files in os.walk(d): for file in files: ext = ".vcproj" if file.endswith(ext) & (file.find('configure') < 0): uid[d]=str(uuid.uuid1()) ## # define project dependances # This table is generated with the command 'tools/python/depend.py exiv2-webready.sln format' project = {} for p in uid: project[p]=empty() project['addmoddel' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['conntest' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['convert-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['easyaccess-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['exifcomment' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['exifdata' ] = set(['libexiv2']) project['exifdata-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['exifprint' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['exifvalue' ] = set(['libexiv2']) project['exiv2' ] = set(['libeay32', 'ssleay32', 'libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['exiv2json' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['geotag' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['httptest' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['ini-test' ] = set(['libexiv2']) project['iotest' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['iptceasy' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['iptcprint' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['iptctest' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['key-test' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['largeiptc-test' ] = set(['zlib', 'libexpat', 'libexiv2', 'libcurl', 'xmpsdk']) project['libcurl' ] = set(['libssh', 'libeay32', 'ssleay32']) project['libeay32' ] = set(['openssl']) project['libexiv2' ] = set(['libeay32', 'ssleay32', 'libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libssh']) project['libexpat' ] = set([ ]) project['libssh' ] = set(['zlib', 'libeay32', 'ssleay32']) project['metacopy' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['mmap-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['openssl' ] = set([ ]) project['path-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['prevtest' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['remotetest' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['ssleay32' ] = set(['openssl']) project['stringto-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['taglist' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['tiff-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['utiltest' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['werror-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['write-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['write2-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['xmpparse' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['xmpparser-test' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['xmpsample' ] = set(['libcurl', 'zlib', 'libexpat', 'xmpsdk', 'libexiv2', 'libssh']) project['xmpsdk' ] = set([ ]) project['zlib' ] = set([ ]) ## # filter filters={} filters['zlib' ] = set(['png' ]) filters['video' ] = set(['video']) filters['xmp' ] = set(['xmp' ]) filters['webready' ] = set([ ]) filter=empty() ## # MSVC strings strings = {} strings['UID' ] = str(uuid.uuid1()) strings['Begin' ]='''Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 ''' + '# Created by:%s at:%s using:%s on:%s in:%s\n' % (sys.argv[0], datetime.datetime.now().time(), platform.node(), platform.platform(), os.path.abspath('.')) strings['End' ] = '' strings['globalBegin' ] = 'Global' strings['globalEnd' ] = 'EndGlobal' strings['platforms' ] = ''' \tGlobalSection(SolutionConfigurationPlatforms) = preSolution \t\tDebug|Win32 = Debug|Win32 \t\tDebug|x64 = Debug|x64 \t\tDebugDLL|Win32 = DebugDLL|Win32 \t\tDebugDLL|x64 = DebugDLL|x64 \t\tRelease|Win32 = Release|Win32 \t\tRelease|x64 = Release|x64 \t\tReleaseDLL|Win32 = ReleaseDLL|Win32 \t\tReleaseDLL|x64 = ReleaseDLL|x64 \t\tEndGlobalSection ''' strings['postSolutionBegin' ] = '\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n' strings['postSolutionEnd' ] = '\tEndGlobalSection\n' strings['postProjectBegin' ] = '\tProjectSection(ProjectDependencies) = postProject\n' strings['postProjectEnd' ] = '\tProjectSectionEnd\n' strings['preSolution' ] = '''\tGlobalSection(SolutionProperties) = preSolution \t\tHideSolutionNode = FALSE \tEndGlobalSection ''' ## # {831EF580-92C8-4CA8-B0CE-3D906280A54D}.Debug|Win32.ActiveCfg = Debug|Win32 def compilationForProject(uid): result = '' for t in [ 'Debug' , 'DebugDLL' , 'Release' , 'ReleaseDLL' ]: for p in [ 'Win32','x64']: for z in ['ActiveCfg','Build.0']: result = result + '\t\t{%s}.%s|%s.%s = %s|%s\n' % (uid,t,p,z,t,p) return result; def compilationTable(): result = strings['postSolutionBegin'] for p in project: if type(project[p]) == type(empty()): result = result + compilationForProject(uid[p]) return result + strings['postSolutionEnd'] ## # Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libexiv2", "libexiv2\libexiv2_configure.vcproj", "{831EF580-92C8-4CA8-B0CE-3D906280A54D}" # ProjectSection(ProjectDependencies) = postProject # {09877CF4-83B6-44FE-A2E2-629AA5C8093E} = {09877CF4-83B6-44FE-A2E2-629AA5C8093E} # ... # EndProjectSection # EndProject ## def projectRecord(project,projects): print( format % ((project), '{ }' if len(projects) == 0 else projects)) UID = strings['UID'] vcnew = "%s\%s_configure.vcproj" % (project,project) # write in DOS notation for Visual Studio result = 'Project("{%s}") = "%s", "%s", "{%s}"\n' % (UID,project,vcnew,uid[project]) count = 0 out = strings['postProjectBegin'] for p in projects: if not p in ignore: count=count+1 out = out + '\t\t{%s} = {%s}\n' % (uid[p],uid[p]) out = out + strings['postProjectEnd'] if count > 0: result = result + out result = result + 'EndProject\n' return result ## # filter ....exv_msvc.h... -> ....exv_msvc_configure.h.... def modifyHeaderName(line): headerold='exv_msvc.h' headernew='exv_msvc_configure.h' if line.find(headerold): line=line.replace(headerold,headernew) return line ## # Filter proj\proj.vcproj -> proj\proj_configure.vcproj def writeVCproj(project,projects): vcold = os.path.join(project,("%s.vcproj" % project) ) # path to old file vcnew = os.path.join(project,("%s_configure.vcproj" % project) ) # path to new file xmllines = xml.dom.minidom.parse(vcold).toprettyxml().split('\n') out = "" for line in xmllines: # 1) Update the project GUID projectGUID='ProjectGUID="{' if line.find( projectGUID) > 0: start = line.find(projectGUID) + len(projectGUID) olduid=line[start:line.find('}',start)-1] line=line.replace(olduid,uid[project]); # 2) Filter off unwanted files and modify the msvc header file if (not project in externlib) & (line.find( 'File RelativePath=' ) >= 0): for pattern in filter: if ( line.find(pattern) > 0 ): line ='' line=modifyHeaderName(line) # 3) Add a preprocessor symbol to ask config.h to read exv_msvc_configure.h ppold= 'PreprocessorDefinitions="' ppnew=ppold+'EXV_MSVC_CONFIGURE;' if line.find( ppold ) > 0: line=line.replace(ppold,ppnew) if line.strip(): out = out + line open(vcnew,'w').write(out) ## # not assert! def cantHappen(condition,message): if condition: print(message) exit(1) def headerFilter(path,options): result= '' lines = open(path).readlines(); truth = {} truth['USE_CURL' ] = options.curl truth['USE_SSH' ] = options.ssh truth['ENABLE_WEBREADY' ] = options.webready truth['ENABLE_VIDEO' ] = options.video truth['HAVE_XMP_TOOLKIT'] = options.xmp truth['HAVE_ZLIB' ] = options.zlib truth['HAVE_EXPAT' ] = options.expat for line in lines: start=line.find('EXV_') if (start > 0) & ((line.find('define')>0) | (line.find('undef')>0)): key = line[start+4:line.find(' ',start+4)] if key in truth: line = ('#define EXV_%s 1\n' % key) if truth[key] else ('#undef EXV_%s\n' % key) line=modifyHeaderName(line) result += line return result def enableWebready(option, opt_str, value, parser): b=True parser.values.webready = b parser.values.openssl = b parser.values.ssh = b parser.values.curl = b def disableWebready(option, opt_str, value, parser): b=False parser.values.webready = b parser.values.openssl = b parser.values.ssh = b parser.values.curl = b def main(): global uid global project global strings global ignore global filter global filters global externlib global format global build ## # set up argument parser usage = "usage: %prog [options]+" parser = optparse.OptionParser(usage) parser = optparse.OptionParser() parser.add_option('-A', '--with-app' , action='store_true' , dest='app' ,help='build sample apps (false)' ,default=False) parser.add_option('-a', '--without-app' , action='store_false', dest='app' ,help='do not build apps' ) parser.add_option('-C', '--with-curl' , action='store_true' , dest='curl' ,help='enable curl' ,default=False) parser.add_option('-c', '--without-curl' , action='store_false', dest='curl' ,help='disable curl' ) parser.add_option('-E', '--with-expat' , action='store_true' , dest='expat' ,help='enable expat (true)' ,default=True) parser.add_option('-e', '--without-expat' , action='store_false', dest='expat' ,help='disable expat' ) parser.add_option('-O', '--with-openssl' , action='store_true' , dest='openssl' ,help='enable openssl' ,default=False) parser.add_option('-o', '--without-openssl' , action='store_false', dest='openssl' ,help='disable openssl' ) parser.add_option('-S', '--with-ssh' , action='store_true' , dest='ssh' ,help='enable ssh' ,default=False) parser.add_option('-s', '--without-ssh' , action='store_false', dest='ssh' ,help='disable ssh' ) parser.add_option('-T', '--with-test' , action='store_true' , dest='test' ,help='build test programs (true)',default=True) parser.add_option('-t', '--without-test' , action='store_false', dest='test' ,help='do not build test progs' ) parser.add_option('-W', '--enable-webready' , action='callback' , dest='webready',help='enable webready (false)' ,callback=enableWebready,default=False) parser.add_option('-w', '--disable-webready', action='callback' , dest='webready',help='enable webready' ,callback=disableWebready) parser.add_option('-V', '--enable-video' , action='store_true' , dest='video' ,help='enable video (false)' ,default=False) parser.add_option('-v', '--disable-video' , action='store_false', dest='video' ,help='disable video' ) parser.add_option('-X', '--enable-xmp' , action='store_true' , dest='xmp' ,help='enable xmp (true)' ,default=True) parser.add_option('-x', '--disable-xmp' , action='store_false', dest='xmp' ,help='disable xmp' ) parser.add_option('-Z', '--with-zlib' , action='store_true' , dest='zlib' ,help='enable zlib/png (true)' ,default=True) parser.add_option('-z', '--without-zlib' , action='store_false', dest='zlib' ,help='disable zlib/png' ) parser.add_option('-d' , '--default' , action='store_true' , dest='default' ,help='default' ,default=False) ## # no arguments, report and quit if len(sys.argv) == 1: parser.print_help() return ## # parse and test for errors (options, args) = parser.parse_args() cantHappen(options.curl & (not options.webready),'cannot use curl without webready' ); cantHappen(options.openssl & (not options.webready),'cannot use openssl without webready'); cantHappen(options.ssh & (not options.webready),'cannot use libssh without webready'); cantHappen(options.xmp & (not options.expat ),'cannot use xmp without expat' ); if not options.app: ignore = ignore | apps; if not options.test: ignore = ignore | tests; ## # print options print(format % ('Option' , 'Value')) print(format % ('------' , '-----')) for o, v in sorted(options.__dict__.items()): if o != 'default': print(format % (o, v)) print() print(format % ('Project','Dependancy')) print(format % ('-------','----------')) ## # learn the filters if options.video: filters['video']=empty() if options.webready: filters['webready']=empty() if options.xmp: filters['xmp']=empty() if options.zlib: filters['zlib']=empty() filter = filters['video'] | filters['xmp'] | filters['webready'] | filters['zlib'] ## # learn build candidates for p in project: skip = p in ignore skip = skip | ((p == 'libssh' ) & ( not options.ssh )) skip = skip | ((p == 'libcurl' ) & ( not options.curl )) skip = skip | ((p == 'openssl' ) & ( not options.openssl)) skip = skip | ((p == 'libeay32' ) & ( not options.openssl)) skip = skip | ((p == 'ssleay32' ) & ( not options.openssl)) skip = skip | ((p == 'xmpsdk' ) & ( not options.xmp )) skip = skip | ((p == 'libexpat' ) & ( not options.expat )) skip = skip | ((p == 'zlib' ) & ( not options.zlib )) if not skip: build.add(p) # build projects that intersect with the build! for p in build: project[p] = project[p] & build ## # write solution file sln='exiv2_configure.sln' s = open(sln,'w') s.write(strings['Begin']) for p in sorted(build): s.write(projectRecord(p,project[p])) # write compilation table s.write(strings['globalBegin']) s.write(strings['platforms' ]) s.write(compilationTable()) s.write(strings['preSolution']) s.write(strings['globalEnd' ]) # finish s.write(strings['End']) s.close() ## # write project files for p in sorted(build): writeVCproj(p,project[p]) ## # write exv_msvc_configure.h by filtering exv_msvc.h include = os.path.join('..','include','exiv2') oldh = os.path.join(include,'exv_msvc.h'); newh = os.path.join(include,'exv_msvc_configure.h'); open(newh,'w').write(headerFilter(oldh,options)) print() print('MSVC 2005 Solution file created: ' + sln) print('header = %s\n' % os.path.abspath(newh)) if __name__ == "__main__": main() # That's all Folks ##