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