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