#! /usr/bin/python #+ # NAME: # mk # CALLING SEQUENCE: # mk.py main sub1 sub2 ... -dir= # INPUTS: # main sub1 sub2 ... # name of main program, followed by additional # files needed for the compilation. # The file type, if specified, is ignored and is # replaced by .f # OPTIONAL INPUTS: # -g77 use g77 compiler # -intel use Intel Fortran 90 compiler # -pgi use Portland compiler # -absoft use Absoft Fortran compiler # # -nogen do not include the forgen library # -nofits do not include the cfitsio library # -noincl do not use default include paths # # If none of these command line switches is set then # the script will try to locate g77 first, then the Intel # compiler. # # -dir=dir destination directory for object files or executable/ # The default destination is the current directory. # -cc include libraries for linking C/C++ code # -static adds switch -static to compile command # -obj only creates object files (used by olb script) # -verbose verbose mode # OUTPUTS: # The executable will be named 'main' (the name of the main program). # RESTRICTIONS: # The g77 command includes the switches # -ffixed-line-length-none # SIDE EFFECTS: # Cannot be executed in the 'root' account. # # Include directories: # $SMEI_FOR/h, $SMEI_FOR/h/linux and $SMEI/for/h # Library directory : # Libraries should be located in $SMEI_LIB or $FOR # Two libraries are expected: gen and cfitsio. # $SMEI_LIB should always contain these. # MODIFICATION HISTORY: # JAN-2000, Paul Hick (UCSD/CASS) # JAN-2001, Paul Hick (UCSD/CASS) # Added loop to handle compilation of multiple files. # SEP-2002, Paul Hick (UCSD/CASS) # Removed -fdollar-ok option from g77 compilations (all dollar # signs in variable names should have been removed by now). # DEC-2003, Paul Hick (UCSD/CASS) # Added -lcfitsio to compile command (for Fortran FITS routines). # MAY-2004, Paul Hick (UCSD/CASS) # Modifications to get this to run on the stesun Unix machines. # Use awk instead of gawk (on our Linux boxes awk is a soft link # to gawk). Changed the syntax for variable assignment from # awk -v i=$i '{print $i}' to awk '{print $i}' i=$i # The first one doesn't work properly on the stesun machines. # JUL-2004, Paul Hick (UCSD/CASS) # Added -Vaxlib switch for Intel compiler # SEP-2004, Paul Hick (UCSD/CASS) # The default location for the libgen library is now $SMEI_LIB # (was $FOR). # OCT-2004, Paul Hick (UCSD/CASS) # Added Portland compiler. # JAN-2005, Paul Hick (UCSD/CASS) # Added -cc switch (will add a couple of C/C++ libraries # needed to cross compile Fortran and C/C++ code). # JAN-2005, Paul Hick (UCSD/CASS) # Converted from bash to Python. # JUL-2005, Paul Hick (UCSD/CASS) # Added code to handle .o, .c and .cpp files # The main program still must be a Fortran program. # MAR-2007, Paul Hick (UCSD/CASS) # SpatialIndex library is no longer included for linking. # OCT-2007, Paul Hick (UCSD/CASS; pphick@ucsd.edu) # Added -nogen and -nofits keyword # Added test for existence of get_compiler_ function. # If it exists already, use it. If not, create one. # Previously the file was always created, resulting with # a conflict with an existing one. #- import os from tiny import is_there, start, args, hide_env, which, run_cmd def set_compiler( f77id ): import tempfile tempfile.tempdir = os.environ['TUB'] tempfile = tempfile.mktemp('get_compiler.f') content = [ \ ' subroutine get_compiler(f77id)' , \ ' character f77id*(*)' , \ " f77id = '"+f77id+"'" , \ ' return' , \ ' end' ] (open(tempfile,'w')).write('\n'.join(content)) return tempfile def mk( argv ): no_result = dict ( [ ('f77', []), ('obj', []) ] ) say = 'mk, ' user = os.environ['USER'] if user == 'root': print say+'do not use from root account' return no_result # Check for keywords incl_cc = is_there( '-cc' , argv ) static = is_there( '-static', argv ) verbose = is_there( '-verbose',argv ) obj = is_there( '-obj' , argv ) all = is_there( '-all' , argv ) nogen = is_there( '-nogen' , argv ) nofits = is_there( '-nofits', argv ) noincl = is_there( '-noincl', argv ) out_dir = start ( '-dir=' , argv ) if out_dir == '': to_remote = False out_dir = os.environ['PWD'] else: to_remote = out_dir.find( ':' ) != -1 if to_remote: remote_dir = out_dir out_dir = os.environ['TUB'] fortran_files = [] cminus_files = [] cplus_files = [] object_files = [] if all: names = os.listdir( os.environ['PWD'] ) for name in names: tmp = os.path.splitext( name ) if tmp[1] == '.f': fortran_files.append( tmp[0] ) if tmp[1] == '.c': cminus_files.append ( tmp[0] ) if tmp[1] == '.cpp': cplus_files.append ( tmp[0] ) if tmp[1] == '.o': object_files.append ( name ) found = 0 for main in fortran_files: tmp = (open( os.path.join( '.', main+'.f') )).read() tmp = tmp.split('\n') for line in tmp: if len(line) > 9: found = line.expandtabs(7).lower().find(' program ') == 0 if found: break if found: break else: print say+'no main program found' return no_result fortran_files.remove(main) fortran_files.insert(0,main) else: names = args( argv ) names = names[1:len(names)] for name in names: tmp = os.path.splitext( name ) if tmp[1] == '.f' or tmp[1] == '': fortran_files.append( tmp[0] ) if tmp[1] == '.c': cminus_files.append ( tmp[0] ) if tmp[1] == '.cpp': cplus_files.append ( tmp[0] ) if tmp[1] == '.o': object_files.append ( name ) if len(fortran_files) == 0: print say+'usage: mk.py main file1 file2 -dir=' return no_result if not os.path.isdir( out_dir ): # Exit if out_dir does not exist print say+hide_env(out_dir)+' does not exist' return no_result if is_there( '-g77' , argv ): f77 = 'g77' elif is_there( '-gfortran', argv ): f77 = 'gfortran' elif is_there( '-intel' , argv ): f77 = 'ifort' elif is_there( '-pgi' , argv ): f77 = 'pgf77' elif is_there( '-absoft' , argv ): f77 = 'abf77' else: f77 = '' if f77 != '': f77_save = f77 if which( f77 ) == '': f77 = '' if f77_save == 'ifort': if which( 'ifc' ) != '': f77 = 'ifc' if f77 == '': print say+'compiler '+f77_save+' not available' return no_result elif which( 'g77' ): f77 = 'g77' elif which( 'gfortran' ): f77 = 'gfortran' elif which( 'ifort' ): f77 = 'ifort' elif which( 'ifc' ): f77 = 'ifc' elif which( 'pgf77' ): f77 = 'pgf77' elif which( 'abf77' ): f77 = 'abf77' else: print say+'no Fortran compiler found' return no_result if f77 == 'g77': cc = 'gcc' cpp = 'g++' elif f77 == 'gfortran': cc = 'gcc' cpp = 'g++' elif f77 == 'ifort': cc = 'icc' cpp = 'icpc' elif f77 == 'pgf77': cc = 'pgcc' cpp = 'pgCC' elif f77 == 'abf77': cc = '' cpp = '' f77link = [] if f77 == 'g77': f77cc = f77+' -w -ffixed-line-length-none' f77id = '_'+os.environ['GNU_COMPILER'] elif f77 == 'gfortran': f77cc = f77+' -w -ffixed-line-length-none' f77id = '_'+os.environ['GNU_COMPILER'] elif f77 == 'ifc': f77cc = f77+' -w -132' f77id = '_'+os.environ['INTEL_COMPILER'] f77link.append('-Vaxlib') elif f77 == 'ifort': f77cc = f77+' -w -132 -assume byterecl' f77id = '_'+os.environ['INTEL_COMPILER'] f77link.append('-Vaxlib') # Fix known bug in V9.0 compiler. # http://support.intel.com/support/performancetools/fortran/linux/sb/CS-021696.htm if os.environ['INTEL_COMPILER'].find('intel_9.0') != -1: f77link.append('-no-ipo') # Suppress warning messages for unused statment function declarations if os.environ['INTEL_COMPILER'].find('intel_9.1') != -1: f77cc = f77cc+' -warn nouncalled' elif f77 == 'pgf77': f77cc = f77+' -w -Mextend' f77id = '_'+os.environ['PGI_COMPILER'] elif f77 == 'abf77': f77cc = f77+' -W -V -N109' f77id = '_'+os.environ['ABSOFT_COMPILER'] f77link.append('-lU77') f77link.append('-lV77') print say+'using '+which( f77 ) # Kludges needed to cross compile with C/C++ if incl_cc: if f77 == 'g77': f77link.append('-lstdc++') elif f77 == 'gfortran': f77link.append('-lstdc++') elif f77 == 'ifort': f77link.append('-cxxlib-gcc') f77link.append('-lstdc++') elif f77 == 'pgf77': f77link.append('-lC') f77link.append('-lstd') if noincl: include_f77 = '' else: include_f77 = '-I'+os.path.join(os.environ['SMEI'],'for','h')+\ ' -I'+os.path.join(os.environ['SMEI_FOR'],'h')+\ ' -I'+os.path.join(os.environ['SMEI_FOR'],'h','linux') #include_cminus = '-I'+os.path.join(os.environ['SMEI'],'cpp','htmIndex20','include') #include_cplus = '-I'+os.path.join(os.environ['SMEI'],'cpp','htmIndex20','include') if static: f77link.append('-static') sources = [] objects = [] top_dirs = [ 'PWD','FOR','SMEI_FOR'] source_dirs = [] for source_dir in top_dirs: if os.environ.has_key( source_dir ): tmp = os.environ[ source_dir ] if os.path.isdir( tmp ): source_dirs.append( tmp ) for entry in fortran_files: base_name = os.path.splitext(entry) if base_name[1] == '.f': base_name = base_name[0] else: base_name = entry found = 0 for source_dir in source_dirs: for root, dirs, files in os.walk( source_dir ): for tmp in ['win','unix','vms','CVS']: if dirs.count(tmp) == 1: dirs.remove(tmp) found = files.count( base_name+'.f' ) == 1 if found: source = os.path.join( root, base_name+'.f' ) sources.append( source ) print say+hide_env(source) object = os.path.join( out_dir, base_name+'.o' ) cmd = 'rm -f '+object+'; '+f77cc+' -c '+include_f77+' '+source+' -o'+object run_cmd( cmd, verbose) if os.path.isfile( object ): objects.append( object ) else: if not obj and entry == fortran_files[0]: print say+' error compiling main program' return break if found: break top_dirs = [ 'PWD','SMEI_CPP'] source_dirs = [] for source_dir in top_dirs: if os.environ.has_key( source_dir ): tmp = os.environ[ source_dir ] if os.path.isdir( tmp ): source_dirs.append( tmp ) for entry in cminus_files: base_name = os.path.splitext(entry) if base_name[1] == '.c': base_name = base_name[0] else: base_name = entry found = 0 for source_dir in source_dirs: for root, dirs, files in os.walk( source_dir ): for tmp in ['CVS']: if dirs.count(tmp) == 1: dirs.remove(tmp) found = files.count( base_name+'.c' ) == 1 if found: source = os.path.join( root, base_name+'.c' ) sources.append( source ) print say+hide_env(source) object = os.path.join( out_dir, base_name+'.o' ) #cmd = 'rm -f '+object+'; '+cc+' -c '+include_cminus+' '+source+' -o'+object cmd = 'rm -f '+object+'; '+cc+' -c '+source+' -o'+object run_cmd( cmd, verbose) if os.path.isfile( object ): objects.append( object ) break if found: break top_dirs = [ 'PWD','SMEI_CPP'] source_dirs = [] for source_dir in top_dirs: if os.environ.has_key( source_dir ): tmp = os.environ[ source_dir ] if os.path.isdir( tmp ): source_dirs.append( tmp ) for entry in cplus_files: base_name = os.path.splitext(entry) if base_name[1] == '.cpp': base_name = base_name[0] else: base_name = entry found = 0 for source_dir in source_dirs: for root, dirs, files in os.walk( source_dir ): for tmp in ['CVS']: if dirs.count(tmp) == 1: dirs.remove(tmp) found = files.count( base_name+'.cpp' ) == 1 if found: source = os.path.join( root, base_name+'.cpp' ) sources.append( source ) print say+hide_env(source) object = os.path.join( out_dir, base_name+'.o' ) #cmd = 'rm -f '+object+'; '+cpp+' -c '+include_cplus+' '+source+' -o'+object cmd = 'rm -f '+object+'; '+cpp+' -c '+' '+source+' -o'+object run_cmd( cmd, verbose) if os.path.isfile( object ): objects.append( object ) break if found: break objects.extend(object_files) if len(sources) == 0: print say+'no source file(s) specified' return no_result if len(objects) == 0: print say+'no objects file(s) created' return no_result if obj: status = dict ( [ ('f77', [f77,f77cc,f77id]), ('obj', objects) ] ) return status # Extract the file name part as name for the executable exename = start ( '-name=' , argv ) if exename == '': exename = fortran_files[0] exename = (os.path.split (exename))[1] exename = (os.path.splitext(exename))[0] exename = os.path.join(out_dir,exename) libsdir = ['-L'+os.environ['SMEI_LIB']] if os.environ.has_key('FOR'): tmp = os.environ['FOR'] if os.path.isdir( tmp ): libsdir.append( '-L'+tmp ) all_libs = [] if not nogen : all_libs.append( 'gen' ) if not nofits: all_libs.append( 'cfitsio' ) libs = [] for lib in all_libs: tmp = os.path.join(os.environ['SMEI_LIB'],'lib'+lib+f77id+'.a') if os.path.isfile( tmp ): libs.append( '-l'+lib+f77id ) else: print say+hide_env(tmp)+' not found' source = 'get_compiler_'+f77id if fortran_files.count(source) == 0: source = set_compiler(f77id) object = os.path.splitext(source)[0]+'.o' cmd = f77cc+' -c '+source+' -o'+object run_cmd( cmd, verbose) if os.path.isfile( object ): objects.append( object ) os.remove(source) cmd = f77cc+ \ ' '+include_f77 + \ ' '+' '.join(libsdir)+ \ ' '+' '.join(objects)+ \ ' '+' '.join(libs) + \ ' '+' '.join(f77link)+ \ ' -o'+exename run_cmd( cmd, verbose) if os.path.isfile(exename): print say+'exec: '+hide_env(exename) if to_remote: run_cmd( 'scp '+exename+' '+remote_dir, True ) os.remove(exename) else: print say+'fail: '+hide_env(exename) run_cmd( 'rm -f '+' '.join(objects), verbose ) status = dict ( [ ('f77', [f77,f77cc,f77id]), ('exe', exename) ] ) return status if __name__ == '__main__': import sys mk( sys.argv ) sys.exit()