Coverage for python/lsst/sconsUtils/state.py: 33%

295 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-08-01 00:45 -0700

1"""Global state for sconsUtils. 

2 

3This module acts like a singleton, holding all global state for sconsUtils. 

4This includes the primary Environment object (`lsst.sconsUtils.state.env`), 

5the message log (`lsst.sconsUtils.state.log`), the command-line variables 

6object (`lsst.sconsUtils.state.state.opts`), and a dictionary of command-line 

7targets used to setup aliases, default targets, and dependencies 

8(`lsst.sconsUtils.state.targets`). All four of these variables are aliased 

9to the main `lsst.sconsUtils` scope, so there should be no need for users to 

10deal with the state module directly. 

11 

12These are all initialized when the module is imported, but may be modified 

13by other code (particularly `lsst.sconsUtils.dependencies.configure`). 

14""" 

15 

16import os 

17import re 

18import shlex 

19 

20import SCons.Script 

21import SCons.Conftest 

22from . import eupsForScons 

23from .utils import get_conda_prefix, use_conda_compilers 

24 

25SCons.Script.EnsureSConsVersion(2, 1, 0) 

26 

27"""A dictionary of SCons aliases and targets. 

28 

29These are used to setup aliases, default targets, and dependencies by 

30`lsst.sconsUtils.scripts.BasicSConstruct.finish`. 

31While one can still use env.Alias to setup aliases (and should for "install"), 

32putting targets here will generally provide better build-time dependency 

33handling (like ensuring everything is built before we try to install, and 

34making sure SCons doesn't rebuild the world before installing). 

35 

36Users can add additional keys to the dictionary if desired. 

37 

38Targets should be added by calling extend() or using ``+=`` on the dict 

39values, to keep the lists of targets from turning into lists-of-lists. 

40""" 

41targets = {"doc": [], "tests": [], "lib": [], "python": [], "examples": [], "include": [], "version": [], 

42 "shebang": []} 

43 

44env = None 

45log = None 

46opts = None 

47 

48 

49def _initOptions(): 

50 SCons.Script.AddOption('--checkDependencies', dest='checkDependencies', 

51 action='store_true', default=False, 

52 help="Verify dependencies with autoconf-style tests.") 

53 SCons.Script.AddOption('--filterWarn', dest='filterWarn', action='store_true', default=False, 

54 help="Filter out a class of warnings deemed irrelevant"), 

55 SCons.Script.AddOption('--force', dest='force', action='store_true', default=False, 

56 help="Set to force possibly dangerous behaviours") 

57 SCons.Script.AddOption('--linkFarmDir', dest='linkFarmDir', action='store', default=None, 

58 help="The directory of symbolic links needed to build and use the package") 

59 SCons.Script.AddOption('--prefix', dest='prefix', action='store', default=False, 

60 help="Specify the install destination") 

61 SCons.Script.AddOption('--setenv', dest='setenv', action='store_true', default=False, 

62 help="Treat arguments such as Foo=bar as defining construction variables") 

63 SCons.Script.AddOption('--tag', dest='tag', action='store', default=None, 

64 help="Declare product with this eups tag") 

65 SCons.Script.AddOption('--verbose', dest='verbose', action='store_true', default=False, 

66 help="Print additional messages for debugging.") 

67 SCons.Script.AddOption('--traceback', dest='traceback', action='store_true', default=False, 

68 help="Print full exception tracebacks when errors occur.") 

69 SCons.Script.AddOption('--no-eups', dest='no_eups', action='store_true', default=False, 

70 help="Do not use EUPS for configuration") 

71 

72 

73def _initLog(): 

74 from . import utils 

75 global log 

76 log = utils.Log() 

77 

78 

79def _get_macosx_deployment_target_default(): 

80 """Determine the default deployment target on macOS. 

81 

82 Returns 

83 ------- 

84 target : `str` 

85 The default target for this platform. Can be returned even 

86 if not running on macOS. 

87 """ 

88 uname = os.uname() 

89 if uname.sysname == 'Darwin' and uname.machine == 'arm64': 89 ↛ 90line 89 didn't jump to line 90, because the condition on line 89 was never true

90 return "11.0" 

91 return "10.9" 

92 

93 

94def _initVariables(): 

