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