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