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": []}
49 SCons.Script.AddOption(
'--checkDependencies', dest=
'checkDependencies',
50 action=
'store_true', default=
False,
51 help=
"Verify dependencies with autoconf-style tests.")
52 SCons.Script.AddOption(
'--filterWarn', dest=
'filterWarn', action=
'store_true', default=
False,
53 help=
"Filter out a class of warnings deemed irrelevant"),
54 SCons.Script.AddOption(
'--force', dest=
'force', action=
'store_true', default=
False,
55 help=
"Set to force possibly dangerous behaviours")
56 SCons.Script.AddOption(
'--linkFarmDir', dest=
'linkFarmDir', action=
'store', default=
None,
57 help=
"The directory of symbolic links needed to build and use the package")
58 SCons.Script.AddOption(
'--prefix', dest=
'prefix', action=
'store', default=
False,
59 help=
"Specify the install destination")
60 SCons.Script.AddOption(
'--setenv', dest=
'setenv', action=
'store_true', default=
False,
61 help=
"Treat arguments such as Foo=bar as defining construction variables")
62 SCons.Script.AddOption(
'--tag', dest=
'tag', action=
'store', default=
None,
63 help=
"Declare product with this eups tag")
64 SCons.Script.AddOption(
'--verbose', dest=
'verbose', action=
'store_true', default=
False,
65 help=
"Print additional messages for debugging.")
66 SCons.Script.AddOption(
'--traceback', dest=
'traceback', action=
'store_true', default=
False,
67 help=
"Print full exception tracebacks when errors occur.")
68 SCons.Script.AddOption(
'--no-eups', dest=
'no_eups', action=
'store_true', default=
False,
69 help=
"Do not use EUPS for configuration")
78 if "optfile" in SCons.Script.ARGUMENTS:
79 configfile = SCons.Script.ARGUMENTS[
"optfile"]
80 if configfile
not in files:
81 files.append(configfile)
83 if not os.path.isfile(file):
84 log.warn(
"Warning: Will ignore non-existent options file, %s" % file)
85 if "optfile" not in SCons.Script.ARGUMENTS:
86 files.append(
"buildOpts.py")
88 opts = SCons.Script.Variables(files)
90 (
'archflags',
'Extra architecture specification to add to CC/LINK flags (e.g. -m32)',
''),
91 (
'cc',
'Choose the compiler to use',
''),
92 SCons.Script.BoolVariable(
'debug',
'Set to enable debugging flags (use --debug)',
True),
93 (
'eupsdb',
'Specify which element of EUPS_PATH should be used',
None),
94 (
'flavor',
'Set the build flavor',
None),
95 SCons.Script.BoolVariable(
'force',
'Set to force possibly dangerous behaviours',
False),
96 (
'optfile',
'Specify a file to read default options from',
None),
97 (
'prefix',
'Specify the install destination',
None),
98 SCons.Script.EnumVariable(
'opt',
'Set the optimisation level', 0,
99 allowed_values=(
'0',
'1',
'2',
'3')),
100 SCons.Script.EnumVariable(
'profile',
'Compile/link for profiler', 0,
101 allowed_values=(
'0',
'1',
'pg',
'gcov')),
102 (
'version',
'Specify the version to declare',
None),
103 (
'baseversion',
'Specify the current base version',
None),
104 (
'optFiles',
"Specify a list of files that SHOULD be optimized",
None),
105 (
'noOptFiles',
"Specify a list of files that should NOT be optimized",
None),
108 def _initEnvironment():
109 """Construction and basic setup of the state.env variable."""
112 for key
in (
'EUPS_DIR',
'EUPS_PATH',
'EUPS_SHELL',
'PATH' ,
'DYLD_LIBRARY_PATH',
'LD_LIBRARY_PATH',
113 'SHELL',
'TMPDIR',
'TEMP',
'TMP',
'EUPS_LOCK_PID',
'XPA_PORT'):
114 if key
in os.environ:
115 ourEnv[key] = os.environ[key]
120 m = re.search(
r"^(?P<name>\w+)_DIR(?P<extra>_EXTRA)?$", k)
122 cfgPath.append(os.path.join(os.environ[k],
"ups"))
124 cfgPath.append(os.environ[k])
126 cfgPath.append(os.path.join(os.environ[k],
"ups"))
128 varname = eupsForScons.utils.setupEnvNameFor(p)
129 if varname
in os.environ:
130 ourEnv[varname] = os.environ[varname]
131 ourEnv[k] = os.environ[k]
136 cfgPath.append(os.path.join(SCons.Script.Dir(
'#').abspath,
'ups'))
139 for root
in os.environ.get(
"LSST_CFG_PATH",
"").split(
":"):
140 for base, dirs, files
in os.walk(root):
141 dirs = [d
for d
in dirs
if not d.startswith(
".")]
142 cfgPath.insert(0, base)
146 exportVal = SCons.Script.ARGUMENTS.pop(
"export",
None)
148 for kv
in exportVal.split(
','):
152 sconsUtilsPath, thisFile = os.path.split(__file__)
153 toolPath = os.path.join(sconsUtilsPath,
"tools")
154 env = SCons.Script.Environment(
158 tools=[
"default",
"cuda"]
160 env.cfgPath = cfgPath
165 env[
'LDMODULEPREFIX'] =
""
166 if env[
'PLATFORM'] ==
'darwin':
167 env[
'LDMODULESUFFIX'] =
".so"
168 if not re.search(
r"-install_name", str(env[
'SHLINKFLAGS'])):
169 env.Append(SHLINKFLAGS = [
"-Wl,-install_name",
"-Wl,${TARGET.file}"])
170 if not re.search(
r"-headerpad_max_install_names", str(env[
'SHLINKFLAGS'])):
171 env.Append(SHLINKFLAGS = [
"-Wl,-headerpad_max_install_names"])
176 for opt
in opts.keys():
178 del SCons.Script.ARGUMENTS[opt]
184 for k
in (
"force",
"prefix"):
185 if SCons.Script.GetOption(k):
186 env[k] = SCons.Script.GetOption(k)
189 env.Append(CCFLAGS = [
'-g'])
197 if SCons.Script.GetOption(
"no_eups"):
198 env[
'no_eups'] =
True
200 env[
'no_eups'] =
not eupsForScons.haveEups()
202 if not env.GetOption(
"no_progress"):
204 log.info(
'EUPS integration: disabled')
206 log.info(
'EUPS integration: enabled')
214 if 'EUPS_PATH' not in os.environ:
215 raise RuntimeError(
"You can't use eupsdb=XXX without an EUPS_PATH set")
217 for d
in os.environ[
'EUPS_PATH'].split(
':'):
218 if re.search(
r"/%s$|^%s/|/%s/" % (db, db, db), d):
222 raise RuntimeError(
"I cannot find DB \"%s\" in $EUPS_PATH" % db)
224 if 'EUPS_PATH' in os.environ:
225 eupsPath = os.environ[
'EUPS_PATH'].split(
':')[0]
226 env[
'eupsPath'] = eupsPath
228 env[
'PLATFORM'] = env[
'flavor']
240 if SCons.Script.GetOption(
"setenv"):
241 for key
in SCons.Script.ARGUMENTS:
242 env[key] = SCons.Script.Split(SCons.Script.ARGUMENTS[key])
244 for key
in SCons.Script.ARGUMENTS:
245 errorStr +=
" %s=%s" % (key, SCons.Script.ARGUMENTS[key])
247 log.fail(
"Unprocessed arguments:%s" % errorStr)
251 env[
'eupsFlavor'] = eupsForScons.flavor()
253 def _configureCommon():
254 """Configuration checks for the compiler, platform, and standard libraries."""
258 def ClassifyCc(context):
259 """Return a pair of string identifying the compiler in use
261 @return (compiler, version) as a pair of strings, or ("unknown", "unknown") if unknown
264 (
r"gcc(?:\-.+)? +\(.+\) +([0-9.a-zA-Z]+)",
"gcc"),
265 (
r"LLVM +version +([0-9.a-zA-Z]+) ",
"clang"),
266 (
r"clang +version +([0-9.a-zA-Z]+) ",
"clang"),
267 (
r"\(ICC\) +([0-9.a-zA-Z]+) ",
"icc"),
270 context.Message(
"Checking who built the CC compiler...")
271 result = context.TryAction(SCons.Script.Action(
r"$CC --version > $TARGET"))
272 ccVersDumpOK, ccVersDump = result[0:2]
274 for reStr, compilerName
in versionNameList:
275 match = re.search(reStr, ccVersDump)
277 compilerVersion = match.groups()[0]
278 return (compilerName, compilerVersion)
279 return (
"unknown",
"unknown")
281 if env.GetOption(
"clean")
or env.GetOption(
"no_exec")
or env.GetOption(
"help") :
282 env.whichCc =
"unknown"
286 if re.search(
r"^gcc(-\d+(\.\d+)*)?( |$)", env[
'cc']):
288 CXX = re.sub(
r"^gcc",
"g++", CC)
289 elif re.search(
r"^icc( |$)", env[
'cc']):
291 CXX = re.sub(
r"^icc",
"icpc", CC)
292 elif re.search(
r"^clang( |$)", env[
'cc']):
294 CXX = re.sub(
r"^clang",
"clang++", CC)
295 elif re.search(
r"^cc( |$)", env[
'cc']):
297 CXX = re.sub(
r"^cc",
"c++", CC)
299 log.fail(
"Unrecognised compiler:%s" % env[
'cc'])
300 env0 = SCons.Script.Environment()
301 if CC
and env[
'CC'] == env0[
'CC']:
303 if CC
and env[
'CXX'] == env0[
'CXX']:
305 conf = env.Configure(custom_tests = {
'ClassifyCc' : ClassifyCc,})
306 env.whichCc, env.ccVersion = conf.ClassifyCc()
307 if not env.GetOption(
"no_progress"):
308 log.info(
"CC is %s version %s" % (env.whichCc, env.ccVersion))
313 ARCHFLAGS = os.environ.get(
"ARCHFLAGS", env.get(
'archflags'))
315 env.Append(CCFLAGS = ARCHFLAGS.split())
316 env.Append(LINKFLAGS = ARCHFLAGS.split())
318 if env[
'profile'] ==
'1' or env[
'profile'] ==
"pg":
319 env.Append(CCFLAGS = [
'-pg'])
320 env.Append(LINKFLAGS = [
'-pg'])
321 elif env[
'profile'] ==
'gcov':
322 env.Append(CCFLAGS =
'--coverage')
323 env.Append(LINKFLAGS =
'--coverage')
328 if not (env.GetOption(
"clean")
or env.GetOption(
"help")
or env.GetOption(
"no_exec")):
329 if not env.GetOption(
"no_progress"):
330 log.info(
"Checking for C++11 support")
331 conf = env.Configure()
332 for cpp11Arg
in (
"-std=%s" % (val,)
for val
in (
"c++11",
"c++0x")):
333 conf.env = env.Clone()
334 conf.env.Append(CXXFLAGS = cpp11Arg)
336 env.Append(CXXFLAGS = cpp11Arg)
337 if not env.GetOption(
"no_progress"):
338 log.info(
"C++11 supported with %r" % (cpp11Arg,))
341 log.fail(
"C++11 extensions could not be enabled for compiler %r" % env.whichCc)
349 if not (env.GetOption(
"clean")
or env.GetOption(
"help")
or env.GetOption(
"no_exec")):
350 conf = env.Configure()
351 env.Append(CCFLAGS = [
'-DLSST_HAVE_TR1=%d' % int(conf.CheckCXXHeader(
"tr1/unordered_map"))])
357 if socket.htons(1) != 1:
358 env.Append(CCFLAGS = [
'-DLSST_LITTLE_ENDIAN=1'])
363 if (re.search(
r"^(Linux|Linux64)$", env[
"eupsFlavor"])
and "LD_LIBRARY_PATH" in os.environ):
364 env.Append(LINKFLAGS = [
"-Wl,-rpath-link"])
365 env.Append(LINKFLAGS = [
"-Wl,%s" % os.environ[
"LD_LIBRARY_PATH"]])
370 env[
"CCFLAGS"] = [o
for o
in env[
"CCFLAGS"]
if not re.search(
r"^-O(\d|s)$", o)]
371 env.MergeFlags(
'-O%d' % int(env[
'opt']))
375 if env.whichCc ==
"clang":
376 env.Append(CCFLAGS = [
'-Wall'])
377 env[
"CCFLAGS"] = [o
for o
in env[
"CCFLAGS"]
if not re.search(
r"^-mno-fused-madd$", o)]
380 "unused-function" :
'boost::regex has functions in anon namespaces in headers',
383 "attributes" :
"clang pretends to be g++, but complains about g++ attributes such as flatten",
384 "char-subscripts" :
'seems innocous enough, and is used by boost',
385 "constant-logical-operand" :
"Used by eigen 2.0.15. Should get this fixed",
386 "format-security" :
"format string is not a string literal",
387 "mismatched-tags" :
"mixed class and struct. Used by gcc 4.2 RTL and eigen 2.0.15",
388 "parentheses" :
"equality comparison with extraneous parentheses",
389 "shorten-64-to-32" :
"implicit conversion loses integer precision",
390 "self-assign" :
"x = x",
391 "unknown-pragmas" :
"unknown pragma ignored",
392 "deprecated-register" :
"register is deprecated",
394 for k
in ignoreWarnings:
395 env.Append(CCFLAGS = [
"-Wno-%s" % k])
396 if env.GetOption(
'filterWarn'):
397 for k
in filterWarnings:
398 env.Append(CCFLAGS = [
"-Wno-%s" % k])
399 elif env.whichCc ==
"gcc":
400 env.Append(CCFLAGS = [
'-Wall'])
401 env.Append(CCFLAGS = [
"-Wno-unknown-pragmas"])
402 elif env.whichCc ==
"icc":
403 env.Append(CCFLAGS = [
'-Wall'])
405 21 :
'type qualifiers are meaningless in this declaration',
406 68 :
'integer conversion resulted in a change of sign',
407 111 :
'statement is unreachable',
408 191 :
'type qualifier is meaningless on cast type',
409 193 :
'zero used for undefined preprocessing identifier "SYMB"',
410 279 :
'controlling expression is constant',
411 304 :
'access control not specified ("public" by default)',
412 383 :
'value copied to temporary, reference to temporary used',
414 444 :
'destructor for base class "CLASS" is not virtual',
415 981 :
'operands are evaluated in unspecified order',
416 1418 :
'external function definition with no prior declaration',
417 1419 :
'external declaration in primary source file',
418 1572 :
'floating-point equality and inequality comparisons are unreliable',
419 1720 :
'function "FUNC" has no corresponding member operator delete (to be called if an exception is thrown during initialization of an allocated object)',
420 2259 :
'non-pointer conversion from "int" to "float" may lose significant bits',
422 if env.GetOption(
'filterWarn'):
423 env.Append(CCFLAGS = [
"-wd%s" % (
",".join([str(k)
for k
in filterWarnings]))])
425 env.Append(LINKFLAGS = [
"-Wl,-no_compact_unwind",
"-wd,11015"])
428 """Save state such as optimization level used. The scons mailing lists were unable to tell
429 RHL how to get this back from .sconsign.dblite
432 if env.GetOption(
"clean"):
437 config = ConfigParser.ConfigParser()
438 config.add_section(
'Build')
439 config.set(
'Build',
'cc', env.whichCc)
441 config.set(
'Build',
'opt', env[
'opt'])
444 confFile = os.path.join(env.Dir(env[
"CONFIGUREDIR"]).abspath,
"build.cfg")
445 with open(confFile,
'wb')
as configfile:
446 config.write(configfile)
447 except Exception
as e:
448 log.warn(
"Unexpected exception in _saveState: %s" % e)
A dead-simple logger for all messages.