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