21 SCons.Script.EnsureSConsVersion(2, 1, 0)
37 targets = {
"doc": [],
"tests": [],
"lib": [],
"python": [],
"examples": [],
"include": [],
"version": []}
47 SCons.Script.AddOption(
'--checkDependencies', dest=
'checkDependencies',
48 action=
'store_true', default=
False,
49 help=
"Verify dependencies with autoconf-style tests.")
50 SCons.Script.AddOption(
'--filterWarn', dest=
'filterWarn', action=
'store_true', default=
False,
51 help=
"Filter out a class of warnings deemed irrelevant"),
52 SCons.Script.AddOption(
'--force', dest=
'force', action=
'store_true', default=
False,
53 help=
"Set to force possibly dangerous behaviours")
54 SCons.Script.AddOption(
'--linkFarmDir', dest=
'linkFarmDir', action=
'store', default=
None,
55 help=
"The directory of symbolic links needed to build and use the package")
56 SCons.Script.AddOption(
'--prefix', dest=
'prefix', action=
'store', default=
False,
57 help=
"Specify the install destination")
58 SCons.Script.AddOption(
'--setenv', dest=
'setenv', action=
'store_true', default=
False,
59 help=
"Treat arguments such as Foo=bar as defining construction variables")
60 SCons.Script.AddOption(
'--tag', dest=
'tag', action=
'store', default=
None,
61 help=
"Declare product with this eups tag")
62 SCons.Script.AddOption(
'--verbose', dest=
'verbose', action=
'store_true', default=
False,
63 help=
"Print additional messages for debugging.")
64 SCons.Script.AddOption(
'--traceback', dest=
'traceback', action=
'store_true', default=
False,
65 help=
"Print full exception tracebacks when errors occur.")
74 if SCons.Script.ARGUMENTS.has_key(
"optfile"):
75 configfile = SCons.Script.ARGUMENTS[
"optfile"]
76 if configfile
not in files:
77 files.append(configfile)
79 if not os.path.isfile(file):
80 log.warn(
"Warning: Will ignore non-existent options file, %s" % file)
81 if not SCons.Script.ARGUMENTS.has_key(
"optfile"):
82 files.append(
"buildOpts.py")
84 opts = SCons.Script.Variables(files)
86 (
'archflags',
'Extra architecture specification to add to CC/LINK flags (e.g. -m32)',
''),
87 (
'cc',
'Choose the compiler to use',
''),
88 SCons.Script.BoolVariable(
'debug',
'Set to enable debugging flags (use --debug)',
True),
89 (
'eupsdb',
'Specify which element of EUPS_PATH should be used',
None),
90 (
'flavor',
'Set the build flavor',
None),
91 SCons.Script.BoolVariable(
'force',
'Set to force possibly dangerous behaviours',
False),
92 (
'optfile',
'Specify a file to read default options from',
None),
93 (
'prefix',
'Specify the install destination',
None),
94 SCons.Script.EnumVariable(
'opt',
'Set the optimisation level', 0,
95 allowed_values=(
'0',
'1',
'2',
'3')),
96 SCons.Script.EnumVariable(
'profile',
'Compile/link for profiler', 0,
97 allowed_values=(
'0',
'1',
'pg',
'gcov')),
98 (
'version',
'Specify the version to declare',
None),
99 (
'baseversion',
'Specify the current base version',
None),
100 (
'optFiles',
"Specify a list of files that SHOULD be optimized",
None),
101 (
'noOptFiles',
"Specify a list of files that should NOT be optimized",
None),
104 def _initEnvironment():
105 """Construction and basic setup of the state.env variable."""
108 for key
in (
'EUPS_DIR',
'EUPS_PATH',
'EUPS_SHELL',
'PATH' ,
'DYLD_LIBRARY_PATH',
'LD_LIBRARY_PATH',
109 'SHELL',
'TMPDIR',
'TEMP',
'TMP',
'EUPS_LOCK_PID',
'XPA_PORT'):
110 if key
in os.environ:
111 ourEnv[key] = os.environ[key]
115 for k
in os.environ.keys():
116 m = re.search(
r"^(?P<name>\w+)_DIR(?P<extra>_EXTRA)?$", k)
118 cfgPath.append(os.path.join(os.environ[k],
"ups"))
120 cfgPath.append(os.environ[k])
122 cfgPath.append(os.path.join(os.environ[k],
"ups"))
124 varname = eupsForScons.utils.setupEnvNameFor(p)
125 if os.environ.has_key(varname):
126 ourEnv[varname] = os.environ[varname]
127 ourEnv[k] = os.environ[k]
130 for root
in os.environ.get(
"LSST_CFG_PATH",
"").split(
":"):
131 for base, dirs, files
in os.walk(root):
132 dirs = [d
for d
in dirs
if not d.startswith(
".")]
133 cfgPath.insert(0, base)
137 exportVal = SCons.Script.ARGUMENTS.pop(
"export",
None)
139 for kv
in exportVal.split(
','):
143 sconsUtilsPath, thisFile = os.path.split(__file__)
144 toolPath = os.path.join(sconsUtilsPath,
"tools")
145 env = SCons.Script.Environment(
149 tools=[
"default",
"cuda"]
151 env.cfgPath = cfgPath
156 env[
'LDMODULEPREFIX'] =
""
157 if env[
'PLATFORM'] ==
'darwin':
158 env[
'LDMODULESUFFIX'] =
".so"
159 if not re.search(
r"-install_name", str(env[
'SHLINKFLAGS'])):
160 env.Append(SHLINKFLAGS = [
"-Wl,-install_name",
"-Wl,${TARGET.file}"])
164 for opt
in opts.keys():
166 del SCons.Script.ARGUMENTS[opt]
172 for k
in (
"force",
"prefix"):
173 if SCons.Script.GetOption(k):
174 env[k] = SCons.Script.GetOption(k)
177 env.Append(CCFLAGS = [
'-g'])
184 if not os.environ.has_key(
'EUPS_PATH'):
185 raise RuntimeError(
"You can't use eupsdb=XXX without an EUPS_PATH set")
187 for d
in os.environ[
'EUPS_PATH'].split(
':'):
188 if re.search(
r"/%s$|^%s/|/%s/" % (db, db, db), d):
192 raise RuntimeError(
"I cannot find DB \"%s\" in $EUPS_PATH" % db)
194 if os.environ.has_key(
'EUPS_PATH'):
195 eupsPath = os.environ[
'EUPS_PATH'].split(
':')[0]
196 env[
'eupsPath'] = eupsPath
198 env[
'PLATFORM'] = env[
'flavor']
210 if SCons.Script.GetOption(
"setenv"):
211 for key
in SCons.Script.ARGUMENTS.keys():
212 env[key] = SCons.Script.Split(SCons.Script.ARGUMENTS[key])
214 for key
in SCons.Script.ARGUMENTS.keys():
215 errorStr +=
" %s=%s" % (key, SCons.Script.ARGUMENTS[key])
217 log.fail(
"Unprocessed arguments:%s" % errorStr)
221 env[
'eupsFlavor'] = eupsForScons.flavor()
223 def _configureCommon():
224 """Configuration checks for the compiler, platform, and standard libraries."""
228 def ClassifyCc(context):
229 """Return a pair of string identifying the compiler in use
231 @return (compiler, version) as a pair of strings, or ("unknown", "unknown") if unknown
234 (
r"gcc +\(.+\) +([0-9.a-zA-Z]+)",
"gcc"),
235 (
r"LLVM +version +([0-9.a-zA-Z]+) ",
"clang"),
236 (
r"clang +version +([0-9.a-zA-Z]+) ",
"clang"),
237 (
r"\(ICC\) +([0-9.a-zA-Z]+) ",
"icc"),
240 context.Message(
"Checking who built the CC compiler...")
241 result = context.TryAction(SCons.Script.Action(
r"$CC --version > $TARGET"))
242 ccVersDumpOK, ccVersDump = result[0:2]
244 for reStr, compilerName
in versionNameList:
245 match = re.search(reStr, ccVersDump)
247 compilerVersion = match.groups()[0]
248 return (compilerName, compilerVersion)
249 return (
"unknown",
"unknown")
251 if env.GetOption(
"clean")
or env.GetOption(
"no_exec")
or env.GetOption(
"help") :
252 env.whichCc =
"unknown"
256 if re.search(
r"^gcc(-\d+(\.\d+)*)?( |$)", env[
'cc']):
258 CXX = re.sub(
r"^gcc",
"g++", CC)
259 elif re.search(
r"^icc( |$)", env[
'cc']):
261 CXX = re.sub(
r"^icc",
"icpc", CC)
262 elif re.search(
r"^clang( |$)", env[
'cc']):
264 CXX = re.sub(
r"^clang",
"clang++", CC)
265 elif re.search(
r"^cc( |$)", env[
'cc']):
267 CXX = re.sub(
r"^cc",
"c++", CC)
269 log.fail(
"Unrecognised compiler:%s" % env[
'cc'])
270 env0 = SCons.Script.Environment()
271 if CC
and env[
'CC'] == env0[
'CC']:
273 if CC
and env[
'CXX'] == env0[
'CXX']:
275 conf = env.Configure(custom_tests = {
'ClassifyCc' : ClassifyCc,})
276 env.whichCc, env.ccVersion = conf.ClassifyCc()
277 log.info(
"CC is %s version %s" % (env.whichCc, env.ccVersion))
282 ARCHFLAGS = os.environ.get(
"ARCHFLAGS", env.get(
'archflags'))
284 env.Append(CCFLAGS = [ARCHFLAGS.split()])
285 env.Append(LINKFLAGS = [ARCHFLAGS.split()])
287 if env[
'profile'] ==
'1' or env[
'profile'] ==
"pg":
288 env.Append(CCFLAGS = [
'-pg'])
289 env.Append(LINKFLAGS = [
'-pg'])
290 elif env[
'profile'] ==
'gcov':
291 env.Append(CCFLAGS =
'--coverage')
292 env.Append(LINKFLAGS =
'--coverage')
297 if not (env.GetOption(
"clean")
or env.GetOption(
"help")
or env.GetOption(
"no_exec")):
298 log.info(
"Checking for C++11 support")
299 conf = env.Configure()
300 for cpp11Arg
in (
"-std=%s" % (val,)
for val
in (
"c++11",
"c++0x")):
301 conf.env = env.Clone()
302 conf.env.Append(CXXFLAGS = cpp11Arg)
304 env.Append(CXXFLAGS = cpp11Arg)
305 log.info(
"C++11 supported with %r" % (cpp11Arg,))
308 log.fail(
"C++11 extensions could not be enabled for compiler %r" % env.whichCc)
316 if not (env.GetOption(
"clean")
or env.GetOption(
"help")
or env.GetOption(
"no_exec")):
317 conf = env.Configure()
318 env.Append(CCFLAGS = [
'-DLSST_HAVE_TR1=%d' % int(conf.CheckCXXHeader(
"tr1/unordered_map"))])
324 if socket.htons(1) != 1:
325 env.Append(CCFLAGS = [
'-DLSST_LITTLE_ENDIAN=1'])
330 if (re.search(
r"^(Linux|Linux64)$", env[
"eupsFlavor"])
and os.environ.has_key(
"LD_LIBRARY_PATH")):
331 env.Append(LINKFLAGS = [
"-Wl,-rpath-link"])
332 env.Append(LINKFLAGS = [
"-Wl,%s" % os.environ[
"LD_LIBRARY_PATH"]])
337 env[
"CCFLAGS"] = [o
for o
in env[
"CCFLAGS"]
if not re.search(
r"^-O(\d|s)$", o)]
338 env.MergeFlags(
'-O%d' % int(env[
'opt']))
342 if env.whichCc ==
"clang":
343 env.Append(CCFLAGS = [
'-Wall'])
344 env[
"CCFLAGS"] = [o
for o
in env[
"CCFLAGS"]
if not re.search(
r"^-mno-fused-madd$", o)]
347 "unused-function" :
'boost::regex has functions in anon namespaces in headers',
350 "attributes" :
"clang pretends to be g++, but complains about g++ attributes such as flatten",
351 "char-subscripts" :
'seems innocous enough, and is used by boost',
352 "constant-logical-operand" :
"Used by eigen 2.0.15. Should get this fixed",
353 "format-security" :
"format string is not a string literal",
354 "mismatched-tags" :
"mixed class and struct. Used by gcc 4.2 RTL and eigen 2.0.15",
355 "parentheses" :
"equality comparison with extraneous parentheses",
356 "shorten-64-to-32" :
"implicit conversion loses integer precision",
357 "self-assign" :
"x = x",
358 "unknown-pragmas" :
"unknown pragma ignored",
359 "deprecated-register" :
"register is deprecated",
361 for k
in ignoreWarnings.keys():
362 env.Append(CCFLAGS = [
"-Wno-%s" % k])
363 if env.GetOption(
'filterWarn'):
364 for k
in filterWarnings.keys():
365 env.Append(CCFLAGS = [
"-Wno-%s" % k])
366 elif env.whichCc ==
"gcc":
367 env.Append(CCFLAGS = [
'-Wall'])
368 env.Append(CCFLAGS = [
"-Wno-unknown-pragmas"])
369 elif env.whichCc ==
"icc":
370 env.Append(CCFLAGS = [
'-Wall'])
372 21 :
'type qualifiers are meaningless in this declaration',
373 68 :
'integer conversion resulted in a change of sign',
374 111 :
'statement is unreachable',
375 191 :
'type qualifier is meaningless on cast type',
376 193 :
'zero used for undefined preprocessing identifier "SYMB"',
377 279 :
'controlling expression is constant',
378 304 :
'access control not specified ("public" by default)',
379 383 :
'value copied to temporary, reference to temporary used',
381 444 :
'destructor for base class "CLASS" is not virtual',
382 981 :
'operands are evaluated in unspecified order',
383 1418 :
'external function definition with no prior declaration',
384 1419 :
'external declaration in primary source file',
385 1572 :
'floating-point equality and inequality comparisons are unreliable',
386 1720 :
'function "FUNC" has no corresponding member operator delete (to be called if an exception is thrown during initialization of an allocated object)',
387 2259 :
'non-pointer conversion from "int" to "float" may lose significant bits',
389 if env.GetOption(
'filterWarn'):
390 env.Append(CCFLAGS = [
"-wd%s" % (
",".join([str(k)
for k
in filterWarnings.keys()]))])
392 env.Append(LINKFLAGS = [
"-Wl,-no_compact_unwind",
"-wd,11015"])
395 """Save state such as optimization level used. The scons mailing lists were unable to tell
396 RHL how to get this back from .sconsign.dblite
399 if env.GetOption(
"clean"):
404 config = ConfigParser.ConfigParser()
405 config.add_section(
'Build')
406 config.set(
'Build',
'cc', env.whichCc)
408 config.set(
'Build',
'opt', env[
'opt'])
411 confFile = os.path.join(env.Dir(env[
"CONFIGUREDIR"]).abspath,
"build.cfg")
412 with open(confFile,
'wb')
as configfile:
413 config.write(configfile)
415 log.warn(
"Unexpected exception in _saveState: %s" % e)
A dead-simple logger for all messages.