1import config.base 2import os 3import re 4import nargs 5 6re_win32fe_cl = re.compile(r'win32fe[\s_]+cl') 7re_win32fe_icl = re.compile(r'win32fe[\s_]+ic[lx]') 8re_win32fe_ifort = re.compile(r'win32fe[\s_]+if(x|ort)') 9 10class CompilerOptions(config.base.Configure): 11 def getCFlags(self, compiler, bopt, language): 12 import config.setCompilers 13 14 if language == 'C': 15 if [s for s in ['mpicc','mpiicc','mpiicx'] if os.path.basename(compiler).find(s)>=0]: 16 try: 17 output = self.executeShellCommand(compiler + ' -show', log = self.log)[0] 18 self.framework.addMakeMacro('MPICC_SHOW',output.strip().replace('\n','\\\\n').replace('"','\\"')) 19 except: 20 self.framework.addMakeMacro('MPICC_SHOW',"Unavailable") 21 else: 22 self.framework.addMakeMacro('MPICC_SHOW',"Unavailable") 23 24 flags = [] 25 # GNU gcc 26 if config.setCompilers.Configure.isGNU(compiler, self.log) or config.setCompilers.Configure.isClang(compiler, self.log): 27 if bopt == '': 28 flags.extend(['-Wall', '-Wwrite-strings', '-Wno-unknown-pragmas']) 29 if config.setCompilers.Configure.isClang(compiler, self.log): 30 # gcc does not support -Wno-implicit-float-conversion so -Wconversion is always noisy 31 flags.extend(['-Wconversion', '-Wno-sign-conversion', '-Wno-float-conversion', '-Wno-implicit-float-conversion', '-Qunused-arguments']) 32 if config.setCompilers.Configure.isDarwinCatalina(self.log): 33 flags.extend(['-fno-stack-check']) 34 else: 35 flags.extend(['-Wno-lto-type-mismatch']) 36 if config.setCompilers.Configure.isGcc110plus(compiler, self.log): 37 flags.extend(['-Wno-stringop-overflow']) 38 if config.setCompilers.Configure.isARM(self.log): 39 flags.extend(['-mfp16-format=ieee']) # ARM for utilizing 16 bit storage of floating point 40 # skip -fstack-protector for brew gcc - as this gives SEGV 41 if not ((config.setCompilers.Configure.isDarwin(self.log) or config.setCompilers.Configure.isMINGW(compiler, self.log)) and config.setCompilers.Configure.isGNU(compiler, self.log)): 42 flags.extend(['-fstack-protector']) 43 if self.argDB['with-visibility']: 44 flags.extend(['-fvisibility=hidden']) 45 if language == 'CUDA': 46 flags.extend(['-x cuda']) 47 elif bopt == 'g': 48 flags.extend(['-O0','-g3']) 49 elif bopt == 'O': 50 flags.append('-g') 51 if config.setCompilers.Configure.isClang(compiler, self.log): 52 flags.append('-O3') 53 else: 54 flags.append('-O') 55 else: 56 # Linux Intel 57 if config.setCompilers.Configure.isIntel(compiler, self.log) and not re_win32fe_icl.search(compiler): 58 if bopt == '': 59 flags.extend(['-wd1572', '-Wno-unknown-pragmas']) 60 # next one fails in OpenMP build and we don't use it anyway so remove 61 # flags.append('-Qoption,cpp,--extended_float_type') 62 elif bopt == 'g': 63 flags.extend(['-g','-O0']) 64 elif bopt == 'O': 65 flags.append('-g') 66 flags.append('-O3') 67 # Windows Intel 68 elif re_win32fe_icl.search(compiler): 69 if bopt == '': 70 flags.extend(['-Qstd=c99']) 71 if self.argDB['with-shared-libraries']: 72 flags.extend(['-MD']) 73 else: 74 flags.extend(['-MT']) 75 elif bopt == 'g': 76 flags.extend(['-Z7','-Od']) 77 elif bopt == 'O': 78 flags.extend(['-O3', '-QxW']) 79 # Windows Microsoft 80 elif re_win32fe_cl.search(compiler): 81 if bopt == '': 82 dir(self) 83 # cause compiler to generate only a single copy of static strings; needed usage of __func__ in PETSc 84 flags.extend(['-GF']) 85 if self.argDB['with-shared-libraries']: 86 flags.extend(['-MD','-wd4996']) 87 else: 88 flags.extend(['-MT','-wd4996']) 89 # cause compiler to handle preprocessor per the standard https://docs.microsoft.com/en-us/cpp/build/reference/zc-preprocessor?view=msvc-170 90 flags.extend(['-Zc:preprocessor ','-experimental:preprocessor']) 91 elif bopt == 'g': 92 flags.extend(['-Z7','-Od']) 93 elif bopt == 'O': 94 flags.extend(['-O2', '-QxW']) 95 elif config.setCompilers.Configure.isNVCC(compiler, self.log): 96 if bopt == '': 97 if self.argDB['with-visibility']: 98 flags.append(('-Xcompiler', '-fvisibility=hidden')) 99 elif bopt == 'g': 100 # nvcc --help says: 101 # -g : Generate debug information for host code. 102 # -G : Generate debug information for device code. Turns off all optimizations. Don't use for profiling; use -lineinfo instead. 103 # -lineinfo: Generate line-number information for device code. 104 # We use '-g -lineinfo' to generate debug info for both host and device code in *.cu files. 105 # If users want to turn off all optimizations, they can use --CUDAOPTFLAGS="-G". 106 flags.extend(['-g', '-lineinfo']) 107 elif bopt == 'O': 108 flags.append('-O3') 109 # NEC 110 elif config.setCompilers.Configure.isNEC(compiler, self.log): 111 if bopt == '': 112 flags.extend(['-Wall', '-fdiag-vector=0', '-fdiag-parallel=0', '-fdiag-inline=0']) 113 elif bopt == 'O': 114 flags.append('-O1') # defaults to O2, which is quite buggy (as of version 3.3.1) 115 elif bopt == 'g': 116 flags.append('-g') 117 flags.append('-traceback=verbose') 118 flags.append('-O0') 119 # Generic 120 if not len(flags): 121 if bopt == 'g': 122 flags.extend(['-g','-O0']) 123 elif bopt == 'O': 124 flags.append('-O') 125 return flags 126 127 def getCxxFlags(self, compiler, bopt, language): 128 import config.setCompilers 129 130 if [s for s in ['mpiCC','mpic++','mpicxx','mpiicxx','mpiicpc','mpiicpx'] if os.path.basename(compiler).find(s)>=0]: 131 try: 132 output = self.executeShellCommand(compiler+' -show', log = self.log)[0] 133 self.framework.addMakeMacro('MPICXX_SHOW',output.strip().replace('\n','\\\\n')) 134 except: 135 self.framework.addMakeMacro('MPICXX_SHOW',"Unavailable") 136 else: 137 self.framework.addMakeMacro('MPICXX_SHOW',"Unavailable") 138 139 flags = [] 140 # GNU g++ 141 if config.setCompilers.Configure.isGNU(compiler, self.log) or config.setCompilers.Configure.isClang(compiler, self.log): 142 if bopt == '': 143 flags.extend(['-Wall', '-Wwrite-strings', '-Wno-strict-aliasing', '-Wno-unknown-pragmas']) 144 if config.setCompilers.Configure.isGNU(compiler, self.log): 145 flags.extend(['-Wno-psabi', '-Wno-lto-type-mismatch']) 146 if not any([ 147 # skip -fstack-protector for brew gcc - as this gives SEGV 148 (config.setCompilers.Configure.isDarwin(self.log) or config.setCompilers.Configure.isMINGW(compiler, self.log)) and config.setCompilers.Configure.isGNU(compiler, self.log), 149 # hipcc for ROCm-4.0 crashes on some source files with -fstack-protector 150 config.setCompilers.Configure.isHIP(compiler, self.log), 151 ]): 152 flags.extend(['-fstack-protector']) 153 if config.setCompilers.Configure.isDarwinCatalina(self.log) and config.setCompilers.Configure.isClang(compiler, self.log): 154 flags.extend(['-fno-stack-check']) 155 # The option below would prevent warnings about compiling C as C++ being deprecated, but it causes Clang to SEGV, http://llvm.org/bugs/show_bug.cgi?id=12924 156 # flags.extend([('-x','c++')]) 157 if self.argDB['with-visibility']: 158 flags.extend(['-fvisibility=hidden']) 159 elif bopt in ['g']: 160 # -g3 causes an as SEGV on OSX 161 if config.setCompilers.Configure.isHIP(compiler, self.log): 162 # HIP can cause buggy code with -O0 163 flags.extend(['-g']) 164 else: 165 flags.extend(['-O0','-g']) 166 elif bopt in ['O']: 167 flags.append('-g') 168 if 'USER' in os.environ: 169 if config.setCompilers.Configure.isClang(compiler, self.log): 170 flags.append('-O3') 171 else: 172 flags.append('-O') 173 # IBM 174 elif compiler.find('mpCC') >= 0 or compiler.find('xlC') >= 0: 175 if bopt == '': 176 flags.append('-qrtti=dyna') # support dynamic casts in C++ 177 elif bopt in ['g']: 178 flags.extend(['-g','-O0']) 179 elif bopt in ['O']: 180 flags.append('-O') 181 else: 182 # Linux Intel 183 if config.setCompilers.Configure.isIntel(compiler, self.log) and not re_win32fe_icl.search(compiler): 184 if bopt == '': 185 flags.append('-wd1572') 186 elif bopt == 'g': 187 flags.extend(['-g','-O0']) 188 elif bopt == 'O': 189 flags.append('-g') 190 flags.append('-O3') 191 # Windows Intel 192 elif re_win32fe_icl.search(compiler): 193 if bopt == '': 194 if self.argDB['with-shared-libraries']: 195 flags.extend(['-MD','-GR','-EHsc']) 196 else: 197 flags.extend(['-MT','-GR','-EHsc']) # removing GX in favor of EHsc 198 elif bopt in ['g']: 199 flags.extend(['-Z7','-Od']) 200 elif bopt in ['O']: 201 flags.extend(['-O3', '-QxW']) 202 # Windows Microsoft 203 elif re_win32fe_cl.search(compiler): 204 if bopt == '': 205 # cause compiler to generate only a single copy of static strings; needed usage of __func__ in PETSc 206 flags.extend(['-GF']) 207 if self.argDB['with-shared-libraries']: 208 flags.extend(['-MD','-GR','-EHsc']) 209 else: 210 flags.extend(['-MT','-GR','-EHsc']) # removing GX in favor of EHsc 211 # cause compiler to handle preprocessor per the standard https://docs.microsoft.com/en-us/cpp/build/reference/zc-preprocessor?view=msvc-170 212 flags.extend(['-Zc:preprocessor ','-experimental:preprocessor']) 213 # cause compiler to emit the correct value for __cplusplus macro as per the 214 # standard 215 # https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-170 216 flags.extend(['-Zc:__cplusplus']) 217 elif bopt == 'g': 218 flags.extend(['-Z7','-Zm200','-Od']) 219 elif bopt == 'O': 220 flags.extend(['-O2','-QxW','-Zm200']) 221 # NEC 222 elif config.setCompilers.Configure.isNEC(compiler, self.log): 223 if bopt == '': 224 flags.extend(['-Wall', '-fdiag-vector=0', '-fdiag-parallel=0', '-fdiag-inline=0']) 225 elif bopt == 'O': 226 flags.append('-O1') # defaults to O2, which is quite buggy (as of version 3.3.1) 227 elif bopt == 'g': 228 flags.append('-g') 229 flags.append('-traceback=verbose') 230 flags.append('-O0') 231 # Generic 232 if not len(flags): 233 if bopt in ['g']: 234 if config.setCompilers.Configure.isHIP(compiler, self.log): 235 # HIP can cause buggy code with -O0 236 flags.extend(['-g']) 237 else: 238 flags.extend(['-g','-O0']) 239 elif bopt in ['O']: 240 flags.append('-O') 241 return flags 242 243 def getFortranFlags(self, compiler, bopt): 244 if [s for s in ['mpif77','mpif90','mpifort','mpiifort','mpiifx'] if os.path.basename(compiler).find(s)>=0]: 245 try: 246 output = self.executeShellCommand(compiler+' -show', log = self.log)[0] 247 self.framework.addMakeMacro('MPIFC_SHOW',output.strip().replace('\n','\\\\n')) 248 except: 249 self.framework.addMakeMacro('MPIFC_SHOW',"Unavailable") 250 else: 251 self.framework.addMakeMacro('MPIFC_SHOW',"Unavailable") 252 253 flags = [] 254 if config.setCompilers.Configure.isGNU(compiler, self.log): 255 if bopt == '': 256 flags.extend(['-Wall', '-ffree-line-length-none', '-ffree-line-length-0', '-Wno-lto-type-mismatch']) 257 if config.setCompilers.Configure.isGfortran8plus(compiler, self.log): 258 flags.extend(['-Wno-unused-dummy-argument']) # Silence warning because dummy parameters are sometimes necessary 259 if config.setCompilers.Configure.isMINGW(compiler, self.log): 260 flags.extend(['-fallow-invalid-boz']) 261 elif bopt == 'g': 262 # g77 3.2.3 preprocesses the file into nothing if we give -g3 263 flags.extend(['-g','-O0']) 264 elif bopt == 'O': 265 flags.append('-g') 266 flags.extend(['-O']) 267 else: 268 # Portland Group Fortran 90 269 if config.setCompilers.Configure.isPGI(compiler, self.log): 270 self.framework.addDefine('PETSC_HAVE_PGF90_COMPILER','1') 271 if bopt == '': 272 flags.append('-Mfree') 273 elif bopt == 'O': 274 flags.extend(['-fast', '-Mnoframe']) 275 # Linux Intel 276 if config.setCompilers.Configure.isIntel(compiler, self.log) and not re_win32fe_ifort.search(compiler): 277 if bopt == '': 278 flags.append('-fpscomp logicals') # enforce Fortran logical to be compatible with C 279 elif bopt == 'g': 280 flags.extend(['-O0','-g']) 281 elif bopt == 'O': 282 flags.append('-g') 283 flags.append('-O3') 284 # Windows Intel 285 elif re_win32fe_ifort.search(compiler): 286 if bopt == '': 287 flags.append('-fpscomp:logicals') # enforce Fortran logical to be compatible with C 288 if self.argDB['with-shared-libraries']: 289 flags.extend(['-MD']) 290 else: 291 flags.extend(['-MT']) 292 elif bopt == 'g': 293 flags.extend(['-Z7','-Od']) 294 elif bopt == 'O': 295 flags.extend(['-O3', '-QxW']) 296 # NEC 297 elif config.setCompilers.Configure.isNEC(compiler, self.log): 298 if bopt == '': 299 flags.extend(['-Wall', '-fdiag-vector=0', '-fdiag-parallel=0', '-fdiag-inline=0']) 300 elif bopt == 'O': 301 flags.append('-O2') 302 flags.append('-fno-reciprocal-math') 303 elif bopt == 'g': 304 flags.append('-g') 305 flags.append('-traceback=verbose') 306 flags.append('-O0') 307 # NVIDIA 308 elif config.setCompilers.Configure.isNVC(compiler, self.log): 309 flags.append('-Munixlogical') # enforce Fortran logical to be compatible with C 310 if bopt == 'g': 311 flags.extend(['-g','-O0']) 312 elif bopt == 'O': 313 flags.append('-O') 314 # Generic 315 if not len(flags): 316 if bopt == 'g': 317 flags.extend(['-g','-O0']) 318 elif bopt == 'O': 319 flags.append('-O') 320 return flags 321 322 def getCompilerFlags(self, language, compiler, bopt): 323 if bopt == 'gcov': 324 raise RuntimeError('Internal error! bopt = gcov is deprecated') 325 326 flags = [] 327 if language == 'C' or language == 'CUDA': 328 flags = self.getCFlags(compiler, bopt, language) 329 elif language == 'Cxx' or language == 'HIP' or language == 'SYCL': 330 flags = self.getCxxFlags(compiler, bopt, language) 331 elif language in ['Fortran', 'FC']: 332 flags = self.getFortranFlags(compiler, bopt) 333 if bopt == 'O': 334 flat_flags = (' '.join(f) if isinstance(f, (list, tuple)) else f for f in flags) 335 fopt_prefix = 'F' if language in ('Fortran', 'FC') else language.upper() 336 self.logPrintWarning('Using default ' + language + ' optimization flags "'+' '.join(flat_flags)+'". You might consider manually setting optimal optimization flags for your system with ' + fopt_prefix + 'OPTFLAGS="optimization flags" see config/examples/arch-*-opt.py for examples') 337 return flags 338 339 def getCompilerVersion(self, language, compiler): 340 if compiler is None: 341 raise RuntimeError('Invalid compiler for version determination') 342 version = 'Unknown' 343 try: 344 if language == 'C' or language == 'CUDA': 345 if compiler.endswith('xlc') or compiler.endswith('mpcc'): 346 flags = "lslpp -L vac.C | grep vac.C | awk '{print $2}'" 347 else: 348 flags = compiler+' --version' 349 elif language == 'Cxx' or language == 'HIP' or language == 'SYCL': 350 if compiler.endswith('xlC') or compiler.endswith('mpCC'): 351 flags = "lslpp -L vacpp.cmp.core | grep vacpp.cmp.core | awk '{print $2}'" 352 else: 353 flags = compiler+' --version' 354 elif language in ['Fortran', 'FC']: 355 if compiler.endswith('xlf') or compiler.endswith('xlf90'): 356 flags = "lslpp -L xlfcmp | grep xlfcmp | awk '{print $2}'" 357 else: 358 flags = compiler+' --version' 359 try: 360 (output, error, status) = config.base.Configure.executeShellCommand(flags, log = self.log) 361 except: 362 flags = compiler+' -v' 363 (output, error, status) = config.base.Configure.executeShellCommand(flags, log = self.log) 364 output = error + output 365 if not status: 366 if compiler.find('win32fe') > -1: 367 version = '\\n'.join(output.split('\n')[0:2]) 368 version = version.replace('\r','') 369 else: 370 #PGI/Windows writes an empty '\r\n' on the first line of output 371 if output.count('\n') > 1 and output.split('\n')[0] == '\r': 372 version = output.split('\r\n')[1] 373 #NVCC 374 elif output.find('Cuda compiler driver') >= 0: 375 version = output.split('\n')[3] 376 else: 377 version = output.split('\n')[0] 378 379 except RuntimeError as e: 380 self.logWrite('Could not determine compiler version: '+str(e)) 381 self.logWrite('getCompilerVersion: '+str(compiler)+' '+str(version)+'\n') 382 self.framework.addMakeMacro(language+'_VERSION',version) 383 return version 384