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