15 from __future__
import absolute_import, division, print_function
21 from .
import eupsForScons
23 SCons.Script.EnsureSConsVersion(2, 1, 0)
39 targets = {
"doc": [],
"tests": [],
"lib": [],
"python": [],
"examples": [],
"include": [],
"version": [],
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")
81 if "optfile" in SCons.Script.ARGUMENTS:
82 configfile = SCons.Script.ARGUMENTS[
"optfile"]
83 if configfile
not in files:
84 files.append(configfile)
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:
89 files.append(
"buildOpts.py")
91 opts = SCons.Script.Variables(files)
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'),
113 def _initEnvironment():
114 """Construction and basic setup of the state.env variable."""
117 for key
in (
'EUPS_DIR',
'EUPS_PATH',
'EUPS_SHELL',
'PATH',
'DYLD_LIBRARY_PATH',
'LD_LIBRARY_PATH',
118 'SHELL',
'TMPDIR',
'TEMP',
'TMP',
'EUPS_LOCK_PID',
'XPA_PORT'):
119 if key
in os.environ:
120 ourEnv[key] = os.environ[key]
125 m = re.search(
r"^(?P<name>\w+)_DIR(?P<extra>_EXTRA)?$", k)
128 cfgPath.append(os.path.join(os.environ[k],
"ups"))
130 cfgPath.append(os.environ[k])
132 cfgPath.append(os.path.join(os.environ[k],
"ups"))
134 varname = eupsForScons.utils.setupEnvNameFor(p)
135 if varname
in os.environ:
136 ourEnv[varname] = os.environ[varname]
137 ourEnv[k] = os.environ[k]
142 cfgPath.append(os.path.join(SCons.Script.Dir(
'#').abspath,
'ups'))
145 for root
in os.environ.get(
"LSST_CFG_PATH",
"").split(
":"):
146 for base, dirs, files
in os.walk(root):
147 dirs = [d
for d
in dirs
if not d.startswith(
".")]
148 cfgPath.insert(0, base)
152 exportVal = SCons.Script.ARGUMENTS.pop(
"export",
None)
154 for kv
in exportVal.split(
','):
158 sconsUtilsPath, thisFile = os.path.split(__file__)
159 toolPath = os.path.join(sconsUtilsPath,
"tools")
160 env = SCons.Script.Environment(
164 tools=[
"default",
"cuda"]
166 env.cfgPath = cfgPath
171 env[
'LDMODULEPREFIX'] =
""
172 if env[
'PLATFORM'] ==
'darwin':
173 env[
'LDMODULESUFFIX'] =
".so"
174 if not re.search(
r"-install_name", str(env[
'SHLINKFLAGS'])):
175 env.Append(SHLINKFLAGS=[
"-install_name",
"${TARGET.file}"])
176 if not re.search(
r"-headerpad_max_install_names", str(env[
'SHLINKFLAGS'])):
177 env.Append(SHLINKFLAGS=[
"-Wl,-headerpad_max_install_names"])
181 env[
'ENV'][
'MACOSX_DEPLOYMENT_TARGET'] = env[
'macosx_deployment_target']
182 log.info(
"Setting OS X binary compatibility level: %s" % env[
'ENV'][
'MACOSX_DEPLOYMENT_TARGET'])
188 env[
'LIBDIRSUFFIX'] =
'/'
194 for opt
in opts.keys():
196 del SCons.Script.ARGUMENTS[opt]
202 for k
in (
"force",
"prefix"):
203 if SCons.Script.GetOption(k):
204 env[k] = SCons.Script.GetOption(k)
207 env.Append(CCFLAGS=[
'-g'])
215 if SCons.Script.GetOption(
"no_eups"):
216 env[
'no_eups'] =
True
218 env[
'no_eups'] =
not eupsForScons.haveEups()
220 if not env.GetOption(
"no_progress"):
222 log.info(
'EUPS integration: disabled')
224 log.info(
'EUPS integration: enabled')
232 if 'EUPS_PATH' not in os.environ:
233 raise RuntimeError(
"You can't use eupsdb=XXX without an EUPS_PATH set")
235 for d
in os.environ[
'EUPS_PATH'].split(
':'):
236 if re.search(
r"/%s$|^%s/|/%s/" % (db, db, db), d):
240 raise RuntimeError(
"I cannot find DB \"%s\" in $EUPS_PATH" % db)
242 if 'EUPS_PATH' in os.environ:
243 eupsPath = os.environ[
'EUPS_PATH'].split(
':')[0]
244 env[
'eupsPath'] = eupsPath
246 env[
'PLATFORM'] = env[
'flavor']
258 if SCons.Script.GetOption(
"setenv"):
259 for key
in SCons.Script.ARGUMENTS:
260 env[key] = SCons.Script.Split(SCons.Script.ARGUMENTS[key])
262 for key
in SCons.Script.ARGUMENTS:
263 errorStr +=
" %s=%s" % (key, SCons.Script.ARGUMENTS[key])
265 log.fail(
"Unprocessed arguments:%s" % errorStr)
269 env[
'eupsFlavor'] = eupsForScons.flavor()
272 def _configureCommon():
273 """Configuration checks for the compiler, platform, and standard libraries."""
277 def ClassifyCc(context):
278 """Return a pair of string identifying the compiler in use
280 @return (compiler, version) as a pair of strings, or ("unknown", "unknown") if unknown
283 (
r"gcc(?:\-.+)? +\(.+\) +([0-9.a-zA-Z]+)",
"gcc"),
284 (
r"\(GCC\) +([0-9.a-zA-Z]+) ",
"gcc"),
285 (
r"LLVM +version +([0-9.a-zA-Z]+) ",
"clang"),
286 (
r"clang +version +([0-9.a-zA-Z]+) ",
"clang"),
287 (
r"\(ICC\) +([0-9.a-zA-Z]+) ",
"icc"),
290 context.Message(
"Checking who built the CC compiler...")
291 result = context.TryAction(SCons.Script.Action(
r"$CC --version > $TARGET"))
292 ccVersDumpOK, ccVersDump = result[0:2]
294 for reStr, compilerName
in versionNameList:
295 match = re.search(reStr, ccVersDump)
297 compilerVersion = match.groups()[0]
298 context.Result(
"%s=%s" % (compilerName, compilerVersion))
299 return (compilerName, compilerVersion)
300 context.Result(
"unknown")
301 return (
"unknown",
"unknown")
303 if env.GetOption(
"clean")
or env.GetOption(
"no_exec")
or env.GetOption(
"help"):
304 env.whichCc =
"unknown"
308 if re.search(
r"^gcc(-\d+(\.\d+)*)?( |$)", env[
'cc']):
310 CXX = re.sub(
r"^gcc",
"g++", CC)
311 elif re.search(
r"^icc( |$)", env[
'cc']):
313 CXX = re.sub(
r"^icc",
"icpc", CC)
314 elif re.search(
r"^clang( |$)", env[
'cc']):
316 CXX = re.sub(
r"^clang",
"clang++", CC)
317 elif re.search(
r"^cc( |$)", env[
'cc']):
319 CXX = re.sub(
r"^cc",
"c++", CC)
321 log.fail(
"Unrecognised compiler:%s" % env[
'cc'])
322 env0 = SCons.Script.Environment()
323 if CC
and env[
'CC'] == env0[
'CC']:
325 if CC
and env[
'CXX'] == env0[
'CXX']:
327 conf = env.Configure(custom_tests={
'ClassifyCc': ClassifyCc})
328 env.whichCc, env.ccVersion = conf.ClassifyCc()
329 if not env.GetOption(
"no_progress"):
330 log.info(
"CC is %s version %s" % (env.whichCc, env.ccVersion))
335 ARCHFLAGS = os.environ.get(
"ARCHFLAGS", env.get(
'archflags'))
337 env.Append(CCFLAGS=ARCHFLAGS.split())
338 env.Append(LINKFLAGS=ARCHFLAGS.split())
340 if env[
'profile'] ==
'1' or env[
'profile'] ==
"pg":
341 env.Append(CCFLAGS=[
'-pg'])
342 env.Append(LINKFLAGS=[
'-pg'])
343 elif env[
'profile'] ==
'gcov':
344 env.Append(CCFLAGS=
'--coverage')
345 env.Append(LINKFLAGS=
'--coverage')
350 if not (env.GetOption(
"clean")
or env.GetOption(
"help")
or env.GetOption(
"no_exec")):
351 if not env.GetOption(
"no_progress"):
352 log.info(
"Checking for C++11 support")
353 conf = env.Configure()
354 for cpp11Arg
in (
"-std=%s" % (val,)
for val
in (
"c++11",)):
355 conf.env = env.Clone()
356 conf.env.Append(CXXFLAGS=cpp11Arg)
358 env.Append(CXXFLAGS=cpp11Arg)
359 if not env.GetOption(
"no_progress"):
360 log.info(
"C++11 supported with %r" % (cpp11Arg,))
363 log.fail(
"C++11 extensions could not be enabled for compiler %r" % env.whichCc)
370 if socket.htons(1) != 1:
371 env.Append(CCFLAGS=[
'-DLSST_LITTLE_ENDIAN=1'])
376 if (re.search(
r"^(Linux|Linux64)$", env[
"eupsFlavor"])
and "LD_LIBRARY_PATH" in os.environ):
377 env.Append(LINKFLAGS=[
"-Wl,-rpath-link"])
378 env.Append(LINKFLAGS=[
"-Wl,%s" % os.environ[
"LD_LIBRARY_PATH"]])
383 env[
"CCFLAGS"] = [o
for o
in env[
"CCFLAGS"]
if not re.search(
r"^-O(\d|s|g|fast)$", o)]
384 env.MergeFlags(
'-O%s' % env[
'opt'])
388 if env.whichCc ==
"clang":
389 env.Append(CCFLAGS=[
'-Wall'])
390 env[
"CCFLAGS"] = [o
for o
in env[
"CCFLAGS"]
if not re.search(
r"^-mno-fused-madd$", o)]
393 "unused-function":
'boost::regex has functions in anon namespaces in headers',
396 "attributes":
"clang pretends to be g++, but complains about g++ attributes such as flatten",
397 "char-subscripts":
'seems innocous enough, and is used by boost',
398 "constant-logical-operand":
"Used by eigen 2.0.15. Should get this fixed",
399 "format-security":
"format string is not a string literal",
400 "mismatched-tags":
"mixed class and struct. Used by gcc 4.2 RTL and eigen 2.0.15",
401 "parentheses":
"equality comparison with extraneous parentheses",
402 "shorten-64-to-32":
"implicit conversion loses integer precision",
403 "self-assign":
"x = x",
404 "unused-local-typedefs":
"unused typedef",
405 "unknown-pragmas":
"unknown pragma ignored",
406 "deprecated-register":
"register is deprecated",
408 for k
in ignoreWarnings:
409 env.Append(CCFLAGS=[
"-Wno-%s" % k])
410 if env.GetOption(
'filterWarn'):
411 for k
in filterWarnings:
412 env.Append(CCFLAGS=[
"-Wno-%s" % k])
413 elif env.whichCc ==
"gcc":
414 env.Append(CCFLAGS=[
'-Wall'])
415 env.Append(CCFLAGS=[
"-Wno-unknown-pragmas"])
416 env.Append(CCFLAGS=[
"-Wno-unused-local-typedefs"])
417 elif env.whichCc ==
"icc":
418 env.Append(CCFLAGS=[
'-Wall'])
420 21:
'type qualifiers are meaningless in this declaration',
421 68:
'integer conversion resulted in a change of sign',
422 111:
'statement is unreachable',
423 191:
'type qualifier is meaningless on cast type',
424 193:
'zero used for undefined preprocessing identifier "SYMB"',
425 279:
'controlling expression is constant',
426 304:
'access control not specified ("public" by default)',
427 383:
'value copied to temporary, reference to temporary used',
429 444:
'destructor for base class "CLASS" is not virtual',
430 981:
'operands are evaluated in unspecified order',
431 1418:
'external function definition with no prior declaration',
432 1419:
'external declaration in primary source file',
433 1572:
'floating-point equality and inequality comparisons are unreliable',
434 1720:
'function "FUNC" has no corresponding member operator delete'
435 '(to be called if an exception is thrown during initialization of an allocated object)',
436 2259:
'non-pointer conversion from "int" to "float" may lose significant bits',
438 if env.GetOption(
'filterWarn'):
439 env.Append(CCFLAGS=[
"-wd%s" % (
",".join([str(k)
for k
in filterWarnings]))])
441 env.Append(LINKFLAGS=[
"-Wl,-no_compact_unwind",
"-wd,11015"])
445 """Save state such as optimization level used. The scons mailing lists were unable to tell
446 RHL how to get this back from .sconsign.dblite
449 if env.GetOption(
"clean"):
454 config = ConfigParser.ConfigParser()
455 config.add_section(
'Build')
456 config.set(
'Build',
'cc', env.whichCc)
458 config.set(
'Build',
'opt', env[
'opt'])
461 confFile = os.path.join(env.Dir(env[
"CONFIGUREDIR"]).abspath,
"build.cfg")
462 with open(confFile,
'wb')
as configfile:
463 config.write(configfile)
464 except Exception
as e:
465 log.warn(
"Unexpected exception in _saveState: %s" % e)
A dead-simple logger for all messages.