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 else: 476 pkgs = ['tao', 'ts', 'snes', 'ksp', 'dm', 'mat', 'vec', 'sys'] 477 def liblist_basic(libs): 478 return [ '-lpetsc'+lib+self.LIB_NAME_SUFFIX for lib in libs] 479 def liblist(libs): 480 return self.libraries.toStringNoDupes(['-L'+PREINSTALL_LIB_DIR]+liblist_basic(libs)+self.packagelibs+self.complibs) 481 self.petsclib = ' '.join(liblist_basic(pkgs)) 482 self.addMakeMacro('PETSC_SYS_LIB', liblist(pkgs[-1:])) 483 self.addMakeMacro('PETSC_VEC_LIB', liblist(pkgs[-2:])) 484 self.addMakeMacro('PETSC_MAT_LIB', liblist(pkgs[-3:])) 485 self.addMakeMacro('PETSC_DM_LIB', liblist(pkgs[-4:])) 486 self.addMakeMacro('PETSC_KSP_LIB', liblist(pkgs[-5:])) 487 self.addMakeMacro('PETSC_SNES_LIB',liblist(pkgs[-6:])) 488 self.addMakeMacro('PETSC_TS_LIB', liblist(pkgs[-7:])) 489 self.addMakeMacro('PETSC_TAO_LIB', liblist(pkgs[-8:])) 490 self.addMakeMacro('PETSC_LIB','${PETSC_TAO_LIB}') 491 self.addMakeMacro('PETSC_LIB_BASIC',self.petsclib) 492 493 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')): 494 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib')) 495 496# add a makefile endtry for display 497 if self.framework.argDB['with-display']: 498 self.addMakeMacro('DISPLAY',self.framework.argDB['with-display']) 499 500 # add a makefile entry for configure options 501 self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')) 502 503 if self.framework.argDB['with-tau-perfstubs']: 504 self.addDefine('HAVE_TAU_PERFSTUBS',1) 505 return 506 507 def dumpConfigInfo(self): 508 import time 509 fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w') 510 fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n') 511 fd.close() 512 return 513 514 def dumpMachineInfo(self): 515 import platform 516 import datetime 517 import time 518 import script 519 def escape(s): 520 return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin 521 fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w') 522 fd.write('static const char *petscmachineinfo = \"\\n\"\n') 523 fd.write('\"-----------------------------------------\\n\"\n') 524 buildhost = platform.node() 525 if os.environ.get('SOURCE_DATE_EPOCH'): 526 buildhost = "reproducible" 527 buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))) 528 fd.write('\"Libraries compiled on %s on %s\\n\"\n' % (buildtime, buildhost)) 529 fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform())) 530 fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir))) 531 fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch))) 532 fd.write('\"-----------------------------------------\\n\";\n') 533 fd.write('static const char *petsccompilerinfo = \"\\n\"\n') 534 self.setCompilers.pushLanguage(self.languages.clanguage) 535 fd.write('\"Using C compiler: %s %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()))) 536 self.setCompilers.popLanguage() 537 if hasattr(self.compilers, 'FC'): 538 self.setCompilers.pushLanguage('FC') 539 fd.write('\"Using Fortran compiler: %s %s %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS))) 540 self.setCompilers.popLanguage() 541 fd.write('\"-----------------------------------------\\n\";\n') 542 fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n') 543 fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir)))) 544 fd.write('\"-----------------------------------------\\n\";\n') 545 fd.write('static const char *petsclinkerinfo = \"\\n\"\n') 546 self.setCompilers.pushLanguage(self.languages.clanguage) 547 fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker()))) 548 self.setCompilers.popLanguage() 549 if hasattr(self.compilers, 'FC'): 550 self.setCompilers.pushLanguage('FC') 551 fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker()))) 552 self.setCompilers.popLanguage() 553 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))) 554 fd.write('\"-----------------------------------------\\n\";\n') 555 fd.close() 556 return 557 558 def configurePrefetch(self): 559 '''Sees if there are any prefetch functions supported''' 560 if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']: 561 self.addDefine('Prefetch(a,b,c)', ' ') 562 return 563 self.pushLanguage(self.languages.clanguage) 564 if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'): 565 # The Intel Intrinsics manual [1] specifies the prototype 566 # 567 # void _mm_prefetch(char const *a, int sel); 568 # 569 # but other vendors seem to insist on using subtly different 570 # prototypes, including void* for the pointer, and an enum for 571 # sel. These are both reasonable changes, but negatively impact 572 # portability. 573 # 574 # [1] https://software.intel.com/file/6373 575 self.addDefine('HAVE_XMMINTRIN_H', 1) 576 self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))') 577 self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA') 578 self.addDefine('PREFETCH_HINT_T0', '_MM_HINT_T0') 579 self.addDefine('PREFETCH_HINT_T1', '_MM_HINT_T1') 580 self.addDefine('PREFETCH_HINT_T2', '_MM_HINT_T2') 581 elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'): 582 self.addDefine('HAVE_XMMINTRIN_H', 1) 583 self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))') 584 self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA') 585 self.addDefine('PREFETCH_HINT_T0', '_MM_HINT_T0') 586 self.addDefine('PREFETCH_HINT_T1', '_MM_HINT_T1') 587 self.addDefine('PREFETCH_HINT_T2', '_MM_HINT_T2') 588 elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'): 589 # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality) 590 # 591 # The value of rw is a compile-time constant one or zero; one 592 # means that the prefetch is preparing for a write to the memory 593 # address and zero, the default, means that the prefetch is 594 # preparing for a read. The value locality must be a compile-time 595 # constant integer between zero and three. A value of zero means 596 # that the data has no temporal locality, so it need not be left 597 # in the cache after the access. A value of three means that the 598 # data has a high degree of temporal locality and should be left 599 # in all levels of cache possible. Values of one and two mean, 600 # respectively, a low or moderate degree of temporal locality. 601 # 602 # Here we adopt Intel's x86/x86-64 naming scheme for the locality 603 # hints. Using macros for these values in necessary since some 604 # compilers require an enum. 605 self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))') 606 self.addDefine('PREFETCH_HINT_NTA', '0') 607 self.addDefine('PREFETCH_HINT_T0', '3') 608 self.addDefine('PREFETCH_HINT_T1', '2') 609 self.addDefine('PREFETCH_HINT_T2', '1') 610 else: 611 self.addDefine('Prefetch(a,b,c)', ' ') 612 self.popLanguage() 613 614 def delGenFiles(self): 615 '''Delete generated files''' 616 delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files') 617 try: 618 os.unlink(delfile) 619 except: pass 620 621 def configureAtoll(self): 622 '''Checks if atoll exists''' 623 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'): 624 self.addDefine('HAVE_ATOLL', '1') 625 626 def configureSanitize(self): 627 '''Checks if fsanitize is supported''' 628 if self.checkLink('#if defined(__has_feature)\n#if !__has_feature(address_sanitizer)\nGarbage\n#endif\n#else\nGarbage\n#endif\n'): 629 self.addDefine('HAVE_SANITIZER', '1') 630 elif self.checkLink('#if !defined(__SANITIZE_ADDRESS__)\nGarbage\n#endif\n'): 631 self.addDefine('HAVE_SANITIZER', '1') 632 633 def configureUnused(self): 634 '''Sees if __attribute((unused)) is supported''' 635 if self.framework.argDB['with-ios']: 636 self.addDefine('UNUSED', ' ') 637 return 638 self.pushLanguage(self.languages.clanguage) 639 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'): 640 self.addDefine('UNUSED', '__attribute((unused))') 641 else: 642 self.addDefine('UNUSED', ' ') 643 self.popLanguage() 644 645 def configureIsatty(self): 646 '''Check if the Unix C function isatty() works correctly 647 Actually just assumes it does not work correctly on batch systems''' 648 if not self.framework.argDB['with-batch']: 649 self.addDefine('USE_ISATTY',1) 650 651 def configureDeprecated(self): 652 '''Check if __attribute((deprecated)) is supported''' 653 def checkDeprecated(macro_base, src, is_intel): 654 ''' 655 run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result 656 it if it compiles. 657 658 If none of the combos work, defines MACRO_BASE(why) as empty 659 ''' 660 full_macro_name = macro_base + '(string_literal_why)' 661 for prefix in ('__attribute__', '__attribute','__declspec'): 662 if prefix == '__declspec': 663 # declspec does not have an extra set of brackets around the arguments 664 attr_bodies = ('deprecated(string_literal_why)', 'deprecated') 665 else: 666 attr_bodies = ('(deprecated(string_literal_why))', '(deprecated)') 667 668 for attr_body in attr_bodies: 669 attr_def = '{}({})'.format(prefix, attr_body) 670 test_src = '\n'.join(( 671 '#define {} {}'.format(full_macro_name, attr_def), 672 src.format(macro_base + '("asdasdadsasd")') 673 )) 674 if self.checkCompile(test_src, ''): 675 self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def)) 676 if is_intel and '(why)' in attr_body: 677 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)) 678 self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def)) 679 continue 680 self.addDefine(full_macro_name, attr_def) 681 return 682 683 self.addDefine(full_macro_name, ' ') 684 return 685 686 lang = self.languages.clanguage 687 with self.Language(lang): 688 is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log) 689 checkDeprecated('DEPRECATED_FUNCTION_BASE', '{} int myfunc(void) {{ return 1; }}', is_intel) 690 checkDeprecated('DEPRECATED_TYPEDEF_BASE', 'typedef int my_int {};', is_intel) 691 checkDeprecated('DEPRECATED_ENUM_BASE', 'enum E {{ oldval {}, newval }};', is_intel) 692 checkDeprecated('DEPRECATED_OBJECT_BASE', '{} int x;', is_intel) 693 # I was unable to make a CPP macro that takes the old and new values as separate 694 # arguments and builds the message needed by _Pragma hence the deprecation message is 695 # handled as it is 696 if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'): 697 self.addDefine('DEPRECATED_MACRO_BASE_(why)', '_Pragma(#why)') 698 self.addDefine('DEPRECATED_MACRO_BASE(string_literal_why)', self.substPrefix + '_DEPRECATED_MACRO_BASE_(GCC warning string_literal_why)') 699 else: 700 self.addDefine('DEPRECATED_MACRO_BASE(why)', ' ') 701 702 def configureAlign(self): 703 '''Check if __attribute(aligned) is supported''' 704 code = '''\ 705struct mystruct {int myint;} __attribute((aligned(16))); 706char assert_aligned[(sizeof(struct mystruct)==16)*2-1]; 707''' 708 self.pushLanguage(self.languages.clanguage) 709 if self.checkCompile(code): 710 self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))') 711 self.addDefine('HAVE_ATTRIBUTEALIGNED', 1) 712 else: 713 self.framework.logPrint('Incorrect attribute(aligned)') 714 self.addDefine('ATTRIBUTEALIGNED(size)', ' ') 715 self.popLanguage() 716 return 717 718 def configureExpect(self): 719 '''Sees if the __builtin_expect directive is supported''' 720 self.pushLanguage(self.languages.clanguage) 721 if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'): 722 self.addDefine('HAVE_BUILTIN_EXPECT', 1) 723 self.popLanguage() 724 725 def configureFunctionName(self): 726 '''Sees if the compiler supports __func__ or a variant.''' 727 def getFunctionName(lang): 728 name = '"unknown"' 729 self.pushLanguage(lang) 730 for fname in ['__func__','__FUNCTION__','__extension__ __func__']: 731 code = "if ("+fname+"[0] != 'm') return 1;" 732 if self.checkCompile('',code) and self.checkLink('',code): 733 name = fname 734 break 735 self.popLanguage() 736 return name 737 langs = [] 738 739 self.addDefine('FUNCTION_NAME_C', getFunctionName('C')) 740 if hasattr(self.compilers, 'CXX'): 741 self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx')) 742 743 def configureIntptrt(self): 744 '''Determine what to use for uintptr_t and intptr_t''' 745 def staticAssertSizeMatchesVoidStar(inc,typename): 746 # The declaration is an error if either array size is negative. 747 # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case 748 return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n' 749 + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename)) 750 751 def generate_uintptr_guesses(): 752 for suff in ('max', '64', '32', '16'): 753 yield '#include <stdint.h>', 'uint{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 754 yield '#include <stdlib.h>\n#include <string.h>', 'size_t', 'zx' 755 yield '', 'unsigned long long', 'llx' 756 yield '', 'unsigned long', 'lx' 757 yield '', 'unsigned', 'x' 758 759 def generate_intptr_guesses(): 760 for suff in ('max', '64', '32', '16'): 761 yield '#include <stdint.h>', 'int{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 762 yield '', 'long long', 'llx' 763 yield '', 'long', 'lx' 764 yield '', 'int', 'x' 765 766 def check(default_typename, generator): 767 macro_name = default_typename.upper() 768 with self.Language(self.languages.clanguage): 769 if self.checkCompile( 770 '#include <stdint.h>', 771 'int x; {type_name} i = ({type_name})&x; (void)i'.format(type_name=default_typename) 772 ): 773 typename = default_typename 774 print_format = 'PRIxPTR' 775 else: 776 for include, typename, print_format in generator(): 777 if staticAssertSizeMatchesVoidStar(include, typename): 778 break 779 else: 780 raise RuntimeError('Could not find any {} type matching void*'.format(macro_name)) 781 self.addDefine(macro_name , typename) 782 self.addDefine(macro_name + '_FMT', '\"#\" ' + print_format) 783 return 784 785 check('uintptr_t', generate_uintptr_guesses) 786 check('intptr_t', generate_intptr_guesses) 787 return 788 789 def configureRTLDDefault(self): 790 '''Check for dynamic library feature''' 791 if self.checkCompile('#include <dlfcn.h>\n void *ptr = RTLD_DEFAULT;'): 792 self.addDefine('HAVE_RTLD_DEFAULT','1') 793 return 794 795 def configureSolaris(self): 796 '''Solaris specific stuff''' 797 if os.path.isdir(os.path.join('/usr','ucblib')): 798 try: 799 flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag') 800 except AttributeError: 801 flag = None 802 if flag is None: 803 self.compilers.LIBS += ' -L/usr/ucblib' 804 else: 805 self.compilers.LIBS += ' '+flag+'/usr/ucblib' 806 return 807 808 def configureDarwin(self): 809 '''Log brew configuration for Apple systems''' 810 try: 811 self.executeShellCommand(['brew', 'config'], log = self.log) 812 self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log) 813 except: 814 pass 815 return 816 817 def configureLinux(self): 818 '''Linux specific stuff''' 819 # TODO: Test for this by mallocing an odd number of floats and checking the address 820 self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1) 821 return 822 823 def configureWin32(self): 824 '''Win32 non-cygwin specific stuff''' 825 kernel32=0 826 if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 827 self.addDefine('HAVE_WINDOWS_H',1) 828 self.addDefine('HAVE_GETCOMPUTERNAME',1) 829 kernel32=1 830 elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 831 self.addDefine('HAVE_WINDOWS_H',1) 832 self.addDefine('HAVE_GETCOMPUTERNAME',1) 833 kernel32=1 834 if kernel32: 835 if self.framework.argDB['with-windows-graphics']: 836 self.addDefine('USE_WINDOWS_GRAPHICS',1) 837 if self.checkLink('#include <windows.h>','LoadLibrary(0)'): 838 self.addDefine('HAVE_LOADLIBRARY',1) 839 if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'): 840 self.addDefine('HAVE_GETPROCADDRESS',1) 841 if self.checkLink('#include <windows.h>','FreeLibrary(0)'): 842 self.addDefine('HAVE_FREELIBRARY',1) 843 if self.checkLink('#include <windows.h>','GetLastError()'): 844 self.addDefine('HAVE_GETLASTERROR',1) 845 if self.checkLink('#include <windows.h>','SetLastError(0)'): 846 self.addDefine('HAVE_SETLASTERROR',1) 847 if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'): 848 self.addDefine('USE_MICROSOFT_TIME',1) 849 if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 850 self.addDefine('HAVE_GET_USER_NAME',1) 851 elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 852 self.addDefine('HAVE_GET_USER_NAME',1) 853 854 if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'): 855 self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);') 856 if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'): 857 self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);') 858 859 if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'): 860 self.addTypedef('int', 'uid_t') 861 self.addTypedef('int', 'gid_t') 862 if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'): 863 self.framework.addDefine('R_OK', '04') 864 self.framework.addDefine('W_OK', '02') 865 self.framework.addDefine('X_OK', '01') 866 if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'): 867 self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)') 868 self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)') 869 if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'): 870 self.addDefine('HAVE_LARGE_INTEGER_U',1) 871 872 # Windows requires a Binary file creation flag when creating/opening binary files. Is a better test in order? 873 if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'): 874 self.addDefine('HAVE_O_BINARY',1) 875 876 if self.compilers.CC.find('win32fe') >= 0: 877 self.addDefine('HAVE_WINDOWS_COMPILERS',1) 878 self.addDefine('DIR_SEPARATOR','\'\\\\\'') 879 self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'') 880 self.addDefine('CANNOT_START_DEBUGGER',1) 881 (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log) 882 self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"') 883 (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log) 884 self.addMakeMacro('wPETSC_DIR',petscdir) 885 if self.dataFilesPath.datafilespath: 886 (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log) 887 self.addMakeMacro('DATAFILESPATH',datafilespath) 888 889 else: 890 self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'') 891 self.addDefine('DIR_SEPARATOR','\'/\'') 892 self.addDefine('DIR','"'+self.installdir.petscDir+'"') 893 self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir) 894 if self.dataFilesPath.datafilespath: 895 self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath) 896 self.addDefine('ARCH','"'+self.installdir.petscArch+'"') 897 return 898 899 def configureCoverageForLang(self, log_printer_cls, lang, extra_coverage_flags=None, extra_debug_flags=None): 900 """ 901 Check that a compiler accepts code-coverage flags. If the compiler does accept code-coverage flags 902 try to set debugging flags equivalent to -Og. 903 904 Arguments: 905 - lang: the language to check the coverage flag for 906 - extra_coverage_flags: a list of extra flags to use when checking the coverage flags 907 - extra_debug_flags: a list of extra flags to try when setting debug flags 908 909 On success: 910 - defines PETSC_USE_COVERAGE to 1 911 """ 912 log_print = log_printer_cls(self) 913 914 def quoted(string): 915 return string.join(("'", "'")) 916 917 def make_flag_list(default, extra): 918 ret = [default] 919 if extra is not None: 920 assert isinstance(extra, list) 921 ret.extend(extra) 922 return ret 923 924 log_print('Checking coverage flag for language {}'.format(lang)) 925 926 compiler = self.getCompiler(lang=lang) 927 if self.setCompilers.isGNU(compiler, self.log): 928 is_gnuish = True 929 elif self.setCompilers.isClang(compiler, self.log): 930 is_gnuish = True 931 else: 932 is_gnuish = False 933 934 # if not gnuish and we don't have a set of extra flags, bail 935 if not is_gnuish and extra_coverage_flags is None: 936 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))) 937 return 938 939 coverage_flags = make_flag_list('--coverage', extra_coverage_flags) 940 log_print('Checking set of coverage flags: {}'.format(coverage_flags)) 941 942 found = None 943 with self.Language(lang): 944 with self.setCompilers.Language(lang): 945 for flag in coverage_flags: 946 # the linker also needs to see the coverage flag 947 with self.setCompilers.extraCompilerFlags([flag], compilerOnly=False) as skip_flags: 948 if not skip_flags and self.checkRun(): 949 # flag was accepted 950 found = flag 951 break 952 953 log_print( 954 'Compiler {} did not accept coverage flag {}'.format(quoted(compiler), quoted(flag)) 955 ) 956 957 if found is None: 958 log_print( 959 'Compiler {} did not accept ANY coverage flags: {}, bailing!'.format( 960 quoted(compiler), coverage_flags 961 ) 962 ) 963 return 964 965 # must do this exactly here since: 966 # 967 # 1. setCompilers.extraCompilerFlags() will reset the compiler flags on __exit__() 968 # (so cannot do it in the loop) 969 # 2. we need to set the compiler flag while setCompilers.Language() is still in 970 # effect (so cannot do it outside the with statements) 971 self.setCompilers.insertCompilerFlag(flag, False) 972 973 if not self.functions.haveFunction('__gcov_dump'): 974 self.functions.checkClassify(['__gcov_dump']) 975 976 # now check if we can override the optimization level. It is only kosher to do so if 977 # the user did not explicitly set the optimization flags (via CFLAGS, CXXFLAGS, 978 # CXXOPTFLAGS, etc). If they have done so, we sternly warn them about their lapse in 979 # judgement 980 with self.Language(lang): 981 compiler_flags = self.getCompilerFlags() 982 983 user_set = 0 984 allowed_opt_flags = re.compile(r'|'.join((r'-O[01g]', r'-g[1-9]*'))) 985 for flagsname in [self.getCompilerFlagsName(lang), self.compilerFlags.getOptionalFlagsName(lang)]: 986 if flagsname in self.argDB: 987 opt_flags = [ 988 f for f in self.compilerFlags.findOptFlags(compiler_flags) if not allowed_opt_flags.match(f) 989 ] 990 if opt_flags: 991 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))) 992 user_set = 1 993 break 994 995 # disable this for now, the warning should be sufficient. If the user still chooses to 996 # ignore it, then that's on them 997 if 0 and not user_set: 998 debug_flags = make_flag_list('-Og', extra_debug_flags) 999 with self.setCompilers.Language(lang): 1000 for flag in debug_flags: 1001 try: 1002 self.setCompilers.addCompilerFlag(flag) 1003 except RuntimeError: 1004 continue 1005 break 1006 1007 self.addDefine('USE_COVERAGE', 1) 1008 return 1009 1010 def configureCoverage(self): 1011 """ 1012 Configure coverage for all available languages. 1013 1014 If user did not request coverage, this function does nothing and returns immediatel. 1015 Therefore the following only apply to the case where the user requested coverage. 1016 1017 On success: 1018 - defines PETSC_USE_COVERAGE to 1 1019 1020 On failure: 1021 - If no compilers supported the coverage flag, throws RuntimeError 1022 - 1023 """ 1024 class LogPrinter: 1025 def __init__(self, cfg): 1026 self.cfg = cfg 1027 try: 1028 import inspect 1029 1030 calling_func_stack = inspect.stack()[1] 1031 if sys.version_info >= (3, 5): 1032 func_name = calling_func_stack.function 1033 else: 1034 func_name = calling_func_stack[3] 1035 except: 1036 func_name = 'Unknown' 1037 self.fmt_str = func_name + '(): {}' 1038 1039 def __call__(self, msg, *args, **kwargs): 1040 return self.cfg.logPrint(self.fmt_str.format(msg), *args, **kwargs) 1041 1042 argdb_flag = 'with-coverage' 1043 log_print = LogPrinter(self) 1044 if not self.argDB[argdb_flag]: 1045 log_print('coverage was disabled from command line or default') 1046 return 1047 1048 tested_langs = [] 1049 for LANG in ['C', 'Cxx', 'CUDA', 'HIP', 'SYCL', 'FC']: 1050 compilerName = LANG.upper() if LANG in {'Cxx', 'FC'} else LANG + 'C' 1051 if hasattr(self.setCompilers, compilerName): 1052 kwargs = {} 1053 if LANG in {'CUDA'}: 1054 # nvcc preprocesses the base file into a bunch of intermediate files, which are 1055 # then compiled by the host compiler. Why is this a problem? Because the 1056 # generated coverage data is based on these preprocessed source files! So gcov 1057 # tries to read it later, but since its in the tmp directory it cannot. Thus we 1058 # need to keep them around (in a place we know about). 1059 nvcc_tmp_dir = os.path.join(self.petscdir.dir, self.arch.arch, 'nvcc_tmp') 1060 try: 1061 os.mkdir(nvcc_tmp_dir) 1062 except FileExistsError: 1063 pass 1064 kwargs['extra_coverage_flags'] = [ 1065 '-Xcompiler --coverage -Xcompiler -fPIC --keep --keep-dir={}'.format(nvcc_tmp_dir) 1066 ] 1067 if self.kokkos.found: 1068 # yet again the kokkos nvcc_wrapper goes out of its way to be as useless as 1069 # possible. Its default arch (sm_35) is actually too low to compile kokkos, 1070 # for whatever reason this works if you dont use the --keep and --keep-dir 1071 # flags above. 1072 kwargs['extra_coverage_flags'].append('-arch=native') 1073 kwargs['extra_debug_flags'] = ['-Xcompiler -Og'] 1074 tested_langs.append(LANG) 1075 self.executeTest(self.configureCoverageForLang, args=[LogPrinter, LANG], kargs=kwargs) 1076 1077 if not self.defines.get('USE_COVERAGE'): 1078 # coverage was requested but no compilers accepted it, this is an error 1079 raise RuntimeError( 1080 'Coverage was requested (--{}={}) but none of the compilers supported it:\n{}\n'.format( 1081 argdb_flag, self.argDB[argdb_flag], 1082 '\n'.join([' - {} ({})'.format(self.getCompiler(lang=lang), lang) for lang in tested_langs]) 1083 ) 1084 ) 1085 1086 return 1087 # Disabled for now, since this does not really work. It solves the problem of 1088 # "undefined reference to __gcov_flush()" but if we add -lgcov we get: 1089 # 1090 # duplicate symbol '___gcov_reset' in: 1091 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1092 # /opt/.../libgcov.a(_gcov_reset.o) 1093 # duplicate symbol '___gcov_dump' in: 1094 # /opt/.../libgcov.a(_gcov_dump.o) 1095 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1096 # duplicate symbol '___gcov_fork' in: 1097 # /opt/.../libgcov.a(_gcov_fork.o) 1098 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1099 # 1100 # I don't know how to solve this. 1101 1102 log_print('Checking if compilers can cross-link disparate coverage libraries') 1103 # At least one of the compilers has coverage enabled. Now need to make sure multiple 1104 # code coverage impls work together, specifically when using clang C/C++ compiler with 1105 # gfortran. 1106 if not hasattr(self.setCompilers, 'FC'): 1107 log_print('No fortran compiler detected. No need to check cross-linking!') 1108 return 1109 1110 c_lang = self.languages.clanguage 1111 if not self.setCompilers.isClang(self.getCompiler(lang=c_lang), self.log): 1112 # must be GCC 1113 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'))) 1114 return 1115 1116 # If we are here we: 1117 # 1. Have both C/C++ compiler and fortran compiler 1118 # 2. The C/C++ compiler is *not* the same as the fortran compiler (unless we start 1119 # using flang) 1120 # 1121 # Now we check if we can cross-link 1122 def can_cross_link(**kwargs): 1123 f_body = " subroutine foo()\n print*,'testing'\n return\n end\n" 1124 c_body = "int main() { }" 1125 1126 return self.compilers.checkCrossLink( 1127 f_body, c_body, language1='FC', language2=c_lang, extralibs=self.compilers.flibs, **kwargs 1128 ) 1129 1130 log_print('Trying to cross-link WITHOUT extra libs') 1131 if can_cross_link(): 1132 log_print('Successfully cross-linked WITHOUT extra libs') 1133 # success, we already can cross-link 1134 return 1135 1136 extra_libs = ['-lgcov'] 1137 log_print('Trying to cross-link with extra libs: {}'.format(extra_libs)) 1138 if can_cross_link(extraObjs=extra_libs): 1139 log_print( 1140 'Successfully cross-linked using extra libs: {}, adding them to LIBS'.format(extra_libs) 1141 ) 1142 self.setCompilers.LIBS += ' ' + ' '.join(extra_libs) 1143 else: 1144 # maybe should be an error? 1145 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)) 1146 return 1147 1148 def configureCoverageExecutable(self): 1149 """ 1150 Check that a code-coverage collecting tool exists and is on PATH. 1151 1152 On success: 1153 - Adds PETSC_COVERAGE_EXEC make macro containing the full path to the coverage tool executable. 1154 1155 Raises RuntimeError if: 1156 - User explicitly requests auto-detection of the coverage tool from command line, and this 1157 routine fails to guess the suitable tool name. 1158 - The routine fails to find the tool, and --with-coverage is true 1159 """ 1160 def log_print(msg, *args, **kwargs): 1161 self.logPrint('checkCoverage: '+str(msg), *args, **kwargs) 1162 return 1163 1164 def quoted(string): 1165 return string.join(("'", "'")) 1166 1167 required = bool(self.argDB['with-coverage']) 1168 arg_opt = self.argDB['with-coverage-exec'] 1169 use_default_path = True 1170 search_path = '' 1171 1172 log_print('{} to find an executable'.format('REQUIRED' if required else 'NOT required')) 1173 if arg_opt in {'auto', 'default-auto', '1'}: 1174 # detect it based on the C language compiler, hopefully this does not clash! 1175 lang = self.setCompilers.languages.clanguage 1176 compiler = self.getCompiler(lang=lang) 1177 log_print('User did not explicitly set coverage exec (got {}), trying to auto-detect based on compiler {}'.format(quoted(arg_opt), quoted(compiler))) 1178 if self.setCompilers.isGNU(compiler, self.log): 1179 compiler_version_re = re.compile(r'[gG][cC\+\-]+[0-9]* \(.+\) (\d+)\.(\d+)\.(\d+)') 1180 exec_names = ['gcov'] 1181 elif self.setCompilers.isClang(compiler, self.log): 1182 compiler_version_re = re.compile(r'clang version (\d+)\.(\d+)\.(\d+)') 1183 exec_names = ['llvm-cov'] 1184 if self.setCompilers.isDarwin(self.log): 1185 # macOS masquerades llvm-cov as just 'gcov', so we add this to the list in case 1186 # bare llvm-cov does not work 1187 exec_names.append('gcov') 1188 elif arg_opt == 'default-auto' and not required: 1189 # default-auto implies the user did not set it via command line! 1190 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))) 1191 return 1192 else: 1193 # implies 'auto' explicitly set by user, or we were required to find 1194 # something. either way we should error 1195 raise RuntimeError('Could not auto-detect coverage tool for {}, please set coverage tool name explicitly'.format(quoted(compiler))) 1196 1197 try: 1198 compiler_version_str = self.compilerFlags.version[lang] 1199 except KeyError: 1200 compiler_version_str = 'Unknown' 1201 1202 log_print('Searching version string {} (for compiler {}) using pattern {}'.format(quoted(compiler_version_str), quoted(compiler), quoted(compiler_version_re.pattern))) 1203 compiler_version = compiler_version_re.search(compiler_version_str) 1204 if compiler_version is not None: 1205 log_print('Found major = {}, minor = {}, patch = {}'.format(compiler_version.group(1), compiler_version.group(2), compiler_version.group(3))) 1206 # form [llvm-cov-14, llvm-cov-14.0, llvm-cov, etc.] 1207 cov_exec_name = exec_names[0] 1208 exec_names = [ 1209 # llvm-cov-14 1210 '{}-{}'.format(cov_exec_name, compiler_version.group(1)), 1211 # llvm-cov-14.0 1212 '{}-{}.{}'.format(cov_exec_name, compiler_version.group(1), compiler_version.group(2)) 1213 ] + exec_names 1214 else: 1215 log_print('User explicitly set coverage exec as {}'.format(quoted(arg_opt))) 1216 par_dir = os.path.dirname(arg_opt) 1217 if os.path.exists(par_dir): 1218 # arg_opt is path-like, we should only search the provided directory when we go 1219 # looking for the tool 1220 use_default_path = False 1221 search_path = par_dir 1222 exec_names = [arg_opt] 1223 1224 make_macro_name = 'PETSC_COVERAGE_EXEC' 1225 log_print('Checking for coverage tool(s):\n{}'.format('\n'.join('- '+t for t in exec_names))) 1226 found_exec = self.getExecutables( 1227 exec_names, 1228 path=search_path, getFullPath=True, useDefaultPath=use_default_path, resultName=make_macro_name 1229 ) 1230 1231 if found_exec is None: 1232 # didn't find the coverage tool 1233 if required: 1234 raise RuntimeError('Coverage tool(s) {} could not be found. Please provide explicit path to coverage tool'.format(exec_names)) 1235 return 1236 1237 found_exec_name = os.path.basename(found_exec) 1238 if 'llvm-cov' in found_exec_name and 'gcov' not in found_exec_name: 1239 # llvm-cov needs to be called as 'llvm-cov gcov' to work 1240 self.addMakeMacro(make_macro_name, found_exec + ' gcov') 1241 return 1242 1243 def configureStrictPetscErrorCode(self): 1244 """ 1245 Enables or disables strict PetscErrorCode checking. 1246 1247 If --with-strict-petscerrorcode = 1: 1248 - defines PETSC_USE_STRICT_PETSCERRORCODE to 1 1249 1250 Else: 1251 - deletes any prior PETSC_USE_STRICT_PETSCERRORCODE definitions (if they exist) 1252 """ 1253 define_name = 'USE_STRICT_PETSCERRORCODE' 1254 if self.argDB['with-strict-petscerrorcode']: 1255 self.addDefine(define_name, 1) 1256 else: 1257 # in case it was somehow added previously 1258 self.delDefine(define_name) 1259 return 1260 1261#----------------------------------------------------------------------------------------------------- 1262 def configureCygwinBrokenPipe(self): 1263 '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make 1264 http://cygwin.com/ml/cygwin/2013-05/msg00340.html ''' 1265 if config.setCompilers.Configure.isCygwin(self.log): 1266 import platform 1267 import re 1268 r=re.compile("([0-9]+).([0-9]+).([0-9]+)") 1269 m=r.match(platform.release()) 1270 major=int(m.group(1)) 1271 minor=int(m.group(2)) 1272 subminor=int(m.group(3)) 1273 if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)): 1274 self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1') 1275 return 1276 1277#----------------------------------------------------------------------------------------------------- 1278 def configureDefaultArch(self): 1279 conffile = os.path.join('lib','petsc','conf', 'petscvariables') 1280 if self.framework.argDB['with-default-arch']: 1281 fd = open(conffile, 'w') 1282 fd.write('PETSC_ARCH='+self.arch.arch+'\n') 1283 fd.write('PETSC_DIR='+self.petscdir.dir+'\n') 1284 fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n') 1285 fd.close() 1286 self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile) 1287 elif os.path.isfile(conffile): 1288 try: 1289 os.unlink(conffile) 1290 except: 1291 raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?') 1292 return 1293 1294#----------------------------------------------------------------------------------------------------- 1295 def configureScript(self): 1296 '''Output a script in the conf directory which will reproduce the configuration''' 1297 import nargs 1298 import sys 1299 scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py') 1300 args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs]) 1301 if 'with-clean' in args: 1302 del args['with-clean'] 1303 if 'force' in args: 1304 del args['force'] 1305 if 'configModules' in args: 1306 if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure': 1307 del args['configModules'] 1308 if 'optionsModule' in args: 1309 if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions': 1310 del args['optionsModule'] 1311 if not 'PETSC_ARCH' in args: 1312 args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch) 1313 f = open(scriptName, 'w') 1314 f.write('#!'+sys.executable+'\n') 1315 f.write('if __name__ == \'__main__\':\n') 1316 f.write(' import sys\n') 1317 f.write(' import os\n') 1318 f.write(' sys.path.insert(0, os.path.abspath(\'config\'))\n') 1319 f.write(' import configure\n') 1320 # pretty print repr(args.values()) 1321 f.write(' configure_options = [\n') 1322 for itm in sorted(args.values()): 1323 f.write(' \''+str(itm)+'\',\n') 1324 f.write(' ]\n') 1325 f.write(' configure.petsc_configure(configure_options)\n') 1326 f.close() 1327 try: 1328 os.chmod(scriptName, 0o775) 1329 except OSError as e: 1330 self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e)) 1331 self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration') 1332 return 1333 1334 def configureInstall(self): 1335 '''Setup the directories for installation''' 1336 if self.framework.argDB['prefix']: 1337 self.addMakeRule('print_mesg_after_build','', 1338 ['-@echo "========================================="', 1339 '-@echo "Now to install the libraries do:"', 1340 '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo, 1341 '-@echo "========================================="']) 1342 else: 1343 self.addMakeRule('print_mesg_after_build','', 1344 ['-@echo "========================================="', 1345 '-@echo "Now to check if the libraries are working do:"', 1346 '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"', 1347 '-@echo "========================================="']) 1348 return 1349 1350 def postProcessPackages(self): 1351 postPackages=[] 1352 for i in self.framework.packages: 1353 if hasattr(i,'postProcess'): postPackages.append(i) 1354 if postPackages: 1355 # ctetgen needs petsc conf files. so attempt to create them early 1356 self.framework.dumpConfFiles() 1357 # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix 1358 for i in postPackages: 1359 if i.name.upper() in ['PFLOTRAN']: 1360 i.postProcess() 1361 postPackages.remove(i) 1362 for i in postPackages: i.postProcess() 1363 for i in postPackages: 1364 if i.installedpetsc: 1365 self.installed = 1 1366 break 1367 return 1368 1369 def generateFortranBindings(self): 1370 if hasattr(self.compilers, 'FC') and self.framework.argDB['with-fortran-bindings']: 1371 self.logPrintBox('Generating Fortran binding') 1372 try: 1373 from utils import generatefortranbindings 1374 generatefortranbindings.main(self.petscdir.dir, self.arch.arch) 1375 except RuntimeError as e: 1376 raise RuntimeError('*******Error generating Fortran stubs: '+str(e)+'*******\n') 1377 1378 def configure(self): 1379 if 'package-prefix-hash' in self.argDB: 1380 # turn off prefix if it was only used to for installing external packages. 1381 self.framework.argDB['prefix'] = '' 1382 self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1383 self.installdir.dir = self.dir 1384 self.installdir.petscDir = self.petscdir.dir 1385 self.petscDir = self.petscdir.dir 1386 self.petscArch = self.arch.arch 1387 self.addMakeMacro('PREFIXDIR',self.dir) 1388 self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1389 1390 if not os.path.samefile(self.petscdir.dir, os.getcwd()): 1391 raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n Configure invoked in: '+os.path.realpath(os.getcwd())) 1392 if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir): 1393 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!') 1394 if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1: 1395 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') 1396 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)): 1397 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!') 1398 self.framework.header = os.path.join(self.arch.arch,'include','petscconf.h') 1399 self.framework.cHeader = os.path.join(self.arch.arch,'include','petscfix.h') 1400 self.framework.poisonheader = os.path.join(self.arch.arch,'include','petscconf_poison.h') 1401 self.framework.pkgheader = os.path.join(self.arch.arch,'include','petscpkg_version.h') 1402 self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables') 1403 self.framework.makeRuleHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules') 1404 if self.libraries.math is None: 1405 raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.') 1406 if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'): 1407 raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.') 1408 self.executeTest(self.configureRTLDDefault) 1409 self.executeTest(self.configurePrefetch) 1410 self.executeTest(self.configureUnused) 1411 self.executeTest(self.configureDeprecated) 1412 self.executeTest(self.configureIsatty) 1413 self.executeTest(self.configureExpect) 1414 self.executeTest(self.configureAlign) 1415 self.executeTest(self.configureFunctionName) 1416 self.executeTest(self.configureIntptrt) 1417 self.executeTest(self.configureSolaris) 1418 self.executeTest(self.configureLinux) 1419 self.executeTest(self.configureDarwin) 1420 self.executeTest(self.configureWin32) 1421 self.executeTest(self.configureCygwinBrokenPipe) 1422 self.executeTest(self.configureDefaultArch) 1423 self.executeTest(self.configureScript) 1424 self.executeTest(self.configureInstall) 1425 self.executeTest(self.configureAtoll) 1426 self.executeTest(self.configureCoverage) 1427 self.executeTest(self.configureCoverageExecutable) 1428 self.executeTest(self.configureStrictPetscErrorCode) 1429 self.executeTest(self.configureSanitize) 1430 self.executeTest(self.generateFortranBindings) 1431 1432 self.Dump() 1433 self.dumpConfigInfo() 1434 self.dumpMachineInfo() 1435 self.delGenFiles() 1436 # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install 1437 self.framework.storeSubstitutions(self.framework.argDB) 1438 self.framework.argDB['configureCache'] = pickle.dumps(self.framework) 1439 self.framework.argDB.save(force = True) 1440 self.DumpPkgconfig('PETSc.pc') 1441 self.DumpPkgconfig('petsc.pc') 1442 self.DumpModule() 1443 self.postProcessPackages() 1444 self.framework.log.write('================================================================================\n') 1445 self.logClear() 1446 return 1447