95 files = [] 

96 if "optfile" in SCons.Script.ARGUMENTS: 96 ↛ 97line 96 didn't jump to line 97, because the condition on line 96 was never true

97 configfile = SCons.Script.ARGUMENTS["optfile"] 

98 if configfile not in files: 

99 files.append(configfile) 

100 for file in files: 100 ↛ 101line 100 didn't jump to line 101, because the loop on line 100 never started

101 if not os.path.isfile(file): 

102 log.warn("Warning: Will ignore non-existent options file, %s" % file) 

103 if "optfile" not in SCons.Script.ARGUMENTS: 103 ↛ 106line 103 didn't jump to line 106, because the condition on line 103 was never false

104 files.append("buildOpts.py") 

105 global opts 

106 opts = SCons.Script.Variables(files) 

107 opts.AddVariables( 

108 ('archflags', 'Extra architecture specification to add to CC/LINK flags (e.g. -m32)', ''), 

109 ('cc', 'Choose the compiler to use', ''), 

110 SCons.Script.BoolVariable('debug', 'Set to enable debugging flags (use --debug)', True), 

111 ('eupsdb', 'Specify which element of EUPS_PATH should be used', None), 

112 ('flavor', 'Set the build flavor', None), 

113 SCons.Script.BoolVariable('force', 'Set to force possibly dangerous behaviours', False), 

114 ('optfile', 'Specify a file to read default options from', None), 

115 ('prefix', 'Specify the install destination', None), 

116 SCons.Script.EnumVariable('opt', 'Set the optimisation level', 3, 

117 allowed_values=('g', '0', '1', '2', '3')), 

118 SCons.Script.EnumVariable('profile', 'Compile/link for profiler', 0, 

119 allowed_values=('0', '1', 'pg', 'gcov')), 

120 ('version', 'Specify the version to declare', None), 

121 ('baseversion', 'Specify the current base version', None), 

122 ('optFiles', "Specify a list of files that SHOULD be optimized", None), 

123 ('noOptFiles', "Specify a list of files that should NOT be optimized", None), 

124 ('macosx_deployment_target', 'Deployment target for Mac OS X', 

125 _get_macosx_deployment_target_default()), 

126 ) 

127 

128 

129def _initEnvironment(): 

130 """Construction and basic setup of the state.env variable.""" 

131 

132 ourEnv = {} 

133 preserveVars = """ 

134 DYLD_LIBRARY_PATH 

135 EUPS_DIR 

136 EUPS_LOCK_PID 

137 EUPS_PATH 

138 EUPS_SHELL 

139 EUPS_USERDATA 

140 LD_LIBRARY_PATH 

141 PATH 

142 SHELL 

143 TEMP 

144 TERM 

145 TMP 

146 TMPDIR 

147 XPA_PORT 

148 CONDA_BUILD_SYSROOT 

149 SDKROOT 

150 """.split() 

151 

152 codeCheckerVars = """ 

153 LD_PRELOAD 

154 CC_LOGGER_FILE 

155 CC_LOGGER_GCC_LIKE 

156 CC_LIB_DIR 

157 CC_DATA_FILES_DIR 

158 CC_LOGGER_BIN 

159 """.split() 

160 

161 for key in preserveVars: 

162 if key in os.environ: 

163 ourEnv[key] = os.environ[key] 

164 

165 # check if running in CodeChecker environment 

166 if "CC_LOGGER_BIN" in os.environ: 166 ↛ 167line 166 didn't jump to line 167, because the condition on line 166 was never true

167 for key in codeCheckerVars: 

168 if key in os.environ: 

169 ourEnv[key] = os.environ[key] 

170 

171 # Find and propagate EUPS environment variables. 

172 cfgPath = [] 

173 for k in os.environ: 

174 m = re.search(r"^(?P<name>\w+)_DIR(?P<extra>_EXTRA)?$", k) 

175 if not m: 

176 continue 

177 cfgPath.append(os.path.join(os.environ[k], "ups")) 

178 cfgPath.append(os.path.join(os.environ[k], "configs")) 

179 if m.group("extra"): 179 ↛ 180line 179 didn't jump to line 180, because the condition on line 179 was never true

180 cfgPath.append(os.environ[k]) 

