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 621 def configureUnused(self): 622 '''Sees if __attribute((unused)) is supported''' 623 if self.framework.argDB['with-ios']: 624 self.addDefine('UNUSED', ' ') 625 return 626 self.pushLanguage(self.languages.clanguage) 627 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'): 628 self.addDefine('UNUSED', '__attribute((unused))') 629 else: 630 self.addDefine('UNUSED', ' ') 631 self.popLanguage() 632 633 def configureIsatty(self): 634 '''Check if the Unix C function isatty() works correctly 635 Actually just assumes it does not work correctly on batch systems''' 636 if not self.framework.argDB['with-batch']: 637 self.addDefine('USE_ISATTY',1) 638 639 def configureDeprecated(self): 640 '''Check if __attribute((deprecated)) is supported''' 641 def checkDeprecated(macro_base, src, is_intel): 642 ''' 643 run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result 644 it if it compiles. 645 646 If none of the combos work, defines MACRO_BASE(why) as empty 647 ''' 648 full_macro_name = macro_base + '(string_literal_why)' 649 for prefix in ('__attribute__', '__attribute','__declspec'): 650 if prefix == '__declspec': 651 # declspec does not have an extra set of brackets around the arguments 652 attr_bodies = ('deprecated(string_literal_why)', 'deprecated') 653 else: 654 attr_bodies = ('(deprecated(string_literal_why))', '(deprecated)') 655 656 for attr_body in attr_bodies: 657 attr_def = '{}({})'.format(prefix, attr_body) 658 test_src = '\n'.join(( 659 '#define {} {}'.format(full_macro_name, attr_def), 660 src.format(macro_base + '("asdasdadsasd")') 661 )) 662 if self.checkCompile(test_src, ''): 663 self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def)) 664 if is_intel and '(why)' in attr_body: 665 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)) 666 self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def)) 667 continue 668 self.addDefine(full_macro_name, attr_def) 669 return 670 671 self.addDefine(full_macro_name, ' ') 672 return 673 674 lang = self.languages.clanguage 675 with self.Language(lang): 676 is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log) 677 checkDeprecated('DEPRECATED_FUNCTION_BASE', '{} int myfunc(void) {{ return 1; }}', is_intel) 678 checkDeprecated('DEPRECATED_TYPEDEF_BASE', 'typedef int my_int {};', is_intel) 679 checkDeprecated('DEPRECATED_ENUM_BASE', 'enum E {{ oldval {}, newval }};', is_intel) 680 checkDeprecated('DEPRECATED_OBJECT_BASE', '{} int x;', is_intel) 681 # I was unable to make a CPP macro that takes the old and new values as separate 682 # arguments and builds the message needed by _Pragma hence the deprecation message is 683 # handled as it is 684 if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'): 685 self.addDefine('DEPRECATED_MACRO_BASE_(why)', '_Pragma(#why)') 686 self.addDefine('DEPRECATED_MACRO_BASE(string_literal_why)', self.substPrefix + '_DEPRECATED_MACRO_BASE_(GCC warning string_literal_why)') 687 else: 688 self.addDefine('DEPRECATED_MACRO_BASE(why)', ' ') 689 690 def configureAlign(self): 691 '''Check if __attribute(aligned) is supported''' 692 code = '''\ 693struct mystruct {int myint;} __attribute((aligned(16))); 694char assert_aligned[(sizeof(struct mystruct)==16)*2-1]; 695''' 696 self.pushLanguage(self.languages.clanguage) 697 if self.checkCompile(code): 698 self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))') 699 self.addDefine('HAVE_ATTRIBUTEALIGNED', 1) 700 else: 701 self.framework.logPrint('Incorrect attribute(aligned)') 702 self.addDefine('ATTRIBUTEALIGNED(size)', ' ') 703 self.popLanguage() 704 return 705 706 def configureExpect(self): 707 '''Sees if the __builtin_expect directive is supported''' 708 self.pushLanguage(self.languages.clanguage) 709 if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'): 710 self.addDefine('HAVE_BUILTIN_EXPECT', 1) 711 self.popLanguage() 712 713 def configureFunctionName(self): 714 '''Sees if the compiler supports __func__ or a variant.''' 715 def getFunctionName(lang): 716 name = '"unknown"' 717 self.pushLanguage(lang) 718 for fname in ['__func__','__FUNCTION__','__extension__ __func__']: 719 code = "if ("+fname+"[0] != 'm') return 1;" 720 if self.checkCompile('',code) and self.checkLink('',code): 721 name = fname 722 break 723 self.popLanguage() 724 return name 725 langs = [] 726 727 self.addDefine('FUNCTION_NAME_C', getFunctionName('C')) 728 if hasattr(self.compilers, 'CXX'): 729 self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx')) 730 731 def configureIntptrt(self): 732 '''Determine what to use for uintptr_t and intptr_t''' 733 def staticAssertSizeMatchesVoidStar(inc,typename): 734 # The declaration is an error if either array size is negative. 735 # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case 736 return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n' 737 + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename)) 738 739 def generate_uintptr_guesses(): 740 for suff in ('max', '64', '32', '16'): 741 yield '#include <stdint.h>', 'uint{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 742 yield '#include <stdlib.h>\n#include <string.h>', 'size_t', 'zx' 743 yield '', 'unsigned long long', 'llx' 744 yield '', 'unsigned long', 'lx' 745 yield '', 'unsigned', 'x' 746 747 def generate_intptr_guesses(): 748 for suff in ('max', '64', '32', '16'): 749 yield '#include <stdint.h>', 'int{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 750 yield '', 'long long', 'llx' 751 yield '', 'long', 'lx' 752 yield '', 'int', 'x' 753 754 def check(default_typename, generator): 755 macro_name = default_typename.upper() 756 with self.Language(self.languages.clanguage): 757 if self.checkCompile( 758 '#include <stdint.h>', 759 'int x; {type_name} i = ({type_name})&x; (void)i'.format(type_name=default_typename) 760 ): 761 typename = default_typename 762 print_format = 'PRIxPTR' 763 else: 764 for include, typename, print_format in generator(): 765 if staticAssertSizeMatchesVoidStar(include, typename): 766 break 767 else: 768 raise RuntimeError('Could not find any {} type matching void*'.format(macro_name)) 769 self.addDefine(macro_name , typename) 770 self.addDefine(macro_name + '_FMT', '\"#\" ' + print_format) 771 return 772 773 check('uintptr_t', generate_uintptr_guesses) 774 check('intptr_t', generate_intptr_guesses) 775 return 776 777 def configureRTLDDefault(self): 778 '''Check for dynamic library feature''' 779 if self.checkCompile('#include <dlfcn.h>\n void *ptr = RTLD_DEFAULT;'): 780 self.addDefine('HAVE_RTLD_DEFAULT','1') 781 return 782 783 def configureSolaris(self): 784 '''Solaris specific stuff''' 785 if os.path.isdir(os.path.join('/usr','ucblib')): 786 try: 787 flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag') 788 except AttributeError: 789 flag = None 790 if flag is None: 791 self.compilers.LIBS += ' -L/usr/ucblib' 792 else: 793 self.compilers.LIBS += ' '+flag+'/usr/ucblib' 794 return 795 796 def configureDarwin(self): 797 '''Log brew configuration for Apple systems''' 798 try: 799 self.executeShellCommand(['brew', 'config'], log = self.log) 800 self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log) 801 except: 802 pass 803 return 804 805 def configureLinux(self): 806 '''Linux specific stuff''' 807 # TODO: Test for this by mallocing an odd number of floats and checking the address 808 self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1) 809 return 810 811 def configureWin32(self): 812 '''Win32 non-cygwin specific stuff''' 813 kernel32=0 814 if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 815 self.addDefine('HAVE_WINDOWS_H',1) 816 self.addDefine('HAVE_GETCOMPUTERNAME',1) 817 kernel32=1 818 elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 819 self.addDefine('HAVE_WINDOWS_H',1) 820 self.addDefine('HAVE_GETCOMPUTERNAME',1) 821 kernel32=1 822 if kernel32: 823 if self.framework.argDB['with-windows-graphics']: 824 self.addDefine('USE_WINDOWS_GRAPHICS',1) 825 if self.checkLink('#include <windows.h>','LoadLibrary(0)'): 826 self.addDefine('HAVE_LOADLIBRARY',1) 827 if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'): 828 self.addDefine('HAVE_GETPROCADDRESS',1) 829 if self.checkLink('#include <windows.h>','FreeLibrary(0)'): 830 self.addDefine('HAVE_FREELIBRARY',1) 831 if self.checkLink('#include <windows.h>','GetLastError()'): 832 self.addDefine('HAVE_GETLASTERROR',1) 833 if self.checkLink('#include <windows.h>','SetLastError(0)'): 834 self.addDefine('HAVE_SETLASTERROR',1) 835 if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'): 836 self.addDefine('USE_MICROSOFT_TIME',1) 837 if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 838 self.addDefine('HAVE_GET_USER_NAME',1) 839 elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 840 self.addDefine('HAVE_GET_USER_NAME',1) 841 842 if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'): 843 self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);') 844 if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'): 845 self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);') 846 847 if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'): 848 self.addTypedef('int', 'uid_t') 849 self.addTypedef('int', 'gid_t') 850 if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'): 851 self.framework.addDefine('R_OK', '04') 852 self.framework.addDefine('W_OK', '02') 853 self.framework.addDefine('X_OK', '01') 854 if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'): 855 self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)') 856 self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)') 857 if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'): 858 self.addDefine('HAVE_LARGE_INTEGER_U',1) 859 860 # Windows requires a Binary file creation flag when creating/opening binary files. Is a better test in order? 861 if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'): 862 self.addDefine('HAVE_O_BINARY',1) 863 864 if self.compilers.CC.find('win32fe') >= 0: 865 self.addDefine('HAVE_WINDOWS_COMPILERS',1) 866 self.addDefine('DIR_SEPARATOR','\'\\\\\'') 867 self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'') 868 self.addDefine('CANNOT_START_DEBUGGER',1) 869 (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log) 870 self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"') 871 (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log) 872 self.addMakeMacro('wPETSC_DIR',petscdir) 873 if self.dataFilesPath.datafilespath: 874 (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log) 875 self.addMakeMacro('DATAFILESPATH',datafilespath) 876 877 else: 878 self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'') 879 self.addDefine('DIR_SEPARATOR','\'/\'') 880 self.addDefine('DIR','"'+self.installdir.petscDir+'"') 881 self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir) 882 if self.dataFilesPath.datafilespath: 883 self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath) 884 self.addDefine('ARCH','"'+self.installdir.petscArch+'"') 885 return 886 887 def configureCoverageForLang(self, log_printer_cls, lang, extra_coverage_flags=None, extra_debug_flags=None): 888 """ 889 Check that a compiler accepts code-coverage flags. If the compiler does accept code-coverage flags 890 try to set debugging flags equivalent to -Og. 891 892 Arguments: 893 - lang: the language to check the coverage flag for 894 - extra_coverage_flags: a list of extra flags to use when checking the coverage flags 895 - extra_debug_flags: a list of extra flags to try when setting debug flags 896 897 On success: 898 - defines PETSC_USE_COVERAGE to 1 899 """ 900 log_print = log_printer_cls(self) 901 902 def quoted(string): 903 return string.join(("'", "'")) 904 905 def make_flag_list(default, extra): 906 ret = [default] 907 if extra is not None: 908 assert isinstance(extra, list) 909 ret.extend(extra) 910 return ret 911 912 log_print('Checking coverage flag for language {}'.format(lang)) 913 914 compiler = self.getCompiler(lang=lang) 915 if self.setCompilers.isGNU(compiler, self.log): 916 is_gnuish = True 917 elif self.setCompilers.isClang(compiler, self.log): 918 is_gnuish = True 919 else: 920 is_gnuish = False 921 922 # if not gnuish and we don't have a set of extra flags, bail 923 if not is_gnuish and extra_coverage_flags is None: 924 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))) 925 return 926 927 coverage_flags = make_flag_list('--coverage', extra_coverage_flags) 928 log_print('Checking set of coverage flags: {}'.format(coverage_flags)) 929 930 found = None 931 with self.Language(lang): 932 with self.setCompilers.Language(lang): 933 for flag in coverage_flags: 934 # the linker also needs to see the coverage flag 935 with self.setCompilers.extraCompilerFlags([flag], compilerOnly=False) as skip_flags: 936 if not skip_flags and self.checkRun(): 937 # flag was accepted 938 found = flag 939 break 940 941 log_print( 942 'Compiler {} did not accept coverage flag {}'.format(quoted(compiler), quoted(flag)) 943 ) 944 945 if found is None: 946 log_print( 947 'Compiler {} did not accept ANY coverage flags: {}, bailing!'.format( 948 quoted(compiler), coverage_flags 949 ) 950 ) 951 return 952 953 # must do this exactly here since: 954 # 955 # 1. setCompilers.extraCompilerFlags() will reset the compiler flags on __exit__() 956 # (so cannot do it in the loop) 957 # 2. we need to set the compiler flag while setCompilers.Language() is still in 958 # effect (so cannot do it outside the with statements) 959 self.setCompilers.insertCompilerFlag(flag, False) 960 961 if not self.functions.haveFunction('__gcov_dump'): 962 self.functions.checkClassify(['__gcov_dump']) 963 964 # now check if we can override the optimization level. It is only kosher to do so if 965 # the user did not explicitly set the optimization flags (via CFLAGS, CXXFLAGS, 966 # CXXOPTFLAGS, etc). If they have done so, we sternly warn them about their lapse in 967 # judgement 968 with self.Language(lang): 969 compiler_flags = self.getCompilerFlags() 970 971 user_set = 0 972 allowed_opt_flags = re.compile(r'|'.join((r'-O[01g]', r'-g[1-9]*'))) 973 for flagsname in [self.getCompilerFlagsName(lang), self.compilerFlags.getOptionalFlagsName(lang)]: 974 if flagsname in self.argDB: 975 opt_flags = [ 976 f for f in self.compilerFlags.findOptFlags(compiler_flags) if not allowed_opt_flags.match(f) 977 ] 978 if opt_flags: 979 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))) 980 user_set = 1 981 break 982 983 # disable this for now, the warning should be sufficient. If the user still chooses to 984 # ignore it, then that's on them 985 if 0 and not user_set: 986 debug_flags = make_flag_list('-Og', extra_debug_flags) 987 with self.setCompilers.Language(lang): 988 for flag in debug_flags: 989 try: 990 self.setCompilers.addCompilerFlag(flag) 991 except RuntimeError: 992 continue 993 break 994 995 self.addDefine('USE_COVERAGE', 1) 996 return 997 998 def configureCoverage(self): 999 """ 1000 Configure coverage for all available languages. 1001 1002 If user did not request coverage, this function does nothing and returns immediatel. 1003 Therefore the following only apply to the case where the user requested coverage. 1004 1005 On success: 1006 - defines PETSC_USE_COVERAGE to 1 1007 1008 On failure: 1009 - If no compilers supported the coverage flag, throws RuntimeError 1010 - 1011 """ 1012 class LogPrinter: 1013 def __init__(self, cfg): 1014 self.cfg = cfg 1015 try: 1016 import inspect 1017 1018 calling_func_stack = inspect.stack()[1] 1019 if sys.version_info >= (3, 5): 1020 func_name = calling_func_stack.function 1021 else: 1022 func_name = calling_func_stack[3] 1023 except: 1024 func_name = 'Unknown' 1025 self.fmt_str = func_name + '(): {}' 1026 1027 def __call__(self, msg, *args, **kwargs): 1028 return self.cfg.logPrint(self.fmt_str.format(msg), *args, **kwargs) 1029 1030 argdb_flag = 'with-coverage' 1031 log_print = LogPrinter(self) 1032 if not self.argDB[argdb_flag]: 1033 log_print('coverage was disabled from command line or default') 1034 return 1035 1036 tested_langs = [] 1037 for LANG in ['C', 'Cxx', 'CUDA', 'HIP', 'SYCL', 'FC']: 1038 compilerName = LANG.upper() if LANG in {'Cxx', 'FC'} else LANG + 'C' 1039 if hasattr(self.setCompilers, compilerName): 1040 kwargs = {} 1041 if LANG in {'CUDA'}: 1042 # nvcc preprocesses the base file into a bunch of intermediate files, which are 1043 # then compiled by the host compiler. Why is this a problem? Because the 1044 # generated coverage data is based on these preprocessed source files! So gcov 1045 # tries to read it later, but since its in the tmp directory it cannot. Thus we 1046 # need to keep them around (in a place we know about). 1047 nvcc_tmp_dir = os.path.join(self.petscdir.dir, self.arch.arch, 'nvcc_tmp') 1048 try: 1049 os.mkdir(nvcc_tmp_dir) 1050 except FileExistsError: 1051 pass 1052 kwargs['extra_coverage_flags'] = [ 1053 '-Xcompiler --coverage -Xcompiler -fPIC --keep --keep-dir={}'.format(nvcc_tmp_dir) 1054 ] 1055 if self.kokkos.found: 1056 # yet again the kokkos nvcc_wrapper goes out of its way to be as useless as 1057 # possible. Its default arch (sm_35) is actually too low to compile kokkos, 1058 # for whatever reason this works if you dont use the --keep and --keep-dir 1059 # flags above. 1060 kwargs['extra_coverage_flags'].append('-arch=native') 1061 kwargs['extra_debug_flags'] = ['-Xcompiler -Og'] 1062 tested_langs.append(LANG) 1063 self.executeTest(self.configureCoverageForLang, args=[LogPrinter, LANG], kargs=kwargs) 1064 1065 if not self.defines.get('USE_COVERAGE'): 1066 # coverage was requested but no compilers accepted it, this is an error 1067 raise RuntimeError( 1068 'Coverage was requested (--{}={}) but none of the compilers supported it:\n{}\n'.format( 1069 argdb_flag, self.argDB[argdb_flag], 1070 '\n'.join([' - {} ({})'.format(self.getCompiler(lang=lang), lang) for lang in tested_langs]) 1071 ) 1072 ) 1073 1074 return 1075 # Disabled for now, since this does not really work. It solves the problem of 1076 # "undefined reference to __gcov_flush()" but if we add -lgcov we get: 1077 # 1078 # duplicate symbol '___gcov_reset' in: 1079 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1080 # /opt/.../libgcov.a(_gcov_reset.o) 1081 # duplicate symbol '___gcov_dump' in: 1082 # /opt/.../libgcov.a(_gcov_dump.o) 1083 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1084 # duplicate symbol '___gcov_fork' in: 1085 # /opt/.../libgcov.a(_gcov_fork.o) 1086 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1087 # 1088 # I don't know how to solve this. 1089 1090 log_print('Checking if compilers can cross-link disparate coverage libraries') 1091 # At least one of the compilers has coverage enabled. Now need to make sure multiple 1092 # code coverage impls work together, specifically when using clang C/C++ compiler with 1093 # gfortran. 1094 if not hasattr(self.setCompilers, 'FC'): 1095 log_print('No fortran compiler detected. No need to check cross-linking!') 1096 return 1097 1098 c_lang = self.languages.clanguage 1099 if not self.setCompilers.isClang(self.getCompiler(lang=c_lang), self.log): 1100 # must be GCC 1101 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'))) 1102 return 1103 1104 # If we are here we: 1105 # 1. Have both C/C++ compiler and fortran compiler 1106 # 2. The C/C++ compiler is *not* the same as the fortran compiler (unless we start 1107 # using flang) 1108 # 1109 # Now we check if we can cross-link 1110 def can_cross_link(**kwargs): 1111 f_body = " subroutine foo()\n print*,'testing'\n return\n end\n" 1112 c_body = "int main() { }" 1113 1114 return self.compilers.checkCrossLink( 1115 f_body, c_body, language1='FC', language2=c_lang, extralibs=self.compilers.flibs, **kwargs 1116 ) 1117 1118 log_print('Trying to cross-link WITHOUT extra libs') 1119 if can_cross_link(): 1120 log_print('Successfully cross-linked WITHOUT extra libs') 1121 # success, we already can cross-link 1122 return 1123 1124 extra_libs = ['-lgcov'] 1125 log_print('Trying to cross-link with extra libs: {}'.format(extra_libs)) 1126 if can_cross_link(extraObjs=extra_libs): 1127 log_print( 1128 'Successfully cross-linked using extra libs: {}, adding them to LIBS'.format(extra_libs) 1129 ) 1130 self.setCompilers.LIBS += ' ' + ' '.join(extra_libs) 1131 else: 1132 # maybe should be an error? 1133 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)) 1134 return 1135 1136 def configureCoverageExecutable(self): 1137 """ 1138 Check that a code-coverage collecting tool exists and is on PATH. 1139 1140 On success: 1141 - Adds PETSC_COVERAGE_EXEC make macro containing the full path to the coverage tool executable. 1142 1143 Raises RuntimeError if: 1144 - User explicitly requests auto-detection of the coverage tool from command line, and this 1145 routine fails to guess the suitable tool name. 1146 - The routine fails to find the tool, and --with-coverage is true 1147 """ 1148 def log_print(msg, *args, **kwargs): 1149 self.logPrint('checkCoverage: '+str(msg), *args, **kwargs) 1150 return 1151 1152 def quoted(string): 1153 return string.join(("'", "'")) 1154 1155 required = bool(self.argDB['with-coverage']) 1156 arg_opt = self.argDB['with-coverage-exec'] 1157 use_default_path = True 1158 search_path = '' 1159 1160 log_print('{} to find an executable'.format('REQUIRED' if required else 'NOT required')) 1161 if arg_opt in {'auto', 'default-auto', '1'}: 1162 # detect it based on the C language compiler, hopefully this does not clash! 1163 lang = self.setCompilers.languages.clanguage 1164 compiler = self.getCompiler(lang=lang) 1165 log_print('User did not explicitly set coverage exec (got {}), trying to auto-detect based on compiler {}'.format(quoted(arg_opt), quoted(compiler))) 1166 if self.setCompilers.isGNU(compiler, self.log): 1167 compiler_version_re = re.compile(r'[gG][cC\+\-]+[0-9]* \(.+\) (\d+)\.(\d+)\.(\d+)') 1168 exec_names = ['gcov'] 1169 elif self.setCompilers.isClang(compiler, self.log): 1170 compiler_version_re = re.compile(r'clang version (\d+)\.(\d+)\.(\d+)') 1171 exec_names = ['llvm-cov'] 1172 if self.setCompilers.isDarwin(self.log): 1173 # macOS masquerades llvm-cov as just 'gcov', so we add this to the list in case 1174 # bare llvm-cov does not work 1175 exec_names.append('gcov') 1176 elif arg_opt == 'default-auto' and not required: 1177 # default-auto implies the user did not set it via command line! 1178 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))) 1179 return 1180 else: 1181 # implies 'auto' explicitly set by user, or we were required to find 1182 # something. either way we should error 1183 raise RuntimeError('Could not auto-detect coverage tool for {}, please set coverage tool name explicitly'.format(quoted(compiler))) 1184 1185 try: 1186 compiler_version_str = self.compilerFlags.version[lang] 1187 except KeyError: 1188 compiler_version_str = 'Unknown' 1189 1190 log_print('Searching version string {} (for compiler {}) using pattern {}'.format(quoted(compiler_version_str), quoted(compiler), quoted(compiler_version_re.pattern))) 1191 compiler_version = compiler_version_re.search(compiler_version_str) 1192 if compiler_version is not None: 1193 log_print('Found major = {}, minor = {}, patch = {}'.format(compiler_version.group(1), compiler_version.group(2), compiler_version.group(3))) 1194 # form [llvm-cov-14, llvm-cov-14.0, llvm-cov, etc.] 1195 cov_exec_name = exec_names[0] 1196 exec_names = [ 1197 # llvm-cov-14 1198 '{}-{}'.format(cov_exec_name, compiler_version.group(1)), 1199 # llvm-cov-14.0 1200 '{}-{}.{}'.format(cov_exec_name, compiler_version.group(1), compiler_version.group(2)) 1201 ] + exec_names 1202 else: 1203 log_print('User explicitly set coverage exec as {}'.format(quoted(arg_opt))) 1204 par_dir = os.path.dirname(arg_opt) 1205 if os.path.exists(par_dir): 1206 # arg_opt is path-like, we should only search the provided directory when we go 1207 # looking for the tool 1208 use_default_path = False 1209 search_path = par_dir 1210 exec_names = [arg_opt] 1211 1212 make_macro_name = 'PETSC_COVERAGE_EXEC' 1213 log_print('Checking for coverage tool(s):\n{}'.format('\n'.join('- '+t for t in exec_names))) 1214 found_exec = self.getExecutables( 1215 exec_names, 1216 path=search_path, getFullPath=True, useDefaultPath=use_default_path, resultName=make_macro_name 1217 ) 1218 1219 if found_exec is None: 1220 # didn't find the coverage tool 1221 if required: 1222 raise RuntimeError('Coverage tool(s) {} could not be found. Please provide explicit path to coverage tool'.format(exec_names)) 1223 return 1224 1225 found_exec_name = os.path.basename(found_exec) 1226 if 'llvm-cov' in found_exec_name and 'gcov' not in found_exec_name: 1227 # llvm-cov needs to be called as 'llvm-cov gcov' to work 1228 self.addMakeMacro(make_macro_name, found_exec + ' gcov') 1229 return 1230 1231 def configureStrictPetscErrorCode(self): 1232 """ 1233 Enables or disables strict PetscErrorCode checking. 1234 1235 If --with-strict-petscerrorcode = 1: 1236 - defines PETSC_USE_STRICT_PETSCERRORCODE to 1 1237 1238 Else: 1239 - deletes any prior PETSC_USE_STRICT_PETSCERRORCODE definitions (if they exist) 1240 """ 1241 define_name = 'USE_STRICT_PETSCERRORCODE' 1242 if self.argDB['with-strict-petscerrorcode']: 1243 self.addDefine(define_name, 1) 1244 else: 1245 # in case it was somehow added previously 1246 self.delDefine(define_name) 1247 return 1248 1249#----------------------------------------------------------------------------------------------------- 1250 def configureCygwinBrokenPipe(self): 1251 '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make 1252 http://cygwin.com/ml/cygwin/2013-05/msg00340.html ''' 1253 if config.setCompilers.Configure.isCygwin(self.log): 1254 import platform 1255 import re 1256 r=re.compile("([0-9]+).([0-9]+).([0-9]+)") 1257 m=r.match(platform.release()) 1258 major=int(m.group(1)) 1259 minor=int(m.group(2)) 1260 subminor=int(m.group(3)) 1261 if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)): 1262 self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1') 1263 return 1264 1265#----------------------------------------------------------------------------------------------------- 1266 def configureDefaultArch(self): 1267 conffile = os.path.join('lib','petsc','conf', 'petscvariables') 1268 if self.framework.argDB['with-default-arch']: 1269 fd = open(conffile, 'w') 1270 fd.write('PETSC_ARCH='+self.arch.arch+'\n') 1271 fd.write('PETSC_DIR='+self.petscdir.dir+'\n') 1272 fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n') 1273 fd.close() 1274 self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile) 1275 elif os.path.isfile(conffile): 1276 try: 1277 os.unlink(conffile) 1278 except: 1279 raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?') 1280 return 1281 1282#----------------------------------------------------------------------------------------------------- 1283 def configureScript(self): 1284 '''Output a script in the conf directory which will reproduce the configuration''' 1285 import nargs 1286 import sys 1287 scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py') 1288 args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs]) 1289 if 'with-clean' in args: 1290 del args['with-clean'] 1291 if 'force' in args: 1292 del args['force'] 1293 if 'configModules' in args: 1294 if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure': 1295 del args['configModules'] 1296 if 'optionsModule' in args: 1297 if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions': 1298 del args['optionsModule'] 1299 if not 'PETSC_ARCH' in args: 1300 args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch) 1301 f = open(scriptName, 'w') 1302 f.write('#!'+sys.executable+'\n') 1303 f.write('if __name__ == \'__main__\':\n') 1304 f.write(' import sys\n') 1305 f.write(' import os\n') 1306 f.write(' sys.path.insert(0, os.path.abspath(\'config\'))\n') 1307 f.write(' import configure\n') 1308 # pretty print repr(args.values()) 1309 f.write(' configure_options = [\n') 1310 for itm in sorted(args.values()): 1311 f.write(' \''+str(itm)+'\',\n') 1312 f.write(' ]\n') 1313 f.write(' configure.petsc_configure(configure_options)\n') 1314 f.close() 1315 try: 1316 os.chmod(scriptName, 0o775) 1317 except OSError as e: 1318 self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e)) 1319 self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration') 1320 return 1321 1322 def configureInstall(self): 1323 '''Setup the directories for installation''' 1324 if self.framework.argDB['prefix']: 1325 self.addMakeRule('print_mesg_after_build','', 1326 ['-@echo "========================================="', 1327 '-@echo "Now to install the libraries do:"', 1328 '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo, 1329 '-@echo "========================================="']) 1330 else: 1331 self.addMakeRule('print_mesg_after_build','', 1332 ['-@echo "========================================="', 1333 '-@echo "Now to check if the libraries are working do:"', 1334 '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"', 1335 '-@echo "========================================="']) 1336 return 1337 1338 def postProcessPackages(self): 1339 postPackages=[] 1340 for i in self.framework.packages: 1341 if hasattr(i,'postProcess'): postPackages.append(i) 1342 if postPackages: 1343 # ctetgen needs petsc conf files. so attempt to create them early 1344 self.framework.dumpConfFiles() 1345 # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix 1346 for i in postPackages: 1347 if i.name.upper() in ['PFLOTRAN']: 1348 i.postProcess() 1349 postPackages.remove(i) 1350 for i in postPackages: i.postProcess() 1351 for i in postPackages: 1352 if i.installedpetsc: 1353 self.installed = 1 1354 break 1355 return 1356 1357 def configure(self): 1358 if 'package-prefix-hash' in self.argDB: 1359 # turn off prefix if it was only used to for installing external packages. 1360 self.framework.argDB['prefix'] = '' 1361 self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1362 self.installdir.dir = self.dir 1363 self.installdir.petscDir = self.petscdir.dir 1364 self.petscDir = self.petscdir.dir 1365 self.petscArch = self.arch.arch 1366 self.addMakeMacro('PREFIXDIR',self.dir) 1367 self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1368 1369 if not os.path.samefile(self.petscdir.dir, os.getcwd()): 1370 raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n Configure invoked in: '+os.path.realpath(os.getcwd())) 1371 if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir): 1372 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!') 1373 if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1: 1374 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') 1375 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)): 1376 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!') 1377 self.framework.header = os.path.join(self.arch.arch,'include','petscconf.h') 1378 self.framework.cHeader = os.path.join(self.arch.arch,'include','petscfix.h') 1379 self.framework.poisonheader = os.path.join(self.arch.arch,'include','petscconf_poison.h') 1380 self.framework.pkgheader = os.path.join(self.arch.arch,'include','petscpkg_version.h') 1381 self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables') 1382 self.framework.makeRuleHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules') 1383 if self.libraries.math is None: 1384 raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.') 1385 if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'): 1386 raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.') 1387 self.executeTest(self.configureRTLDDefault) 1388 self.executeTest(self.configurePrefetch) 1389 self.executeTest(self.configureUnused) 1390 self.executeTest(self.configureDeprecated) 1391 self.executeTest(self.configureIsatty) 1392 self.executeTest(self.configureExpect) 1393 self.executeTest(self.configureAlign) 1394 self.executeTest(self.configureFunctionName) 1395 self.executeTest(self.configureIntptrt) 1396 self.executeTest(self.configureSolaris) 1397 self.executeTest(self.configureLinux) 1398 self.executeTest(self.configureDarwin) 1399 self.executeTest(self.configureWin32) 1400 self.executeTest(self.configureCygwinBrokenPipe) 1401 self.executeTest(self.configureDefaultArch) 1402 self.executeTest(self.configureScript) 1403 self.executeTest(self.configureInstall) 1404 self.executeTest(self.configureAtoll) 1405 self.executeTest(self.configureCoverage) 1406 self.executeTest(self.configureCoverageExecutable) 1407 self.executeTest(self.configureStrictPetscErrorCode) 1408 self.executeTest(self.configureSanitize) 1409 1410 self.Dump() 1411 self.dumpConfigInfo() 1412 self.dumpMachineInfo() 1413 self.delGenFiles() 1414 # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install 1415 self.framework.storeSubstitutions(self.framework.argDB) 1416 self.framework.argDB['configureCache'] = pickle.dumps(self.framework) 1417 self.framework.argDB.save(force = True) 1418 self.DumpPkgconfig('PETSc.pc') 1419 self.DumpPkgconfig('petsc.pc') 1420 self.DumpModule() 1421 self.postProcessPackages() 1422 self.framework.log.write('================================================================================\n') 1423 self.logClear() 1424 return 1425