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