181 else: 

182 cfgPath.append(os.path.join(os.environ[k], "ups")) 

183 p = m.group("name") 

184 varname = eupsForScons.utils.setupEnvNameFor(p) 

185 if varname in os.environ: 185 ↛ 173line 185 didn't jump to line 173, because the condition on line 185 was never false

186 ourEnv[varname] = os.environ[varname] 

187 ourEnv[k] = os.environ[k] 

188 

189 # add <build root>/ups directory to the configuration search path 

190 # this allows the .cfg file for the package being built to be found without 

191 # requiring <product name>_DIR to be in the env 

192 cfgPath.append(os.path.join(SCons.Script.Dir('#').abspath, 'ups')) 

193 

194 # 

195 # Add any values marked as export=FOO=XXX[,GOO=YYY] to ourEnv 

196 # 

197 exportVal = SCons.Script.ARGUMENTS.pop("export", None) 

198 if exportVal: 198 ↛ 199line 198 didn't jump to line 199, because the condition on line 198 was never true

199 for kv in exportVal.split(','): 

200 k, v = kv.split('=') 

201 ourEnv[k] = v 

202 global env 

203 sconsUtilsPath, thisFile = os.path.split(__file__) 

204 toolPath = os.path.join(sconsUtilsPath, "tools") 

205 env = SCons.Script.Environment( 

206 ENV=ourEnv, 

207 variables=opts, 

208 toolpath=[toolPath], 

209 tools=["default", "cuda"] 

210 ) 

211 env.cfgPath = cfgPath 

212 # 

213 # We don't want "lib" inserted at the beginning of loadable module names; 

214 # we'll import them under their given names. 

215 # 

216 env['LDMODULEPREFIX'] = "" 

217 if env['PLATFORM'] == 'darwin': 217 ↛ 240line 217 didn't jump to line 240, because the condition on line 217 was never false

218 env['LDMODULESUFFIX'] = ".so" 

219 if not re.search(r"-install_name", str(env['SHLINKFLAGS'])): 219 ↛ 221line 219 didn't jump to line 221, because the condition on line 219 was never false

220 env.Append(SHLINKFLAGS=["-install_name", "${TARGET.file}"]) 

221 if not re.search(r"-headerpad_max_install_names", str(env['SHLINKFLAGS'])): 221 ↛ 226line 221 didn't jump to line 226, because the condition on line 221 was never false

222 env.Append(SHLINKFLAGS=["-Wl,-headerpad_max_install_names"]) 

223 # 

224 # We want to be explicit about the OS X version we're targeting 

225 # 

226 env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = env['macosx_deployment_target'] 

227 # This flag is required for std::variant and std::filesystem 

228 # on deployment platforms < 10.13 and 10.15 

229 for flag in ("-D_LIBCPP_DISABLE_AVAILABILITY=1", ): 

230 env["CFLAGS"].append(flag) 

231 env["CXXFLAGS"].append(flag) 

232 log.info("Setting OS X binary compatibility level: %s" % env['ENV']['MACOSX_DEPLOYMENT_TARGET']) 

233 # 

234 # For XCode 7.3 we need to explicitly add a trailing slash to library 

235 # paths. This does not hurt things on older XCodes. We can remove this 

236 # once XCode is fixed. See Apple radar rdr://25313838 

237 # 

238 env['LIBDIRSUFFIX'] = '/' 

239 

240 if use_conda_compilers(): 240 ↛ 241line 240 didn't jump to line 241, because the condition on line 240 was never true

241 _conda_prefix = get_conda_prefix() 

242 if "LDFLAGS" in os.environ: 

243 LDFLAGS = shlex.split(os.environ['LDFLAGS']) # respects quoting! 

244 LDFLAGS = [v for v in LDFLAGS if v[0:2] != '-L'] 

245 # this one breaks some linking in the eups build 

246 LDFLAGS = [v for v in LDFLAGS if v != '-Wl,-dead_strip_dylibs'] 

247 env.Append(LIBPATH=["%s/lib" % _conda_prefix]) 

248 env.Append(LINKFLAGS=LDFLAGS) 

249 env.Append(SHLINKFLAGS=LDFLAGS) 

250 

251 if "CFLAGS" in os.environ: 

