1*df3bd252SSatish Balay#!/usr/bin/env python3 20ee81e68SLisandro Dalcin 30ee81e68SLisandro Dalcinimport os 4becf0a19SJed Brownfrom sysconfig import _parse_makefile as parse_makefile 50ee81e68SLisandro Dalcinimport sys 60ee81e68SLisandro Dalcinimport logging 70ee81e68SLisandro Dalcinsys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) 87b8851e6SJed Brownfrom collections import defaultdict 90ee81e68SLisandro Dalcin 10b892d579SJed BrownAUTODIRS = set('ftn-auto ftn-custom f90-custom ftn-auto-interfaces'.split()) # Automatically recurse into these, if they exist 11f22bedf1SBarry SmithSKIPDIRS = set('benchmarks build'.split()) # Skip these during the build 12dc0529c6SBarry SmithNOWARNDIRS = set('tests tutorials'.split()) # Do not warn about mismatch in these 13dc0529c6SBarry Smith 14dc0529c6SBarry Smithdef pathsplit(path): 15dc0529c6SBarry Smith """Recursively split a path, returns a tuple""" 16dc0529c6SBarry Smith stem, basename = os.path.split(path) 17dc0529c6SBarry Smith if stem == '': 18dc0529c6SBarry Smith return (basename,) 19dc0529c6SBarry Smith if stem == path: # fixed point, likely '/' 20dc0529c6SBarry Smith return (path,) 21dc0529c6SBarry Smith return pathsplit(stem) + (basename,) 22dc0529c6SBarry Smith 23c0558f20SBarry Smithdef getlangext(name): 24c0558f20SBarry Smith """Returns everything after the first . in the filename, including the .""" 25c0558f20SBarry Smith file = os.path.basename(name) 26c0558f20SBarry Smith loc = file.find('.') 27c0558f20SBarry Smith if loc > -1: return file[loc:] 28c0558f20SBarry Smith else: return '' 29c0558f20SBarry Smith 30c0558f20SBarry Smithdef getlangsplit(name): 31c0558f20SBarry Smith """Returns everything before the first . in the filename, excluding the .""" 32c0558f20SBarry Smith file = os.path.basename(name) 33c0558f20SBarry Smith loc = file.find('.') 34c0558f20SBarry Smith if loc > -1: return os.path.join(os.path.dirname(name),file[:loc]) 35c0558f20SBarry Smith raise RuntimeError("No . in filename") 36c0558f20SBarry Smith 37dc0529c6SBarry Smithclass Mistakes(object): 38dc0529c6SBarry Smith def __init__(self, log, verbose=False): 39dc0529c6SBarry Smith self.mistakes = [] 40dc0529c6SBarry Smith self.verbose = verbose 41dc0529c6SBarry Smith self.log = log 42dc0529c6SBarry Smith 43dc0529c6SBarry Smith def compareDirLists(self,root, mdirs, dirs): 44dc0529c6SBarry Smith if NOWARNDIRS.intersection(pathsplit(root)): 45dc0529c6SBarry Smith return 46dc0529c6SBarry Smith smdirs = set(mdirs) 47dc0529c6SBarry Smith sdirs = set(dirs).difference(AUTODIRS) 48dc0529c6SBarry Smith if not smdirs.issubset(sdirs): 49cca3327aSJed Brown self.mistakes.append('%s/makefile contains a directory not on the filesystem: %r' % (root, sorted(smdirs - sdirs))) 50dc0529c6SBarry Smith if not self.verbose: return 51dc0529c6SBarry Smith if smdirs != sdirs: 52dc0529c6SBarry Smith from sys import stderr 53dc0529c6SBarry Smith stderr.write('Directory mismatch at %s:\n\t%s: %r\n\t%s: %r\n\t%s: %r\n' 54dc0529c6SBarry Smith % (root, 55dc0529c6SBarry Smith 'in makefile ',sorted(smdirs), 56dc0529c6SBarry Smith 'on filesystem ',sorted(sdirs), 57dc0529c6SBarry Smith 'symmetric diff',sorted(smdirs.symmetric_difference(sdirs)))) 58dc0529c6SBarry Smith 59dc0529c6SBarry Smith def compareSourceLists(self, root, msources, files): 60dc0529c6SBarry Smith if NOWARNDIRS.intersection(pathsplit(root)): 61dc0529c6SBarry Smith return 62dc0529c6SBarry Smith smsources = set(msources) 63d23021a0SBarry Smith ssources = set(f for f in files if getlangext(f) in ['.c', '.kokkos.cxx','.cxx', '.cc', '.cu', '.cpp', '.F', '.F90', '.hip.cpp', '.sycl.cxx', 'raja.cxx']) 64dc0529c6SBarry Smith if not smsources.issubset(ssources): 65a943032dSBarry Smith self.mistakes.append('%s/makefile contains a file not on the filesystem: %r' % (root, sorted(smsources - ssources))) 66dc0529c6SBarry Smith if not self.verbose: return 67dc0529c6SBarry Smith if smsources != ssources: 68dc0529c6SBarry Smith from sys import stderr 69dc0529c6SBarry Smith stderr.write('Source mismatch at %s:\n\t%s: %r\n\t%s: %r\n\t%s: %r\n' 70dc0529c6SBarry Smith % (root, 71dc0529c6SBarry Smith 'in makefile ',sorted(smsources), 72dc0529c6SBarry Smith 'on filesystem ',sorted(ssources), 73dc0529c6SBarry Smith 'symmetric diff',sorted(smsources.symmetric_difference(ssources)))) 74dc0529c6SBarry Smith 75dc0529c6SBarry Smith def summary(self): 76dc0529c6SBarry Smith for m in self.mistakes: 77dc0529c6SBarry Smith self.log.write(m + '\n') 78dc0529c6SBarry Smith if self.mistakes: 79a943032dSBarry Smith raise RuntimeError('\n\nThe PETSc makefiles contain mistakes or files are missing on the filesystem.\n%s\nPossible reasons:\n\t1. Files were deleted locally, try "git checkout filename", where "filename" is the missing file.\n\t2. Files were deleted from the repository, but were not removed from the makefile. Send mail to petsc-maint@mcs.anl.gov.\n\t3. Someone forgot to "add" new files to the repository. Send mail to petsc-maint@mcs.anl.gov.\n\n' % ('\n'.join(self.mistakes))) 80dc0529c6SBarry Smith 81dc0529c6SBarry Smithdef stripsplit(line): 82dc0529c6SBarry Smith return line[len('#requires'):].replace("'","").split() 83dc0529c6SBarry Smith 8447fd361eSStefano ZampiniPetscPKGS = 'sys vec mat dm ksp snes ts tao'.split() 85c0558f20SBarry Smith# the key is actually the language suffix, it won't work for suffixes such as 'kokkos.cxx' so use an _ and replace the _ as needed with . 8659af0bd3SScott KrugerLANGS = dict(kokkos_cxx='KOKKOS', c='C', cxx='CXX', cpp='CPP', cu='CU', F='F', 8750dcbc5aSJunchao Zhang F90='F90', hip_cpp='HIP', sycl_cxx='SYCL', raja_cxx='RAJA') 880ee81e68SLisandro Dalcin 890ee81e68SLisandro Dalcinclass debuglogger(object): 900ee81e68SLisandro Dalcin def __init__(self, log): 910ee81e68SLisandro Dalcin self._log = log 920ee81e68SLisandro Dalcin 930ee81e68SLisandro Dalcin def write(self, string): 940ee81e68SLisandro Dalcin self._log.debug(string) 950ee81e68SLisandro Dalcin 960ee81e68SLisandro Dalcinclass Petsc(object): 9747fd361eSStefano Zampini def __init__(self, petsc_dir=None, petsc_arch=None, pkg_dir=None, pkg_name=None, pkg_arch=None, pkg_pkgs=None, verbose=False): 980ee81e68SLisandro Dalcin if petsc_dir is None: 990ee81e68SLisandro Dalcin petsc_dir = os.environ.get('PETSC_DIR') 1000ee81e68SLisandro Dalcin if petsc_dir is None: 1010ee81e68SLisandro Dalcin try: 102af0996ceSBarry Smith petsc_dir = parse_makefile(os.path.join('lib','petsc','conf', 'petscvariables')).get('PETSC_DIR') 1030ee81e68SLisandro Dalcin finally: 1040ee81e68SLisandro Dalcin if petsc_dir is None: 1050ee81e68SLisandro Dalcin raise RuntimeError('Could not determine PETSC_DIR, please set in environment') 1060ee81e68SLisandro Dalcin if petsc_arch is None: 1070ee81e68SLisandro Dalcin petsc_arch = os.environ.get('PETSC_ARCH') 1080ee81e68SLisandro Dalcin if petsc_arch is None: 1090ee81e68SLisandro Dalcin try: 110af0996ceSBarry Smith petsc_arch = parse_makefile(os.path.join(petsc_dir, 'lib','petsc','conf', 'petscvariables')).get('PETSC_ARCH') 1110ee81e68SLisandro Dalcin finally: 1120ee81e68SLisandro Dalcin if petsc_arch is None: 1130ee81e68SLisandro Dalcin raise RuntimeError('Could not determine PETSC_ARCH, please set in environment') 114add6df95SStefano Zampini self.petsc_dir = os.path.normpath(petsc_dir) 115add6df95SStefano Zampini self.petsc_arch = petsc_arch.rstrip(os.sep) 116add6df95SStefano Zampini self.pkg_dir = pkg_dir 117add6df95SStefano Zampini self.pkg_name = pkg_name 118c4bccdb5SStefano Zampini self.pkg_arch = pkg_arch 119add6df95SStefano Zampini if self.pkg_dir is None: 120add6df95SStefano Zampini self.pkg_dir = petsc_dir 121add6df95SStefano Zampini self.pkg_name = 'petsc' 122c4bccdb5SStefano Zampini self.pkg_arch = self.petsc_arch 123add6df95SStefano Zampini if self.pkg_name is None: 124add6df95SStefano Zampini self.pkg_name = os.path.basename(os.path.normpath(self.pkg_dir)) 125c4bccdb5SStefano Zampini if self.pkg_arch is None: 126c4bccdb5SStefano Zampini self.pkg_arch = self.petsc_arch 12747fd361eSStefano Zampini self.pkg_pkgs = PetscPKGS 12847fd361eSStefano Zampini if pkg_pkgs is not None: 12947fd361eSStefano Zampini self.pkg_pkgs += list(set(pkg_pkgs.split(','))-set(self.pkg_pkgs)) 13047fd361eSStefano Zampini self.read_conf() 1318e69c5ecSJed Brown try: 132add6df95SStefano Zampini logging.basicConfig(filename=self.pkg_arch_path('lib',self.pkg_name,'conf', 'gmake.log'), level=logging.DEBUG) 1338e69c5ecSJed Brown except IOError: 1348e69c5ecSJed Brown # Disable logging if path is not writeable (e.g., prefix install) 1358e69c5ecSJed Brown logging.basicConfig(filename='/dev/null', level=logging.DEBUG) 1360ee81e68SLisandro Dalcin self.log = logging.getLogger('gmakegen') 1370ee81e68SLisandro Dalcin self.mistakes = Mistakes(debuglogger(self.log), verbose=verbose) 1380ee81e68SLisandro Dalcin self.gendeps = [] 1390ee81e68SLisandro Dalcin 1400ee81e68SLisandro Dalcin def arch_path(self, *args): 1410ee81e68SLisandro Dalcin return os.path.join(self.petsc_dir, self.petsc_arch, *args) 1420ee81e68SLisandro Dalcin 143add6df95SStefano Zampini def pkg_arch_path(self, *args): 144c4bccdb5SStefano Zampini return os.path.join(self.pkg_dir, self.pkg_arch, *args) 145add6df95SStefano Zampini 1460ee81e68SLisandro Dalcin def read_conf(self): 1470ee81e68SLisandro Dalcin self.conf = dict() 148021a2b48SJed Brown with open(self.arch_path('include', 'petscconf.h')) as petscconf_h: 149021a2b48SJed Brown for line in petscconf_h: 1500ee81e68SLisandro Dalcin if line.startswith('#define '): 1510ee81e68SLisandro Dalcin define = line[len('#define '):] 1520ee81e68SLisandro Dalcin space = define.find(' ') 1530ee81e68SLisandro Dalcin key = define[:space] 1540ee81e68SLisandro Dalcin val = define[space+1:] 1550ee81e68SLisandro Dalcin self.conf[key] = val 156af0996ceSBarry Smith self.conf.update(parse_makefile(self.arch_path('lib','petsc','conf', 'petscvariables'))) 15747fd361eSStefano Zampini # allow parsing package additional configurations (if any) 15847fd361eSStefano Zampini if self.pkg_name != 'petsc' : 15947fd361eSStefano Zampini f = self.pkg_arch_path('include', self.pkg_name + 'conf.h') 16047fd361eSStefano Zampini if os.path.isfile(f): 161021a2b48SJed Brown with open(self.pkg_arch_path('include', self.pkg_name + 'conf.h')) as pkg_conf_h: 162021a2b48SJed Brown for line in pkg_conf_h: 16347fd361eSStefano Zampini if line.startswith('#define '): 16447fd361eSStefano Zampini define = line[len('#define '):] 16547fd361eSStefano Zampini space = define.find(' ') 16647fd361eSStefano Zampini key = define[:space] 16747fd361eSStefano Zampini val = define[space+1:] 16847fd361eSStefano Zampini self.conf[key] = val 16947fd361eSStefano Zampini f = self.pkg_arch_path('lib',self.pkg_name,'conf', self.pkg_name + 'variables') 17047fd361eSStefano Zampini if os.path.isfile(f): 17147fd361eSStefano Zampini self.conf.update(parse_makefile(self.pkg_arch_path('lib',self.pkg_name,'conf', self.pkg_name + 'variables'))) 1720ee81e68SLisandro Dalcin self.have_fortran = int(self.conf.get('PETSC_HAVE_FORTRAN', '0')) 1730ee81e68SLisandro Dalcin 1740ee81e68SLisandro Dalcin def inconf(self, key, val): 1750ee81e68SLisandro Dalcin if key in ['package', 'function', 'define']: 1760ee81e68SLisandro Dalcin return self.conf.get(val) 1770ee81e68SLisandro Dalcin elif key == 'precision': 1780ee81e68SLisandro Dalcin return val == self.conf['PETSC_PRECISION'] 1790ee81e68SLisandro Dalcin elif key == 'scalar': 1800ee81e68SLisandro Dalcin return val == self.conf['PETSC_SCALAR'] 1810ee81e68SLisandro Dalcin elif key == 'language': 1820ee81e68SLisandro Dalcin return val == self.conf['PETSC_LANGUAGE'] 1830ee81e68SLisandro Dalcin raise RuntimeError('Unknown conf check: %s %s' % (key, val)) 1840ee81e68SLisandro Dalcin 1850ee81e68SLisandro Dalcin def relpath(self, root, src): 186add6df95SStefano Zampini return os.path.relpath(os.path.join(root, src), self.pkg_dir) 1870ee81e68SLisandro Dalcin 1880ee81e68SLisandro Dalcin def get_sources(self, makevars): 1890ee81e68SLisandro Dalcin """Return dict {lang: list_of_source_files}""" 1900ee81e68SLisandro Dalcin source = dict() 1910ee81e68SLisandro Dalcin for lang, sourcelang in LANGS.items(): 192c0558f20SBarry Smith source[lang] = [f for f in makevars.get('SOURCE'+sourcelang,'').split() if f.endswith(lang.replace('_','.'))] 19359af0bd3SScott Kruger 19459af0bd3SScott Kruger #source[lang] = [f for f in makevars.get('SOURCE'+sourcelang,'').split() if f.endswith(lang)] 19559af0bd3SScott Kruger#SEK source[lang] = [f for f in 19659af0bd3SScott Kruger#SEK makevars.get('SOURCE'+sourcelang,'').split() if 19759af0bd3SScott Kruger#SEK f.endswith(LANGSEXT[lang])] 1980ee81e68SLisandro Dalcin return source 1990ee81e68SLisandro Dalcin 2000ee81e68SLisandro Dalcin def gen_pkg(self, pkg): 2010ee81e68SLisandro Dalcin pkgsrcs = dict() 2020ee81e68SLisandro Dalcin for lang in LANGS: 2030ee81e68SLisandro Dalcin pkgsrcs[lang] = [] 204add6df95SStefano Zampini for root, dirs, files in os.walk(os.path.join(self.pkg_dir, 'src', pkg)): 20509a6cbfcSBernhard M. Wiedemann dirs.sort() 20609a6cbfcSBernhard M. Wiedemann files.sort() 2070ee81e68SLisandro Dalcin makefile = os.path.join(root,'makefile') 2080ee81e68SLisandro Dalcin if not os.path.exists(makefile): 2090ee81e68SLisandro Dalcin dirs[:] = [] 2100ee81e68SLisandro Dalcin continue 211021a2b48SJed Brown with open(makefile) as mklines: 2120ee81e68SLisandro Dalcin conditions = set(tuple(stripsplit(line)) for line in mklines if line.startswith('#requires')) 2130ee81e68SLisandro Dalcin if not all(self.inconf(key, val) for key, val in conditions): 2140ee81e68SLisandro Dalcin dirs[:] = [] 2150ee81e68SLisandro Dalcin continue 2160ee81e68SLisandro Dalcin makevars = parse_makefile(makefile) 2170ee81e68SLisandro Dalcin mdirs = makevars.get('DIRS','').split() # Directories specified in the makefile 2180ee81e68SLisandro Dalcin self.mistakes.compareDirLists(root, mdirs, dirs) # diagnostic output to find unused directories 2190ee81e68SLisandro Dalcin candidates = set(mdirs).union(AUTODIRS).difference(SKIPDIRS) 2200ee81e68SLisandro Dalcin dirs[:] = list(candidates.intersection(dirs)) 2210ee81e68SLisandro Dalcin allsource = [] 2220ee81e68SLisandro Dalcin def mkrel(src): 2230ee81e68SLisandro Dalcin return self.relpath(root, src) 2240ee81e68SLisandro Dalcin source = self.get_sources(makevars) 2250ee81e68SLisandro Dalcin for lang, s in source.items(): 2262b757757SJed Brown pkgsrcs[lang] += [mkrel(t) for t in s] 2270ee81e68SLisandro Dalcin allsource += s 2280ee81e68SLisandro Dalcin self.mistakes.compareSourceLists(root, allsource, files) # Diagnostic output about unused source files 2290ee81e68SLisandro Dalcin self.gendeps.append(self.relpath(root, 'makefile')) 2300ee81e68SLisandro Dalcin return pkgsrcs 2310ee81e68SLisandro Dalcin 232b0790570SJed Brown def gen_gnumake(self, fd): 2330ee81e68SLisandro Dalcin def write(stem, srcs): 2340ee81e68SLisandro Dalcin for lang in LANGS: 235c0558f20SBarry Smith fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang.replace('_','.'), srcs=' '.join(srcs[lang]))) 23647fd361eSStefano Zampini for pkg in self.pkg_pkgs: 2370ee81e68SLisandro Dalcin srcs = self.gen_pkg(pkg) 238b0790570SJed Brown write('srcs-' + pkg, srcs) 2390ee81e68SLisandro Dalcin return self.gendeps 2400ee81e68SLisandro Dalcin 2410ee81e68SLisandro Dalcin def gen_ninja(self, fd): 2420ee81e68SLisandro Dalcin libobjs = [] 24347fd361eSStefano Zampini for pkg in self.pkg_pkgs: 2440ee81e68SLisandro Dalcin srcs = self.gen_pkg(pkg) 2450ee81e68SLisandro Dalcin for lang in LANGS: 2460ee81e68SLisandro Dalcin for src in srcs[lang]: 2470ee81e68SLisandro Dalcin obj = '$objdir/%s.o' % src 248add6df95SStefano Zampini fd.write('build %(obj)s : %(lang)s_COMPILE %(src)s\n' % dict(obj=obj, lang=lang.upper(), src=os.path.join(self.pkg_dir,src))) 2490ee81e68SLisandro Dalcin libobjs.append(obj) 2500ee81e68SLisandro Dalcin fd.write('\n') 2510ee81e68SLisandro Dalcin fd.write('build $libdir/libpetsc.so : %s_LINK_SHARED %s\n\n' % ('CF'[self.have_fortran], ' '.join(libobjs))) 2520ee81e68SLisandro Dalcin fd.write('build petsc : phony || $libdir/libpetsc.so\n\n') 2530ee81e68SLisandro Dalcin 2540ee81e68SLisandro Dalcin def summary(self): 2550ee81e68SLisandro Dalcin self.mistakes.summary() 2560ee81e68SLisandro Dalcin 2570ee81e68SLisandro Dalcindef WriteGnuMake(petsc): 258add6df95SStefano Zampini arch_files = petsc.pkg_arch_path('lib',petsc.pkg_name,'conf', 'files') 259021a2b48SJed Brown with open(arch_files, 'w') as fd: 2600ee81e68SLisandro Dalcin gendeps = petsc.gen_gnumake(fd) 2610ee81e68SLisandro Dalcin fd.write('\n') 2620ee81e68SLisandro Dalcin fd.write('# Dependency to regenerate this file\n') 263add6df95SStefano Zampini fd.write('%s : %s %s\n' % (os.path.relpath(arch_files, petsc.pkg_dir), 264add6df95SStefano Zampini os.path.relpath(__file__, os.path.realpath(petsc.pkg_dir)), 2650ee81e68SLisandro Dalcin ' '.join(gendeps))) 2660ee81e68SLisandro Dalcin fd.write('\n') 2670ee81e68SLisandro Dalcin fd.write('# Dummy dependencies in case makefiles are removed\n') 2680ee81e68SLisandro Dalcin fd.write(''.join([dep + ':\n' for dep in gendeps])) 2690ee81e68SLisandro Dalcin 2700ee81e68SLisandro Dalcindef WriteNinja(petsc): 2710ee81e68SLisandro Dalcin conf = dict() 272af0996ceSBarry Smith parse_makefile(os.path.join(petsc.petsc_dir, 'lib', 'petsc','conf', 'variables'), conf) 273af0996ceSBarry Smith parse_makefile(petsc.arch_path('lib','petsc','conf', 'petscvariables'), conf) 2740ee81e68SLisandro Dalcin build_ninja = petsc.arch_path('build.ninja') 275021a2b48SJed Brown with open(build_ninja, 'w') as fd: 2760ee81e68SLisandro Dalcin fd.write('objdir = obj-ninja\n') 2770ee81e68SLisandro Dalcin fd.write('libdir = lib\n') 2780ee81e68SLisandro Dalcin fd.write('c_compile = %(PCC)s\n' % conf) 2790ee81e68SLisandro Dalcin fd.write('c_flags = %(PETSC_CC_INCLUDES)s %(PCC_FLAGS)s %(CCPPFLAGS)s\n' % conf) 2800ee81e68SLisandro Dalcin fd.write('c_link = %(PCC_LINKER)s\n' % conf) 2810ee81e68SLisandro Dalcin fd.write('c_link_flags = %(PCC_LINKER_FLAGS)s\n' % conf) 2820ee81e68SLisandro Dalcin if petsc.have_fortran: 2830ee81e68SLisandro Dalcin fd.write('f_compile = %(FC)s\n' % conf) 2840ee81e68SLisandro Dalcin fd.write('f_flags = %(PETSC_FC_INCLUDES)s %(FC_FLAGS)s %(FCPPFLAGS)s\n' % conf) 2850ee81e68SLisandro Dalcin fd.write('f_link = %(FC_LINKER)s\n' % conf) 2860ee81e68SLisandro Dalcin fd.write('f_link_flags = %(FC_LINKER_FLAGS)s\n' % conf) 2870ee81e68SLisandro Dalcin fd.write('petsc_external_lib = %(PETSC_EXTERNAL_LIB_BASIC)s\n' % conf) 2880ee81e68SLisandro Dalcin fd.write('python = %(PYTHON)s\n' % conf) 2890ee81e68SLisandro Dalcin fd.write('\n') 2900ee81e68SLisandro Dalcin fd.write('rule C_COMPILE\n' 2910ee81e68SLisandro Dalcin ' command = $c_compile -MMD -MF $out.d $c_flags -c $in -o $out\n' 2920ee81e68SLisandro Dalcin ' description = CC $out\n' 2930ee81e68SLisandro Dalcin ' depfile = $out.d\n' 2940ee81e68SLisandro Dalcin # ' deps = gcc\n') # 'gcc' is default, 'msvc' only recognized by newer versions of ninja 2950ee81e68SLisandro Dalcin '\n') 2960ee81e68SLisandro Dalcin fd.write('rule C_LINK_SHARED\n' 2970ee81e68SLisandro Dalcin ' command = $c_link $c_link_flags -shared -o $out $in $petsc_external_lib\n' 2980ee81e68SLisandro Dalcin ' description = CLINK_SHARED $out\n' 2990ee81e68SLisandro Dalcin '\n') 3000ee81e68SLisandro Dalcin if petsc.have_fortran: 3010ee81e68SLisandro Dalcin fd.write('rule F_COMPILE\n' 3020ee81e68SLisandro Dalcin ' command = $f_compile -MMD -MF $out.d $f_flags -c $in -o $out\n' 3030ee81e68SLisandro Dalcin ' description = FC $out\n' 3040ee81e68SLisandro Dalcin ' depfile = $out.d\n' 3050ee81e68SLisandro Dalcin '\n') 3060ee81e68SLisandro Dalcin fd.write('rule F_LINK_SHARED\n' 3070ee81e68SLisandro Dalcin ' command = $f_link $f_link_flags -shared -o $out $in $petsc_external_lib\n' 3080ee81e68SLisandro Dalcin ' description = FLINK_SHARED $out\n' 3090ee81e68SLisandro Dalcin '\n') 3100ee81e68SLisandro Dalcin fd.write('rule GEN_NINJA\n' 3110ee81e68SLisandro Dalcin ' command = $python $in --output=ninja\n' 3120ee81e68SLisandro Dalcin ' generator = 1\n' 3130ee81e68SLisandro Dalcin '\n') 3140ee81e68SLisandro Dalcin petsc.gen_ninja(fd) 3150ee81e68SLisandro Dalcin fd.write('\n') 3160ee81e68SLisandro Dalcin fd.write('build %s : GEN_NINJA | %s %s %s %s\n' % (build_ninja, 3170ee81e68SLisandro Dalcin os.path.abspath(__file__), 318af0996ceSBarry Smith os.path.join(petsc.petsc_dir, 'lib','petsc','conf', 'variables'), 319af0996ceSBarry Smith petsc.arch_path('lib','petsc','conf', 'petscvariables'), 320add6df95SStefano Zampini ' '.join(os.path.join(petsc.pkg_dir, dep) for dep in petsc.gendeps))) 3210ee81e68SLisandro Dalcin 32247fd361eSStefano Zampinidef main(petsc_dir=None, petsc_arch=None, pkg_dir=None, pkg_name=None, pkg_arch=None, pkg_pkgs=None, output=None, verbose=False): 3230ee81e68SLisandro Dalcin if output is None: 3240ee81e68SLisandro Dalcin output = 'gnumake' 3250ee81e68SLisandro Dalcin writer = dict(gnumake=WriteGnuMake, ninja=WriteNinja) 32647fd361eSStefano Zampini petsc = Petsc(petsc_dir=petsc_dir, petsc_arch=petsc_arch, pkg_dir=pkg_dir, pkg_name=pkg_name, pkg_arch=pkg_arch, pkg_pkgs=pkg_pkgs, verbose=verbose) 3270ee81e68SLisandro Dalcin writer[output](petsc) 3280ee81e68SLisandro Dalcin petsc.summary() 3290ee81e68SLisandro Dalcin 3300ee81e68SLisandro Dalcinif __name__ == '__main__': 3310ee81e68SLisandro Dalcin import optparse 3320ee81e68SLisandro Dalcin parser = optparse.OptionParser() 3330ee81e68SLisandro Dalcin parser.add_option('--verbose', help='Show mismatches between makefiles and the filesystem', action='store_true', default=False) 3340ee81e68SLisandro Dalcin parser.add_option('--petsc-arch', help='Set PETSC_ARCH different from environment', default=os.environ.get('PETSC_ARCH')) 335add6df95SStefano Zampini parser.add_option('--pkg-dir', help='Set the directory of the package (different from PETSc) you want to generate the makefile rules for', default=None) 336add6df95SStefano Zampini parser.add_option('--pkg-name', help='Set the name of the package you want to generate the makefile rules for', default=None) 337c4bccdb5SStefano Zampini parser.add_option('--pkg-arch', help='Set the package arch name you want to generate the makefile rules for', default=None) 33847fd361eSStefano Zampini parser.add_option('--pkg-pkgs', help='Set the package folders (comma separated list, different from the usual sys,vec,mat etc) you want to generate the makefile rules for', default=None) 3390ee81e68SLisandro Dalcin parser.add_option('--output', help='Location to write output file', default=None) 3400ee81e68SLisandro Dalcin opts, extra_args = parser.parse_args() 3410ee81e68SLisandro Dalcin if extra_args: 3420ee81e68SLisandro Dalcin import sys 3430ee81e68SLisandro Dalcin sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 3440ee81e68SLisandro Dalcin exit(1) 34547fd361eSStefano Zampini main(petsc_arch=opts.petsc_arch, pkg_dir=opts.pkg_dir, pkg_name=opts.pkg_name, pkg_arch=opts.pkg_arch, pkg_pkgs=opts.pkg_pkgs, output=opts.output, verbose=opts.verbose) 346