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