1import config.base 2 3import re 4import os 5import shutil 6 7def remove_xcode_verbose(buf): 8 retbuf =[] 9 for line in buf.splitlines(): 10 if not line.startswith('ld: warning: text-based stub file'): retbuf.append(line) 11 return ('\n').join(retbuf) 12 13class MissingProcessor(AttributeError): 14 pass 15 16class Configure(config.base.Configure): 17 def __init__(self, framework): 18 config.base.Configure.__init__(self, framework) 19 self.headerPrefix = '' 20 self.substPrefix = '' 21 self.fortranMangling = 'unchanged' 22 self.fmainlibs = [] 23 self.fincs = [] 24 self.flibs = [] # libraries needed for linking using the C or C++ compiler Fortran source code compiled with Fortran 25 self.clibs = [] # libraries needed for linking using the C++ or Fortran compiler C source code compiled with C 26 self.cxxlibs = [] # libraries needed for linking using the C or Fortran compiler C++ source code compiled with C++ 27 # clibs is only used in this file. The final link line that PETSc users use includes cxxlibs and flibs 28 self.skipdefaultpaths = [] 29 self.cxxCompileC = False 30 self.cxxRestrict = ' ' 31 self.c99flag = None 32 return 33 34 def getSkipDefaultPaths(self): 35 if len(self.skipdefaultpaths): 36 return self.skipdefaultpaths 37 else: 38 self.skipdefaultpaths = ['/usr/lib','/lib','/usr/lib64','/lib64'] 39 for loc in ['/usr/lib','/lib']: 40 for arch in ['x86_64','i386','aarch64']: 41 self.skipdefaultpaths.append(os.path.join(loc,arch+'-linux-gnu')) 42 conda_sysrt = os.getenv('CONDA_BUILD_SYSROOT') 43 if conda_sysrt: 44 conda_sysrt = os.path.abspath(conda_sysrt) 45 self.skipdefaultpaths.extend([conda_sysrt+lib for lib in self.skipdefaultpaths]) 46 return self.skipdefaultpaths 47 48 def setupHelp(self, help): 49 import nargs 50 51 help.addArgument('Compilers','-with-clib-autodetect=<bool>', nargs.ArgBool(None,1,'Autodetect C compiler libraries')) 52 help.addArgument('Compilers','-with-fortranlib-autodetect=<bool>',nargs.ArgBool(None,1,'Autodetect Fortran compiler libraries')) 53 help.addArgument('Compilers','-with-cxxlib-autodetect=<bool>', nargs.ArgBool(None,1,'Autodetect C++ compiler libraries')) 54 help.addArgument('Compilers','-with-dependencies=<bool>', nargs.ArgBool(None,1,'Compile with -MMD or equivalent flag if possible')) 55 return 56 57 def getDispatchNames(self): 58 '''Return all the attributes which are dispatched from config.setCompilers''' 59 names = {} 60 names['CC'] = 'No C compiler found.' 61 names['CPP'] = 'No C preprocessor found.' 62 names['CUDAC'] = 'No CUDA compiler found.' 63 names['CUDAPP'] = 'No CUDA preprocessor found.' 64 names['HIPC'] = 'No HIP compiler found.' 65 names['HIPPP'] = 'No HIP preprocessor found.' 66 names['SYCLC'] = 'No SYCL compiler found.' 67 names['SYCLPP'] = 'No SYCL preprocessor found.' 68 names['CXX'] = 'No C++ compiler found.' 69 names['CXXPP'] = 'No C++ preprocessor found.' 70 names['FC'] = 'No Fortran compiler found.' 71 names['FPP'] = 'No Fortran preprocessor found.' 72 names['AR'] = 'No archiver found.' 73 names['RANLIB'] = 'No ranlib found.' 74 names['LD_SHARED'] = 'No shared linker found.' 75 names['CC_LD'] = 'No C linker found.' 76 names['dynamicLinker'] = 'No dynamic linker found.' 77 for language in ['C', 'CUDA', 'HIP', 'SYCL', 'Cxx', 'FC']: 78 self.pushLanguage(language) 79 key = self.getCompilerFlagsName(language, 0) 80 names[key] = 'No '+language+' compiler flags found.' 81 key = self.getCompilerFlagsName(language, 1) 82 names[key] = 'No '+language+' compiler flags found.' 83 key = self.getLinkerFlagsName(language) 84 names[key] = 'No '+language+' linker flags found.' 85 self.popLanguage() 86 names['CPPFLAGS'] = 'No preprocessor flags found.' 87 names['FPPFLAGS'] = 'No Fortran preprocessor flags found.' 88 names['CUDAPPFLAGS'] = 'No CUDA preprocessor flags found.' 89 names['HIPPPFLAGS'] = 'No HIP preprocessor flags found.' 90 names['SYCLPPFLAGS'] = 'No SYCL preprocessor flags found.' 91 names['CXXPPFLAGS'] = 'No C++ preprocessor flags found.' 92 names['AR_FLAGS'] = 'No archiver flags found.' 93 names['AR_LIB_SUFFIX'] = 'No static library suffix found.' 94 names['LIBS'] = 'No extra libraries found.' 95 return names 96 97 def setupDependencies(self, framework): 98 config.base.Configure.setupDependencies(self, framework) 99 self.setCompilers = framework.require('config.setCompilers', self) 100 self.compilerFlags = framework.require('config.compilerFlags', self) 101 self.libraries = framework.require('config.libraries', None) 102 self.dispatchNames = self.getDispatchNames() 103 return 104 105 def __getattr__(self, name): 106 if 'dispatchNames' in self.__dict__: 107 if name in self.dispatchNames: 108 if not hasattr(self.setCompilers, name): 109 raise MissingProcessor(self.dispatchNames[name]) 110 return getattr(self.setCompilers, name) 111 if name in ['CC_LINKER_FLAGS', 'FC_LINKER_FLAGS', 'CXX_LINKER_FLAGS', 'CUDAC_LINKER_FLAGS', 'HIPC_LINKER_FLAGS', 'SYCLC_LINKER_FLAGS','sharedLibraryFlags', 'dynamicLibraryFlags']: 112 flags = getattr(self.setCompilers, name) 113 if not isinstance(flags, list): flags = [flags] 114 return ' '.join(flags) 115 raise AttributeError('Configure attribute not found: '+name) 116 117 def __setattr__(self, name, value): 118 if 'dispatchNames' in self.__dict__: 119 if name in self.dispatchNames: 120 return setattr(self.setCompilers, name, value) 121 config.base.Configure.__setattr__(self, name, value) 122 return 123 124 def checkCxxRestrict(self): 125 '''Check for the CXX restrict keyword equivalent to C99 restrict''' 126 with self.Language('Cxx'): 127 for kw in ['__restrict', ' __restrict__', 'restrict', ' ']: 128 if self.checkCompile('', 'float * '+kw+' x;\n(void)x'): 129 self.cxxRestrict = kw 130 break 131 self.logPrint('Set Cxx restrict keyword to : '+self.cxxRestrict, 4, 'compilers') 132 self.addDefine('CXX_RESTRICT', self.cxxRestrict) 133 return 134 135 def checkCrossLink(self, func1, func2, language1 = 'C', language2='FC',extraObjs = None, extralibs=None): 136 '''Compiles C/C++ and Fortran code and tries to link them together; the C and Fortran code are independent so no name mangling is needed 137 language1 is used to compile the first code, language2 compiles the second and links them togetether''' 138 obj1 = os.path.join(self.tmpDir, 'confc.o') 139 found = 0 140 # Compile the C test object 141 self.pushLanguage(language1) 142 if not self.checkCompile(func1, None, cleanup = 0): 143 self.logPrint('Cannot compile C function: '+func1, 3, 'compilers') 144 self.popLanguage() 145 return found 146 if not os.path.isfile(self.compilerObj): 147 self.logPrint('Cannot locate object file: '+os.path.abspath(self.compilerObj), 3, 'compilers') 148 self.popLanguage() 149 return found 150 os.rename(self.compilerObj, obj1) 151 self.popLanguage() 152 # Link the test object against a Fortran driver 153 self.pushLanguage(language2) 154 oldLIBS = self.setCompilers.LIBS 155 self.setCompilers.LIBS = obj1+' '+self.setCompilers.LIBS 156 if extraObjs or extralibs: 157 if extraObjs is None: 158 extraObjs = [] 159 if extralibs is None: 160 extralibs = self.clibs 161 self.setCompilers.LIBS = ' '.join(extraObjs)+' '+' '.join([self.libraries.getLibArgument(lib) for lib in extralibs])+' '+self.setCompilers.LIBS 162 found = self.checkLink("", func2,codeBegin = " ", codeEnd = " ") 163 self.setCompilers.LIBS = oldLIBS 164 self.popLanguage() 165 if os.path.isfile(obj1): 166 os.remove(obj1) 167 return found 168 169 def checkCLibraries(self): 170 '''Determines the libraries needed to link using the C++ or Fortran compiler C source code compiled with C. Result is stored in clibs''' 171 skipclibraries = 1 172 if hasattr(self.setCompilers, 'FC'): 173 self.setCompilers.saveLog() 174 try: 175 if self.checkCrossLink('#include <stdio.h>\nvoid asub(void)\n{char s[16];printf("testing %s",s);}\n'," program main\n print*,'testing'\n stop\n end\n",language1='C',language2='FC'): 176 self.logWrite(self.setCompilers.restoreLog()) 177 self.logPrint('C libraries are not needed when using Fortran linker') 178 else: 179 self.logWrite(self.setCompilers.restoreLog()) 180 self.logPrint('C code cannot directly be linked with Fortran linker, therefore will determine needed C libraries') 181 skipclibraries = 0 182 except RuntimeError as e: 183 self.logWrite(self.setCompilers.restoreLog()) 184 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 185 self.logPrint('C code cannot directly be linked with Fortran linker, therefore will determine needed C libraries') 186 skipclibraries = 0 187 if hasattr(self.setCompilers, 'CXX'): 188 self.setCompilers.saveLog() 189 try: 190 if self.checkCrossLink('#include <stdio.h>\nvoid asub(void)\n{char s[16];printf("testing %s",s);}\n',"int main(int argc,char **args)\n{(void)argc, (void)args; return 0;}\n",language1='C',language2='C++'): 191 self.logWrite(self.setCompilers.restoreLog()) 192 self.logPrint('C libraries are not needed when using C++ linker') 193 else: 194 self.logWrite(self.setCompilers.restoreLog()) 195 self.logPrint('C code cannot directly be linked with C++ linker, therefore will determine needed C libraries') 196 skipclibraries = 0 197 except RuntimeError as e: 198 self.logWrite(self.setCompilers.restoreLog()) 199 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 200 self.logPrint('C code cannot directly be linked with C++ linker, therefore will determine needed C libraries') 201 skipclibraries = 0 202 if skipclibraries == 1: return 203 204 oldFlags = self.setCompilers.LDFLAGS 205 self.setCompilers.LDFLAGS += ' -v' 206 self.pushLanguage('C') 207 (output, returnCode) = self.outputLink('', '') 208 self.setCompilers.LDFLAGS = oldFlags 209 self.popLanguage() 210 211 # Cray: remove libsci link 212 iscray = config.setCompilers.Configure.isCray(self.getCompiler('C'), self.log) 213 214 output = remove_xcode_verbose(output) 215 # PGI: kill anything enclosed in single quotes 216 if output.find('\'') >= 0: 217 # Cray has crazy non-matching single quotes so skip the removal 218 if not output.count('\'')%2: 219 while output.find('\'') >= 0: 220 start = output.index('\'') 221 end = output.index('\'', start+1)+1 222 output = output.replace(output[start:end], '') 223 224 # The easiest thing to do for xlc output is to replace all the commas 225 # with spaces. Try to only do that if the output is really from xlc, 226 # since doing that causes problems on other systems. 227 if output.find('XL_CONFIG') >= 0: 228 output = output.replace(',', ' ') 229 230 # Parse output 231 argIter = iter(output.split()) 232 clibs = [] 233 skipdefaultpaths = self.getSkipDefaultPaths() 234 lflags = [] 235 rpathflags = [] 236 try: 237 while 1: 238 arg = next(argIter) 239 self.logPrint( 'Checking arg '+arg, 4, 'compilers') 240 241 # Intel compiler sometimes puts " " around an option like "-lsomething" 242 if arg.startswith('"') and arg.endswith('"'): 243 arg = arg[1:-1] 244 # Intel also puts several options together inside a " " so the last one 245 # has a stray " at the end 246 if arg.endswith('"') and arg[:-1].find('"') == -1: 247 arg = arg[:-1] 248 # Intel 11 has a bogus -long_double option 249 if arg == '-long_double': 250 continue 251 if arg == '-lto_library': 252 lib = next(argIter) 253 self.logPrint('Skipping Apple LLVM linker option -lto_library '+lib) 254 continue 255 # ASan 256 if arg in ['-lasan', '-lubsan']: 257 self.logPrint('Skipping ASan libraries') 258 continue 259 # if options of type -L foobar 260 if arg == '-L': 261 lib = next(argIter) 262 self.logPrint('Found -L '+lib, 4, 'compilers') 263 clibs.append('-L'+lib) 264 continue 265 # Check for full library name 266 m = re.match(r'^/.*\.a$', arg) 267 if m: 268 if not arg in lflags: 269 lflags.append(arg) 270 self.logPrint('Found full library spec: '+arg, 4, 'compilers') 271 clibs.append(arg) 272 else: 273 self.logPrint('Skipping, already in lflags: '+arg, 4, 'compilers') 274 continue 275 # Check for full dylib library name 276 m = re.match(r'^/.*\.dylib$', arg) 277 if m: 278 if not arg in lflags: 279 lflags.append(arg) 280 self.logPrint('Found full library spec: '+arg, 4, 'compilers') 281 clibs.append(arg) 282 else: 283 self.logPrint('already in lflags: '+arg, 4, 'compilers') 284 continue 285 # Check for system libraries 286 m = re.match(r'^-l(ang.*|crt[0-9].o|crtbegin.o|c|gcc|gcc_ext(.[0-9]+)*|System|cygwin|xlomp_ser|crt[0-9].[0-9][0-9].[0-9].o)$', arg) 287 if m: 288 self.logPrint('Skipping system library: '+arg, 4, 'compilers') 289 continue 290 # Check for special library arguments 291 m = re.match(r'^-l.*$', arg) 292 if m: 293 if not arg in lflags: 294 if arg == '-lkernel32': 295 continue 296 elif iscray and (arg == '-lsci_cray_mpi' or arg == '-lsci_cray' or arg == '-lsci_cray_mp'): 297 self.logPrint('Skipping CRAY LIBSCI library: '+arg, 4, 'compilers') 298 continue 299 else: 300 lflags.append(arg) 301 self.logPrint('Found library : '+arg, 4, 'compilers') 302 clibs.append(arg) 303 continue 304 m = re.match(r'^-L.*$', arg) 305 if m: 306 arg = os.path.abspath(arg[2:]) 307 if arg in skipdefaultpaths: continue 308 arg = '-L'+arg 309 lflags.append(arg) 310 self.logPrint('Found library directory: '+arg, 4, 'compilers') 311 clibs.append(arg) 312 continue 313 # Check for '-rpath /sharedlibpath/ or -R /sharedlibpath/' 314 if arg == '-rpath' or arg == '-R': 315 lib = next(argIter) 316 if lib.startswith('-') or lib.startswith('@loader_path'): continue # perhaps the path was striped due to quotes? 317 if lib.startswith('"') and lib.endswith('"') and lib.find(' ') == -1: lib = lib[1:-1] 318 lib = os.path.abspath(lib) 319 if lib in skipdefaultpaths: continue 320 if not lib in rpathflags: 321 rpathflags.append(lib) 322 self.logPrint('Found '+arg+' library: '+lib, 4, 'compilers') 323 clibs.append(self.setCompilers.CSharedLinkerFlag+lib) 324 else: 325 self.logPrint('Already in rpathflags, skipping'+arg, 4, 'compilers') 326 continue 327 # Check for '-R/sharedlibpath/' 328 m = re.match(r'^-R.*$', arg) 329 if m: 330 lib = os.path.abspath(arg[2:]) 331 if not lib in rpathflags: 332 rpathflags.append(lib) 333 self.logPrint('Found -R library: '+lib, 4, 'compilers') 334 clibs.append(self.setCompilers.CSharedLinkerFlag+lib) 335 else: 336 self.logPrint('Already in rpathflags, skipping'+arg, 4, 'compilers') 337 continue 338 self.logPrint('Unknown arg '+arg, 4, 'compilers') 339 except StopIteration: 340 pass 341 342 self.clibs = [] 343 for lib in clibs: 344 if not self.setCompilers.staticLibraries and lib.startswith('-L') and not self.setCompilers.CSharedLinkerFlag == '-L': 345 self.clibs.append(self.setCompilers.CSharedLinkerFlag+lib[2:]) 346 self.clibs.append(lib) 347 348 self.logPrint('Libraries needed to link C code with another linker: '+str(self.clibs), 3, 'compilers') 349 350 if hasattr(self.setCompilers, 'FC') or hasattr(self.setCompilers, 'CXX'): 351 self.logPrint('Check that C libraries can be used with Fortran as linker', 4, 'compilers') 352 oldLibs = self.setCompilers.LIBS 353 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.clibs])+' '+self.setCompilers.LIBS 354 if hasattr(self.setCompilers, 'FC'): 355 self.setCompilers.saveLog() 356 try: 357 self.setCompilers.checkCompiler('FC') 358 except RuntimeError as e: 359 self.setCompilers.LIBS = oldLibs 360 self.logWrite(self.setCompilers.restoreLog()) 361 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 362 raise RuntimeError('C libraries cannot directly be used with Fortran as linker') 363 except OSError as e: 364 self.setCompilers.LIBS = oldLibs 365 self.logWrite(self.setCompilers.restoreLog()) 366 raise e 367 self.logWrite(self.setCompilers.restoreLog()) 368 return 369 370 def checkCFormatting(self): 371 '''Activate format string checking if using the GNU compilers''' 372 '''No checking because we use additional formatting conventions''' 373 if self.isGCC and 0: 374 self.gccFormatChecking = ('PRINTF_FORMAT_CHECK(A,B)', '__attribute__((format (printf, A, B)))') 375 self.logPrint('Added gcc printf format checking', 4, 'compilers') 376 self.addDefine(self.gccFormatChecking[0], self.gccFormatChecking[1]) 377 else: 378 self.gccFormatChecking = None 379 return 380 381 def checkDynamicLoadFlag(self): 382 '''Checks that dlopen() takes RTLD_XXX, and defines PETSC_HAVE_RTLD_XXX if it does''' 383 if self.setCompilers.dynamicLibraries: 384 if self.checkLink('#include <dlfcn.h>\nchar *libname;\n', 'dlopen(libname, RTLD_LAZY);dlopen(libname, RTLD_NOW);dlopen(libname, RTLD_LOCAL);dlopen(libname, RTLD_GLOBAL)'): 385 self.addDefine('HAVE_RTLD_LAZY', 1) 386 self.addDefine('HAVE_RTLD_NOW', 1) 387 self.addDefine('HAVE_RTLD_LOCAL', 1) 388 self.addDefine('HAVE_RTLD_GLOBAL', 1) 389 else: 390 if self.checkLink('#include <dlfcn.h>\nchar *libname;\n', 'dlopen(libname, RTLD_LAZY)'): 391 self.addDefine('HAVE_RTLD_LAZY', 1) 392 if self.checkLink('#include <dlfcn.h>\nchar *libname;\n', 'dlopen(libname, RTLD_NOW)'): 393 self.addDefine('HAVE_RTLD_NOW', 1) 394 if self.checkLink('#include <dlfcn.h>\nchar *libname;\n', 'dlopen(libname, RTLD_LOCAL)'): 395 self.addDefine('HAVE_RTLD_LOCAL', 1) 396 if self.checkLink('#include <dlfcn.h>\nchar *libname;\n', 'dlopen(libname, RTLD_GLOBAL)'): 397 self.addDefine('HAVE_RTLD_GLOBAL', 1) 398 if self.checkLink('#include <dlfcn.h>\nchar *libname;\n', 'dlopen(libname, RTLD_NOLOAD)'): 399 self.addDefine('HAVE_RTLD_NOLOAD', 1) 400 return 401 402 def checkCxxOptionalExtensions(self): 403 '''Check whether the C++ compiler (IBM xlC, OSF5) need special flag for .c files which contain C++''' 404 self.setCompilers.saveLog() 405 self.setCompilers.pushLanguage('Cxx') 406 cxxObj = self.framework.getCompilerObject('Cxx') 407 oldExt = cxxObj.sourceExtension 408 cxxObj.sourceExtension = self.framework.getCompilerObject('C').sourceExtension 409 for flag in ['', '-+', '-x cxx -tlocal', '-Kc++']: 410 try: 411 self.setCompilers.addCompilerFlag(flag, body = 'class somename { public: int i; };\nsomename b;\nb.i = 0;\n(void)b.i') 412 self.cxxCompileC = True 413 break 414 except RuntimeError: 415 pass 416 if not self.cxxCompileC: 417 for flag in ['-x c++', '-TP','-P']: 418 try: 419 self.setCompilers.addCompilerFlag(flag, body = 'class somename { public: int i; };\nsomename b;\nb.i = 0;\n(void)b.i', compilerOnly = 1) 420 self.cxxCompileC = True 421 break 422 except RuntimeError: 423 pass 424 cxxObj.sourceExtension = oldExt 425 self.setCompilers.popLanguage() 426 self.logWrite(self.setCompilers.restoreLog()) 427 return 428 429 def checkCxxComplexFix(self): 430 """Determine if the CXX compiler supports utilities provided by petsccxxcomplexfix.h""" 431 includes = """ 432 #include <iostream> 433 #include <complex> 434 #define Type int 435 #define PetscReal double 436 #define PetscComplex std::complex<double> 437 /* The two lines, from petsccxxcomplexfix.h, can cause the combination "C++14 + GCC-4.x libstdc++ library" to fail, complaining imag() 438 is not marked const. If the compiler can compile these two lines, it should be able to compile other lines. 439 */ 440 static inline PetscComplex operator-(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) - const_cast<PetscComplex&>(rhs); } 441 static inline PetscComplex operator/(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) / const_cast<PetscComplex&>(rhs); } 442 """ 443 body = """ 444 Type x = 2; 445 PetscComplex y(1.0,1.0),z,w; 446 z = x - y; 447 w = x / y; 448 std::cout << z << w; 449 """ 450 self.pushLanguage('Cxx') 451 if self.checkCompile(includes,body): 452 self.logPrint('the CXX compiler supports petsccxxcomplexfix.h') 453 self.addDefine('HAVE_CXX_COMPLEX_FIX',1) 454 else: 455 self.logPrint('the CXX compiler does not support petsccxxcomplexfix.h') 456 self.popLanguage() 457 458 def checkCxxLibraries(self): 459 '''Determines the libraries needed to link using the C or Fortran compiler C++ source code compiled with C++. Result is stored in cxxlibs''' 460 skipcxxlibraries = 1 461 self.setCompilers.saveLog() 462 body = '''#include <iostream>\n#include <vector>\nvoid asub(void)\n{std::vector<int> v;\ntry { throw 20; } catch (int e) { std::cout << "An exception occurred"; }}''' 463 oldLibs = '' 464 try: 465 if self.checkCrossLink(body,"int main(int argc,char **args)\n{return 0;}\n",language1='C++',language2='C'): 466 self.logWrite(self.setCompilers.restoreLog()) 467 self.logPrint('C++ libraries are not needed when using C linker') 468 else: 469 skipcxxlibraries = 0 470 self.logWrite(self.setCompilers.restoreLog()) 471 if self.setCompilers.isDarwin(self.log) and config.setCompilers.Configure.isClang(self.getCompiler('C'), self.log): 472 oldLibs = self.setCompilers.LIBS 473 self.setCompilers.LIBS = '-lc++ '+self.setCompilers.LIBS 474 self.setCompilers.saveLog() 475 if self.checkCrossLink(body,"int main(int argc,char **args)\n{return 0;}\n",language1='C++',language2='C'): 476 self.setCompilers.LIBS = oldLibs 477 self.logWrite(self.setCompilers.restoreLog()) 478 self.logPrint('C++ requires -lc++ to link with C compiler', 3, 'compilers') 479 self.cxxlibs.append('-lc++') 480 skipcxxlibraries = 1 481 else: 482 self.logWrite(self.setCompilers.restoreLog()) 483 self.setCompilers.LIBS = oldLibs 484 self.logPrint('C++ code cannot directly be linked with C linker using -lc++, therefore will determine needed C++ libraries') 485 skipcxxlibraries = 0 486 if self.setCompilers.isNEC(self.getCompiler('C'),self.log): 487 oldLibs = self.setCompilers.LIBS 488 self.setCompilers.LIBS = '-lnc++ '+self.setCompilers.LIBS 489 self.setCompilers.saveLog() 490 if self.checkCrossLink(body,"int main(int argc,char **args)\n{return 0;}\n",language1='C++',language2='C'): 491 self.setCompilers.LIBS = oldLibs 492 self.logWrite(self.setCompilers.restoreLog()) 493 self.logPrint('C++ requires -lnc++ to link with C compiler', 3, 'compilers') 494 self.cxxlibs.append('-lnc++') 495 skipcxxlibraries = 1 496 else: 497 self.logWrite(self.setCompilers.restoreLog()) 498 self.setCompilers.LIBS = oldLibs 499 self.logPrint('C++ code cannot directly be linked with C linker using -lnc++, therefore will determine needed C++ libraries') 500 skipcxxlibraries = 0 501 if not skipcxxlibraries: 502 self.setCompilers.saveLog() 503 oldLibs = self.setCompilers.LIBS 504 self.setCompilers.LIBS = '-lstdc++ '+self.setCompilers.LIBS 505 if self.checkCrossLink(body,"int main(int argc,char **args)\n{return 0;}\n",language1='C++',language2='C'): 506 self.setCompilers.LIBS = oldLibs 507 self.logWrite(self.setCompilers.restoreLog()) 508 self.logPrint('C++ requires -lstdc++ to link with C compiler', 3, 'compilers') 509 self.cxxlibs.append('-lstdc++') 510 skipcxxlibraries = 1 511 else: 512 self.logWrite(self.setCompilers.restoreLog()) 513 self.setCompilers.LIBS = oldLibs 514 self.logPrint('C++ code cannot directly be linked with C linker using -lstdc++, therefore will determine needed C++ libraries') 515 skipcxxlibraries = 0 516 except RuntimeError as e: 517 self.logWrite(self.setCompilers.restoreLog()) 518 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 519 self.logPrint('C++ code cannot directly be linked with C linker, therefore will determine needed C++ libraries') 520 skipcxxlibraries = 0 521 if skipcxxlibraries and hasattr(self.setCompilers, 'FC'): 522 self.setCompilers.saveLog() 523 oldLibs = self.setCompilers.LIBS 524 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.cxxlibs])+' '+self.setCompilers.LIBS 525 try: 526 if self.checkCrossLink(body," program main\n print*,'testing'\n stop\n end\n",language1='C++',language2='FC'): 527 self.logWrite(self.setCompilers.restoreLog()) 528 self.logPrint('Additional C++ libraries are not needed when using FC linker') 529 else: 530 self.logWrite(self.setCompilers.restoreLog()) 531 self.logPrint('Additional C++ libraries are needed when using FC linker') 532 skipcxxlibraries = 0 533 except RuntimeError as e: 534 self.logWrite(self.setCompilers.restoreLog()) 535 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 536 self.logPrint('C++ code cannot directly be linked with FC linker, therefore will determine needed C++ libraries') 537 skipcxxlibraries = 0 538 self.setCompilers.LIBS = oldLibs 539 540 if skipcxxlibraries: return 541 542 oldFlags = self.setCompilers.LDFLAGS 543 self.setCompilers.LDFLAGS += ' -v' 544 self.pushLanguage('Cxx') 545 (output, returnCode) = self.outputLink('', '') 546 self.setCompilers.LDFLAGS = oldFlags 547 self.popLanguage() 548 549 # Cray: remove libsci link 550 iscray = config.setCompilers.Configure.isCray(self.getCompiler('Cxx'), self.log) 551 552 output = remove_xcode_verbose(output) 553 # PGI: kill anything enclosed in single quotes 554 if output.find('\'') >= 0: 555 if output.count('\'')%2: raise RuntimeError('Mismatched single quotes in C library string') 556 while output.find('\'') >= 0: 557 start = output.index('\'') 558 end = output.index('\'', start+1)+1 559 output = output.replace(output[start:end], '') 560 561 # The easiest thing to do for xlc output is to replace all the commas 562 # with spaces. Try to only do that if the output is really from xlc, 563 # since doing that causes problems on other systems. 564 if output.find('XL_CONFIG') >= 0: 565 output = output.replace(',', ' ') 566 567 # Parse output 568 argIter = iter(output.split()) 569 cxxlibs = [] 570 skipdefaultpaths = self.getSkipDefaultPaths() 571 lflags = [] 572 rpathflags = [] 573 try: 574 while 1: 575 arg = next(argIter) 576 self.logPrint( 'Checking arg '+arg, 4, 'compilers') 577 578 # Intel compiler sometimes puts " " around an option like "-lsomething" 579 if arg.startswith('"') and arg.endswith('"'): 580 arg = arg[1:-1] 581 # Intel also puts several options together inside a " " so the last one 582 # has a stray " at the end 583 if arg.endswith('"') and arg[:-1].find('"') == -1: 584 arg = arg[:-1] 585 # Intel 11 has a bogus -long_double option 586 if arg == '-long_double': 587 continue 588 589 # ASan 590 if arg in ['-lasan', '-lubsan']: 591 self.logPrint('Skipping ASan libraries') 592 continue 593 # if options of type -L foobar 594 if arg == '-L': 595 lib = next(argIter) 596 self.logPrint('Found -L '+lib, 4, 'compilers') 597 cxxlibs.append('-L'+lib) 598 continue 599 if arg == '-lto_library': 600 lib = next(argIter) 601 self.logPrint('Skipping Apple LLVM linker option -lto_library '+lib) 602 continue 603 # Check for full library name 604 m = re.match(r'^/.*\.a$', arg) 605 if m: 606 if not arg in lflags: 607 lflags.append(arg) 608 self.logPrint('Found full library spec: '+arg, 4, 'compilers') 609 cxxlibs.append(arg) 610 else: 611 self.logPrint('Already in lflags: '+arg, 4, 'compilers') 612 continue 613 # Check for full dylib library name 614 m = re.match(r'^/.*\.dylib$', arg) 615 if m: 616 if not arg in lflags and not arg.endswith('LTO.dylib'): 617 lflags.append(arg) 618 self.logPrint('Found full library spec: '+arg, 4, 'compilers') 619 cxxlibs.append(arg) 620 else: 621 self.logPrint('already in lflags: '+arg, 4, 'compilers') 622 continue 623 # Check for system libraries 624 m = re.match(r'^-l(ang.*|crt[0-9].o|crtbegin.o|c|gcc|gcc_ext(.[0-9]+)*|System|cygwin|xlomp_ser|crt[0-9].[0-9][0-9].[0-9].o)$', arg) 625 if m: 626 self.logPrint('Skipping system library: '+arg, 4, 'compilers') 627 continue 628 # Check for special library arguments 629 m = re.match(r'^-l.*$', arg) 630 if m: 631 if not arg in lflags: 632 if arg == '-lkernel32': 633 continue 634 elif arg == '-lLTO' and self.setCompilers.isDarwin(self.log): 635 self.logPrint('Skipping -lTO') 636 continue 637 elif arg.find('-libpath:')>=0: 638 self.logPrint('Skipping Intel oneAPI icx (on Microsoft Windows) compiler option: '+arg) 639 continue 640 elif iscray and (arg == '-lsci_cray_mpi' or arg == '-lsci_cray' or arg == '-lsci_cray_mp'): 641 self.logPrint('Skipping CRAY LIBSCI library: '+arg, 4, 'compilers') 642 continue 643 elif arg in self.clibs: 644 self.logPrint('Library already in C list so skipping in C++', 4, 'compilers') 645 continue 646 else: 647 lflags.append(arg) 648 self.logPrint('Found library: '+arg, 4, 'compilers') 649 cxxlibs.append(arg) 650 else: 651 self.logPrint('Already in flags: '+arg, 4, 'compilers') 652 continue 653 m = re.match(r'^-L.*$', arg) 654 if m: 655 arg = os.path.abspath(arg[2:]) 656 if arg in skipdefaultpaths: continue 657 arg = '-L'+arg 658 if not arg in lflags: 659 lflags.append(arg) 660 self.logPrint('Found library directory: '+arg, 4, 'compilers') 661 cxxlibs.append(arg) 662 continue 663 # Check for '-rpath /sharedlibpath/ or -R /sharedlibpath/' 664 if arg == '-rpath' or arg == '-R': 665 lib = next(argIter) 666 if lib.startswith('-') or lib.startswith('@loader_path'): continue # perhaps the path was striped due to quotes? 667 if lib.startswith('"') and lib.endswith('"') and lib.find(' ') == -1: lib = lib[1:-1] 668 lib = os.path.abspath(lib) 669 if lib in skipdefaultpaths: continue 670 if not lib in rpathflags: 671 rpathflags.append(lib) 672 self.logPrint('Found '+arg+' library: '+lib, 4, 'compilers') 673 cxxlibs.append(self.setCompilers.CSharedLinkerFlag+lib) 674 else: 675 self.logPrint('Already in rpathflags, skipping:'+arg, 4, 'compilers') 676 continue 677 # Check for '-R/sharedlibpath/' 678 m = re.match(r'^-R.*$', arg) 679 if m: 680 lib = os.path.abspath(arg[2:]) 681 if not lib in rpathflags: 682 rpathflags.append(lib) 683 self.logPrint('Found -R library: '+lib, 4, 'compilers') 684 cxxlibs.append(self.setCompilers.CSharedLinkerFlag+lib) 685 else: 686 self.logPrint('Already in rpathflags, skipping:'+arg, 4, 'compilers') 687 continue 688 self.logPrint('Unknown arg '+arg, 4, 'compilers') 689 except StopIteration: 690 pass 691 692 self.cxxlibs = [] 693 for lib in cxxlibs: 694 if not self.setCompilers.staticLibraries and lib.startswith('-L') and not self.setCompilers.CSharedLinkerFlag == '-L': 695 self.cxxlibs.append(self.setCompilers.CSharedLinkerFlag+lib[2:]) 696 self.cxxlibs.append(lib) 697 698 self.logPrint('Libraries needed to link Cxx code with another linker: '+str(self.cxxlibs), 3, 'compilers') 699 700 self.logPrint('Check that Cxx libraries can be used with C as linker', 4, 'compilers') 701 oldLibs = self.setCompilers.LIBS 702 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.cxxlibs])+' '+self.setCompilers.LIBS 703 self.setCompilers.saveLog() 704 try: 705 self.setCompilers.checkCompiler('C') 706 except RuntimeError as e: 707 self.logWrite(self.setCompilers.restoreLog()) 708 self.logPrint('Cxx libraries cannot directly be used with C as linker', 4, 'compilers') 709 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 710 raise RuntimeError("Cxx libraries cannot directly be used with C as linker.\n\ 711If you don't need the C++ compiler to build external packages or for you application you can run\n\ 712./configure with --with-cxx=0. Otherwise you need a different combination of C and C++ compilers") 713 else: 714 self.logWrite(self.setCompilers.restoreLog()) 715 self.setCompilers.LIBS = oldLibs 716 717 if hasattr(self.setCompilers, 'FC'): 718 719 self.logPrint('Check that Cxx libraries can be used with Fortran as linker', 4, 'compilers') 720 oldLibs = self.setCompilers.LIBS 721 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.cxxlibs])+' '+self.setCompilers.LIBS 722 self.setCompilers.saveLog() 723 try: 724 self.setCompilers.checkCompiler('FC') 725 except RuntimeError as e: 726 self.logWrite(self.setCompilers.restoreLog()) 727 self.logPrint('Cxx libraries cannot directly be used with Fortran as linker', 4, 'compilers') 728 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 729 raise RuntimeError("Cxx libraries cannot directly be used with Fortran as linker.\n\ 730If you don't need the C++ compiler to build external packages or for you application you can run\n\ 731./configure with --with-cxx=0. If you don't need the Fortran compiler to build external packages\n\ 732or for you application you can run ./configure with --with-fc=0.\n\ 733Otherwise you need a different combination of C, C++, and Fortran compilers") 734 else: 735 self.logWrite(self.setCompilers.restoreLog()) 736 self.setCompilers.LIBS = oldLibs 737 return 738 739 def mangleFortranFunction(self, name): 740 if self.fortranMangling == 'underscore': 741 if self.fortranManglingDoubleUnderscore and name.find('_') >= 0: 742 return name.lower()+'__' 743 else: 744 return name.lower()+'_' 745 elif self.fortranMangling == 'unchanged': 746 return name.lower() 747 elif self.fortranMangling == 'caps': 748 return name.upper() 749 elif self.fortranMangling == 'stdcall': 750 return name.upper() 751 raise RuntimeError('Unknown Fortran name mangling: '+self.fortranMangling) 752 753 def testMangling(self, cfunc, ffunc, clanguage = 'C', extraObjs = []): 754 '''Test a certain name mangling''' 755 cobj = os.path.join(self.tmpDir, 'confc.o') 756 found = 0 757 # Compile the C test object 758 self.pushLanguage(clanguage) 759 if not self.checkCompile(cfunc, None, cleanup = 0): 760 self.logPrint('Cannot compile C function: '+cfunc, 3, 'compilers') 761 self.popLanguage() 762 return found 763 if not os.path.isfile(self.compilerObj): 764 self.logPrint('Cannot locate object file: '+os.path.abspath(self.compilerObj), 3, 'compilers') 765 self.popLanguage() 766 return found 767 os.rename(self.compilerObj, cobj) 768 self.popLanguage() 769 # Link the test object against a Fortran driver 770 self.pushLanguage('FC') 771 oldLIBS = self.setCompilers.LIBS 772 self.setCompilers.LIBS = cobj+' '+' '.join([self.libraries.getLibArgument(lib) for lib in self.clibs])+' '+self.setCompilers.LIBS 773 if extraObjs: 774 self.setCompilers.LIBS = ' '.join(extraObjs)+' '+' '.join([self.libraries.getLibArgument(lib) for lib in self.clibs])+' '+self.setCompilers.LIBS 775 found = self.checkLink(None, ffunc) 776 self.setCompilers.LIBS = oldLIBS 777 self.popLanguage() 778 if os.path.isfile(cobj): 779 os.remove(cobj) 780 return found 781 782 def checkFortranNameMangling(self): 783 '''Checks Fortran name mangling, and defines HAVE_FORTRAN_UNDERSCORE, HAVE_FORTRAN_NOUNDERSCORE, HAVE_FORTRAN_CAPS''' 784 self.manglerFuncs = {'underscore': ('void d1chk_(void);', 'void d1chk_(void){return;}\n', ' call d1chk()\n'), 785 'unchanged': ('void d1chk(void);', 'void d1chk(void){return;}\n', ' call d1chk()\n'), 786 'caps': ('void D1CHK(void);', 'void D1CHK(void){return;}\n', ' call d1chk()\n'), 787 'stdcall': ('void __stdcall D1CHK(void);', 'void __stdcall D1CHK(void){return;}\n', ' call d1chk()\n'), 788 'double': ('void d1_chk__(void)', 'void d1_chk__(void){return;}\n', ' call d1_chk()\n')} 789 #some compilers silently ignore '__stdcall' directive, so do stdcall test last 790 # double test is not done here, so its not listed 791 key_list = ['underscore','unchanged','caps','stdcall'] 792 for mangler in key_list: 793 cfunc = self.manglerFuncs[mangler][1] 794 ffunc = self.manglerFuncs[mangler][2] 795 self.logWrite('Testing Fortran mangling type '+mangler+' with code '+cfunc) 796 if self.testMangling(cfunc, ffunc): 797 self.fortranMangling = mangler 798 break 799 else: 800 if self.setCompilers.isDarwin(self.log): 801 mess = ' See https://petsc.org/release/faq/#macos-gfortran' 802 else: 803 mess = '' 804 raise RuntimeError('Unknown Fortran name mangling: Are you sure the C and Fortran compilers are compatible?\n Perhaps one is 64-bit and one is 32-bit?\n'+mess) 805 self.logPrint('Fortran name mangling is '+self.fortranMangling, 4, 'compilers') 806 if self.fortranMangling == 'underscore': 807 self.addDefine('HAVE_FORTRAN_UNDERSCORE', 1) 808 elif self.fortranMangling == 'unchanged': 809 self.addDefine('HAVE_FORTRAN_NOUNDERSCORE', 1) 810 elif self.fortranMangling == 'caps': 811 self.addDefine('HAVE_FORTRAN_CAPS', 1) 812 elif self.fortranMangling == 'stdcall': 813 raise RuntimeError('Fortran STDCALL compilers are unsupported!\n') 814 if config.setCompilers.Configure.isGfortran8plus(self.getCompiler('FC'), self.log): 815 self.addDefine('FORTRAN_CHARLEN_T', 'size_t') 816 else: 817 self.addDefine('FORTRAN_CHARLEN_T', 'int') 818 return 819 820 def checkFortranNameManglingDouble(self): 821 '''Checks if symbols containing an underscore append an extra underscore, and defines HAVE_FORTRAN_UNDERSCORE_UNDERSCORE if necessary''' 822 if self.testMangling(self.manglerFuncs['double'][1], self.manglerFuncs['double'][2]): 823 self.logPrint('Fortran appends an extra underscore to names containing underscores', 4, 'compilers') 824 self.fortranManglingDoubleUnderscore = 1 825 self.addDefine('HAVE_FORTRAN_UNDERSCORE_UNDERSCORE',1) 826 else: 827 self.fortranManglingDoubleUnderscore = 0 828 return 829 830 def checkFortranLibraries(self): 831 '''Substitutes for FLIBS the libraries needed to link using the C or C++ compiler Fortran source code compiled with Fortran. Result is stored in flibs. 832 833 This macro is intended to be used in those situations when it is 834 necessary to mix, e.g. C++ and Fortran 77, source code into a single 835 program or shared library. 836 837 For example, if object files from a C++ and Fortran 77 compiler must 838 be linked together, then the C++ compiler/linker must be used for 839 linking (since special C++-ish things need to happen at link time 840 like calling global constructors, instantiating templates, enabling 841 exception support, etc.). 842 843 However, the Fortran 77 intrinsic and run-time libraries must be 844 linked in as well, but the C++ compiler/linker does not know how to 845 add these Fortran 77 libraries. 846 847 This code was translated from the autoconf macro which was packaged in 848 its current form by Matthew D. Langston <langston@SLAC.Stanford.EDU>. 849 However, nearly all of this macro came from the OCTAVE_FLIBS macro in 850 octave-2.0.13/aclocal.m4, and full credit should go to John W. Eaton 851 for writing this extremely useful macro.''' 852 if not hasattr(self.setCompilers, 'CC') or not hasattr(self.setCompilers, 'FC'): 853 return 854 skipfortranlibraries = 1 855 self.setCompilers.saveLog() 856 asub=self.mangleFortranFunction("asub") 857 cbody = "extern void "+asub+"(void);\nint main(int argc,char **args)\n{\n "+asub+"();\n (void)argc, (void)args;\n return 0;\n}\n"; 858 cxxbody = 'extern "C" void '+asub+'(void);\nint main(int argc,char **args)\n{\n '+asub+'();\n (void)argc, (void)args;\n return 0;\n}\n'; 859 self.pushLanguage('FC') 860 if self.checkLink(body=' use mpi\n call MPI_Allreduce()\n'): 861 fbody = " subroutine asub()\n use mpi\n print*,'testing'\n call MPI_Allreduce()\n return\n end\n" 862 elif self.checkLink(includes='#include <mpif.h>',body=' call MPI_Allreduce()\n'): 863 fbody = " subroutine asub()\n print*,'testing'\n call MPI_Allreduce()\n return\n end\n" 864 else: 865 fbody = " subroutine asub()\n print*,'testing'\n return\n end\n" 866 self.popLanguage() 867 iscray = config.setCompilers.Configure.isCray(self.getCompiler('FC'), self.log) 868 isintel = config.setCompilers.Configure.isIntel(self.getCompiler('C'), self.log) 869 try: 870 if self.checkCrossLink(fbody,cbody,language1='FC',language2='C'): 871 self.logWrite(self.setCompilers.restoreLog()) 872 self.logPrint('Fortran libraries are not needed when using C linker') 873 else: 874 skipfortranlibraries = 0 875 self.logWrite(self.setCompilers.restoreLog()) 876 oldLibs = self.setCompilers.LIBS 877 testlibs = ['-lgfortran'] 878 if iscray: testlibs.append('-lmpifort_cray') 879 if isintel: testlibs.append('-fortlib') 880 for testlib in testlibs: 881 self.setCompilers.LIBS = testlib+' '+self.setCompilers.LIBS 882 self.setCompilers.saveLog() 883 if self.checkCrossLink(fbody,cbody,language1='FC',language2='C'): 884 self.logWrite(self.setCompilers.restoreLog()) 885 self.logPrint('Fortran requires '+testlib+' to link with C compiler', 3, 'compilers') 886 self.setCompilers.LIBS = oldLibs 887 self.flibs.append(testlib) 888 skipfortranlibraries = 1 889 break 890 else: 891 self.logWrite(self.setCompilers.restoreLog()) 892 self.setCompilers.LIBS = oldLibs 893 skipfortranlibraries = 0 894 if not skipfortranlibraries: 895 self.logPrint('Fortran code cannot directly be linked with C linker, therefore will determine needed Fortran libraries') 896 except RuntimeError as e: 897 self.logWrite(self.setCompilers.restoreLog()) 898 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 899 self.logPrint('Fortran code cannot directly be linked with C linker, therefore will determine needed Fortran libraries') 900 skipfortranlibraries = 0 901 if skipfortranlibraries and hasattr(self.setCompilers, 'CXX'): 902 self.setCompilers.saveLog() 903 oldLibs = self.setCompilers.LIBS 904 try: 905 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs]) + ' ' + self.setCompilers.LIBS 906 if self.checkCrossLink(fbody,cxxbody,language1='FC',language2='C++'): 907 self.logWrite(self.setCompilers.restoreLog()) 908 self.setCompilers.LIBS = oldLibs 909 self.logPrint('Additional Fortran libraries are not needed when using C++ linker') 910 else: 911 self.logWrite(self.setCompilers.restoreLog()) 912 self.setCompilers.LIBS = oldLibs 913 self.logPrint('Fortran code cannot directly be linked with C++ linker, therefore will determine needed Fortran libraries') 914 skipfortranlibraries = 0 915 except RuntimeError as e: 916 self.logWrite(self.setCompilers.restoreLog()) 917 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 918 self.setCompilers.LIBS = oldLibs 919 self.logPrint('Fortran code cannot directly be linked with CXX linker, therefore will determine needed Fortran libraries') 920 skipfortranlibraries = 0 921 922 if skipfortranlibraries == 1: return 923 924 self.pushLanguage('FC') 925 oldFlags = self.setCompilers.LDFLAGS 926 self.setCompilers.LDFLAGS += ' -v' 927 (output, returnCode) = self.outputLink('', '') 928 if returnCode: raise RuntimeError('Unable to run linker to determine needed Fortran libraries') 929 output = self.filterLinkOutput(output, filterAlways = 1) 930 self.setCompilers.LDFLAGS = oldFlags 931 self.popLanguage() 932 933 output = remove_xcode_verbose(output) 934 # replace \CR that ifc puts in each line of output 935 output = output.replace('\\\n', '') 936 937 if output.lower().find('absoft') >= 0: 938 loc = output.find(' -lf90math') 939 if loc == -1: loc = output.find(' -lf77math') 940 if loc >= -1: 941 output = output[0:loc]+' -lU77 -lV77 '+output[loc:] 942 943 # PGI/Windows: to properly resolve symbols, we need to list the fortran runtime libraries before -lpgf90 944 # PGI Fortran compiler uses PETSC_HAVE_F90_2PTR_ARG which is incompatible with 945 # certain PETSc example uses of Fortran (like passing classes) hence we need to define 946 # HAVE_PGF90_COMPILER so those examples are not run 947 if output.find(' -lpgf90') >= 0 and output.find(' -lkernel32') >= 0: 948 loc = output.find(' -lpgf90') 949 loc2 = output.find(' -lpgf90rtl -lpgftnrtl') 950 if loc2 >= -1: 951 output = output[0:loc] + ' -lpgf90rtl -lpgftnrtl' + output[loc:] 952 elif output.find(' -lpgf90rtl -lpgftnrtl') >= 0: 953 # somehow doing this hacky thing appears to get rid of error with undefined __hpf_exit 954 self.logPrint('Adding -lpgftnrtl before -lpgf90rtl in librarylist') 955 output = output.replace(' -lpgf90rtl -lpgftnrtl',' -lpgftnrtl -lpgf90rtl -lpgftnrtl') 956 957 # PGI: kill anything enclosed in single quotes 958 if output.find('\'') >= 0: 959 if output.count('\'')%2: raise RuntimeError('Mismatched single quotes in Fortran library string') 960 while output.find('\'') >= 0: 961 start = output.index('\'') 962 end = output.index('\'', start+1)+1 963 output = output.replace(output[start:end], '') 964 965 # The easiest thing to do for xlf output is to replace all the commas 966 # with spaces. Try to only do that if the output is really from xlf, 967 # since doing that causes problems on other systems. 968 if output.find('XL_CONFIG') >= 0: 969 output = output.replace(',', ' ') 970 # We are only supposed to find LD_RUN_PATH on Solaris systems 971 # and the run path should be absolute 972 ldRunPath = re.findall(r'^.*LD_RUN_PATH *= *([^ ]*).*', output) 973 if ldRunPath: ldRunPath = ldRunPath[0] 974 if ldRunPath and ldRunPath[0] == '/': 975 if self.isGCC: 976 ldRunPath = ['-Xlinker -R -Xlinker '+ldRunPath] 977 else: 978 ldRunPath = ['-R '+ldRunPath] 979 else: 980 ldRunPath = [] 981 982 # Parse output 983 argIter = iter(output.split()) 984 fincs = [] 985 flibs = [] 986 skipdefaultpaths = self.getSkipDefaultPaths() 987 fmainlibs = [] 988 lflags = [] 989 rpathflags = [] 990 try: 991 while 1: 992 arg = next(argIter) 993 self.logPrint( 'Checking arg '+arg, 4, 'compilers') 994 995 # Intel compiler sometimes puts " " around an option like "-lsomething" 996 if arg.startswith('"') and arg.endswith('"'): 997 arg = arg[1:-1] 998 # Intel also puts several options together inside a " " so the last one 999 # has a stray " at the end 1000 if arg.endswith('"') and arg[:-1].find('"') == -1: 1001 arg = arg[:-1] 1002 1003 # ASan 1004 if arg in ['-lasan', '-lubsan']: 1005 self.logPrint('Skipping ASan libraries') 1006 continue 1007 if arg == '-lto_library': 1008 lib = next(argIter) 1009 self.logPrint('Skipping Apple LLVM linker option -lto_library '+lib) 1010 continue 1011 # Check for full library name 1012 m = re.match(r'^/.*\.a$', arg) 1013 if m: 1014 if not arg in lflags: 1015 lflags.append(arg) 1016 self.logPrint('Found full library spec: '+arg, 4, 'compilers') 1017# # check for Nag Fortran library that must be handled as static because shared version does not have all the symbols 1018 base = os.path.basename(arg) 1019 m = re.match(r'libf[1-9][0-9]rts.a', base) 1020 if m: 1021 self.logPrint('Detected Nag Fortran compiler library; preserving as static library: '+arg, 4, 'compilers') 1022 flibs.append(arg) 1023 flibs.append('-Wl,-Bstatic') 1024 flibs.append(arg) 1025 flibs.append('-Wl,-Bdynamic') 1026 else: 1027 flibs.append(arg) 1028 else: 1029 self.logPrint('already in lflags: '+arg, 4, 'compilers') 1030 continue 1031 # Check for full dylib library name 1032 m = re.match(r'^/.*\.dylib$', arg) 1033 if m: 1034 if not arg.endswith('LTO.dylib') and not arg in lflags: 1035 lflags.append(arg) 1036 self.logPrint('Found full library spec: '+arg, 4, 'compilers') 1037 flibs.append(arg) 1038 else: 1039 self.logPrint('already in lflags: '+arg, 4, 'compilers') 1040 continue 1041 # prevent false positives for include with pathscalr 1042 if re.match(r'^-INTERNAL.*$', arg): continue 1043 # Check for special include argument 1044 # AIX does this for MPI and perhaps other things 1045 m = re.match(r'^-I.*$', arg) 1046 if m: 1047 inc = arg.replace('-I','',1) 1048 self.logPrint('Found include directory: '+inc, 4, 'compilers') 1049 fincs.append(inc) 1050 continue 1051 # Check for ??? 1052 m = re.match(r'^-bI:.*$', arg) 1053 if m: 1054 if not arg in lflags: 1055 if self.isGCC: 1056 lflags.append('-Xlinker') 1057 lflags.append(arg) 1058 self.logPrint('Found binary include: '+arg, 4, 'compilers') 1059 flibs.append(arg) 1060 else: 1061 self.logPrint('Already in lflags so skipping: '+arg, 4, 'compilers') 1062 continue 1063 # Check for system libraries 1064 m = re.match(r'^-l(ang.*|crt[0-9].o|crtbegin.o|c|gcc|gcc_ext(.[0-9]+)*|System|cygwin|xlomp_ser|crt[0-9].[0-9][0-9].[0-9].o)$', arg) 1065 if m: 1066 self.logPrint('Found system library therefore skipping: '+arg, 4, 'compilers') 1067 continue 1068 # Check for canonical library argument 1069 m = re.match(r'^-[lL]$', arg) 1070 if m: 1071 lib = arg+next(argIter) 1072 self.logPrint('Found canonical library: '+lib, 4, 'compilers') 1073 if not lib == '-LLTO' or not self.setCompilers.isDarwin(self.log): 1074 flibs.append(lib) 1075 continue 1076 # Check for special library arguments 1077 m = re.match(r'^-l.*$', arg) 1078 if m: 1079 # HP Fortran prints these libraries in a very strange way 1080 if arg == '-l:libU77.a': arg = '-lU77' 1081 if arg == '-l:libF90.a': arg = '-lF90' 1082 if arg == '-l:libIO77.a': arg = '-lIO77' 1083 if not arg in lflags: 1084 if arg == '-lkernel32': 1085 continue 1086 elif arg == '-lgfortranbegin': 1087 fmainlibs.append(arg) 1088 continue 1089 elif arg == '-lfrtbegin' and not config.setCompilers.Configure.isCygwin(self.log): 1090 fmainlibs.append(arg) 1091 continue 1092 elif arg == '-lLTO' and self.setCompilers.isDarwin(self.log): 1093 self.logPrint('Skipping -lTO') 1094 elif arg == '-lnvc': 1095 self.logPrint('Skipping -lnvc: https://forums.developer.nvidia.com/t/failed-cuda-device-detection-when-explicitly-linking-libnvc/203225') 1096 continue 1097 elif arg.find('-libpath:')>=0: 1098 self.logPrint('Skipping Intel oneAPI ifort (on Microsoft Windows) compiler option: '+arg) 1099 continue 1100 elif iscray and (arg == '-lsci_cray_mpi' or arg == '-lsci_cray' or arg == '-lsci_cray_mp'): 1101 self.logPrint('Skipping CRAY LIBSCI library: '+arg, 4, 'compilers') 1102 continue 1103 elif arg in self.clibs: 1104 self.logPrint('Library already in C list so skipping in Fortran', 4, 'compilers') 1105 continue 1106 else: 1107 lflags.append(arg) 1108 self.logPrint('Found library: '+arg, 4, 'compilers') 1109 flibs.append(arg) 1110 else: 1111 self.logPrint('Already in lflags: '+arg, 4, 'compilers') 1112 continue 1113 m = re.match(r'^-L.*$', arg) 1114 if m: 1115 arg = os.path.abspath(arg[2:]) 1116 if arg in skipdefaultpaths: continue 1117 arg = '-L'+arg 1118 if not arg in lflags: 1119 lflags.append(arg) 1120 self.logPrint('Found library directory: '+arg, 4, 'compilers') 1121 flibs.append(arg) 1122 else: 1123 self.logPrint('Already in lflags so skipping: '+arg, 4, 'compilers') 1124 continue 1125 # Check for '-rpath /sharedlibpath/ or -R /sharedlibpath/' 1126 if arg == '-rpath' or arg == '-R': 1127 lib = next(argIter) 1128 if lib == '\\': lib = next(argIter) 1129 if lib.startswith('-') or lib.startswith('@loader_path'): continue # perhaps the path was striped due to quotes? 1130 if lib.startswith('"') and lib.endswith('"') and lib.find(' ') == -1: lib = lib[1:-1] 1131 lib = os.path.abspath(lib) 1132 if lib in skipdefaultpaths: continue 1133 if not lib in rpathflags: 1134 rpathflags.append(lib) 1135 self.logPrint('Found '+arg+' library: '+lib, 4, 'compilers') 1136 flibs.append(self.setCompilers.CSharedLinkerFlag+lib) 1137 else: 1138 self.logPrint('Already in rpathflags so skipping: '+arg, 4, 'compilers') 1139 continue 1140 # Check for '-R/sharedlibpath/' 1141 m = re.match(r'^-R.*$', arg) 1142 if m: 1143 lib = os.path.abspath(arg[2:]) 1144 if not lib in rpathflags: 1145 rpathflags.append(lib) 1146 self.logPrint('Found -R library: '+lib, 4, 'compilers') 1147 flibs.append(self.setCompilers.CSharedLinkerFlag+lib) 1148 else: 1149 self.logPrint('Already in rpathflags so skipping: '+arg, 4, 'compilers') 1150 continue 1151 if arg.startswith('-zallextract') or arg.startswith('-zdefaultextract') or arg.startswith('-zweakextract'): 1152 self.logWrite( 'Found Solaris -z option: '+arg+'\n') 1153 flibs.append(arg) 1154 continue 1155 # Check for ??? 1156 # Should probably try to ensure unique directory options here too. 1157 # This probably only applies to Solaris systems, and then will only 1158 # work with gcc... 1159 if arg == '-Y': 1160 libs = next(argIter) 1161 if libs.startswith('"') and libs.endswith('"'): 1162 libs = libs[1:-1] 1163 for lib in libs.split(':'): 1164 #solaris gnu g77 has this extra P, here, not sure why it means 1165 if lib.startswith('P,'):lib = lib[2:] 1166 self.logPrint('Handling -Y option: '+lib, 4, 'compilers') 1167 lib1 = os.path.abspath(lib) 1168 if lib1 in skipdefaultpaths: continue 1169 lib1 = '-L'+lib1 1170 flibs.append(lib1) 1171 continue 1172 if arg.startswith('COMPILER_PATH=') or arg.startswith('LIBRARY_PATH='): 1173 self.logPrint('Skipping arg '+arg, 4, 'compilers') 1174 continue 1175 # HPUX lists a bunch of library directories separated by : 1176 if arg.find(':') >=0: 1177 founddir = 0 1178 for l in arg.split(':'): 1179 if os.path.isdir(l): 1180 lib1 = os.path.abspath(l) 1181 if lib1 in skipdefaultpaths: continue 1182 lib1 = '-L'+lib1 1183 if not arg in lflags: 1184 flibs.append(lib1) 1185 lflags.append(lib1) 1186 self.logPrint('Handling HPUX list of directories: '+l, 4, 'compilers') 1187 founddir = 1 1188 if founddir: 1189 continue 1190 # needed with NCC/NFORT 3.2.0 on NEC and by the FORTRAN NAG Compiler (f61init and quickfit) https://www.nag.com/nagware/np/r62_doc/manual/compiler_11_1.html 1191 if arg.find('f61init.o')>=0 or arg.find('quickfit.o')>=0 or arg.find('f90_init.o')>=0 or arg.find('nousemmap.o')>=0 or arg.find('async_noio.o')>=0: 1192 flibs.append(arg) 1193 self.logPrint('Found '+arg+' in argument, adding it') 1194 continue 1195 # gcc+pgf90 might require pgi.dl 1196 if arg.find('pgi.ld')>=0: 1197 flibs.append(arg) 1198 self.logPrint('Found strange PGI file ending with .ld, adding it') 1199 continue 1200 self.logPrint('Unknown arg '+arg, 4, 'compilers') 1201 except StopIteration: 1202 pass 1203 1204 self.fincs = fincs 1205 self.flibs = [] 1206 for lib in flibs: 1207 if not self.setCompilers.staticLibraries and lib.startswith('-L') and not self.setCompilers.FCSharedLinkerFlag == '-L': 1208 self.flibs.append(self.setCompilers.FCSharedLinkerFlag+lib[2:]) 1209 self.flibs.append(lib) 1210 self.fmainlibs = fmainlibs 1211 # Append run path 1212 self.flibs = ldRunPath+self.flibs 1213 1214 # on OS X, mixing g77 3.4 with gcc-3.3 requires using -lcc_dynamic 1215 for l in self.flibs: 1216 if l.find('-L/sw/lib/gcc/powerpc-apple-darwin') >= 0: 1217 self.logWrite('Detected Apple Mac Fink libraries') 1218 appleLib = 'libcc_dynamic.so' 1219 self.libraries.saveLog() 1220 if self.libraries.check(appleLib, 'foo'): 1221 self.flibs.append(self.libraries.getLibArgument(appleLib)) 1222 self.logWrite('Adding '+self.libraries.getLibArgument(appleLib)+' so that Fortran can work with C++') 1223 self.logWrite(self.libraries.restoreLog()) 1224 break 1225 1226 self.logPrint('Libraries needed to link Fortran code with the C linker: '+str(self.flibs), 3, 'compilers') 1227 self.logPrint('Libraries needed to link Fortran main with the C linker: '+str(self.fmainlibs), 3, 'compilers') 1228 1229 self.logPrint('Check that Fortran libraries can be used with Fortran as the linker', 4, 'compilers') 1230 oldLibs = self.setCompilers.LIBS 1231 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs])+' '+self.setCompilers.LIBS 1232 try: 1233 self.setCompilers.checkCompiler('FC') 1234 except RuntimeError as e: 1235 self.logPrint('Fortran libraries cannot directly be used with Fortran as the linker, try with -Wl,-z -Wl,muldefs', 4, 'compilers') 1236 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 1237 try: 1238 self.setCompilers.pushLanguage('FC') 1239 # this is needed with NEC Fortran compiler 1240 self.setCompilers.addLinkerFlag('-Wl,-z -Wl,muldefs') 1241 self.setCompilers.popLanguage() 1242 except RuntimeError as e: 1243 self.logPrint('Fortran libraries still cannot directly be used with Fortran as the linker', 4, 'compilers') 1244 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 1245 raise RuntimeError('Fortran libraries cannot be used with Fortran as linker') 1246 self.setCompilers.LIBS = oldLibs 1247 1248 self.logPrint('Check that Fortran libraries can be used with C as the linker', 4, 'compilers') 1249 oldLibs = self.setCompilers.LIBS 1250 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs])+' '+self.setCompilers.LIBS 1251 self.setCompilers.saveLog() 1252 try: 1253 self.setCompilers.checkCompiler('C') 1254 except RuntimeError as e: 1255 self.logWrite(self.setCompilers.restoreLog()) 1256 self.logPrint('Fortran libraries cannot directly be used with C as the linker, try without -lcrt2.o', 4, 'compilers') 1257 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 1258 # try removing this one 1259 if '-lcrt2.o' in self.flibs: self.flibs.remove('-lcrt2.o') 1260 self.setCompilers.LIBS = oldLibs+' '+' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs]) 1261 self.setCompilers.saveLog() 1262 try: 1263 self.setCompilers.checkCompiler('C') 1264 except RuntimeError as e: 1265 self.logWrite(self.setCompilers.restoreLog()) 1266 self.logPrint('Fortran libraries still cannot directly be used with C as the linker, try without pgi.ld files', 4, 'compilers') 1267 self.logPrint('Error message from compiling {'+str(e)+'}', 4, 'compilers') 1268 tmpflibs = self.flibs 1269 for lib in tmpflibs: 1270 if lib.find('pgi.ld')>=0: 1271 self.flibs.remove(lib) 1272 self.setCompilers.LIBS = oldLibs+' '+' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs]) 1273 self.setCompilers.saveLog() 1274 try: 1275 self.setCompilers.checkCompiler('C') 1276 except: 1277 self.logWrite(self.setCompilers.restoreLog()) 1278 self.logPrint(str(e), 4, 'compilers') 1279 raise RuntimeError('Fortran libraries cannot be used with C as linker') 1280 else: 1281 self.logWrite(self.setCompilers.restoreLog()) 1282 else: 1283 self.logWrite(self.setCompilers.restoreLog()) 1284 1285 if hasattr(self.setCompilers, 'CXX'): 1286 self.logPrint('Check that Fortran libraries can be used with C++ as linker', 4, 'compilers') 1287 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs])+' '+oldLibs 1288 self.setCompilers.saveLog() 1289 try: 1290 self.setCompilers.checkCompiler('Cxx') 1291 self.logPrint('Fortran libraries can be used from C++', 4, 'compilers') 1292 except RuntimeError as e: 1293 self.logWrite(self.setCompilers.restoreLog()) 1294 self.logPrint(str(e), 4, 'compilers') 1295 # try removing this one causes grief with gnu g++ and Intel Fortran 1296 if '-lintrins' in self.flibs: self.flibs.remove('-lintrins') 1297 self.setCompilers.LIBS = oldLibs+' '+' '.join([self.libraries.getLibArgument(lib) for lib in self.flibs]) 1298 self.setCompilers.saveLog() 1299 try: 1300 self.setCompilers.checkCompiler('Cxx') 1301 except RuntimeError as e: 1302 self.logWrite(self.setCompilers.restoreLog()) 1303 self.logPrint(str(e), 4, 'compilers') 1304 if str(e).find('INTELf90_dclock') >= 0: 1305 self.logPrint('Intel 7.1 Fortran compiler cannot be used with g++ 3.2!', 2, 'compilers') 1306 else: 1307 self.logWrite(self.setCompilers.restoreLog()) 1308 raise RuntimeError('Fortran libraries cannot be used with C++ as linker.\n Run with --with-fc=0 or --with-cxx=0') 1309 else: 1310 self.logWrite(self.setCompilers.restoreLog()) 1311 1312 self.setCompilers.LIBS = oldLibs 1313 return 1314 1315 def checkFortranLinkingCxx(self): 1316 '''Check that Fortran can link C++ libraries''' 1317 link = 0 1318 cinc, cfunc, ffunc = self.manglerFuncs[self.fortranMangling] 1319 cinc = 'extern "C" '+cinc+'\n' 1320 1321 cxxCode = 'void foo(void){'+self.mangleFortranFunction('d1chk')+'();}' 1322 cxxobj = os.path.join(self.tmpDir, 'cxxobj.o') 1323 self.pushLanguage('Cxx') 1324 if not self.checkCompile(cinc+cxxCode, None, cleanup = 0): 1325 self.logPrint('Cannot compile Cxx function: '+cfunc, 3, 'compilers') 1326 raise RuntimeError('Fortran could not successfully link C++ objects') 1327 if not os.path.isfile(self.compilerObj): 1328 self.logPrint('Cannot locate object file: '+os.path.abspath(self.compilerObj), 3, 'compilers') 1329 raise RuntimeError('Fortran could not successfully link C++ objects') 1330 os.rename(self.compilerObj, cxxobj) 1331 self.popLanguage() 1332 1333 if self.testMangling(cinc+cfunc, ffunc, 'Cxx', extraObjs = [cxxobj]): 1334 self.logPrint('Fortran can link C++ functions', 3, 'compilers') 1335 link = 1 1336 else: 1337 oldLibs = self.setCompilers.LIBS 1338 self.setCompilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.cxxlibs])+' '+self.setCompilers.LIBS 1339 if self.testMangling(cinc+cfunc, ffunc, 'Cxx', extraObjs = [cxxobj]): 1340 self.logPrint('Fortran can link C++ functions using the C++ compiler libraries', 3, 'compilers') 1341 link = 1 1342 else: 1343 self.setCompilers.LIBS = oldLibs 1344 if os.path.isfile(cxxobj): 1345 os.remove(cxxobj) 1346 if not link: 1347 raise RuntimeError('Fortran could not successfully link C++ objects with Fortran as linker') 1348 return 1349 1350 def checkDependencyGenerationFlag(self): 1351 '''Check if -MMD works for dependency generation, and add it if it does''' 1352 self.generateDependencies = {} 1353 self.dependenciesGenerationFlag = {} 1354 if not self.argDB['with-dependencies'] : 1355 self.logPrint("Skip checking dependency compiler options on user request") 1356 return 1357 languages = ['C'] 1358 if hasattr(self, 'CXX'): 1359 languages.append('Cxx') 1360 # Fortran is handled in compilersfortran.py 1361 if hasattr(self, 'CUDAC'): 1362 languages.append('CUDA') 1363 if hasattr(self, 'HIPC'): 1364 languages.append('HIP') 1365 if hasattr(self, 'SYCLC'): 1366 languages.append('SYCL') 1367 for language in languages: 1368 self.generateDependencies[language] = 0 1369 self.setCompilers.saveLog() 1370 self.setCompilers.pushLanguage(language) 1371 for testFlag in ['-MMD -MP', # GCC, Intel, Clang, Pathscale 1372 '-MMD', # PGI 1373 '-xMMD', # Sun 1374 '-qmakedep=gcc', # xlc 1375 '-MD', 1376 # Cray only supports -M, which writes to stdout 1377 ]: 1378 try: 1379 self.logPrint('Trying '+language+' compiler flag '+testFlag) 1380 if self.setCompilers.checkCompilerFlag(testFlag, compilerOnly = 1): 1381 depFilename = os.path.splitext(self.setCompilers.compilerObj)[0]+'.d' 1382 if os.path.isfile(depFilename): 1383 os.remove(depFilename) 1384 #self.setCompilers.insertCompilerFlag(testFlag, compilerOnly = 1) 1385 self.framework.addMakeMacro(language.upper()+'_DEPFLAGS',testFlag) 1386 self.dependenciesGenerationFlag[language] = testFlag 1387 self.generateDependencies[language] = 1 1388 break 1389 else: 1390 self.logPrint('Rejected '+language+' compiler flag '+testFlag+' because no dependency file ('+depFilename+') was generated') 1391 else: 1392 self.logPrint('Rejected '+language+' compiler flag '+testFlag) 1393 except RuntimeError: 1394 self.logPrint('Rejected '+language+' compiler flag '+testFlag) 1395 self.setCompilers.popLanguage() 1396 self.logWrite(self.setCompilers.restoreLog()) 1397 return 1398 1399 def checkLinux(self): 1400 '''Check for __linux__''' 1401 includes = """ 1402 #if !defined(__linux__) 1403 #error "__linux__ not defined" 1404 #endif 1405 """ 1406 body = "" 1407 if self.checkCompile(includes, body): 1408 self.addDefine('HAVE_LINUX', 1) 1409 1410 def checkC99Flag(self): 1411 '''Check for -std=c99 or equivalent flag''' 1412 includes = "#include <float.h>" 1413 body = """ 1414 float x[2],y; 1415 float *restrict z = &y; 1416 y = FLT_ROUNDS; 1417 // c++ comment 1418 int j = 2; 1419 for (int i=0; i<2; i++){ 1420 x[i] = i*j*(*z); 1421 } 1422 (void)x""" 1423 self.setCompilers.pushLanguage('C') 1424 flags_to_try = ['','-std=c99','-std=gnu99','-std=c11','-std=gnu11','-c99'] 1425 for flag in flags_to_try: 1426 self.setCompilers.saveLog() 1427 if self.setCompilers.checkCompilerFlag(flag, includes, body): 1428 self.logWrite(self.setCompilers.restoreLog()) 1429 self.c99flag = flag 1430 if flag: 1431 self.setCompilers.CPPFLAGS += ' ' + flag 1432 self.framework.logPrint('Accepted C99 compile flag: '+flag) 1433 break 1434 else: 1435 self.logWrite(self.setCompilers.restoreLog()) 1436 self.setCompilers.popLanguage() 1437 if self.c99flag is None: 1438 if self.isGCC: additionalErrorMsg = '\nPerhaps you have an Intel compiler environment or module set that is interfering with the GNU compilers.\nTry removing that environment or module and running ./configure again.' 1439 else: additionalErrorMsg = '' 1440 raise RuntimeError('PETSc requires c99 compiler! Configure could not determine compatible compiler flag.\nPerhaps you can specify it via CFLAGS.'+additionalErrorMsg) 1441 return 1442 1443 def checkStdAtomic(self,cxx=False): 1444 includes = """ 1445 #if defined(__cplusplus) 1446 #include <atomic> 1447 using namespace std; 1448 #else 1449 #include <stdatomic.h> 1450 #endif 1451 double dcount = 0; 1452 atomic_flag cat = ATOMIC_FLAG_INIT; 1453 """ 1454 body = """ 1455 do {} while (atomic_flag_test_and_set(&cat)); 1456 dcount++; 1457 atomic_flag_clear(&cat); 1458 """ 1459 if self.checkCompile(includes, body): 1460 if cxx: 1461 self.addDefine('HAVE_CXX_ATOMIC', 1) 1462 else: 1463 self.addDefine('HAVE_STDATOMIC_H', 1) 1464 1465 def configure(self): 1466 import config.setCompilers 1467 if hasattr(self.setCompilers, 'CC'): 1468 self.isGCC = config.setCompilers.Configure.isGNU(self.setCompilers.CC, self.log) 1469 self.executeTest(self.checkLinux) 1470 self.executeTest(self.checkC99Flag) 1471 self.executeTest(self.checkCFormatting) 1472 self.executeTest(self.checkDynamicLoadFlag) 1473 self.executeTest(self.checkStdAtomic) 1474 if self.argDB['with-clib-autodetect']: 1475 self.executeTest(self.checkCLibraries) 1476 self.executeTest(self.checkDependencyGenerationFlag) 1477 else: 1478 self.isGCC = 0 1479 1480 if hasattr(self.setCompilers, 'CXX'): 1481 self.isGCXX = config.setCompilers.Configure.isGNU(self.setCompilers.CXX, self.log) 1482 self.executeTest(self.checkCxxRestrict) 1483 # Adding -x c++ it causes Clang to SEGV, http://llvm.org/bugs/show_bug.cgi?id=12924 1484 if not config.setCompilers.Configure.isClang(self.setCompilers.CXX, self.log): 1485 self.executeTest(self.checkCxxOptionalExtensions) 1486 self.executeTest(self.checkCxxComplexFix) 1487 self.executeTest(self.checkStdAtomic,kargs={'cxx' : True}) 1488 if self.argDB['with-cxxlib-autodetect']: 1489 self.executeTest(self.checkCxxLibraries) 1490 # To skip Sun C++ compiler warnings/errors 1491 if config.setCompilers.Configure.isSun(self.setCompilers.CXX, self.log): 1492 self.addDefine('HAVE_SUN_CXX', 1) 1493 else: 1494 self.isGCXX = 0 1495 if hasattr(self.setCompilers, 'FC'): 1496 self.executeTest(self.checkFortranNameMangling) 1497 self.executeTest(self.checkFortranNameManglingDouble) 1498 if self.argDB['with-fortranlib-autodetect']: 1499 self.executeTest(self.checkFortranLibraries) 1500 if hasattr(self.setCompilers, 'CXX'): 1501 self.executeTest(self.checkFortranLinkingCxx) 1502 1503 self.no_configure() 1504 return 1505 1506 def setupFrameworkCompilers(self): 1507 '''Sets the selected compilers into the framework''' 1508 if self.framework.compilers is None: 1509 self.logPrint('Setting framework compilers to this module', 2, 'compilers') 1510 self.framework.compilers = self 1511 return 1512 1513 def no_configure(self): 1514 self.executeTest(self.setupFrameworkCompilers) 1515 return 1516