mitsuba/build/SConscript.configure

337 lines
12 KiB
Plaintext
Raw Normal View History

2011-08-19 06:47:21 +08:00
import re, multiprocessing
2011-03-01 22:03:37 +08:00
2011-06-01 08:20:53 +08:00
Import('sys', 'os', 'SCons', 'resources')
AddOption("--cfg", dest="cfg", type="string", nargs=1, action='store', help='Manually specify a configuration file')
configFile = GetOption('cfg')
if configFile == None:
configFile = "config.py"
configFile = os.path.normpath(os.path.join(os.path.dirname(os.getcwd()), configFile))
2011-06-05 23:28:02 +08:00
print("Using configuation file \"%s\"" % configFile)
2011-03-01 22:03:37 +08:00
AddOption("--parallelize", dest="parallelize", action='store_true', help='Parallelize to the available number of cores?')
parallelize = GetOption('parallelize')
if parallelize == True:
SetOption('num_jobs', multiprocessing.cpu_count())
if not os.path.exists(configFile):
2011-08-15 10:55:20 +08:00
print '\nA configuration file must be selected! Have a look at http://www.mitsuba-renderer.org/docs.html'
Exit(1)
2011-08-15 10:55:20 +08:00
if not os.path.exists(GetBuildPath('#dependencies')):
print '\nThe build dependency files are missing -- please check them out'
print 'from Mercurial by running the following command *inside* the '
print 'Mitsuba directory:\n'
print '$ hg clone https://www.mitsuba-renderer.org/hg/dependencies\n'
Exit(1)
# Parse configuration options
vars = Variables(configFile)
2011-06-01 08:20:53 +08:00
vars.Add('BUILDDIR', 'Target directory for intermediate files')
vars.Add('DISTDIR', 'Target directory for the final build')
vars.Add('CXX', 'C++ compiler')
vars.Add('CC', 'C compiler')
vars.Add('CXXFLAGS', 'C++ flags')
2011-08-19 06:47:21 +08:00
vars.Add('SHCXXFLAGS', 'Extra C++ flags (for shared libraries)')
vars.Add('CCFLAGS', 'Extra C++ flags (for C files)')
vars.Add('LINK', 'Linker')
vars.Add('LINKFLAGS', 'Linker flags')
vars.Add('SHLINKFLAGS', 'Linker flags (dynamic libraries)')
vars.Add('BASEINCLUDE', 'Base include path')
vars.Add('BASELIB', 'Base libraries')
vars.Add('BASELIBDIR', 'Base library search path')
2011-08-13 14:49:58 +08:00
vars.Add('PYTHONINCLUDE', 'Python include path')
vars.Add('PYTHONLIB', 'Python libraries')
vars.Add('PYTHONLIBDIR', 'Python library path')
vars.Add('XERCESINCLUDE', 'Xerces-C include path')
vars.Add('XERCESLIB', 'Xerces-C libraries')
vars.Add('XERCESLIBDIR', 'Xerces-C library path')
vars.Add('OEXRINCLUDE', 'OpenEXR include path')
vars.Add('OEXRLIB', 'OpenEXR libraries')
vars.Add('OEXRFLAGS', 'OpenEXR-related compiler flags')
vars.Add('OEXRLIBDIR', 'OpenEXR library path')
vars.Add('PNGINCLUDE', 'libpng include path')
vars.Add('PNGLIB', 'libpng libraries')
vars.Add('PNGLIBDIR', 'libpng library path')
vars.Add('JPEGINCLUDE', 'libjpeg include path')
vars.Add('JPEGLIB', 'libjpeg libraries')
vars.Add('JPEGLIBDIR', 'libjpeg library path')
vars.Add('COLLADAINCLUDE','COLLADA DOM include path')
vars.Add('COLLADALIB', 'COLLADA DOM libraries')
vars.Add('COLLADALIBDIR', 'COLLADA DOM library path')
vars.Add('SHLIBPREFIX', 'Prefix for shared libraries')
vars.Add('SHLIBSUFFIX', 'Suffix for shared libraries')
vars.Add('PROGSUFFIX', 'Suffix for executables')
vars.Add('GLLIB', 'OpenGL+GLEW libraries')
vars.Add('GLINCLUDE', 'OpenGL+GLEW include path')
vars.Add('GLFLAGS', 'OpenGL+GLEW-related compiler flags')
vars.Add('GLLIBDIR', 'OpenGL+GLEW library path')
vars.Add('BOOSTINCLUDE', 'Boost include path')
vars.Add('BOOSTLIB', 'Boost libraries')
vars.Add('BOOSTLIBDIR', 'Boost library path')
vars.Add('TARGET_ARCH', 'Target architecture')
vars.Add('MSVC_VERSION', 'MS Visual C++ compiler version')
vars.Add('QTDIR', 'Qt installation directory')
2011-06-02 00:46:00 +08:00
vars.Add('INTEL_COMPILER','Should the Intel C++ compiler be used?')
try:
2011-06-02 00:32:55 +08:00
env = Environment(options=vars, ENV = os.environ, tools=['default', 'qt4', 'icl12'], toolpath=['#data/scons'])
print 'Checking for Qt 4.x... yes'
hasQt = True
except Exception:
2011-06-02 00:32:55 +08:00
env = Environment(options=vars, ENV = os.environ, tools=['default', 'icl12'], toolpath=['#data/scons'])
print 'Unable to detect a Qt installation -- not building the GUI!'
hasQt = False
hasCollada=True
2011-08-13 14:49:58 +08:00
hasPython = True
env.Append(CPPPATH=env['BASEINCLUDE'])
env.Append(CPPFLAGS=[])
env.Append(LIBPATH=[])
env.Append(LIBS=env['BASELIB'])
if env.has_key('BOOSTINCLUDE'):
env.Prepend(CPPPATH=env['BOOSTINCLUDE'])
if env.has_key('BOOSTLIBDIR'):
env.Prepend(LIBPATH=env['BOOSTLIBDIR'])
if env.has_key('BOOSTLIB'):
env.Prepend(LIBS=env['BOOSTLIB'])
if env.has_key('BASELIBDIR'):
env.Append(LIBPATH=env['BASELIBDIR'])
env.Decider('MD5-timestamp')
2011-03-01 22:03:37 +08:00
AddOption("--dist", dest="dist", action="store_true", help='Make an official release')
# Check whether everything important is available
def CheckCXX(context):
context.Message('Checking for ' + env['CXX'] + ' ...')
ret = context.TryLink("#include <sstream>\n int main(int argc, char **argv) {\n std::ostringstream oss;\n return 0;\n }", '.cpp')
context.Result(ret)
return ret
conf = Configure(env, custom_tests = { 'CheckCXX' : CheckCXX })
cppPathPrevious = SCons.Util.semi_deepcopy(env['CPPPATH'])
libPathPrevious = SCons.Util.semi_deepcopy(env['LIBPATH'])
cppFlagsPrevious = SCons.Util.semi_deepcopy(env['CPPFLAGS'])
cxxFlagsPrevious = SCons.Util.semi_deepcopy(env['CXXFLAGS'])
if env.has_key('PNGINCLUDE'):
env.Prepend(CPPPATH=env['PNGINCLUDE'])
if env.has_key('PNGLIBDIR'):
env.Prepend(LIBPATH=env['PNGLIBDIR'])
if env.has_key('JPEGINCLUDE'):
env.Prepend(CPPPATH=env['JPEGINCLUDE'])
if env.has_key('JPEGLIBDIR'):
env.Prepend(LIBPATH=env['JPEGLIBDIR'])
if env.has_key('OEXRFLAGS'):
env.Prepend(CPPFLAGS=env['OEXRFLAGS'])
if env.has_key('OEXRINCLUDE'):
env.Prepend(CPPPATH=env['OEXRINCLUDE'])
if env.has_key('OEXRLIBDIR'):
env.Prepend(LIBPATH=env['OEXRLIBDIR'])
if env.has_key('XERCESINCLUDE'):
env.Prepend(CPPPATH=env['XERCESINCLUDE'])
if env.has_key('XERCESLIBDIR'):
env.Prepend(LIBPATH=env['XERCESLIBDIR'])
if env.has_key('GLINCLUDE'):
env.Prepend(CPPPATH=env['GLINCLUDE'])
if env.has_key('GLFLAGS'):
env.Prepend(CPPFLAGS=env['GLFLAGS'])
if env.has_key('COLLADAINCLUDE'):
env.Prepend(CPPPATH=env['COLLADAINCLUDE'])
if env.has_key('COLLADALIBDIR'):
env.Prepend(LIBPATH=env['COLLADALIBDIR'])
2011-08-13 14:49:58 +08:00
if env.has_key('PYTHONINCLUDE'):
env.Prepend(CPPPATH=env['PYTHONINCLUDE'])
if not conf.CheckCXX():
print 'Could not compile a simple C++ fragment, verify that ' + \
env['CXX'] + ' is installed! This could also mean that the ' + \
'Boost libraries are missing. The file "config.log" should ' + \
'contain more information.'
Exit(1)
if not conf.CheckCHeader(['png.h']):
print 'libpng is missing (install libpng12-dev)'
Exit(1)
if not conf.CheckCHeader(['stdio.h', 'jpeglib.h']):
print 'libjpeg is missing (install libjpeg62-dev)'
Exit(1)
if not conf.CheckCXXHeader('ImfRgba.h'):
print 'OpenEXR is missing (install libopenexr-dev)'
Exit(1)
if not conf.CheckCXXHeader('xercesc/dom/DOMLSParser.hpp'):
print 'Xerces-C++ 3.x must be installed (install libxerces-c-dev)!'
Exit(1)
if not conf.CheckCXXHeader('dae.h'):
hasCollada = False
print 'COLLADA DOM is missing: not building the COLLADA importer'
2011-08-13 14:49:58 +08:00
if not conf.CheckCXXHeader('pyconfig.h'):
hasPython = False
print 'Python is missing: not building the python support library'
if not conf.CheckCXXHeader('boost/math/distributions/students_t.hpp'):
print 'Boost is missing (install libboost-dev)!'
Exit(1)
if sys.platform == 'win32':
if not (conf.CheckCHeader(['windows.h', 'GL/gl.h']) \
and conf.CheckCHeader(['windows.h', 'GL/glu.h']) \
and conf.CheckCHeader(['windows.h', 'GL/gl.h', 'GL/glext.h'])):
print 'OpenGL headers are missing!'
Exit(1)
if not conf.CheckCHeader('GL/glew.h'):
print 'GLEW headers are missing!'
Exit(1)
elif sys.platform == 'linux2':
if not (conf.CheckCHeader('GL/gl.h') and conf.CheckCHeader('GL/glu.h') and conf.CheckCHeader(['GL/gl.h', 'GL/glext.h'])):
print 'OpenGL headers are missing!'
Exit(1)
if not conf.CheckCHeader('GL/glew.h'):
print 'GLEW headers are missing (install libglewmx1.5-dev)!'
Exit(1)
if not conf.CheckType('GLEWContext', '#include <GL/glew.h>'):
print 'GLEW-MX must be present!'
Exit(1)
if not conf.TryCompile("#include <GL/glew.h>\n int i = GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV;", '.cpp'):
print 'Your version of GLEW-MX seems to be outdated!'
Exit(1)
elif sys.platform == 'darwin':
if not (conf.CheckCHeader('OpenGL/gl.h') and conf.CheckCHeader('OpenGL/glu.h') and conf.CheckCHeader(['OpenGL/gl.h', 'OpenGL/glext.h'])):
print 'OpenGL headers are missing!'
Exit(1)
if not conf.CheckCHeader('OpenGL/glew.h'):
print 'GLEW headers are missing!'
Exit(1)
if sys.platform == 'linux2':
if not (conf.CheckCHeader(['X11/Xlib.h', 'X11/extensions/xf86vmode.h'])):
print 'X Video Mode selection library headers are missing! (Install libxxf86vm-dev)'
Exit(1)
env.Replace(CPPPATH=cppPathPrevious)
env.Replace(LIBPATH=libPathPrevious)
env.Replace(CPPFLAGS=cppFlagsPrevious)
env.Replace(CXXFLAGS=cxxFlagsPrevious)
sys.stdout.write("Checking for Mitsuba version .. ")
file = open(env.GetBuildPath('#include/mitsuba/core/version.h'), 'r')
MTS_VERSION=""
for line in file:
if line.startswith("#define MTS_VERSION "):
MTS_VERSION = line[21:len(line)-2]
if MTS_VERSION == "":
print 'could not be determined!'
Exit(1)
else:
print MTS_VERSION
Export('MTS_VERSION')
2011-08-15 10:55:20 +08:00
versionFilename = GetBuildPath('#dependencies/version')
versionMismatch = False
if not os.path.exists(versionFilename):
versionMismatch = True
depVersion = "<unknown>"
else:
with open(versionFilename) as f:
depVersion = f.readline().strip()
if MTS_VERSION != depVersion:
versionMismatch = True
if versionMismatch:
print '\nThe dependency directory and your Mitsuba codebase have different version'
print 'numbers! Your copy of Mitsuba has version %s, whereas the dependencies ' % MTS_VERSION
print 'have version %s. Please bring them into sync, either by running\n' % depVersion
print '$ hg update -r v%s\n' % depVersion
print 'in the Mitsuba directory, or by running\n'
print '$ cd dependencies'
2011-08-15 10:57:53 +08:00
print '$ hg pull'
print '$ hg update -r v%s\n' % MTS_VERSION
Exit(1)
env = conf.Finish()
2011-06-01 08:20:53 +08:00
dist = GetOption('dist') != None
Export('dist')
def osxlibinst_build_function(self, target, source, pkgname = None, use_own = None):
inst = self.Install(target, source)
prefix, name = os.path.split(source)
self.AddPostAction(inst, 'install_name_tool -id @loader_path/../Frameworks/' + name + ' $TARGET')
return inst
def osxlibinst_as_build_function(self, target, source, pkgname = None, use_own = None):
inst = self.InstallAs(target, source)
prefix, name = os.path.split(source)
self.AddPostAction(inst, 'install_name_tool -id @loader_path/../Frameworks/' + name + ' $TARGET')
return inst
2011-08-19 06:47:21 +08:00
def remove_flag(env, flag):
2011-08-16 14:18:38 +08:00
try:
2011-08-19 06:47:21 +08:00
env['CXXFLAGS'].remove(flag)
2011-08-17 02:17:11 +08:00
return True
2011-08-16 14:18:38 +08:00
except:
2011-08-17 02:17:11 +08:00
return False
2011-08-16 14:18:38 +08:00
2011-08-19 06:47:21 +08:00
def remove_flags(env, patterns):
new_cxxflags = []
for flag in env['CXXFLAGS']:
found = False
for pattern in patterns:
if re.search(pattern, flag):
found = True
break
if not found:
new_cxxflags.append(flag)
env['CXXFLAGS'] = new_cxxflags
2011-08-16 14:18:38 +08:00
def append_flag(env, value):
env['CXXFLAGS'].append(value)
env.__class__.RemoveFlag = remove_flag
2011-08-19 06:47:21 +08:00
env.__class__.RemoveFlags = remove_flags
2011-08-16 14:18:38 +08:00
env.__class__.AppendFlag = append_flag
env.__class__.OSXLibInst = osxlibinst_build_function
env.__class__.OSXLibInstAs = osxlibinst_as_build_function
2011-08-17 02:17:11 +08:00
def configure_for_objective_cpp(env):
2011-08-19 06:47:21 +08:00
# The OSX Objective C++ compiler does not permit the following flags
env.RemoveFlags(['-fstrict-aliasing', '-ftree-vectorize',
'-std=c\+\+0x'])
# Remove Intel compiler-specific optimization flags
env.RemoveFlags(['-x.*', '-ax.*', '-ipo', '-no-prec-div',
'-fp-model', 'fast=.*', '-wd.*', '-openmp'])
2011-08-16 14:18:38 +08:00
env.AppendFlag('-fno-strict-aliasing')
2011-08-19 06:47:21 +08:00
env.AppendFlag('-fopenmp')
# Enforce GCC usage (Intel compiler doesn't handle Objective C/C++)
env['CXX'] = 'g++'
env['CC'] = 'gcc'
2011-08-16 14:18:38 +08:00
2011-08-17 02:17:11 +08:00
def relax_compiler_settings(env):
# Relax the compiler settings when compiling heavy templated code
# (e.g. Boost::Spirit parsers, etc., which don't necessarily have
# to be that fast)
2011-08-19 06:47:21 +08:00
env.RemoveFlags(['-g', '/Z7', '-ipo', '/GL'])
2011-08-17 02:17:11 +08:00
if env.RemoveFlag('-O3'):
env.AppendFlag('-O1')
if env.RemoveFlag('/O2'):
env.AppendFlag('/O1')
env.__class__.ConfigureForObjectiveCPP = configure_for_objective_cpp
env.__class__.RelaxCompilerSettings = relax_compiler_settings
2011-08-16 14:18:38 +08:00
if hasCollada:
env.Append(CPPDEFINES = [['MTS_HAS_COLLADA', 1]] )
env.SConsignFile()
# MSVC: Embed the manifest into libraries and executables
if sys.platform == 'win32':
env['LINKCOM'] = [env['LINKCOM'], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1']
env['SHLINKCOM'] = [env['SHLINKCOM'], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2']
env.Export('hasQt', 'hasCollada', 'hasPython', 'resources')
Return('env')