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

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

289 statements  

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 _initVariables(): 

80 files = [] 

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

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

83 if configfile not in files: 

84 files.append(configfile) 

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

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

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

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

89 files.append("buildOpts.py") 

90 global opts 

91 opts = SCons.Script.Variables(files) 

92 opts.AddVariables( 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

109 ('macosx_deployment_target', 'Deployment target for Mac OS X', '10.9'), 

110 ) 

111 

112 

113def _initEnvironment(): 

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

115 

116 ourEnv = {} 

117 preserveVars = """ 

118 DYLD_LIBRARY_PATH 

119 EUPS_DIR 

120 EUPS_LOCK_PID 

121 EUPS_PATH 

122 EUPS_SHELL 

123 EUPS_USERDATA 

124 LD_LIBRARY_PATH 

125 PATH 

126 SHELL 

127 TEMP 

128 TERM 

129 TMP 

130 TMPDIR 

131 XPA_PORT 

132 CONDA_BUILD_SYSROOT 

133 SDKROOT 

134 """.split() 

135 

136 codeCheckerVars = """ 

137 LD_PRELOAD 

138 CC_LOGGER_FILE 

139 CC_LOGGER_GCC_LIKE 

140 CC_LIB_DIR 

141 CC_DATA_FILES_DIR 

142 CC_LOGGER_BIN 

143 """.split() 

144 

145 for key in preserveVars: 

146 if key in os.environ: 

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

148 

149 # check if running in CodeChecker environment 

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

151 for key in codeCheckerVars: 

152 if key in os.environ: 

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

154 

155 # Find and propagate EUPS environment variables. 

156 cfgPath = [] 

157 for k in os.environ: 

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

159 if not m: 

160 continue 

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

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

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

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

165 else: 

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

167 p = m.group("name") 

168 varname = eupsForScons.utils.setupEnvNameFor(p) 

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

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

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

172 

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

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

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

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

177 

178 # 

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

180 # 

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

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

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

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

185 ourEnv[k] = v 

186 global env 

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

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

189 env = SCons.Script.Environment( 

190 ENV=ourEnv, 

191 variables=opts, 

192 toolpath=[toolPath], 

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

194 ) 

195 env.cfgPath = cfgPath 

196 # 

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

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

199 # 

200 env['LDMODULEPREFIX'] = "" 

201 if env['PLATFORM'] == 'darwin': 201 ↛ 202line 201 didn't jump to line 202, because the condition on line 201 was never true

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

203 if not re.search(r"-install_name", str(env['SHLINKFLAGS'])): 

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

205 if not re.search(r"-headerpad_max_install_names", str(env['SHLINKFLAGS'])): 

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

207 # 

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

209 # 

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

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

212 # on deployment platforms < 10.13 and 10.15 

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

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

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

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

217 # 

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

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

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

221 # 

222 env['LIBDIRSUFFIX'] = '/' 

223 

224 if use_conda_compilers(): 224 ↛ 251line 224 didn't jump to line 251, because the condition on line 224 was never false

225 _conda_prefix = get_conda_prefix() 

226 if "LDFLAGS" in os.environ: 226 ↛ 227line 226 didn't jump to line 227, because the condition on line 226 was never true

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

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

229 # this one breaks some linking in the eups build 

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

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

232 env.Append(LINKFLAGS=LDFLAGS) 

233 env.Append(SHLINKFLAGS=LDFLAGS) 

234 

235 if "CFLAGS" in os.environ: 235 ↛ 236line 235 didn't jump to line 236, because the condition on line 235 was never true

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

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

238 env.Append(CCFLAGS=CFLAGS) 

239 

240 if "CXXFLAGS" in os.environ: 240 ↛ 241line 240 didn't jump to line 241, because the condition on line 240 was never true

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

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

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

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

245 env.Append(CXXFLAGS=CXXFLAGS) 

246 

247 # 

248 # Remove valid options from the arguments 

249 # 

250 # SCons Variables do not behave like dicts 

251 for opt in opts.keys(): 

252 try: 

253 del SCons.Script.ARGUMENTS[opt] 

254 except KeyError: 

255 pass 

256 # 

257 # Process those arguments 

258 # 

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

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

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

262 

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

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

265 

266 # 

267 # determine if EUPS is present 

268 # 

269 

270 # --no-eups overides probing 

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

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

273 env['no_eups'] = True 

274 else: 

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

276 

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

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

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

280 else: 

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

282 

283 # 

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

285 # 

286 eupsPath = None 

287 try: 

288 db = env['eupsdb'] 

289 if 'EUPS_PATH' not in os.environ: 

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

291 eupsPath = None 

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

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

294 eupsPath = d 

295 break 

296 if not eupsPath: 

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

