1import config.base 2 3import os 4import sys 5import re 6import pickle 7 8class Configure(config.base.Configure): 9 def __init__(self, framework): 10 config.base.Configure.__init__(self, framework) 11 self.headerPrefix = 'PETSC' 12 self.substPrefix = 'PETSC' 13 self.installed = 0 # 1 indicates that Configure itself has already compiled and installed PETSc 14 self.found = 1 15 return 16 17 def __str2__(self): 18 import logger 19 20 desc = [' Using GNU make: ' + self.make.make] 21 if self.defines.get('USE_COVERAGE'): 22 desc.extend([ 23 ' Code coverage: yes', 24 ' Using code coverage executable: {}'.format(self.getMakeMacro('PETSC_COVERAGE_EXEC')) 25 ]) 26 banner_ends = 'xxx' 27 banner_middle = '=' * (logger.get_global_divider_length() - 2 * len(banner_ends)) 28 banner_line = banner_middle.join((banner_ends, banner_ends)) 29 desc.append(banner_line) 30 if not self.installed: 31 desc.append(' Configure stage complete. Now build PETSc libraries with:') 32 desc.append(' %s PETSC_DIR=%s PETSC_ARCH=%s all' % (self.make.make_user, self.petscdir.dir, self.arch.arch)) 33 else: 34 desc.append(' Installation complete. You do not need to run make to compile or install the software') 35 desc.extend([banner_line, '']) 36 return '\n'.join(desc) 37 38 def setupHelp(self, help): 39 import nargs 40 help.addArgument('PETSc', '-prefix=<dir>', nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)')) 41 help.addArgument('PETSc', '-with-prefetch=<bool>', nargs.ArgBool(None, 1,'Enable checking for prefetch instructions')) 42 help.addArgument('Windows','-with-windows-graphics=<bool>', nargs.ArgBool(None, 1,'Enable check for Windows Graphics')) 43 help.addArgument('PETSc', '-with-default-arch=<bool>', nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH')) 44 help.addArgument('PETSc','-with-single-library=<bool>', nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library')) 45 help.addArgument('PETSc','-with-fortran-bindings=<bool>', nargs.ArgBool(None, 1,'Build PETSc fortran bindings in the library and corresponding module files')) 46 help.addArgument('PETSc', '-with-ios=<bool>', nargs.ArgBool(None, 0, 'Build an iPhone/iPad version of PETSc library')) 47 help.addArgument('PETSc', '-with-display=<x11display>', nargs.Arg(None, '', 'Specifiy DISPLAY environmental variable for use with MATLAB test)')) 48 help.addArgument('PETSc', '-with-package-scripts=<pyscripts>', nargs.ArgFileList(None,None,'Specify configure package scripts for user provided packages')) 49 help.addArgument('PETSc', '-with-coverage=<bool>', nargs.ArgFuzzyBool(None, value=0, help='Enable or disable code-coverage collection')) 50 help.addArgument('PETSc', '-with-coverage-exec=<executable>', nargs.ArgExecutable(None, value='default-auto', mustExist=0, help='Name of executable to use for post-processing coverage data, e.g. \'gcov\' or \'llvm-cov\'. Pass \'auto\' to let configure infer from compiler')) 51 help.addArgument('PETSc', '-with-tau-perfstubs=<bool>', nargs.ArgBool(None, 1,'Enable TAU profiler stubs')) 52 help.addArgument('PETSc', '-with-strict-petscerrorcode=<bool>', nargs.ArgFuzzyBool(None, value=0, help='Enable strict PetscErrorCode mode, which enables additional compile-time checking for misuse of PetscErrorCode and error handling')) 53 return 54 55 def registerPythonFile(self,filename,directory): 56 ''' Add a python file to the framework and registers its headerprefix, ... externalpackagedir 57 directory is the directory where the file relative to the BuildSystem or config path in python notation with . ''' 58 (utilityName, ext) = os.path.splitext(filename) 59 if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__': 60 if directory: directory = directory+'.' 61 utilityObj = self.framework.require(directory+utilityName, self) 62 utilityObj.headerPrefix = self.headerPrefix 63 utilityObj.archProvider = self.arch 64 utilityObj.languageProvider = self.languages 65 utilityObj.installDirProvider = self.installdir 66 utilityObj.externalPackagesDirProvider = self.externalpackagesdir 67 utilityObj.precisionProvider = self.scalartypes 68 utilityObj.indexProvider = self.indexTypes 69 setattr(self, utilityName.lower(), utilityObj) 70 return utilityObj 71 return None 72 73 def setupDependencies(self, framework): 74 config.base.Configure.setupDependencies(self, framework) 75 self.programs = framework.require('config.programs', self) 76 self.setCompilers = framework.require('config.setCompilers', self) 77 self.compilerFlags = framework.require('config.compilerFlags', self) 78 self.compilers = framework.require('config.compilers', self) 79 self.arch = framework.require('PETSc.options.arch', self.setCompilers) 80 self.petscdir = framework.require('PETSc.options.petscdir', self.arch) 81 self.installdir = framework.require('PETSc.options.installDir', self) 82 self.dataFilesPath = framework.require('PETSc.options.dataFilesPath',self) 83 self.scalartypes = framework.require('PETSc.options.scalarTypes', self) 84 self.indexTypes = framework.require('PETSc.options.indexTypes', self) 85 self.languages = framework.require('PETSc.options.languages', self.setCompilers) 86 self.indexTypes = framework.require('PETSc.options.indexTypes', self.compilers) 87 self.types = framework.require('config.types', self) 88 self.headers = framework.require('config.headers', self) 89 self.functions = framework.require('config.functions', self) 90 self.libraries = framework.require('config.libraries', self) 91 self.atomics = framework.require('config.atomics', self) 92 self.make = framework.require('config.packages.make', self) 93 self.blasLapack = framework.require('config.packages.BlasLapack',self) 94 self.mpi = framework.require('config.packages.MPI', self) 95 self.fortran = framework.require('config.compilersFortran', self) 96 self.externalpackagesdir = framework.require('PETSc.options.externalpackagesdir',self) 97 98 for utility in sorted(os.listdir(os.path.join('config','PETSc','options'))): 99 self.registerPythonFile(utility,'PETSc.options') 100 101 for utility in sorted(os.listdir(os.path.join('config','BuildSystem','config','utilities'))): 102 self.registerPythonFile(utility,'config.utilities') 103 104 for package in sorted(os.listdir(os.path.join('config', 'BuildSystem', 'config', 'packages'))): 105 obj = self.registerPythonFile(package,'config.packages') 106 if obj: 107 obj.archProvider = self.framework.requireModule(obj.archProvider, obj) 108 obj.languageProvider = self.framework.requireModule(obj.languageProvider, obj) 109 obj.installDirProvider = self.framework.requireModule(obj.installDirProvider, obj) 110 obj.externalPackagesDirProvider = self.framework.requireModule(obj.externalPackagesDirProvider, obj) 111 obj.precisionProvider = self.framework.requireModule(obj.precisionProvider, obj) 112 obj.indexProvider = self.framework.requireModule(obj.indexProvider, obj) 113 114 # Force blaslapack and opencl to depend on scalarType so precision is set before BlasLapack is built 115 framework.require('PETSc.options.scalarTypes', self.f2cblaslapack) 116 framework.require('PETSc.options.scalarTypes', self.fblaslapack) 117 framework.require('PETSc.options.scalarTypes', self.blaslapack) 118 framework.require('PETSc.options.scalarTypes', self.opencl) 119 120 self.programs.headerPrefix = self.headerPrefix 121 self.setCompilers.headerPrefix = self.headerPrefix 122 self.compilers.headerPrefix = self.headerPrefix 123 self.fortran.headerPrefix = self.headerPrefix 124 self.types.headerPrefix = self.headerPrefix 125 self.headers.headerPrefix = self.headerPrefix 126 self.functions.headerPrefix = self.headerPrefix 127 self.libraries.headerPrefix = self.headerPrefix 128 129 # Register user provided package scripts 130 if 'with-package-scripts' in self.framework.argDB: 131 for script in self.framework.argDB['with-package-scripts']: 132 if os.path.splitext(script)[1] != '.py': 133 raise RuntimeError('Only python scripts compatible with configure package script format should be specified! Invalid option -with-package-scripts='+script) 134 self.framework.logPrint('User is registering a new package script: '+script) 135 dname,fname = os.path.split(script) 136 if dname: sys.path.append(dname) 137 self.registerPythonFile(fname,'') 138 139 # test for a variety of basic headers and functions 140 headersC = map(lambda name: name+'.h',['setjmp','dos','fcntl','float','io','malloc','pwd','strings', 141 'unistd','machine/endian','sys/param','sys/procfs','sys/resource', 142 'sys/systeminfo','sys/times','sys/utsname', 143 'sys/socket','sys/wait','netinet/in','netdb','direct','time','Ws2tcpip','sys/types', 144 'WindowsX','float','ieeefp','stdint','inttypes','immintrin']) 145 functions = ['access','_access','clock','drand48','getcwd','_getcwd','getdomainname','gethostname', 146 'posix_memalign','popen','PXFGETARG','rand','getpagesize', 147 'readlink','realpath','usleep','sleep','_sleep', 148 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp', 149 'strcasecmp','bzero','dlopen','dlsym','dlclose','dlerror', 150 '_set_output_format','_mkdir','socket','gethostbyname','fpresetsticky', 151 'fpsetsticky','__gcov_dump'] 152 libraries = [(['fpe'],'handle_sigfpes')] 153 librariessock = [(['socket','nsl'],'socket')] 154 self.headers.headers.extend(headersC) 155 self.functions.functions.extend(functions) 156 self.libraries.libraries.extend(libraries) 157 if not hasattr(self,'socket'): 158 self.libraries.libraries.extend(librariessock) 159 return 160 161 def DumpPkgconfig(self, petsc_pc): 162 ''' Create a pkg-config file ''' 163 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')): 164 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')) 165 with open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig',petsc_pc),'w') as fd: 166 cflags_inc = ['-I${includedir}'] 167 if self.framework.argDB['prefix']: 168 fd.write('prefix='+self.installdir.dir+'\n') 169 else: 170 fd.write('prefix='+os.path.join(self.petscdir.dir, self.arch.arch)+'\n') 171 cflags_inc.append('-I' + os.path.join(self.petscdir.dir, 'include')) 172 fd.write('exec_prefix=${prefix}\n') 173 fd.write('includedir=${prefix}/include\n') 174 fd.write('libdir=${prefix}/lib\n') 175 176 with self.setCompilers.Language('C'): 177 fd.write('ccompiler='+self.setCompilers.getCompiler()+'\n') 178 fd.write('cflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 179 fd.write('cflags_dep='+self.compilers.dependenciesGenerationFlag.get('C','')+'\n') 180 fd.write('ldflag_rpath='+self.setCompilers.CSharedLinkerFlag+'\n') 181 if hasattr(self.compilers, 'CXX'): 182 with self.setCompilers.Language('C++'): 183 fd.write('cxxcompiler='+self.setCompilers.getCompiler()+'\n') 184 fd.write('cxxflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 185 if hasattr(self.compilers, 'FC'): 186 with self.setCompilers.Language('FC'): 187 fd.write('fcompiler='+self.setCompilers.getCompiler()+'\n') 188 fd.write('fflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 189 if hasattr(self.compilers, 'CUDAC'): 190 with self.setCompilers.Language('CUDA'): 191 fd.write('cudacompiler='+self.setCompilers.getCompiler()+'\n') 192 fd.write('cudaflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 193 p = self.framework.require('config.packages.cuda') 194 fd.write('cudalib='+self.libraries.toStringNoDupes(p.lib)+'\n') 195 fd.write('cudainclude='+self.headers.toStringNoDupes(p.include)+'\n') 196 if hasattr(self.setCompilers,'CUDA_CXX'): 197 fd.write('cuda_cxx='+self.setCompilers.CUDA_CXX+'\n') 198 fd.write('cuda_cxxflags='+self.setCompilers.CUDA_CXXFLAGS+'\n') 199 200 fd.write('\n') 201 fd.write('Name: PETSc\n') 202 fd.write('Description: Library to solve ODEs and algebraic equations\n') 203 fd.write('Version: %s\n' % self.petscdir.version) 204 fd.write('Cflags: ' + ' '.join([self.setCompilers.CPPFLAGS] + cflags_inc) + '\n') 205 fd.write('Libs: '+self.libraries.toStringNoDupes(['-L${libdir}', self.petsclib], with_rpath=False)+'\n') 206 # Remove RPATH flags from library list. User can add them using 207 # pkg-config --variable=ldflag_rpath and pkg-config --libs-only-L 208 fd.write('Libs.private: '+self.libraries.toStringNoDupes([f for f in self.packagelibs+self.complibs if not f.startswith(self.setCompilers.CSharedLinkerFlag)], with_rpath=False)+'\n') 209 return 210 211 def DumpModule(self): 212 ''' Create a module file ''' 213 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')): 214 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')) 215 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')): 216 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')) 217 if self.framework.argDB['prefix']: 218 installdir = self.installdir.dir 219 installarch = '' 220 installpath = os.path.join(installdir,'bin') 221 else: 222 installdir = self.petscdir.dir 223 installarch = self.arch.arch 224 installpath = os.path.join(installdir,installarch,'bin')+':'+os.path.join(installdir,'bin') 225 fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc',self.petscdir.version),'w') 226 fd.write('''\ 227#%%Module 228 229proc ModulesHelp { } { 230 puts stderr "This module sets the path and environment variables for petsc-%s" 231 puts stderr " see https://petsc.org/ for more information " 232 puts stderr "" 233} 234module-whatis "PETSc - Portable, Extensible Toolkit for Scientific Computation" 235 236set petsc_dir "%s" 237set petsc_arch "%s" 238 239setenv PETSC_ARCH "$petsc_arch" 240setenv PETSC_DIR "$petsc_dir" 241prepend-path PATH "%s" 242''' % (self.petscdir.version, installdir, installarch, installpath)) 243 fd.close() 244 return 245 246 def Dump(self): 247 ''' Actually put the values into the configuration files ''' 248 # eventually everything between -- should be gone 249 if self.mpi.usingMPIUni: 250 # 251 # Remove any MPI/MPICH include files that may have been put here by previous runs of ./configure 252 self.executeShellCommand('rm -rf '+os.path.join(self.petscdir.dir,self.arch.arch,'include','mpi*')+' '+os.path.join(self.petscdir.dir,self.arch.arch,'include','opa*'), log = self.log) 253 254 self.logPrintDivider() 255 # Test for compiler-specific macros that need to be defined. 256 if self.setCompilers.isCrayVector('CC', self.log): 257 self.addDefine('HAVE_CRAY_VECTOR','1') 258 259 if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'): 260 self.addDefine('USE_SOCKET_VIEWER','1') 261 if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'): 262 self.addDefine('HAVE_SO_REUSEADDR','1') 263 264 self.logPrintDivider() 265 self.setCompilers.pushLanguage('C') 266 compiler = self.setCompilers.getCompiler() 267 if [s for s in ['mpicc','mpiicc'] if os.path.basename(compiler).find(s)>=0]: 268 try: 269 output = self.executeShellCommand(compiler + ' -show', log = self.log)[0] 270 compiler = output.split(' ')[0] 271 self.addDefine('MPICC_SHOW','"'+output.strip().replace('\n','\\\\n').replace('"','')+'"') 272 except: 273 self.addDefine('MPICC_SHOW','"Unavailable"') 274 else: 275 self.addDefine('MPICC_SHOW','"Unavailable"') 276 self.setCompilers.popLanguage() 277#----------------------------------------------------------------------------------------------------- 278 279 # Sometimes we need C compiler, even if built with C++ 280 self.setCompilers.pushLanguage('C') 281 # do not use getCompilerFlags() because that automatically includes the CPPFLAGS so one ends up with duplication flags in makefile usage 282 self.addMakeMacro('CC_FLAGS',self.setCompilers.CFLAGS) 283 self.setCompilers.popLanguage() 284 285 # And sometimes we need a C++ compiler even when PETSc is built with C 286 if hasattr(self.compilers, 'CXX'): 287 self.setCompilers.pushLanguage('Cxx') 288 self.addDefine('HAVE_CXX','1') 289 self.addMakeMacro('CXXPP_FLAGS',self.setCompilers.CXXPPFLAGS) 290 # do not use getCompilerFlags() because that automatically includes the CXXPPFLAGS so one ends up with duplication flags in makefile usage 291 self.addMakeMacro('CXX_FLAGS',self.setCompilers.CXXFLAGS+' '+self.setCompilers.CXX_CXXFLAGS) 292 cxx_linker = self.setCompilers.getLinker() 293 self.addMakeMacro('CXX_LINKER',cxx_linker) 294 self.addMakeMacro('CXX_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 295 self.setCompilers.popLanguage() 296 else: 297 self.addMakeMacro('CXX','') 298 299 # C preprocessor values 300 self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS) 301 302 # compiler values 303 self.setCompilers.pushLanguage(self.languages.clanguage) 304 self.addMakeMacro('PCC',self.setCompilers.getCompiler()) 305 # do not use getCompilerFlags() because that automatically includes the preprocessor flags so one ends up with duplication flags in makefile usage 306 if self.languages.clanguage == 'C': 307 self.addMakeMacro('PCC_FLAGS','$(CC_FLAGS)') 308 else: 309 self.addMakeMacro('PCC_FLAGS','$(CXX_FLAGS)') 310 self.setCompilers.popLanguage() 311 # .o or .obj 312 self.addMakeMacro('CC_SUFFIX','o') 313 314 # executable linker values 315 self.setCompilers.pushLanguage(self.languages.clanguage) 316 pcc_linker = self.setCompilers.getLinker() 317 self.addMakeMacro('PCC_LINKER',pcc_linker) 318 # We need to add sycl flags when linking petsc. See more in sycl.py. 319 if hasattr(self.compilers, 'SYCLC'): 320 self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags()+' '+self.setCompilers.SYCLFLAGS+' '+self.setCompilers.SYCLC_LINKER_FLAGS) 321 else: 322 self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 323 self.setCompilers.popLanguage() 324 # '' for Unix, .exe for Windows 325 self.addMakeMacro('CC_LINKER_SUFFIX','') 326 327 if hasattr(self.compilers, 'FC'): 328 if self.framework.argDB['with-fortran-bindings']: 329 if not self.fortran.fortranIsF90: 330 raise RuntimeError('Error! Fortran compiler "'+self.compilers.FC+'" does not support F90! PETSc fortran bindings require a F90 compiler') 331 self.addDefine('USE_FORTRAN_BINDINGS','1') 332 self.setCompilers.pushLanguage('FC') 333 # need FPPFLAGS in config/setCompilers 334 self.addMakeMacro('FPP_FLAGS',self.setCompilers.FPPFLAGS) 335 336 # compiler values 337 self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags()) 338 self.setCompilers.popLanguage() 339 # .o or .obj 340 self.addMakeMacro('FC_SUFFIX','o') 341 342 # executable linker values 343 self.setCompilers.pushLanguage('FC') 344 self.addMakeMacro('FC_LINKER',self.setCompilers.getLinker()) 345 self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 346 self.setCompilers.popLanguage() 347 348 # F90 Modules 349 if self.setCompilers.fortranModuleIncludeFlag: 350 self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag) 351 else: # for non-f90 compilers like g77 352 self.addMakeMacro('FC_MODULE_FLAG', '-I') 353 if self.setCompilers.fortranModuleIncludeFlag: 354 self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag) 355 else: 356 self.addMakeMacro('FC','') 357 358 if hasattr(self.compilers, 'CUDAC'): 359 self.setCompilers.pushLanguage('CUDA') 360 self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags()) 361 self.addMakeMacro('CUDAPP_FLAGS',self.setCompilers.CUDAPPFLAGS) 362 self.setCompilers.popLanguage() 363 364 if hasattr(self.compilers, 'HIPC'): 365 self.setCompilers.pushLanguage('HIP') 366 self.addMakeMacro('HIPC_FLAGS',self.setCompilers.getCompilerFlags()) 367 self.addMakeMacro('HIPPP_FLAGS',self.setCompilers.HIPPPFLAGS) 368 self.setCompilers.popLanguage() 369 370 if hasattr(self.compilers, 'SYCLC'): 371 self.setCompilers.pushLanguage('SYCL') 372 self.addMakeMacro('SYCLC_FLAGS',self.setCompilers.getCompilerFlags()) 373 self.addMakeMacro('SYCLC_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 374 self.addMakeMacro('SYCLPP_FLAGS',self.setCompilers.SYCLPPFLAGS) 375 self.setCompilers.popLanguage() 376 377 # shared library linker values 378 self.setCompilers.pushLanguage(self.languages.clanguage) 379 # need to fix BuildSystem to collect these separately 380 self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker()) 381 self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}') 382 self.setCompilers.popLanguage() 383 # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture 384 # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX 385 if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX: 386 self.addMakeMacro('SL_LINKER_SUFFIX', '') 387 self.addDefine('SLSUFFIX','""') 388 else: 389 self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt) 390 self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"') 391 392 self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}') 393 394#----------------------------------------------------------------------------------------------------- 395 396 # CONLY or CPP. We should change the PETSc makefiles to do this better 397 if self.languages.clanguage == 'C': lang = 'CONLY' 398 else: lang = 'CXXONLY' 399 self.addMakeMacro('PETSC_LANGUAGE',lang) 400 401 # real or complex 402 self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype) 403 # double or float 404 self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision) 405 406 if self.framework.argDB['with-batch']: 407 self.addMakeMacro('PETSC_WITH_BATCH','1') 408 409#----------------------------------------------------------------------------------------------------- 410 # print include and lib for makefiles 411 self.logPrintDivider() 412 self.framework.packages.reverse() 413 petscincludes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')] 414 petscincludes_install = [os.path.join(self.installdir.dir, 'include')] if self.framework.argDB['prefix'] else petscincludes 415 includes = [] 416 self.packagelibs = [] 417 for i in self.framework.packages: 418 if not i.required: 419 if i.devicePackage: 420 self.addDefine('HAVE_DEVICE',1) 421 self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1) # ONLY list package if it is used directly by PETSc (and not only by another package) 422 if not isinstance(i.lib, list): 423 i.lib = [i.lib] 424 if i.linkedbypetsc: self.packagelibs.extend(i.lib) 425 self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib)) 426 if hasattr(i,'include'): 427 if not isinstance(i.include,list): 428 i.include = [i.include] 429 includes.extend(i.include) 430 self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include)) 431 432 self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split() 433 self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs) 434 435 self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC) 436 allincludes = petscincludes + includes 437 allincludes_install = petscincludes_install + includes 438 self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes) 439 self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install) 440 self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES) 441 self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL) 442 if hasattr(self.compilers, 'FC'): 443 def modinc(includes): 444 return includes if self.fortran.fortranIsF90 else [] 445 self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes))) 446 self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install))) 447 448 LIB_DIR = os.path.join(self.installdir.dir,'lib') 449 self.addDefine('LIB_DIR','"'+LIB_DIR+'"') 450 451 if self.framework.argDB['with-single-library']: 452 self.petsclib = '-lpetsc' 453 self.addDefine('USE_SINGLE_LIBRARY', '1') 454 self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}') 455 self.addMakeMacro('SHLIBS','libpetsc') 456 self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.libraries.toStringNoDupes(['-L'+LIB_DIR, '-lpetsc']+self.packagelibs+self.complibs)) 457 self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}') 458 self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}') 459 self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}') 460 self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}') 461 self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}') 462 self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}') 463 self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}') 464 self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}') 465 else: 466 self.petsclib = '-lpetsctao -lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys' 467 self.addMakeMacro('PETSC_SYS_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscsys']+self.packagelibs+self.complibs)) 468 self.addMakeMacro('PETSC_VEC_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 469 self.addMakeMacro('PETSC_MAT_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscmat','-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 470 self.addMakeMacro('PETSC_DM_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscdm','-lpetscmat','-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 471 self.addMakeMacro('PETSC_KSP_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscksp','-lpetscdm','-lpetscmat','-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 472 self.addMakeMacro('PETSC_SNES_LIB',self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscsnes','-lpetscksp','-lpetscdm','-lpetscmat','-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 473 self.addMakeMacro('PETSC_TS_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetscts','-lpetscsnes','-lpetscksp','-lpetscdm','-lpetscmat','-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 474 self.addMakeMacro('PETSC_TAO_LIB', self.libraries.toStringNoDupes(['-L'+LIB_DIR,'-lpetsctao','-lpetscts','-lpetscsnes','-lpetscksp','-lpetscdm','-lpetscmat','-lpetscvec','-lpetscsys']+self.packagelibs+self.complibs)) 475 self.addMakeMacro('PETSC_LIB','${PETSC_TAO_LIB}') 476 self.addMakeMacro('PETSC_LIB_BASIC',self.petsclib) 477 478 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')): 479 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib')) 480 481# add a makefile endtry for display 482 if self.framework.argDB['with-display']: 483 self.addMakeMacro('DISPLAY',self.framework.argDB['with-display']) 484 485 # add a makefile entry for configure options 486 self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')) 487 488 if self.framework.argDB['with-tau-perfstubs']: 489 self.addDefine('HAVE_TAU_PERFSTUBS',1) 490 return 491 492 def dumpConfigInfo(self): 493 import time 494 fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w') 495 fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n') 496 fd.close() 497 return 498 499 def dumpMachineInfo(self): 500 import platform 501 import datetime 502 import time 503 import script 504 def escape(s): 505 return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin 506 fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w') 507 fd.write('static const char *petscmachineinfo = \"\\n\"\n') 508 fd.write('\"-----------------------------------------\\n\"\n') 509 buildhost = platform.node() 510 if os.environ.get('SOURCE_DATE_EPOCH'): 511 buildhost = "reproducible" 512 buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))) 513 fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost)) 514 fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform())) 515 fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir))) 516 fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch))) 517 fd.write('\"-----------------------------------------\\n\";\n') 518 fd.write('static const char *petsccompilerinfo = \"\\n\"\n') 519 self.setCompilers.pushLanguage(self.languages.clanguage) 520 fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()))) 521 self.setCompilers.popLanguage() 522 if hasattr(self.compilers, 'FC'): 523 self.setCompilers.pushLanguage('FC') 524 fd.write('\"Using Fortran compiler: %s %s %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS))) 525 self.setCompilers.popLanguage() 526 fd.write('\"-----------------------------------------\\n\";\n') 527 fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n') 528 fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir)))) 529 fd.write('\"-----------------------------------------\\n\";\n') 530 fd.write('static const char *petsclinkerinfo = \"\\n\"\n') 531 self.setCompilers.pushLanguage(self.languages.clanguage) 532 fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker()))) 533 self.setCompilers.popLanguage() 534 if hasattr(self.compilers, 'FC'): 535 self.setCompilers.pushLanguage('FC') 536 fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker()))) 537 self.setCompilers.popLanguage() 538 fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC))) 539 fd.write('\"-----------------------------------------\\n\";\n') 540 fd.close() 541 return 542 543 def configurePrefetch(self): 544 '''Sees if there are any prefetch functions supported''' 545 if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']: 546 self.addDefine('Prefetch(a,b,c)', ' ') 547 return 548 self.pushLanguage(self.languages.clanguage) 549 if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'): 550 # The Intel Intrinsics manual [1] specifies the prototype 551 # 552 # void _mm_prefetch(char const *a, int sel); 553 # 554 # but other vendors seem to insist on using subtly different 555 # prototypes, including void* for the pointer, and an enum for 556 # sel. These are both reasonable changes, but negatively impact 557 # portability. 558 # 559 # [1] https://software.intel.com/file/6373 560 self.addDefine('HAVE_XMMINTRIN_H', 1) 561 self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))') 562 self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA') 563 self.addDefine('PREFETCH_HINT_T0', '_MM_HINT_T0') 564 self.addDefine('PREFETCH_HINT_T1', '_MM_HINT_T1') 565 self.addDefine('PREFETCH_HINT_T2', '_MM_HINT_T2') 566 elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'): 567 self.addDefine('HAVE_XMMINTRIN_H', 1) 568 self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))') 569 self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA') 570 self.addDefine('PREFETCH_HINT_T0', '_MM_HINT_T0') 571 self.addDefine('PREFETCH_HINT_T1', '_MM_HINT_T1') 572 self.addDefine('PREFETCH_HINT_T2', '_MM_HINT_T2') 573 elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'): 574 # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality) 575 # 576 # The value of rw is a compile-time constant one or zero; one 577 # means that the prefetch is preparing for a write to the memory 578 # address and zero, the default, means that the prefetch is 579 # preparing for a read. The value locality must be a compile-time 580 # constant integer between zero and three. A value of zero means 581 # that the data has no temporal locality, so it need not be left 582 # in the cache after the access. A value of three means that the 583 # data has a high degree of temporal locality and should be left 584 # in all levels of cache possible. Values of one and two mean, 585 # respectively, a low or moderate degree of temporal locality. 586 # 587 # Here we adopt Intel's x86/x86-64 naming scheme for the locality 588 # hints. Using macros for these values in necessary since some 589 # compilers require an enum. 590 self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))') 591 self.addDefine('PREFETCH_HINT_NTA', '0') 592 self.addDefine('PREFETCH_HINT_T0', '3') 593 self.addDefine('PREFETCH_HINT_T1', '2') 594 self.addDefine('PREFETCH_HINT_T2', '1') 595 else: 596 self.addDefine('Prefetch(a,b,c)', ' ') 597 self.popLanguage() 598 599 def delGenFiles(self): 600 '''Delete generated files''' 601 delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files') 602 try: 603 os.unlink(delfile) 604 except: pass 605 606 def configureAtoll(self): 607 '''Checks if atoll exists''' 608 if self.checkLink('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>','long v = atoll("25");\n(void)v') or self.checkLink ('#include <stdlib.h>','long v = atoll("25");\n(void)v'): 609 self.addDefine('HAVE_ATOLL', '1') 610 611 def configureUnused(self): 612 '''Sees if __attribute((unused)) is supported''' 613 if self.framework.argDB['with-ios']: 614 self.addDefine('UNUSED', ' ') 615 return 616 self.pushLanguage(self.languages.clanguage) 617 if self.checkLink('__attribute((unused)) static int myfunc(__attribute((unused)) void *name){ return 1;}', 'int i = 0;\nint j = myfunc(&i);\n(void)j;\ntypedef void* atype;\n__attribute((unused)) atype a'): 618 self.addDefine('UNUSED', '__attribute((unused))') 619 else: 620 self.addDefine('UNUSED', ' ') 621 self.popLanguage() 622 623 def configureIsatty(self): 624 '''Check if the Unix C function isatty() works correctly 625 Actually just assumes it does not work correctly on batch systems''' 626 if not self.framework.argDB['with-batch']: 627 self.addDefine('USE_ISATTY',1) 628 629 def configureDeprecated(self): 630 '''Check if __attribute((deprecated)) is supported''' 631 def checkDeprecated(macro_base, src, is_intel): 632 ''' 633 run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result 634 it if it compiles. 635 636 If none of the combos work, defines MACRO_BASE(why) as empty 637 ''' 638 full_macro_name = macro_base + '(string_literal_why)' 639 for prefix in ('__attribute__', '__attribute','__declspec'): 640 if prefix == '__declspec': 641 # declspec does not have an extra set of brackets around the arguments 642 attr_bodies = ('deprecated(string_literal_why)', 'deprecated') 643 else: 644 attr_bodies = ('(deprecated(string_literal_why))', '(deprecated)') 645 646 for attr_body in attr_bodies: 647 attr_def = '{}({})'.format(prefix, attr_body) 648 test_src = '\n'.join(( 649 '#define {} {}'.format(full_macro_name, attr_def), 650 src.format(macro_base + '("asdasdadsasd")') 651 )) 652 if self.checkCompile(test_src, ''): 653 self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def)) 654 if is_intel and '(why)' in attr_body: 655 self.logPrint('configureDeprecated: Intel has conspired to make a supremely environment-sensitive compiler. The Intel compiler looks at the gcc executable in the environment to determine the language compatibility that it should attempt to emulate. Some important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g. 4.7). Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc found in the default user environment is older and does not support the argument.\n'.format(attr_def)) 656 self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def)) 657 continue 658 self.addDefine(full_macro_name, attr_def) 659 return 660 661 self.addDefine(full_macro_name, ' ') 662 return 663 664 lang = self.languages.clanguage 665 with self.Language(lang): 666 is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log) 667 checkDeprecated('DEPRECATED_FUNCTION_BASE', '{} int myfunc(void) {{ return 1; }}', is_intel) 668 checkDeprecated('DEPRECATED_TYPEDEF_BASE', 'typedef int my_int {};', is_intel) 669 checkDeprecated('DEPRECATED_ENUM_BASE', 'enum E {{ oldval {}, newval }};', is_intel) 670 checkDeprecated('DEPRECATED_OBJECT_BASE', '{} int x;', is_intel) 671 # I was unable to make a CPP macro that takes the old and new values as separate 672 # arguments and builds the message needed by _Pragma hence the deprecation message is 673 # handled as it is 674 if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'): 675 self.addDefine('DEPRECATED_MACRO_BASE_(why)', '_Pragma(#why)') 676 self.addDefine('DEPRECATED_MACRO_BASE(string_literal_why)', self.substPrefix + '_DEPRECATED_MACRO_BASE_(GCC warning string_literal_why)') 677 else: 678 self.addDefine('DEPRECATED_MACRO_BASE(why)', ' ') 679 680 def configureAlign(self): 681 '''Check if __attribute(aligned) is supported''' 682 code = '''\ 683struct mystruct {int myint;} __attribute((aligned(16))); 684char assert_aligned[(sizeof(struct mystruct)==16)*2-1]; 685''' 686 self.pushLanguage(self.languages.clanguage) 687 if self.checkCompile(code): 688 self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))') 689 self.addDefine('HAVE_ATTRIBUTEALIGNED', 1) 690 else: 691 self.framework.logPrint('Incorrect attribute(aligned)') 692 self.addDefine('ATTRIBUTEALIGNED(size)', ' ') 693 self.popLanguage() 694 return 695 696 def configureExpect(self): 697 '''Sees if the __builtin_expect directive is supported''' 698 self.pushLanguage(self.languages.clanguage) 699 if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'): 700 self.addDefine('HAVE_BUILTIN_EXPECT', 1) 701 self.popLanguage() 702 703 def configureFunctionName(self): 704 '''Sees if the compiler supports __func__ or a variant.''' 705 def getFunctionName(lang): 706 name = '"unknown"' 707 self.pushLanguage(lang) 708 for fname in ['__func__','__FUNCTION__','__extension__ __func__']: 709 code = "if ("+fname+"[0] != 'm') return 1;" 710 if self.checkCompile('',code) and self.checkLink('',code): 711 name = fname 712 break 713 self.popLanguage() 714 return name 715 langs = [] 716 717 self.addDefine('FUNCTION_NAME_C', getFunctionName('C')) 718 if hasattr(self.compilers, 'CXX'): 719 self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx')) 720 721 def configureIntptrt(self): 722 '''Determine what to use for uintptr_t and intptr_t''' 723 def staticAssertSizeMatchesVoidStar(inc,typename): 724 # The declaration is an error if either array size is negative. 725 # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case 726 return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n' 727 + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename)) 728 729 def generate_uintptr_guesses(): 730 for suff in ('max', '64', '32', '16'): 731 yield '#include <stdint.h>', 'uint{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 732 yield '#include <stdlib.h>\n#include <string.h>', 'size_t', 'zx' 733 yield '', 'unsigned long long', 'llx' 734 yield '', 'unsigned long', 'lx' 735 yield '', 'unsigned', 'x' 736 737 def generate_intptr_guesses(): 738 for suff in ('max', '64', '32', '16'): 739 yield '#include <stdint.h>', 'int{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 740 yield '', 'long long', 'llx' 741 yield '', 'long', 'lx' 742 yield '', 'int', 'x' 743 744 def check(default_typename, generator): 745 macro_name = default_typename.upper() 746 with self.Language(self.languages.clanguage): 747 if self.checkCompile( 748 '#include <stdint.h>', 749 'int x; {type_name} i = ({type_name})&x; (void)i'.format(type_name=default_typename) 750 ): 751 typename = default_typename 752 print_format = 'PRIxPTR' 753 else: 754 for include, typename, print_format in generator(): 755 if staticAssertSizeMatchesVoidStar(include, typename): 756 break 757 else: 758 raise RuntimeError('Could not find any {} type matching void*'.format(macro_name)) 759 self.addDefine(macro_name , typename) 760 self.addDefine(macro_name + '_FMT', '\"#\" ' + print_format) 761 return 762 763 check('uintptr_t', generate_uintptr_guesses) 764 check('intptr_t', generate_intptr_guesses) 765 return 766 767 def configureRTLDDefault(self): 768 '''Check for dynamic library feature''' 769 if self.checkCompile('#include <dlfcn.h>\n void *ptr = RTLD_DEFAULT;'): 770 self.addDefine('HAVE_RTLD_DEFAULT','1') 771 return 772 773 def configureSolaris(self): 774 '''Solaris specific stuff''' 775 if os.path.isdir(os.path.join('/usr','ucblib')): 776 try: 777 flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag') 778 except AttributeError: 779 flag = None 780 if flag is None: 781 self.compilers.LIBS += ' -L/usr/ucblib' 782 else: 783 self.compilers.LIBS += ' '+flag+'/usr/ucblib' 784 return 785 786 def configureDarwin(self): 787 '''Log brew configuration for Apple systems''' 788 try: 789 self.executeShellCommand(['brew', 'config'], log = self.log) 790 self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log) 791 except: 792 pass 793 return 794 795 def configureLinux(self): 796 '''Linux specific stuff''' 797 # TODO: Test for this by mallocing an odd number of floats and checking the address 798 self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1) 799 return 800 801 def configureWin32(self): 802 '''Win32 non-cygwin specific stuff''' 803 kernel32=0 804 if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 805 self.addDefine('HAVE_WINDOWS_H',1) 806 self.addDefine('HAVE_GETCOMPUTERNAME',1) 807 kernel32=1 808 elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 809 self.addDefine('HAVE_WINDOWS_H',1) 810 self.addDefine('HAVE_GETCOMPUTERNAME',1) 811 kernel32=1 812 if kernel32: 813 if self.framework.argDB['with-windows-graphics']: 814 self.addDefine('USE_WINDOWS_GRAPHICS',1) 815 if self.checkLink('#include <windows.h>','LoadLibrary(0)'): 816 self.addDefine('HAVE_LOADLIBRARY',1) 817 if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'): 818 self.addDefine('HAVE_GETPROCADDRESS',1) 819 if self.checkLink('#include <windows.h>','FreeLibrary(0)'): 820 self.addDefine('HAVE_FREELIBRARY',1) 821 if self.checkLink('#include <windows.h>','GetLastError()'): 822 self.addDefine('HAVE_GETLASTERROR',1) 823 if self.checkLink('#include <windows.h>','SetLastError(0)'): 824 self.addDefine('HAVE_SETLASTERROR',1) 825 if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'): 826 self.addDefine('USE_MICROSOFT_TIME',1) 827 if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 828 self.addDefine('HAVE_GET_USER_NAME',1) 829 elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 830 self.addDefine('HAVE_GET_USER_NAME',1) 831 832 if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'): 833 self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);') 834 if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'): 835 self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);') 836 837 if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'): 838 self.addTypedef('int', 'uid_t') 839 self.addTypedef('int', 'gid_t') 840 if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'): 841 self.framework.addDefine('R_OK', '04') 842 self.framework.addDefine('W_OK', '02') 843 self.framework.addDefine('X_OK', '01') 844 if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'): 845 self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)') 846 self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)') 847 if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'): 848 self.addDefine('HAVE_LARGE_INTEGER_U',1) 849 850 # Windows requires a Binary file creation flag when creating/opening binary files. Is a better test in order? 851 if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'): 852 self.addDefine('HAVE_O_BINARY',1) 853 854 if self.compilers.CC.find('win32fe') >= 0: 855 self.addDefine('HAVE_WINDOWS_COMPILERS',1) 856 self.addDefine('DIR_SEPARATOR','\'\\\\\'') 857 self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'') 858 self.addDefine('CANNOT_START_DEBUGGER',1) 859 (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log) 860 self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"') 861 (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log) 862 self.addMakeMacro('wPETSC_DIR',petscdir) 863 if self.dataFilesPath.datafilespath: 864 (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log) 865 self.addMakeMacro('DATAFILESPATH',datafilespath) 866 867 else: 868 self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'') 869 self.addDefine('DIR_SEPARATOR','\'/\'') 870 self.addDefine('DIR','"'+self.installdir.petscDir+'"') 871 self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir) 872 if self.dataFilesPath.datafilespath: 873 self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath) 874 self.addDefine('ARCH','"'+self.installdir.petscArch+'"') 875 return 876 877 def configureCoverageForLang(self, log_printer_cls, lang, extra_coverage_flags=None, extra_debug_flags=None): 878 """ 879 Check that a compiler accepts code-coverage flags. If the compiler does accept code-coverage flags 880 try to set debugging flags equivalent to -Og. 881 882 Arguments: 883 - lang: the language to check the coverage flag for 884 - extra_coverage_flags: a list of extra flags to use when checking the coverage flags 885 - extra_debug_flags: a list of extra flags to try when setting debug flags 886 887 On success: 888 - defines PETSC_USE_COVERAGE to 1 889 """ 890 log_print = log_printer_cls(self) 891 892 def quoted(string): 893 return string.join(("'", "'")) 894 895 def make_flag_list(default, extra): 896 ret = [default] 897 if extra is not None: 898 assert isinstance(extra, list) 899 ret.extend(extra) 900 return ret 901 902 log_print('Checking coverage flag for language {}'.format(lang)) 903 904 compiler = self.getCompiler(lang=lang) 905 if self.setCompilers.isGNU(compiler, self.log): 906 is_gnuish = True 907 elif self.setCompilers.isClang(compiler, self.log): 908 is_gnuish = True 909 else: 910 is_gnuish = False 911 912 # if not gnuish and we don't have a set of extra flags, bail 913 if not is_gnuish and extra_coverage_flags is None: 914 log_print('Don\'t know how to add coverage for compiler {}. Only know how to add coverage for gnu-like compilers (either gcc or clang). Skipping it!'.format(quoted(compiler))) 915 return 916 917 coverage_flags = make_flag_list('--coverage', extra_coverage_flags) 918 log_print('Checking set of coverage flags: {}'.format(coverage_flags)) 919 920 found = None 921 with self.Language(lang): 922 with self.setCompilers.Language(lang): 923 for flag in coverage_flags: 924 # the linker also needs to see the coverage flag 925 with self.setCompilers.extraCompilerFlags([flag], compilerOnly=False) as skip_flags: 926 if not skip_flags and self.checkRun(): 927 # flag was accepted 928 found = flag 929 break 930 931 log_print( 932 'Compiler {} did not accept coverage flag {}'.format(quoted(compiler), quoted(flag)) 933 ) 934 935 if found is None: 936 log_print( 937 'Compiler {} did not accept ANY coverage flags: {}, bailing!'.format( 938 quoted(compiler), coverage_flags 939 ) 940 ) 941 return 942 943 # must do this exactly here since: 944 # 945 # 1. setCompilers.extraCompilerFlags() will reset the compiler flags on __exit__() 946 # (so cannot do it in the loop) 947 # 2. we need to set the compiler flag while setCompilers.Language() is still in 948 # effect (so cannot do it outside the with statements) 949 self.setCompilers.insertCompilerFlag(flag, False) 950 951 if not self.functions.haveFunction('__gcov_dump'): 952 self.functions.checkClassify(['__gcov_dump']) 953 954 # now check if we can override the optimization level. It is only kosher to do so if 955 # the user did not explicitly set the optimization flags (via CFLAGS, CXXFLAGS, 956 # CXXOPTFLAGS, etc). If they have done so, we sternly warn them about their lapse in 957 # judgement 958 with self.Language(lang): 959 compiler_flags = self.getCompilerFlags() 960 961 user_set = 0 962 allowed_opt_flags = re.compile(r'|'.join((r'-O[01g]', r'-g[1-9]*'))) 963 for flagsname in [self.getCompilerFlagsName(lang), self.compilerFlags.getOptionalFlagsName(lang)]: 964 if flagsname in self.argDB: 965 opt_flags = [ 966 f for f in self.compilerFlags.findOptFlags(compiler_flags) if not allowed_opt_flags.match(f) 967 ] 968 if opt_flags: 969 self.logPrintWarning('Coverage requested, but optimization flag(s) {} found in {}. Coverage collection will work, but may be less accurate. Suggest removing the flag and/or using -Og (or equivalent) instead'.format(', '.join(map(quoted, opt_flags)), quoted(flagsname))) 970 user_set = 1 971 break 972 973 # disable this for now, the warning should be sufficient. If the user still chooses to 974 # ignore it, then that's on them 975 if 0 and not user_set: 976 debug_flags = make_flag_list('-Og', extra_debug_flags) 977 with self.setCompilers.Language(lang): 978 for flag in debug_flags: 979 try: 980 self.setCompilers.addCompilerFlag(flag) 981 except RuntimeError: 982 continue 983 break 984 985 self.addDefine('USE_COVERAGE', 1) 986 return 987 988 def configureCoverage(self): 989 """ 990 Configure coverage for all available languages. 991 992 If user did not request coverage, this function does nothing and returns immediatel. 993 Therefore the following only apply to the case where the user requested coverage. 994 995 On success: 996 - defines PETSC_USE_COVERAGE to 1 997 998 On failure: 999 - If no compilers supported the coverage flag, throws RuntimeError 1000 - 1001 """ 1002 class LogPrinter: 1003 def __init__(self, cfg): 1004 self.cfg = cfg 1005 try: 1006 import inspect 1007 1008 calling_func_stack = inspect.stack()[1] 1009 if sys.version_info >= (3, 5): 1010 func_name = calling_func_stack.function 1011 else: 1012 func_name = calling_func_stack[3] 1013 except: 1014 func_name = 'Unknown' 1015 self.fmt_str = func_name + '(): {}' 1016 1017 def __call__(self, msg, *args, **kwargs): 1018 return self.cfg.logPrint(self.fmt_str.format(msg), *args, **kwargs) 1019 1020 argdb_flag = 'with-coverage' 1021 log_print = LogPrinter(self) 1022 if not self.argDB[argdb_flag]: 1023 log_print('coverage was disabled from command line or default') 1024 return 1025 1026 tested_langs = [] 1027 for LANG in ['C', 'Cxx', 'CUDA', 'HIP', 'SYCL', 'FC']: 1028 compilerName = LANG.upper() if LANG in {'Cxx', 'FC'} else LANG + 'C' 1029 if hasattr(self.setCompilers, compilerName): 1030 kwargs = {} 1031 if LANG in {'CUDA'}: 1032 # nvcc preprocesses the base file into a bunch of intermediate files, which are 1033 # then compiled by the host compiler. Why is this a problem? Because the 1034 # generated coverage data is based on these preprocessed source files! So gcov 1035 # tries to read it later, but since its in the tmp directory it cannot. Thus we 1036 # need to keep them around (in a place we know about). 1037 nvcc_tmp_dir = os.path.join(self.petscdir.dir, self.arch.arch, 'nvcc_tmp') 1038 try: 1039 os.mkdir(nvcc_tmp_dir) 1040 except FileExistsError: 1041 pass 1042 kwargs['extra_coverage_flags'] = [ 1043 '-Xcompiler --coverage -Xcompiler -fPIC --keep --keep-dir={}'.format(nvcc_tmp_dir) 1044 ] 1045 if self.kokkos.found: 1046 # yet again the kokkos nvcc_wrapper goes out of its way to be as useless as 1047 # possible. Its default arch (sm_35) is actually too low to compile kokkos, 1048 # for whatever reason this works if you dont use the --keep and --keep-dir 1049 # flags above. 1050 kwargs['extra_coverage_flags'].append('-arch=native') 1051 kwargs['extra_debug_flags'] = ['-Xcompiler -Og'] 1052 tested_langs.append(LANG) 1053 self.executeTest(self.configureCoverageForLang, args=[LogPrinter, LANG], kargs=kwargs) 1054 1055 if not self.defines.get('USE_COVERAGE'): 1056 # coverage was requested but no compilers accepted it, this is an error 1057 raise RuntimeError( 1058 'Coverage was requested (--{}={}) but none of the compilers supported it:\n{}\n'.format( 1059 argdb_flag, self.argDB[argdb_flag], 1060 '\n'.join([' - {} ({})'.format(self.getCompiler(lang=lang), lang) for lang in tested_langs]) 1061 ) 1062 ) 1063 1064 return 1065 # Disabled for now, since this does not really work. It solves the problem of 1066 # "undefined reference to __gcov_flush()" but if we add -lgcov we get: 1067 # 1068 # duplicate symbol '___gcov_reset' in: 1069 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1070 # /opt/.../libgcov.a(_gcov_reset.o) 1071 # duplicate symbol '___gcov_dump' in: 1072 # /opt/.../libgcov.a(_gcov_dump.o) 1073 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1074 # duplicate symbol '___gcov_fork' in: 1075 # /opt/.../libgcov.a(_gcov_fork.o) 1076 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1077 # 1078 # I don't know how to solve this. 1079 1080 log_print('Checking if compilers can cross-link disparate coverage libraries') 1081 # At least one of the compilers has coverage enabled. Now need to make sure multiple 1082 # code coverage impls work together, specifically when using clang C/C++ compiler with 1083 # gfortran. 1084 if not hasattr(self.setCompilers, 'FC'): 1085 log_print('No fortran compiler detected. No need to check cross-linking!') 1086 return 1087 1088 c_lang = self.languages.clanguage 1089 if not self.setCompilers.isClang(self.getCompiler(lang=c_lang), self.log): 1090 # must be GCC 1091 log_print('C-language ({}) compiler is not clang, assuming it is GCC, so cross-linking with FC ({}) assumed to be OK'.format(c_lang, self.getCompiler(lang='FC'))) 1092 return 1093 1094 # If we are here we: 1095 # 1. Have both C/C++ compiler and fortran compiler 1096 # 2. The C/C++ compiler is *not* the same as the fortran compiler (unless we start 1097 # using flang) 1098 # 1099 # Now we check if we can cross-link 1100 def can_cross_link(**kwargs): 1101 f_body = " subroutine foo()\n print*,'testing'\n return\n end\n" 1102 c_body = "int main() { }" 1103 1104 return self.compilers.checkCrossLink( 1105 f_body, c_body, language1='FC', language2=c_lang, extralibs=self.compilers.flibs, **kwargs 1106 ) 1107 1108 log_print('Trying to cross-link WITHOUT extra libs') 1109 if can_cross_link(): 1110 log_print('Successfully cross-linked WITHOUT extra libs') 1111 # success, we already can cross-link 1112 return 1113 1114 extra_libs = ['-lgcov'] 1115 log_print('Trying to cross-link with extra libs: {}'.format(extra_libs)) 1116 if can_cross_link(extraObjs=extra_libs): 1117 log_print( 1118 'Successfully cross-linked using extra libs: {}, adding them to LIBS'.format(extra_libs) 1119 ) 1120 self.setCompilers.LIBS += ' ' + ' '.join(extra_libs) 1121 else: 1122 # maybe should be an error? 1123 self.logPrintWarning("Could not successfully cross-link covered code between {} and FC. Sometimes this is a false positive. Assuming this does eventually end up working when the full link-line is assembled when building PETSc. If you later encounter linker errors about missing __gcov_exit(), __gcov_init(), __llvm_cov_flush() etc. this is why!".format(c_lang)) 1124 return 1125 1126 def configureCoverageExecutable(self): 1127 """ 1128 Check that a code-coverage collecting tool exists and is on PATH. 1129 1130 On success: 1131 - Adds PETSC_COVERAGE_EXEC make macro containing the full path to the coverage tool executable. 1132 1133 Raises RuntimeError if: 1134 - User explicitly requests auto-detection of the coverage tool from command line, and this 1135 routine fails to guess the suitable tool name. 1136 - The routine fails to find the tool, and --with-coverage is true 1137 """ 1138 def log_print(msg, *args, **kwargs): 1139 self.logPrint('checkCoverage: '+str(msg), *args, **kwargs) 1140 return 1141 1142 def quoted(string): 1143 return string.join(("'", "'")) 1144 1145 required = bool(self.argDB['with-coverage']) 1146 arg_opt = self.argDB['with-coverage-exec'] 1147 use_default_path = True 1148 search_path = '' 1149 1150 log_print('{} to find an executable'.format('REQUIRED' if required else 'NOT required')) 1151 if arg_opt in {'auto', 'default-auto', '1'}: 1152 # detect it based on the C language compiler, hopefully this does not clash! 1153 lang = self.setCompilers.languages.clanguage 1154 compiler = self.getCompiler(lang=lang) 1155 log_print('User did not explicitly set coverage exec (got {}), trying to auto-detect based on compiler {}'.format(quoted(arg_opt), quoted(compiler))) 1156 if self.setCompilers.isGNU(compiler, self.log): 1157 compiler_version_re = re.compile(r'[gG][cC\+\-]+[0-9]* \(.+\) (\d+)\.(\d+)\.(\d+)') 1158 exec_names = ['gcov'] 1159 elif self.setCompilers.isClang(compiler, self.log): 1160 compiler_version_re = re.compile(r'clang version (\d+)\.(\d+)\.(\d+)') 1161 exec_names = ['llvm-cov'] 1162 if self.setCompilers.isDarwin(self.log): 1163 # macOS masquerades llvm-cov as just 'gcov', so we add this to the list in case 1164 # bare llvm-cov does not work 1165 exec_names.append('gcov') 1166 elif arg_opt == 'default-auto' and not required: 1167 # default-auto implies the user did not set it via command line! 1168 log_print('Could not auto-detect coverage tool for {}, not a gnuish compiler. Bailing since user did not explicitly set exec on the commandline'.format(quoted(compiler))) 1169 return 1170 else: 1171 # implies 'auto' explicitly set by user, or we were required to find 1172 # something. either way we should error 1173 raise RuntimeError('Could not auto-detect coverage tool for {}, please set coverage tool name explicitly'.format(quoted(compiler))) 1174 1175 try: 1176 compiler_version_str = self.compilerFlags.version[lang] 1177 except KeyError: 1178 compiler_version_str = 'Unknown' 1179 1180 log_print('Searching version string {} (for compiler {}) using pattern {}'.format(quoted(compiler_version_str), quoted(compiler), quoted(compiler_version_re.pattern))) 1181 compiler_version = compiler_version_re.search(compiler_version_str) 1182 if compiler_version is not None: 1183 log_print('Found major = {}, minor = {}, patch = {}'.format(compiler_version.group(1), compiler_version.group(2), compiler_version.group(3))) 1184 # form [llvm-cov-14, llvm-cov-14.0, llvm-cov, etc.] 1185 cov_exec_name = exec_names[0] 1186 exec_names = [ 1187 # llvm-cov-14 1188 '{}-{}'.format(cov_exec_name, compiler_version.group(1)), 1189 # llvm-cov-14.0 1190 '{}-{}.{}'.format(cov_exec_name, compiler_version.group(1), compiler_version.group(2)) 1191 ] + exec_names 1192 else: 1193 log_print('User explicitly set coverage exec as {}'.format(quoted(arg_opt))) 1194 par_dir = os.path.dirname(arg_opt) 1195 if os.path.exists(par_dir): 1196 # arg_opt is path-like, we should only search the provided directory when we go 1197 # looking for the tool 1198 use_default_path = False 1199 search_path = par_dir 1200 exec_names = [arg_opt] 1201 1202 make_macro_name = 'PETSC_COVERAGE_EXEC' 1203 log_print('Checking for coverage tool(s):\n{}'.format('\n'.join('- '+t for t in exec_names))) 1204 found_exec = self.getExecutables( 1205 exec_names, 1206 path=search_path, getFullPath=True, useDefaultPath=use_default_path, resultName=make_macro_name 1207 ) 1208 1209 if found_exec is None: 1210 # didn't find the coverage tool 1211 if required: 1212 raise RuntimeError('Coverage tool(s) {} could not be found. Please provide explicit path to coverage tool'.format(exec_names)) 1213 return 1214 1215 found_exec_name = os.path.basename(found_exec) 1216 if 'llvm-cov' in found_exec_name and 'gcov' not in found_exec_name: 1217 # llvm-cov needs to be called as 'llvm-cov gcov' to work 1218 self.addMakeMacro(make_macro_name, found_exec + ' gcov') 1219 return 1220 1221 def configureStrictPetscErrorCode(self): 1222 """ 1223 Enables or disables strict PetscErrorCode checking. 1224 1225 If --with-strict-petscerrorcode = 1: 1226 - defines PETSC_USE_STRICT_PETSCERRORCODE to 1 1227 1228 Else: 1229 - deletes any prior PETSC_USE_STRICT_PETSCERRORCODE definitions (if they exist) 1230 """ 1231 define_name = 'USE_STRICT_PETSCERRORCODE' 1232 if self.argDB['with-strict-petscerrorcode']: 1233 self.addDefine(define_name, 1) 1234 else: 1235 # in case it was somehow added previously 1236 self.delDefine(define_name) 1237 return 1238 1239#----------------------------------------------------------------------------------------------------- 1240 def configureCygwinBrokenPipe(self): 1241 '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make 1242 http://cygwin.com/ml/cygwin/2013-05/msg00340.html ''' 1243 if config.setCompilers.Configure.isCygwin(self.log): 1244 import platform 1245 import re 1246 r=re.compile("([0-9]+).([0-9]+).([0-9]+)") 1247 m=r.match(platform.release()) 1248 major=int(m.group(1)) 1249 minor=int(m.group(2)) 1250 subminor=int(m.group(3)) 1251 if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)): 1252 self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1') 1253 return 1254 1255#----------------------------------------------------------------------------------------------------- 1256 def configureDefaultArch(self): 1257 conffile = os.path.join('lib','petsc','conf', 'petscvariables') 1258 if self.framework.argDB['with-default-arch']: 1259 fd = open(conffile, 'w') 1260 fd.write('PETSC_ARCH='+self.arch.arch+'\n') 1261 fd.write('PETSC_DIR='+self.petscdir.dir+'\n') 1262 fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n') 1263 fd.close() 1264 self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile) 1265 elif os.path.isfile(conffile): 1266 try: 1267 os.unlink(conffile) 1268 except: 1269 raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?') 1270 return 1271 1272#----------------------------------------------------------------------------------------------------- 1273 def configureScript(self): 1274 '''Output a script in the conf directory which will reproduce the configuration''' 1275 import nargs 1276 import sys 1277 scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py') 1278 args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs]) 1279 if 'with-clean' in args: 1280 del args['with-clean'] 1281 if 'force' in args: 1282 del args['force'] 1283 if 'configModules' in args: 1284 if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure': 1285 del args['configModules'] 1286 if 'optionsModule' in args: 1287 if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions': 1288 del args['optionsModule'] 1289 if not 'PETSC_ARCH' in args: 1290 args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch) 1291 f = open(scriptName, 'w') 1292 f.write('#!'+sys.executable+'\n') 1293 f.write('if __name__ == \'__main__\':\n') 1294 f.write(' import sys\n') 1295 f.write(' import os\n') 1296 f.write(' sys.path.insert(0, os.path.abspath(\'config\'))\n') 1297 f.write(' import configure\n') 1298 # pretty print repr(args.values()) 1299 f.write(' configure_options = [\n') 1300 for itm in sorted(args.values()): 1301 f.write(' \''+str(itm)+'\',\n') 1302 f.write(' ]\n') 1303 f.write(' configure.petsc_configure(configure_options)\n') 1304 f.close() 1305 try: 1306 os.chmod(scriptName, 0o775) 1307 except OSError as e: 1308 self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e)) 1309 self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration') 1310 return 1311 1312 def configureInstall(self): 1313 '''Setup the directories for installation''' 1314 if self.framework.argDB['prefix']: 1315 self.addMakeRule('print_mesg_after_build','', 1316 ['-@echo "========================================="', 1317 '-@echo "Now to install the libraries do:"', 1318 '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo, 1319 '-@echo "========================================="']) 1320 else: 1321 self.addMakeRule('print_mesg_after_build','', 1322 ['-@echo "========================================="', 1323 '-@echo "Now to check if the libraries are working do:"', 1324 '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"', 1325 '-@echo "========================================="']) 1326 return 1327 1328 def postProcessPackages(self): 1329 postPackages=[] 1330 for i in self.framework.packages: 1331 if hasattr(i,'postProcess'): postPackages.append(i) 1332 if postPackages: 1333 # ctetgen needs petsc conf files. so attempt to create them early 1334 self.framework.dumpConfFiles() 1335 # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix 1336 for i in postPackages: 1337 if i.name.upper() in ['PFLOTRAN']: 1338 i.postProcess() 1339 postPackages.remove(i) 1340 for i in postPackages: i.postProcess() 1341 for i in postPackages: 1342 if i.installedpetsc: 1343 self.installed = 1 1344 break 1345 return 1346 1347 def configure(self): 1348 if 'package-prefix-hash' in self.argDB: 1349 # turn off prefix if it was only used to for installing external packages. 1350 self.framework.argDB['prefix'] = '' 1351 self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1352 self.installdir.dir = self.dir 1353 self.installdir.petscDir = self.petscdir.dir 1354 self.petscDir = self.petscdir.dir 1355 self.petscArch = self.arch.arch 1356 self.addMakeMacro('PREFIXDIR',self.dir) 1357 self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1358 1359 if not os.path.samefile(self.petscdir.dir, os.getcwd()): 1360 raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n Configure invoked in: '+os.path.realpath(os.getcwd())) 1361 if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir): 1362 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!') 1363 if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1: 1364 raise RuntimeError('Your --prefix '+self.framework.argDB['prefix']+' has spaces in it; this is not allowed.\n Use a --prefix that does not have spaces in it') 1365 if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],os.path.join(self.petscdir.dir,self.arch.arch)): 1366 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!') 1367 self.framework.header = os.path.join(self.arch.arch,'include','petscconf.h') 1368 self.framework.cHeader = os.path.join(self.arch.arch,'include','petscfix.h') 1369 self.framework.poisonheader = os.path.join(self.arch.arch,'include','petscconf_poison.h') 1370 self.framework.pkgheader = os.path.join(self.arch.arch,'include','petscpkg_version.h') 1371 self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables') 1372 self.framework.makeRuleHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules') 1373 if self.libraries.math is None: 1374 raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.') 1375 if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'): 1376 raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.') 1377 self.executeTest(self.configureRTLDDefault) 1378 self.executeTest(self.configurePrefetch) 1379 self.executeTest(self.configureUnused) 1380 self.executeTest(self.configureDeprecated) 1381 self.executeTest(self.configureIsatty) 1382 self.executeTest(self.configureExpect) 1383 self.executeTest(self.configureAlign) 1384 self.executeTest(self.configureFunctionName) 1385 self.executeTest(self.configureIntptrt) 1386 self.executeTest(self.configureSolaris) 1387 self.executeTest(self.configureLinux) 1388 self.executeTest(self.configureDarwin) 1389 self.executeTest(self.configureWin32) 1390 self.executeTest(self.configureCygwinBrokenPipe) 1391 self.executeTest(self.configureDefaultArch) 1392 self.executeTest(self.configureScript) 1393 self.executeTest(self.configureInstall) 1394 self.executeTest(self.configureAtoll) 1395 self.executeTest(self.configureCoverage) 1396 self.executeTest(self.configureCoverageExecutable) 1397 self.executeTest(self.configureStrictPetscErrorCode) 1398 1399 self.Dump() 1400 self.dumpConfigInfo() 1401 self.dumpMachineInfo() 1402 self.delGenFiles() 1403 # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install 1404 self.framework.storeSubstitutions(self.framework.argDB) 1405 self.framework.argDB['configureCache'] = pickle.dumps(self.framework) 1406 self.framework.argDB.save(force = True) 1407 self.DumpPkgconfig('PETSc.pc') 1408 self.DumpPkgconfig('petsc.pc') 1409 self.DumpModule() 1410 self.postProcessPackages() 1411 self.framework.log.write('================================================================================\n') 1412 self.logClear() 1413 return 1414