252 CFLAGS = shlex.split(os.environ['CFLAGS']) # respects quoting! 

253 CFLAGS = [v for v in CFLAGS if v[0:2] != '-I'] 

254 env.Append(CCFLAGS=CFLAGS) 

255 

256 if "CXXFLAGS" in os.environ: 

257 CXXFLAGS = shlex.split(os.environ['CXXFLAGS']) # respects quoting! 

258 CXXFLAGS = [v for v in CXXFLAGS if v[0:2] != '-I'] 

259 CXXFLAGS = [v for v in CXXFLAGS if v[0:5] != '-std='] # we let LSST set this 

260 CXXFLAGS = [v for v in CXXFLAGS if v not in CFLAGS] # conda puts in duplicates 

261 env.Append(CXXFLAGS=CXXFLAGS) 

262 

263 # 

264 # Remove valid options from the arguments 

265 # 

266 # SCons Variables do not behave like dicts 

267 for opt in opts.keys(): 

268 try: 

269 del SCons.Script.ARGUMENTS[opt] 

270 except KeyError: 

271 pass 

272 # 

273 # Process those arguments 

274 # 

275 for k in ("force", "prefix"): # these may now be set as options instead of variables 

276 if SCons.Script.GetOption(k): 276 ↛ 277line 276 didn't jump to line 277, because the condition on line 276 was never true

277 env[k] = SCons.Script.GetOption(k) 

278 

279 if env['debug']: 279 ↛ 288line 279 didn't jump to line 288, because the condition on line 279 was never false

280 env.Append(CCFLAGS=['-g']) 

281 

282 # 

283 # determine if EUPS is present 

284 # 

285 

286 # --no-eups overides probing 

287 # XXX is it possible to test python snippets as a scons action? 

288 if SCons.Script.GetOption("no_eups"): 288 ↛ 289line 288 didn't jump to line 289, because the condition on line 288 was never true

289 env['no_eups'] = True 

290 else: 

291 env['no_eups'] = not eupsForScons.haveEups() 

292 

293 if not env.GetOption("no_progress"): 293 ↛ 302line 293 didn't jump to line 302, because the condition on line 293 was never false

294 if env['no_eups']: 294 ↛ 295line 294 didn't jump to line 295, because the condition on line 294 was never true

295 log.info('EUPS integration: disabled') 

296 else: 

297 log.info('EUPS integration: enabled') 

298 

299 # 

300 # Find the eups path, replace 'flavor' in favor of 'PLATFORM' if needed. 

301 # 

302 eupsPath = None 

303 try: 

304 db = env['eupsdb'] 

305 if 'EUPS_PATH' not in os.environ: 

306 raise RuntimeError("You can't use eupsdb=XXX without an EUPS_PATH set") 

307 eupsPath = None 

308 for d in os.environ['EUPS_PATH'].split(':'): 

309 if re.search(r"/%s$|^%s/|/%s/" % (db, db, db), d): 

310 eupsPath = d 

311 break 

312 if not eupsPath: 

313 raise RuntimeError("I cannot find DB \"%s\" in $EUPS_PATH" % db) 

314 except KeyError: 

315 if 'EUPS_PATH' in os.environ: 315 ↛ 317line 315 didn't jump to line 317, because the condition on line 315 was never false

316 eupsPath = os.environ['EUPS_PATH'].split(':')[0] 

317 env['eupsPath'] = eupsPath 

318 try: 

319 env['PLATFORM'] = env['flavor'] 

320 del env['flavor'] 

321 except KeyError: 

322 pass 

323 # 

324 # Check arguments 

325 # 

326 errorStr = "" 

327 # 

328 # Process otherwise unknown arguments. If setenv is true, 

329 # set construction variables; otherwise generate an error 

330 # 

331 if SCons.Script.GetOption("setenv"): 331 ↛ 332line 331 didn't jump to line 332, because the condition on line 331 was never true

332 for key in SCons.Script.ARGUMENTS: 

333 env[key] = SCons.Script.Split(SCons.Script.ARGUMENTS[key]) 

334 else: 

335 for key in SCons.Script.ARGUMENTS: 335 ↛ 336line 335 didn't jump to line 336, because the loop on line 335 never started

