#!/usr/bin/env python import os,re,sys,string,subprocess,shutil from optparse import OptionParser, Option # ----------------------------- class extendableOption(Option): # ----------------------------- # used for definition of new option parser action 'extend', which enables to take multiple option arguments # taken from online tutorial http://docs.python.org/library/optparse.html ACTIONS = Option.ACTIONS + ("extend",) STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) def take_action(self, action, dest, opt, value, values, parser): if action == "extend": lvalue = value.split(",") values.ensure_value(dest, []).extend(lvalue) else: Option.take_action(self, action, dest, opt, value, values, parser) ######################################################## # MAIN ######################################################## parser = OptionParser(option_class=extendableOption, usage='%prog options', description = """ Configures the compilation and installation of DAMASK """ + string.replace('$Id$','\n','\\n') ) #--- determine default compiler ---------------------------------------------------------------------- compiler = os.getenv('F90') if compiler == None: compiler ={True:'ifort',False:'gfortran'}[\ subprocess.call(['which', 'ifort'],\ stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0] #--- default option values -------------------------------------------------------------------------- BLAS_order = ['IMKL','ACML','LAPACK'] defaults={'F90':compiler,\ 'FFTW_ROOT':'/usr/local',\ 'MSC_ROOT' :'/msc',\ 'HDF5_ROOT':'/usr/local',\ 'DAMASK_NUM_THREADS':4,\ 'blasType':'LAPACK',\ 'blasRoot':{'LAPACK':'/usr',\ 'ACML' :'/opt/acml5.3.1',\ 'IMKL' :{True:'/opt/intel/composerxe/mkl',False:os.getenv('MKLROOT')}\ [os.getenv('MKLROOT')==None]},\ 'spectralOptions':{}} print 'defaults at start',defaults #--- if local config file exists, read, otherwise assume global config file ------------------------ if os.path.isfile(os.path.join(os.getenv('HOME'),'.damask/damask.conf')): configFile = os.path.join(os.getenv('HOME'),'.damask/damask.conf') else: configFile = '/etc/damask.conf' #--- set default values according to read in values ------------------------------------------------ try: with open(configFile,'r') as f: print('\n-----\n reading default values from %s\n-----'%configFile) for line in f: [key,value] = (re.split('[= ]',line)+[None,None])[:2] value = value.rstrip() if (not line.strip() or key.startswith('#')): pass if key == 'DAMASK_NUM_THREADS': defaults['DAMASK_NUM_THREADS'] = int(value) for theKey in ['F90','FFTW_ROOT','HDF5_ROOT','MSC_ROOT','spectralOptions']: if key == theKey: defaults[key] = value for theKey in reversed(BLAS_order): if key == theKey+'_ROOT' and (value != None or value != ''): defaults['blasType'] = key defaults['blasRoot'][key] = value except IOError: pass parser.add_option('--with-fc', dest='compiler', type='string', metavar='string', \ help='F90 compiler [%default]') parser.add_option('--with-fftw-dir', dest='fftwRoot', type='string', metavar='string', \ help='root directory of FFTW [%default]') parser.add_option('--with-msc-dir', dest='mscRoot', type='string', metavar='string', \ help='root directory of MSC.Marc/Mentat [%default]') parser.add_option('--with-HDF5-dir', dest='hdf5Root', type='string', metavar='string', \ help='root directory of HDF5 [%default]') parser.add_option('--with-OMP-threads', dest='threads', type='int', metavar='int',\ help='number of openMP threads [%default]') parser.add_option('--with-blas-type', dest='blasType', type='string', metavar='string', \ help='type of BLAS/LAPACK library [%default]') parser.add_option('--with-blas-dir', dest='blasRoot', type='string', metavar='string', \ help='root directory of BLAS/LAPACK library [%default]') parser.add_option('--with-spectral-options', dest='spectraloptions', type='string', action='extend', metavar='', \ help='options for compilation of spectral solver') parser.set_defaults(compiler = defaults['F90']) parser.set_defaults(fftwRoot = defaults['FFTW_ROOT']) parser.set_defaults(mscRoot = defaults['MSC_ROOT']) parser.set_defaults(hdf5Root = defaults['HDF5_ROOT']) parser.set_defaults(threads = defaults['DAMASK_NUM_THREADS']) parser.set_defaults(blasType = defaults['blasType']) #--- set default for blasRoot depending on current option (or default) for blasType -------------------- blasType = defaults['blasType'].upper() for i, arg in enumerate(sys.argv): if arg.startswith('--with-blas-type'): if arg.endswith('--with-blas-type'): blasType = sys.argv[i+1].upper() else: blasType = sys.argv[i][17:].upper() if blasType not in BLAS_order: blasType = 'LAPACK' parser.set_defaults(blasRoot = [defaults['blasRoot'][blasType]][0]) parser.set_defaults(spectraloptions = []) (options,filenames) = parser.parse_args() #--- consistency checks -------------------------------------------------------------------------------- options.compiler=options.compiler.lower() options.blasType=options.blasType.upper() options.fftwRoot=options.fftwRoot.rstrip('/') options.mscRoot =options.mscRoot.rstrip('/') options.hdf5Root=options.hdf5Root.rstrip('/') options.blasRoot=options.blasRoot.rstrip('/') if options.compiler not in ['ifort','gfortran']: print('Error: Unknown compiler option: %s'%options.compiler) sys.exit(1) if not subprocess.call(['which', options.compiler],stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: print('Compiler Warning: executable %s not found!'%options.compiler) fftwLocations =[os.path.join(options.fftwRoot,'lib'),os.path.join(options.fftwRoot,'lib64')] for lib in ['libfftw3.so','libfftw3.a',\ 'libfftw3_threads.so','libfftw3_threads.a']: if (not os.path.isfile(os.path.join(fftwLocations[0],lib))) and \ (not os.path.isfile(os.path.join(fftwLocations[1],lib))): print('FFTW Warning: %s not found in %s or %s!'%(lib,fftwLocations[0],fftwLocations[1])) if not os.path.isdir(options.mscRoot): print('MSC.Marc/Mentat Warning: Root directory %s not found!'%options.mscRoot) if options.blasType == 'LAPACK': lapackLocations =[os.path.join(options.blasRoot,'lib'),os.path.join(options.blasRoot,'lib64')] for lib in ['liblapack.so','liblapack.a']: if (not os.path.isfile(os.path.join(lapackLocations[0],lib))) and \ (not os.path.isfile(os.path.join(lapackLocations[1],lib))): print('LAPACK Warning: %s not found in %s or %s!'%(lib,lapackLocations[0],lapackLocations[1])) elif options.blasType == 'ACML': blasLocationSerial=os.path.join(options.blasRoot,'%s64/lib'%options.compiler) for lib in ['libacml.so','libacml.a']: if not os.path.isfile(os.path.join(blasLocationSerial,lib)): print('ACML Warning: %s not found in %s!'%(lib,blasLocationSerial)) blasLocationParallel=os.path.join(options.blasRoot,'%s64_mp/lib'%options.compiler) for lib in ['libacml_mp.so','libacml_mp.a']: if not os.path.isfile(os.path.join(blasLocationParallel,lib)): print('ACML Warning: %s not found in %s!'%(lib,blasLocationParallel)) elif options.blasType == 'IMKL': blasLocation=os.path.join(options.blasRoot,'lib/intel64') for lib in ['libmkl_core.so','libmkl_core.a',\ 'libmkl_sequential.so','libmkl_sequential.a',\ 'libmkl_intel_thread.so','libmkl_intel_thread.a',\ 'libmkl_intel_lp64.so','libmkl_intel_lp64.a',\ 'libmkl_gnu_thread.so','libmkl_gnu_thread.a',\ 'libmkl_gf_lp64.so','libmkl_gf_lp64.a']: if not os.path.isfile(os.path.join(blasLocation,lib)): print('IMKL Warning: %s not found in %s!'%(lib,blasLocation)) else: print('Error: Unknown BLAS/LAPACK library: %s'%options.blasType) sys.exit(1) #--- read config file if present to keep comments and order --------------------------------------- output = [] try: with open(configFile,'r') as f: for line in f: items = re.split('[= ]',line) if (not line.strip() or items[0].startswith('#')): pass if items[0] == 'F90': line = '%s=%s\n'%(items[0],options.compiler) options.compiler ='' if items[0] == 'FFTW_ROOT': line = '%s=%s\n'%(items[0],options.fftwRoot) options.fftwRoot ='' if items[0] == 'MSC_ROOT': line = '%s=%s\n'%(items[0],options.mscRoot) options.mscRoot ='' if items[0] == 'HDF5_ROOT': line = '%s=%s\n'%(items[0],options.hdf5Root) options.hdf5Root ='' if items[0] == 'DAMASK_NUM_THREADS': line = '%s=%s\n'%(items[0],options.threads) options.threads ='' for blasType in defaults['blasRoot'].keys(): if items[0] == '%s_ROOT'%blasType and items[0] == '%s_ROOT'%options.blasType: line = '%s=%s\n'%(items[0],options.blasRoot) options.blasType='' elif items[0] == '#%s_ROOT'%blasType and items[0] == '#%s_ROOT'%options.blasType: line = '%s=%s\n'%(items[0][1:],options.blasRoot) options.blasType='' elif items[0] == '%s_ROOT'%blasType: line = '#'+line for spectralOption in options.spectraloptions: [key,value] = re.split('[= ]',spectralOption)[0:2] if key == items[0]: line = '%s=%s\n'%(items[0],value) options.spectraloptions.remove(spectralOption) output.append(line) except IOError: pass #--- write remaining options -------------------------------------------------------------------------- for opt, value in options.__dict__.items(): if opt == 'compiler' and value !='': output.append('F90=%s\n'%value) if opt == 'fftwRoot' and value !='': output.append('FFTW_ROOT=%s\n'%value) if opt == 'mscRoot' and value !='': output.append('MSC_ROOT=%s\n'%value) if opt == 'hdf5Root' and value !='': output.append('HDF5_ROOT=%s\n'%value) if opt == 'threads' and value !='': output.append('DAMASK_NUM_THREADS=%s\n'%value) if opt == 'blasType' and value !='': output.append('%s_ROOT=%s\n'%(options.blasType,options.blasRoot)) for spectralOption in options.spectraloptions: output.append(spectralOption+'\n') #--- decide where do save the data ---------------------------------------------------------------------- root=os.access('/etc/', os.W_OK) if root: configFileNew = '/etc/damask.conf' else: configFileNew = os.path.join(os.getenv('HOME'),'.damask/damask.conf') if not os.path.isdir(os.path.join(os.getenv('HOME'),'.damask')): os.mkdir(os.path.join(os.getenv('HOME'),'.damask')) print('\n-----\n writing values to %s\n-----'%configFileNew) with open(configFileNew,'w') as f: for line in output: print(line.rstrip('\n')) f.write(line)