298 except KeyError: 

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

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

301 env['eupsPath'] = eupsPath 

302 try: 

303 env['PLATFORM'] = env['flavor'] 

304 del env['flavor'] 

305 except KeyError: 

306 pass 

307 # 

308 # Check arguments 

309 # 

310 errorStr = "" 

311 # 

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

313 # set construction variables; otherwise generate an error 

314 # 

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

316 for key in SCons.Script.ARGUMENTS: 

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

318 else: 

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

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

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

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

323 # 

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

325 # 

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

327 

328 

329_configured = False 

330 

331 

332def _configureCommon(): 

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

334 libraries.""" 

335 global _configured 

336 if _configured: 

337 return 

338 _configured = True 

339 

340 def ClassifyCc(context): 

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

342 

343 Parameters 

344 ---------- 

345 context : context 

346 Context. 

347 

348 Returns 

349 ------- 

350 compiler : `str` 

351 Compiler to use, or "unknown". 

352 version : `str` 

353 Compiler version or "unknown". 

354 """ 

355 versionNameList = ( 

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

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

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

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

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

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

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

363 ) 

364 

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

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

367 ccVersDumpOK, ccVersDump = result[0:2] 

368 if ccVersDumpOK: 

369 for reStr, compilerName in versionNameList: 

370 match = re.search(reStr, ccVersDump) 

371 if match: 

372 compilerVersion = match.groups()[0] 

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

374 return (compilerName, compilerVersion) 

375 context.Result("unknown") 

376 return ("unknown", "unknown") 

377 

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

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

380 else: 

381 if use_conda_compilers(): 

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

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

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

385 

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

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

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

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

390 conf.Finish() 

391 else: 

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

393 CC = CXX = None 

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

395 CC = env['cc'] 

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

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

398 CC = env['cc'] 

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

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

401 CC = env['cc'] 

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

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

404 CC = env['cc'] 

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

406 else: 

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

408 env0 = SCons.Script.Environment() 

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

410 env['CC'] = CC 

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

412 env['CXX'] = CXX 

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

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

415 

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

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

418 # subtly different options) 

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

420 env['CC'] = "clang" 

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

422 

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

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

425 conf.Finish() 

426 

427 # 

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

429 # 

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

431 if ARCHFLAGS: 

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

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

434 # We'll add warning and optimisation options last 

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

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

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

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

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

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

441 

442 # 

443 # Enable C++17 support 

444 # 

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

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

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

448 conf = env.Configure() 

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

450 conf.env = env.Clone() 

451 conf.env.Append(CXXFLAGS=cpp17Arg) 

452 if conf.CheckCXX(): 

453 env.Append(CXXFLAGS=cpp17Arg) 

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

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

456 break 

457 else: 

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

459 conf.Finish() 

460 

461 # 

462 # Byte order 

463 # 

464 import socket 

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

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

467 # 

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

469 # shareable libraries we need to do something special. 

470 # 

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

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

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

474 # 

475 # Set the optimization level. 

476 # 

477 if env['opt']: 

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

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

480 # 

481 # Set compiler-specific warning flags. 

482 # 

483 if env.whichCc == "clang": 

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

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

486 

487 ignoreWarnings = { 

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

489 } 

490 filterWarnings = { 

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

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

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

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

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

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

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

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

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

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

501 "deprecated-register": "register is deprecated", 

502 } 

503 for k in ignoreWarnings: 

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

505 if env.GetOption('filterWarn'): 

506 for k in filterWarnings: 

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

508 elif env.whichCc == "gcc": 

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

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

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

512 elif env.whichCc == "icc": 

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

514 filterWarnings = { 

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

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

517 111: 'statement is unreachable', 

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

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

520 279: 'controlling expression is constant', 

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

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

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

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

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

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

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

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

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

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

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

532 } 

533 if env.GetOption('filterWarn'): 

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

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

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

537 # 

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

539 # binaries 

540 # 

541 if env.whichCc == "gcc": 

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

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

544 

545 

546def _saveState(): 

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

548 

549 Notes 

550 ----- 

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

552 from ``.sconsign.dblite``. 

553 """ 

554 

555 if env.GetOption("clean"): 

556 return 

557 

558 # Python 2 uses ConfigParser, Python 3 uses configparser 

559 try: 

560 from configparser import ConfigParser 

561 except ImportError: 

562 from ConfigParser import ConfigParser 

563 

564 config = ConfigParser() 

565 config.add_section('Build') 

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

567 if env['opt']: 

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

569 

570 try: 

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

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

573 config.write(configfile) 

574 except Exception as e: 

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

576 

577 

578_initOptions() 

579_initLog() 

580_initVariables() 

581_initEnvironment()