336 errorStr += " %s=%s" % (key, SCons.Script.ARGUMENTS[key]) 

337 if errorStr: 337 ↛ 338line 337 didn't jump to line 338, because the condition on line 337 was never true

338 log.fail("Unprocessed arguments:%s" % errorStr) 

339 # 

340 # We need a binary name, not just "Posix" 

341 # 

342 env['eupsFlavor'] = eupsForScons.flavor() 

343 

344 

345_configured = False 

346 

347 

348def _configureCommon(): 

349 """Configuration checks for the compiler, platform, and standard 

350 libraries.""" 

351 global _configured 

352 if _configured: 

353 return 

354 _configured = True 

355 

356 def ClassifyCc(context): 

357 """Return a pair of string identifying the compiler in use. 

358 

359 Parameters 

360 ---------- 

361 context : context 

362 Context. 

363 

364 Returns 

365 ------- 

366 compiler : `str` 

367 Compiler to use, or "unknown". 

368 version : `str` 

369 Compiler version or "unknown". 

370 """ 

371 versionNameList = ( 

372 (r"gcc(?:\-.+)? +\(.+\) +([0-9.a-zA-Z]+)", "gcc"), 

373 (r"gnu-cc(?:\-.+)? +\(.+\) +([0-9.a-zA-Z]+)", "gcc"), # catch the conda-build compiler on linux 

374 (r"\(GCC\) +([0-9.a-zA-Z]+) ", "gcc"), 

375 (r"LLVM +version +([0-9.a-zA-Z]+) ", "clang"), # clang on Mac 

376 (r"clang +version +([0-9.a-zA-Z]+) ", "clang"), # clang on linux or clang w/ conda on Mac 

377 (r"\(ICC\) +([0-9.a-zA-Z]+) ", "icc"), 

378 (r"cc \(Ubuntu +([0-9\~\-.a-zA-Z]+)\)", "gcc"), # gcc on Ubuntu (not always caught by #3 above) 

379 ) 

380 

381 context.Message("Checking who built the CC compiler...") 

382 result = context.TryAction(SCons.Script.Action(r"$CC --version > $TARGET")) 

383 ccVersDumpOK, ccVersDump = result[0:2] 

384 if ccVersDumpOK: 

385 for reStr, compilerName in versionNameList: 

386 match = re.search(reStr, ccVersDump) 

387 if match: 

388 compilerVersion = match.groups()[0] 

389 context.Result("%s=%s" % (compilerName, compilerVersion)) 

390 return (compilerName, compilerVersion) 

391 context.Result("unknown") 

392 return ("unknown", "unknown") 

393 

394 if env.GetOption("clean") or env.GetOption("no_exec") or env.GetOption("help"): 

395 env.whichCc = "unknown" # who cares? We're cleaning/not execing, not building 

396 else: 

397 if use_conda_compilers(): 

398 # conda-build expects you to use the compilers as-is 

399 env['CC'] = os.environ['CC'] 

400 env['CXX'] = os.environ['CXX'] 

401 

402 conf = env.Configure(custom_tests={'ClassifyCc': ClassifyCc}) 

403 env.whichCc, env.ccVersion = conf.ClassifyCc() 

404 if not env.GetOption("no_progress"): 

405 log.info("CC is **CONDA** %s version %s" % (env.whichCc, env.ccVersion)) 

406 conf.Finish() 

407 else: 

408 if env['cc'] != '': 

409 CC = CXX = None 

410 if re.search(r"^gcc(-\d+(\.\d+)*)?( |$)", env['cc']): 

411 CC = env['cc'] 

412 CXX = re.sub(r"^gcc", "g++", CC) 

413 elif re.search(r"^icc( |$)", env['cc']): 

414 CC = env['cc'] 

415 CXX = re.sub(r"^icc", "icpc", CC) 

416 elif re.search(r"^clang( |$)", env['cc']): 

417 CC = env['cc'] 

418 CXX = re.sub(r"^clang", "clang++", CC) 

419 elif re.search(r"^cc( |$)", env['cc']): 

420 CC = env['cc'] 

421 CXX = re.sub(r"^cc", "c++", CC) 

422 else: 

423 log.fail("Unrecognised compiler: %s" % env['cc']) 

424 env0 = SCons.Script.Environment() 

