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