You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
530 lines
12 KiB
Python
530 lines
12 KiB
Python
1 year ago
|
#!/usr/bin/python3
|
||
|
|
||
|
#Python3 compilation library
|
||
|
#Aaron M. Schinder
|
||
|
#29 Dec 2020
|
||
|
#
|
||
|
#Cleanup and refactor from 2017 python2 version compilation libraries
|
||
|
|
||
|
import os,sys,math,subprocess
|
||
|
|
||
|
#####################
|
||
|
#Directory Functions#
|
||
|
#####################
|
||
|
|
||
|
##flist - list all files in a given directory pth
|
||
|
##optional arguments:
|
||
|
# recurse - (T/F): Whether to recursively search for files in directory tree
|
||
|
# exts - (list): A list of file extensions to filter on
|
||
|
# normpath (T/F): whether to normalize path variables after
|
||
|
#filelist = flist(pth,**kwargs):
|
||
|
def flist(pth,**kwargs):
|
||
|
flst = []
|
||
|
if(not('recurse' in kwargs)):
|
||
|
recurse_ = False
|
||
|
else:
|
||
|
recurse_ = kwargs['recurse']
|
||
|
if(not('exts' in kwargs)):
|
||
|
filterexts_ = False
|
||
|
else:
|
||
|
filterexts_ = True
|
||
|
exts = kwargs['exts']
|
||
|
if(not('normpath' in kwargs)):
|
||
|
normpath_ = True
|
||
|
else:
|
||
|
normpath_ = kwargs['normpath']
|
||
|
if(not('linuxpath' in kwargs)):
|
||
|
linuxpath_ = False
|
||
|
else:
|
||
|
linuxpath_ = kwargs['linuxpath']
|
||
|
if(not('followlinks' in kwargs)):
|
||
|
followlinks_ = False
|
||
|
else:
|
||
|
followlinks_ = kwargs['followlinks']
|
||
|
|
||
|
dirlist = []
|
||
|
rawlist = os.listdir(pth)
|
||
|
|
||
|
for F in rawlist:
|
||
|
F2 = os.path.join(pth,F)
|
||
|
if(os.path.isdir(F2)):
|
||
|
b = (followlinks_) or ((not followlinks_) and not(os.path.islink(F2)))
|
||
|
if(b):
|
||
|
if((F2!=".")&(F2!="..")):
|
||
|
dirlist.append(F2)
|
||
|
elif(os.path.isfile(F2)):
|
||
|
flst.append(F2)
|
||
|
|
||
|
#Recurse through directories
|
||
|
if(recurse_):
|
||
|
for D in dirlist:
|
||
|
lst = flist(D,**kwargs)
|
||
|
for L in lst:
|
||
|
flst.append(L)
|
||
|
|
||
|
#Postprocess:
|
||
|
#Filter out all extensions except the selected ext list
|
||
|
if(filterexts_):
|
||
|
flst = filterexts(flst,exts)
|
||
|
|
||
|
#Normalize filename path according to os
|
||
|
if(normpath_):
|
||
|
flst2 = list(flst)
|
||
|
for I in range(0,len(flst2)):
|
||
|
flst[I] = os.path.normpath(flst2[I])
|
||
|
|
||
|
#If linuxpath, convert all \\ to /
|
||
|
#if(linuxpath_):
|
||
|
# flst2 = list(flst)
|
||
|
# for I in range(0,len(flst2)):
|
||
|
# flst[I] = linuxpath(flst2[I])
|
||
|
|
||
|
return flst
|
||
|
|
||
|
#Filters by extensions in a list of files
|
||
|
#flst = def filterexts(flst,exts):
|
||
|
def filterexts(flst,exts):
|
||
|
flst2 = []
|
||
|
if(isinstance(exts,str)):
|
||
|
exts = list([exts])
|
||
|
for F in flst:
|
||
|
b = False
|
||
|
for ext in exts:
|
||
|
if(ext[0]!='.'):
|
||
|
ext = '.'+ext
|
||
|
F2 = os.path.splitext(F)
|
||
|
if(len(F2)>=2):
|
||
|
ex = F2[1]
|
||
|
if(len(ex)>0):
|
||
|
if(ex[0]!='.'):
|
||
|
ex = '.'+ex
|
||
|
if(ex==ext):
|
||
|
b = True
|
||
|
if(b):
|
||
|
flst2.append(F)
|
||
|
|
||
|
return flst2
|
||
|
|
||
|
#Find a file fname, starting in pth and recursing
|
||
|
#Used for finding library files to link
|
||
|
def findfile(fname,pth,**kwargs):
|
||
|
fullfname = ""
|
||
|
flst = flist(pth,recurse=True)
|
||
|
for F in flst:
|
||
|
F2 = os.path.split(F)[1]
|
||
|
if(F2 == fname):
|
||
|
fullfname = F
|
||
|
|
||
|
return fullfname
|
||
|
|
||
|
#List to space-seperated-string
|
||
|
def list_to_sss(lst):
|
||
|
lout = ""
|
||
|
for I in range(0,len(lst)-1):
|
||
|
lout = lout + lst[I] + " "
|
||
|
if(len(lst)>0):
|
||
|
lout = lout + lst[len(lst)-1]
|
||
|
return lout
|
||
|
|
||
|
def strip_whitespace(strin):
|
||
|
strout = ""
|
||
|
I1 = -1
|
||
|
I2 = -1
|
||
|
for I in range(0,len(strin)):
|
||
|
if(strin[I]!=' ' and strin[I]!='\t' and strin[I]!='\r'and strin[I]!='\n'):
|
||
|
I1 = I
|
||
|
break
|
||
|
q = list(range(0,len(strin)))
|
||
|
q.reverse()
|
||
|
for I in q:
|
||
|
if(strin[I]!=' ' and strin[I]!='\t' and strin[I]!='\r'and strin[I]!='\n'):
|
||
|
I2 = I+1
|
||
|
break
|
||
|
if(I1>=0 and I2>=0):
|
||
|
strout = strin[I1:I2]
|
||
|
return strout
|
||
|
|
||
|
def sss_to_list(sss):
|
||
|
lout = []
|
||
|
l1 = sss.split(' ')
|
||
|
for l in l1:
|
||
|
l2 = strip_whitespace(l)
|
||
|
lout.append(l2)
|
||
|
return lout
|
||
|
|
||
|
|
||
|
def replaceext(fname,ext):
|
||
|
fname2 = ""
|
||
|
if(len(ext)>0):
|
||
|
if(ext[0]!='.'):
|
||
|
ext = '.'+ext
|
||
|
fname2 = os.path.splitext(fname)[0]+ext
|
||
|
else:
|
||
|
fname2 = os.path.splitext(fname)[0]
|
||
|
return fname2
|
||
|
|
||
|
def replaceexts(fnamelist,ext):
|
||
|
fname2list = []
|
||
|
for F in fnamelist:
|
||
|
F2 = replaceext(F,ext)
|
||
|
fname2list.append(F2)
|
||
|
return fname2list
|
||
|
|
||
|
# def except_contains_oldv(lst1,exc):
|
||
|
# lst2 = []
|
||
|
# for item in lst1:
|
||
|
# b = 1
|
||
|
# for item2 in exc:
|
||
|
# if(item.find(item2)>=0):
|
||
|
# b = 0
|
||
|
# break
|
||
|
# if(b==1):
|
||
|
# lst2.append(item)
|
||
|
# return lst2
|
||
|
|
||
|
#filenames must match
|
||
|
def except_contains(lst1,exc):
|
||
|
lst2 = []
|
||
|
for item in lst1:
|
||
|
b = 1
|
||
|
for item2 in exc:
|
||
|
fsplit = os.path.split(item)
|
||
|
fn = fsplit[len(fsplit)-1]
|
||
|
if(fn==item2):
|
||
|
b = 0
|
||
|
break
|
||
|
if(b==1):
|
||
|
lst2.append(item)
|
||
|
return lst2
|
||
|
|
||
|
##########################
|
||
|
##System Call Procedures##
|
||
|
##########################
|
||
|
|
||
|
def callproc(cmd, **kwargs):
|
||
|
if(not('logfile' in kwargs)):
|
||
|
use_lf = False
|
||
|
else:
|
||
|
logfile = kwargs['logfile']
|
||
|
if(logfile!=""):
|
||
|
fp = open(kwargs['logfile'],'a+')
|
||
|
use_lf = True
|
||
|
else:
|
||
|
use_lf = False
|
||
|
|
||
|
if(not('echo' in kwargs)):
|
||
|
echo = True
|
||
|
else:
|
||
|
echo = kwargs['echo']
|
||
|
|
||
|
if(echo):
|
||
|
print(cmd)
|
||
|
|
||
|
#encoding/deconding to/from bytes is necessary to use the subprocess command
|
||
|
#in python3.7
|
||
|
cmd2 = cmd.encode(encoding='utf-8')
|
||
|
proc = subprocess.Popen(cmd2,stderr = subprocess.STDOUT, stdout=subprocess.PIPE, shell=True)
|
||
|
(out, err) = proc.communicate()
|
||
|
out = out.decode(encoding='utf-8')
|
||
|
|
||
|
if(echo):
|
||
|
print(out)
|
||
|
#print(err);
|
||
|
if(use_lf):
|
||
|
fp.writelines(cmd+'\n')
|
||
|
fp.writelines(out+'\n')
|
||
|
|
||
|
if(use_lf):
|
||
|
fp.close()
|
||
|
|
||
|
#######################################
|
||
|
##Compiler, Archive, and Linker Calls##
|
||
|
#######################################
|
||
|
|
||
|
def smartcompile(srcfile,objext='.o'):
|
||
|
mtsrc = os.path.getmtime(srcfile)
|
||
|
objfile = replaceext(srcfile,objext)
|
||
|
objexists = os.path.exists(objfile)
|
||
|
ret = True
|
||
|
if(objexists):
|
||
|
mtobj = os.path.getmtime(objfile)
|
||
|
if(mtobj>=mtsrc):
|
||
|
ret = False
|
||
|
|
||
|
return ret
|
||
|
|
||
|
#gnu-style compiler compile: Should work with gcc, g++, gfortran
|
||
|
def gs_compile(compiler,srcfile,**kwargs):
|
||
|
if(not('include' in kwargs)):
|
||
|
include = ''
|
||
|
else:
|
||
|
include = kwargs['include']
|
||
|
if(isinstance(include,list)):
|
||
|
include = list_to_sss(include)
|
||
|
|
||
|
if(not('flags' in kwargs)):
|
||
|
flags = ''
|
||
|
else:
|
||
|
flags = kwargs['flags']
|
||
|
if(isinstance(flags,list)):
|
||
|
flags = list_to_sss(flags)
|
||
|
|
||
|
if(not('objext' in kwargs)):
|
||
|
objext = '.o'
|
||
|
else:
|
||
|
objext = kwargs['objext']
|
||
|
|
||
|
if(not('srcfileflag' in kwargs)):
|
||
|
srcfileflag = '-c'
|
||
|
else:
|
||
|
srcfileflag = kwargs['srcfileflag']
|
||
|
|
||
|
if(not('outfileflag' in kwargs)):
|
||
|
outfileflag = '-o'
|
||
|
else:
|
||
|
outfileflag = kwargs['outfileflag']
|
||
|
|
||
|
if(not('logfile' in kwargs)):
|
||
|
logfile = ""
|
||
|
else:
|
||
|
logfile = kwargs['logfile']
|
||
|
|
||
|
if(not('smartcompile' in kwargs)):
|
||
|
_smartcompile = True
|
||
|
else:
|
||
|
_smartcompile = kwargs['smartcompile']
|
||
|
|
||
|
#Do I want to make this thing this general?
|
||
|
|
||
|
if(not(_smartcompile) or smartcompile(srcfile,objext)):
|
||
|
outfile = replaceext(srcfile,objext)
|
||
|
ln = compiler+" "+flags+" " + outfileflag+" "+outfile+" "+srcfileflag+" "+srcfile
|
||
|
ln = ln + " " + include
|
||
|
|
||
|
callproc(ln,echo=True,logfile=logfile)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gs_compile_list(compiler,srclist,**kwargs):
|
||
|
for S in srclist:
|
||
|
gs_compile(compiler,S,**kwargs)
|
||
|
return
|
||
|
|
||
|
def gs_compile_all(compiler,srcdir,srcexts,**kwargs):
|
||
|
if(not('recurse' in kwargs)):
|
||
|
recurse = True
|
||
|
else:
|
||
|
recurse = kwargs['recurse']
|
||
|
|
||
|
srcfils = flist(srcdir,exts=srcexts,recurse=recurse)
|
||
|
|
||
|
for S in srcfils:
|
||
|
gs_compile(compiler,S,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gs_link_all(linker,srcpath,target,**kwargs):
|
||
|
|
||
|
if(not('objext' in kwargs)):
|
||
|
objext = '.o'
|
||
|
else:
|
||
|
objext = kwargs['objext']
|
||
|
|
||
|
if(not('recurse' in kwargs)):
|
||
|
recurse = True
|
||
|
else:
|
||
|
recurse = kwargs['recurse']
|
||
|
|
||
|
|
||
|
objfils = flist(srcpath,exts=objext,recurse=recurse)
|
||
|
oflst = list_to_sss(objfils)
|
||
|
|
||
|
gs_link_list(linker,oflst,target,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gs_link_list(linker,objlist,target,**kwargs):
|
||
|
|
||
|
if(not('objext' in kwargs)):
|
||
|
objext = '.o'
|
||
|
else:
|
||
|
objext = kwargs['objext']
|
||
|
|
||
|
if(not('libdir' in kwargs)):
|
||
|
libdir = ''
|
||
|
else:
|
||
|
libdir = kwargs['libdir']
|
||
|
|
||
|
if(not('staticlibs' in kwargs)):
|
||
|
staticlibs = ''
|
||
|
else:
|
||
|
staticlibs = kwargs['staticlibs']
|
||
|
|
||
|
if(not('libflags' in kwargs)):
|
||
|
libflags = ''
|
||
|
else:
|
||
|
libflags = kwargs['libflags']
|
||
|
|
||
|
if(not('linkerflags' in kwargs)):
|
||
|
linkerflags = ''
|
||
|
else:
|
||
|
linkerflags = kwargs['linkerflags']
|
||
|
|
||
|
if(not('recurse' in kwargs)):
|
||
|
recurse = True
|
||
|
else:
|
||
|
recurse = kwargs['recurse']
|
||
|
|
||
|
if(not('logfile' in kwargs)):
|
||
|
logfile = ''
|
||
|
else:
|
||
|
logfile = kwargs['logfile']
|
||
|
|
||
|
ln = linker+" -o "+target+" "+libdir
|
||
|
ln = ln+" "+objlist+" "+staticlibs+" "+libflags+" "+linkerflags
|
||
|
|
||
|
callproc(ln,logfile=logfile)
|
||
|
return
|
||
|
|
||
|
|
||
|
def ar_all(srcpath,arname,**kwargs):
|
||
|
if(not('recurse' in kwargs)):
|
||
|
recurse = True
|
||
|
else:
|
||
|
recurse = kwargs['recurse']
|
||
|
if(not('objext' in kwargs)):
|
||
|
objext = '.o'
|
||
|
else:
|
||
|
objext = kwargs['objext']
|
||
|
|
||
|
objlist = flist(srcpath,exts=objext,recurse=recurse)
|
||
|
ar_list(objlist,arname,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def ar_list(objlist,arname,**kwargs):
|
||
|
objlist2 = list_to_sss(objlist)
|
||
|
|
||
|
ln = "ar cr "+ arname+" "+objlist2
|
||
|
callproc(ln)
|
||
|
|
||
|
return
|
||
|
|
||
|
def ar_add_list(objlist,arname,**kwargs):
|
||
|
objlist2 = list_to_sss(objlist)
|
||
|
|
||
|
ln = "ar t "+arname+" "+objlist2
|
||
|
callproc(ln)
|
||
|
return
|
||
|
|
||
|
##############################
|
||
|
##Derived Compiler Functions##
|
||
|
##############################
|
||
|
|
||
|
def gcc_compile(srcfile,**kwargs):
|
||
|
compiler = 'gcc'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.c']
|
||
|
|
||
|
gs_compile(compiler,srcfile,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gcc_compile_all(srcdir,**kwargs):
|
||
|
compiler = 'gcc'
|
||
|
kwargs['objext'] = '.o'
|
||
|
srcexts = ['.c']
|
||
|
|
||
|
gs_compile_all(compiler,srcdir,srcexts,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gcc_compile_list(srclist,**kwargs):
|
||
|
compiler = 'gcc'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.c']
|
||
|
|
||
|
gs_compile_list(compiler,srclist,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gpp_compile(srcfile,**kwargs):
|
||
|
compiler = 'g++'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.c','.cpp']
|
||
|
|
||
|
gs_compile(compiler,srcfile,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gpp_compile_all(srcdir,**kwargs):
|
||
|
compiler = 'g++'
|
||
|
kwargs['objext'] = '.o'
|
||
|
srcexts = ['.c','.cpp']
|
||
|
|
||
|
gs_compile_all(compiler,srcdir,srcexts,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gpp_compile_list(srclist,**kwargs):
|
||
|
compiler = 'g++'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.c','.cpp']
|
||
|
|
||
|
gs_compile_list(compiler,srclist,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gfortran_compile(srcfile,**kwargs):
|
||
|
compiler = 'gfortran'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.f','.f90','.f77']
|
||
|
|
||
|
gs_compile(compiler,srcfile,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gfortran_compile_all(srcdir,**kwargs):
|
||
|
compiler = 'gfortran'
|
||
|
kwargs['objext'] = '.o'
|
||
|
srcexts = ['.f','.f90','.f77']
|
||
|
|
||
|
gs_compile_all(compiler,srcdir,srcexts,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def gfortran_compile_list(srclist,**kwargs):
|
||
|
compiler = 'gfortran'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.f','.f90','.f77']
|
||
|
|
||
|
gs_compile_list(compiler,srclist,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def clang_compile(srcfile,**kwargs):
|
||
|
compiler = 'clang++'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.c','.cpp']
|
||
|
|
||
|
gs_compile(compiler,srcfile,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def clang_compile_all(srcdir,**kwargs):
|
||
|
compiler = 'clang++'
|
||
|
kwargs['objext'] = '.o'
|
||
|
srcexts = ['.c','.cpp']
|
||
|
|
||
|
gs_compile_all(compiler,srcdir,srcexts,**kwargs)
|
||
|
|
||
|
return
|
||
|
|
||
|
def clang_compile_list(srclist,**kwargs):
|
||
|
compiler = 'clang++'
|
||
|
kwargs['objext'] = '.o'
|
||
|
#srcexts = ['.c','.cpp']
|
||
|
|
||
|
gs_compile_list(compiler,srclist,**kwargs)
|
||
|
|
||
|
return
|