425 if CC and env['CC'] == env0['CC']: 

426 env['CC'] = CC 

427 if CC and env['CXX'] == env0['CXX']: 

428 env['CXX'] = CXX 

429 conf = env.Configure(custom_tests={'ClassifyCc': ClassifyCc}) 

430 env.whichCc, env.ccVersion = conf.ClassifyCc() 

431 

432 # If we have picked up a default compiler called gcc that is really 

433 # clang, we call it clang to avoid confusion (gcc on macOS has 

434 # subtly different options) 

435 if not env['cc'] and env.whichCc == "clang" and env['CC'] == "gcc": 

436 env['CC'] = "clang" 

437 env['CXX'] = "clang++" 

438 

439 if not env.GetOption("no_progress"): 

440 log.info("CC is %s version %s" % (env.whichCc, env.ccVersion)) 

441 conf.Finish() 

442 

443 # 

444 # Compiler flags, including CCFLAGS for C and C++ and CXXFLAGS for C++ only 

445 # 

446 ARCHFLAGS = os.environ.get("ARCHFLAGS", env.get('archflags')) 

447 if ARCHFLAGS: 

448 env.Append(CCFLAGS=ARCHFLAGS.split()) 

449 env.Append(LINKFLAGS=ARCHFLAGS.split()) 

450 # We'll add warning and optimisation options last 

451 if env['profile'] == '1' or env['profile'] == "pg": 

452 env.Append(CCFLAGS=['-pg']) 

453 env.Append(LINKFLAGS=['-pg']) 

454 elif env['profile'] == 'gcov': 

455 env.Append(CCFLAGS='--coverage') 

456 env.Append(LINKFLAGS='--coverage') 

457 

458 # 

459 # Enable C++17 support 

460 # 

461 if not (env.GetOption("clean") or env.GetOption("help") or env.GetOption("no_exec")): 

462 if not env.GetOption("no_progress"): 

463 log.info("Checking for C++17 support") 

464 conf = env.Configure() 

465 for cpp17Arg in ("-std=%s" % (val,) for val in ("c++17",)): 

466 conf.env = env.Clone() 

467 conf.env.Append(CXXFLAGS=cpp17Arg) 

468 if conf.CheckCXX(): 

469 env.Append(CXXFLAGS=cpp17Arg) 

470 if not env.GetOption("no_progress"): 

471 log.info("C++17 supported with %r" % (cpp17Arg,)) 

472 break 

473 else: 

474 log.fail("C++17 extensions could not be enabled for compiler %r" % env.whichCc) 

475 conf.Finish() 

476 

477 # 

478 # Byte order 

479 # 

480 import socket 

481 if socket.htons(1) != 1: 

482 env.Append(CCFLAGS=['-DLSST_LITTLE_ENDIAN=1']) 

483 # 

484 # If we're linking to libraries that themselves linked to 

485 # shareable libraries we need to do something special. 

486 # 

487 if (re.search(r"^(Linux|Linux64)$", env["eupsFlavor"]) and "LD_LIBRARY_PATH" in os.environ): 

488 env.Append(LINKFLAGS=["-Wl,-rpath-link"]) 

489 env.Append(LINKFLAGS=["-Wl,%s" % os.environ["LD_LIBRARY_PATH"]]) 

490 # 

491 # Set the optimization level. 

492 # 

493 if env['opt']: 

494 env["CCFLAGS"] = [o for o in env["CCFLAGS"] if not re.search(r"^-O(\d|s|g|fast)$", o)] 

495 env.MergeFlags('-O%s' % env['opt']) 

496 # 

497 # Set compiler-specific warning flags. 

498 # 

499 if env.whichCc == "clang": 

500 env.Append(CCFLAGS=['-Wall']) 

501 env["CCFLAGS"] = [o for o in env["CCFLAGS"] if not re.search(r"^-mno-fused-madd$", o)] 

502 

503 ignoreWarnings = { 

504 "unused-function": 'boost::regex has functions in anon namespaces in headers', 

505 } 

