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