506 filterWarnings = { 

507 "attributes": "clang pretends to be g++, but complains about g++ attributes such as flatten", 

508 "char-subscripts": 'seems innocous enough, and is used by boost', 

509 "constant-logical-operand": "Used by eigen 2.0.15. Should get this fixed", 

510 "format-security": "format string is not a string literal", 

511 "mismatched-tags": "mixed class and struct. Used by gcc 4.2 RTL and eigen 2.0.15", 

512 "parentheses": "equality comparison with extraneous parentheses", 

513 "shorten-64-to-32": "implicit conversion loses integer precision", 

514 "self-assign": "x = x", 

515 "unused-local-typedefs": "unused typedef", # lots from boost 

516 "unknown-pragmas": "unknown pragma ignored", 

517 "deprecated-register": "register is deprecated", 

518 } 

519 for k in ignoreWarnings: 

520 env.Append(CCFLAGS=["-Wno-%s" % k]) 

521 if env.GetOption('filterWarn'): 

522 for k in filterWarnings: 

523 env.Append(CCFLAGS=["-Wno-%s" % k]) 

524 elif env.whichCc == "gcc": 

525 env.Append(CCFLAGS=['-Wall']) 

526 env.Append(CCFLAGS=["-Wno-unknown-pragmas"]) # we don't want complaints about icc/clang pragmas 

527 env.Append(CCFLAGS=["-Wno-unused-local-typedefs"]) # boost generates a lot of these 

528 elif env.whichCc == "icc": 

529 env.Append(CCFLAGS=['-Wall']) 

530 filterWarnings = { 

531 21: 'type qualifiers are meaningless in this declaration', 

532 68: 'integer conversion resulted in a change of sign', 

533 111: 'statement is unreachable', 

534 191: 'type qualifier is meaningless on cast type', 

535 193: 'zero used for undefined preprocessing identifier "SYMB"', 

536 279: 'controlling expression is constant', 

537 304: 'access control not specified ("public" by default)', # comes from boost 

538 383: 'value copied to temporary, reference to temporary used', 

539 # 424: 'Extra ";" ignored', 

540 444: 'destructor for base class "CLASS" is not virtual', 

541 981: 'operands are evaluated in unspecified order', 

542 1418: 'external function definition with no prior declaration', 

543 1419: 'external declaration in primary source file', 

544 1572: 'floating-point equality and inequality comparisons are unreliable', 

545 1720: 'function "FUNC" has no corresponding member operator delete' 

546 '(to be called if an exception is thrown during initialization of an allocated object)', 

547 2259: 'non-pointer conversion from "int" to "float" may lose significant bits', 

548 } 

549 if env.GetOption('filterWarn'): 

550 env.Append(CCFLAGS=["-wd%s" % (",".join([str(k) for k in filterWarnings]))]) 

551 # Workaround intel bug; cf. RHL's intel bug report 580167 

552 env.Append(LINKFLAGS=["-Wl,-no_compact_unwind", "-wd,11015"]) 

553 # 

554 # Disable link-time-optimization on GCC, for compatibility with conda 

555 # binaries 

556 # 

557 if env.whichCc == "gcc": 

558 env.Append(CCFLAGS=['-fno-lto']) 

559 env.Append(LINKFLAGS=['-fno-lto']) 

560 

561 

562def _saveState(): 

563 """Save state such as optimization level used. 

564 

565 Notes 

566 ----- 

567 The scons mailing lists were unable to tell RHL how to get this back 

568 from ``.sconsign.dblite``. 

569 """ 

570 

571 if env.GetOption("clean"): 

572 return 

573 

574 # Python 2 uses ConfigParser, Python 3 uses configparser 

575 try: 

576 from configparser import ConfigParser 

577 except ImportError: 

578 from ConfigParser import ConfigParser 

579 

580 config = ConfigParser() 

581 config.add_section('Build') 

582 config.set('Build', 'cc', env.whichCc) 

583 if env['opt']: 

584 config.set('Build', 'opt', env['opt']) 

585 

586 try: 

587 confFile = os.path.join(env.Dir(env["CONFIGUREDIR"]).abspath, "build.cfg") 

588 with open(confFile, 'w') as configfile: 

589 config.write(configfile) 

590 except Exception as e: 

591 log.warn("Unexpected exception in _saveState: %s" % e) 

592 

593 

594_initOptions() 

595_initLog() 

596_initVariables() 

597_initEnvironment()