Advertisement
Guest User

Untitled

a guest
Jul 17th, 2014
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.05 KB | None | 0 0
  1. # preCICE/SConstruct
  2.  
  3. # Main buildfile for Linux based systems.
  4.  
  5. import os
  6.  
  7. ##################################################################### FUNCTIONS
  8.  
  9. def uniqueCheckLib(conf, lib):
  10.     """ Checks for a library and appends it to env if not already appended. """
  11.     if conf.CheckLib(lib, autoadd=0):
  12.         conf.env.AppendUnique(LIBS = [lib])
  13.         return True
  14.     else:
  15.         return False
  16.        
  17. def errorMissingLib(lib, usage):
  18.     print "ERROR: Library '" + lib + "' (needed for " + usage + ") not found!"
  19.     Exit(1)
  20.    
  21. def errorMissingHeader(header, usage):
  22.     print "ERROR: Header '" + header + "' (needed for " + usage + ") not found or does not compile!"
  23.     Exit(1)
  24.    
  25. def print_options(vars):
  26.     """ Print all build option and if they have been modified from their default value. """    
  27.     for opt in vars.options:
  28.         try:
  29.             is_default = vars.args[opt.key] == opt.default
  30.         except KeyError:
  31.             is_default = True
  32.         vprint(opt.key, env[opt.key], is_default, opt.help)
  33.  
  34. def vprint(name, value, default=True, description = None):
  35.     """ Pretty prints an environment variabe with value and modified or not. """
  36.     mod = "(default)" if default else "(modified)"
  37.     desc = "   " + description if description else ""
  38.     print "{:10} {:25} = {!s:6}{}".format(mod, name, value, desc)
  39.  
  40. def checkset_var(varname, default):
  41.     """ Checks if environment variable is set, use default otherwise and print the value. """    
  42.     var = os.getenv(varname)
  43.     if not var:
  44.         var = default
  45.         vprint(varname, var)
  46.     else:
  47.         vprint(varname, var, False)
  48.     return var
  49.  
  50. def compiler_validator(key, value, environment):
  51.     """ Validator function for the compiler option. Checks if the given compiler is either (g++ or icc or clang) or an MPI compiler. """
  52.     if value in ["g++", "icc", "clang"] or value.startswith("mpic"):
  53.         return True
  54.     else:
  55.         return False
  56.        
  57.  
  58. ########################################################################## MAIN
  59.    
  60. vars = Variables(None, ARGUMENTS)
  61.  
  62. vars.Add(PathVariable("builddir", "Directory holding build files.", "build", PathVariable.PathAccept))
  63. vars.Add(EnumVariable('build', 'Build type, either release or debug', "debug", allowed_values=('release', 'debug')))
  64. vars.Add("compiler", "Compiler must be either g++ or icc or clang or starting with mpic when using MPI.", "g++", validator=compiler_validator)
  65. vars.Add(BoolVariable("mpi", "Enables MPI-based communication and running coupling tests.", True))
  66. vars.Add(BoolVariable("sockets", "Enables Socket-based communication.", True))
  67. vars.Add(BoolVariable("boost_inst", "Enable if Boost is available compiled and installed.", False))
  68. vars.Add(BoolVariable("spirit2", "Used for parsing VRML file geometries and checkpointing.", True))
  69. vars.Add(BoolVariable("python", "Used for Python scripted solver actions.", True))
  70. vars.Add(BoolVariable("gprof", "Used in detailed performance analysis.", False))
  71.  
  72.  
  73. env = Environment(variables = vars)   # For configuring build variables
  74. conf = Configure(env) # For checking libraries, headers, ...
  75. env['ENV'] = os.environ
  76.  
  77. Help(vars.GenerateHelpText(env))
  78. env.Append(CPPPATH = ['#src'])
  79. # env.Append(CPPDEFINES = ['tarch=tarchp2']) # Was (!) needed for linking to Peano 1
  80.  
  81. # Produce position independent code for dynamic linking. makes a difference on the m68k, PowerPC and SPARC.
  82. env.Append(CCFLAGS = ['-fPIC'])
  83.  
  84.  
  85. #---------------------------------------------------------- Check build options
  86.  
  87. print
  88. print "Build options ..."
  89. print_options(vars)
  90.  
  91. buildpath = os.path.join(env["builddir"], "") # Ensures to have a trailing slash
  92.  
  93. if not env["mpi"] and env["compiler"].startswith('mpic'):
  94.     print "ERROR: Option 'compiler' must be set to an MPI compiler wrapper only when using MPI!"
  95.     Exit(1)
  96.      
  97. print '... done'
  98.  
  99.  
  100. #-------------------------------------------------- Fetch environment variables
  101.  
  102. print
  103. print 'Environment variables used for this build ...'
  104. print '(have to be defined by the user to configure build)'
  105.  
  106. boostRootPath = checkset_var('PRECICE_BOOST_ROOT', "./src")
  107.  
  108. if env["boost_inst"]:
  109.     if env["sockets"]:
  110.         boostLibPath = checkset_var('PRECICE_BOOST_LIB_PATH', "/usr/lib/")
  111.         boostSystemLib = checkset_var('PRECICE_BOOST_SYSTEM_LIB', "boost_system")
  112.         boostThreadLib = checkset_var('PRECICE_BOOST_THREAD_LIB', "boost_thread")
  113.  
  114.      
  115.    #boostIncPath = os.getenv('PRECICE_BOOST_INC_PATH')
  116.    #if ((boostIncPath == None) or (boostIncPath == "")):
  117.    #   boostIncPath = '/usr/include/'
  118.    #   print 'PRECICE_BOOST_INC_PATH = ' + boostIncPath + ' (default)'  
  119.    #else:
  120.    #   print 'PRECICE_BOOST_INC_PATH =', boostIncPath
  121.  
  122. if env["mpi"]:
  123.     mpiLibPath = checkset_var('PRECICE_MPI_LIB_PATH', "/usr/lib/")
  124.    
  125.     # Determine MPI library name
  126.     mpiLib = checkset_var('PRECICE_MPI_LIB', "mpich")
  127.     mpiIncPath = checkset_var('PRECICE_MPI_INC_PATH', '/usr/include/mpich2')
  128.    
  129.  
  130. if env["sockets"]:
  131.     socketLibPath = checkset_var('PRECICE_SOCKET_LIB_PATH', "/usr/lib")
  132.     socketLib = checkset_var('PRECICE_SOCKET_LIB', "pthread")
  133.     socketIncPath =  checkset_var('PRECICE_SOCKET_INC_PATH', '/usr/include')
  134.  
  135.  
  136. #useSAGA = ARGUMENTS.get('saga', 'off')
  137. #if useSAGA == 'off':
  138. #    cppdefines.append('PRECICE_NO_SAGA')
  139. #elif useSAGA == 'on':
  140. #    libs.append('saga_package_advert')
  141. #    libs.append('xyz')
  142. #    libpath.append('/opt/saga-1.5.4/lib/')
  143.  
  144.  
  145. if env["python"]:
  146.     pythonLibPath = checkset_var('PRECICE_PYTHON_LIB_PATH', '/usr/lib/')
  147.     pythonLib = checkset_var('PRECICE_PYTHON_LIB', "python2.7")
  148.     pythonIncPath = checkset_var('PRECICE_PYTHON_INC_PATH', '/usr/include/python2.7/')
  149.     numpyIncPath = checkset_var('PRECICE_NUMPY_INC_PATH',  '/usr/include/python2.7/numpy/')
  150.  
  151. print '... done'
  152.  
  153.  
  154. #---------------------------- Modify environment according to fetched variables
  155.  
  156. print
  157. print 'Configuring build variables ...'
  158.  
  159. env.Append(LIBPATH = [('#' + buildpath)])
  160.  
  161. env.Replace(CXX = env["compiler"])
  162.  
  163. if env["compiler"] == 'icc':
  164.     env.AppendUnique(LIBPATH = ['/usr/lib/'])
  165.     env.Append(LIBS = ['stdc++'])
  166.     if env["build"] == 'debug':
  167.         env.Append(CCFLAGS = ['-align'])
  168.     elif env["build"] == 'release':
  169.         env.Append(CCFLAGS = ['-w', '-fast', '-align', '-ansi-alias'])
  170. elif env["compiler"] == 'g++':
  171.     pass
  172. elif env["compiler"] == "clang":
  173.     # env.Append(CCFLAGS = ["-stdlib=libc++"])
  174.     # env.Append(CCFLAGS = ["-std=c++"])
  175.     env['ENV']['TERM'] = os.environ['TERM'] # colored compile messages from clang
  176.  
  177.  
  178.  
  179. if env["build"] == 'debug':
  180.     env.Append(CPPDEFINES = ['Debug', 'Asserts'])
  181.     env.Append(CCFLAGS = ['-g3', '-O0'])
  182.     buildpath += "debug"
  183. elif env["build"] == 'release':
  184.     env.Append(CCFLAGS = ['-O3'])
  185.     buildpath += "release"    
  186.  
  187.  
  188.  
  189. if env["boost_inst"]:
  190.     #env.AppendUnique(CPPPATH = [boostIncPath])
  191.     # The socket implementation is based on Boost libs
  192.     if env["sockets"]:
  193.         env.AppendUnique(LIBPATH = [boostLibPath])
  194.     if not uniqueCheckLib(conf, boostSystemLib):
  195.         errorMissingLib(boostSystemLib, 'Boost')
  196.     if not uniqueCheckLib(conf, boostThreadLib):
  197.         errorMissingLib(boostThreadLib, 'Boost')
  198. env.AppendUnique(CPPPATH = [boostRootPath])
  199. if not conf.CheckCXXHeader('boost/array.hpp'):
  200.     errorMissingHeader('boost/array.hpp', 'Boost')
  201.    
  202.    
  203. if not env["spirit2"]:
  204.     env.Append(CPPDEFINES = ['PRECICE_NO_SPIRIT2'])
  205.     env["buildpath"] += "-nospirit2"
  206.      
  207.  
  208. if env["mpi"]:
  209.     if not env["compiler"].startswith('mpic'):
  210.         env.AppendUnique(LIBPATH = [mpiLibPath])
  211.         if not uniqueCheckLib(conf, mpiLib):
  212.             errorMissingLib(mpiLib, 'MPI')
  213.         if (mpiLib == 'mpich'): # MPICH1/2/3 library
  214.             uniqueCheckLib(conf, 'mpl')
  215.             uniqueCheckLib(conf, 'pthread')
  216.             #conf.CheckLib('pthread')
  217.         elif (mpiLib == 'mpi'): # OpenMPI library
  218.             uniqueCheckLib(conf, 'mpi_cxx')  
  219.         env.AppendUnique(CPPPATH = [mpiIncPath])
  220.         if not conf.CheckHeader('mpi.h'):
  221.             errorMissingHeader('mpi.h', 'MPI')
  222. elif not env["mpi"]:
  223.     env.Append(CPPDEFINES = ['PRECICE_NO_MPI'])
  224.     buildpath += "-nompi"
  225. uniqueCheckLib(conf, 'rt') # To work with tarch::utils::Watch::clock_gettime
  226.  
  227.  
  228. if env["sockets"]:
  229.     env.AppendUnique(LIBPATH = [socketLibPath])
  230.     uniqueCheckLib(conf, socketLib)
  231.     env.AppendUnique(CPPPATH = [socketIncPath])
  232.     if socketLib == 'pthread':
  233.         if not conf.CheckHeader('pthread.h'):
  234.             errorMissingHeader('pthread.h', 'Sockets')
  235.     #env.Append(LINKFLAGS = ['-pthread']) # Maybe better???
  236. else:
  237.     env.Append(CPPDEFINES = ['PRECICE_NO_SOCKETS'])
  238.     buildpath += "-nosockets"
  239.  
  240. if env["python"]:
  241.     env.AppendUnique(LIBPATH = [pythonLibPath])
  242.     if not uniqueCheckLib(conf, pythonLib):
  243.         errorMissingLib(pythonLib, 'Python')
  244.     env.AppendUnique(CPPPATH = [pythonIncPath, numpyIncPath])
  245.     if not conf.CheckHeader('Python.h'):
  246.         errorMissingHeader('Python.h', 'Python')
  247.     # Check for numpy header needs python header first to compile
  248.     if not conf.CheckHeader(['Python.h', 'arrayobject.h']):
  249.         errorMissingHeader('arrayobject.h', 'Python NumPy')
  250. else:
  251.     buildpath += "-nopython"
  252.     env.Append(CPPDEFINES = ['PRECICE_NO_PYTHON'])
  253.  
  254.  
  255. if env["gprof"]:
  256.     env.Append(CCFLAGS = ['-p', '-pg'])
  257.     env.Append(LINKFLAGS = ['-p', '-pg'])
  258.     buildpath += "-gprof"
  259.  
  260. print '... done'
  261.  
  262. env = conf.Finish() # Used to check libraries
  263.  
  264. #--------------------------------------------- Define sources and build targets
  265.    
  266. (sourcesPreCICE, sourcesPreCICEMain) = SConscript (
  267.     'src/SConscript-linux',
  268.     variant_dir = buildpath,
  269.     duplicate = 0
  270. )
  271.  
  272. sourcesBoost = []
  273. if env["sockets"] and not env["boost_inst"]:
  274.     print
  275.     print "Copy boost sources for socket communication to build ..."
  276.     if not os.path.exists(buildpath + "/boost/"):
  277.         Execute(Mkdir(buildpath + "/boost/"))
  278.     for file in Glob(boostRootPath + "/libs/system/src/*"):
  279.         Execute(Copy(buildpath + "/boost/", file))  
  280.     for file in Glob(boostRootPath + "/libs/thread/src/pthread/*"):
  281.         Execute(Copy(buildpath + "/boost/", file))  
  282.     sourcesBoost = Glob(buildpath + '/boost/*.cpp')
  283.     print "... done"
  284.    
  285.  
  286. lib = env.StaticLibrary (
  287.     target = buildpath + '/libprecice',
  288.     source = [sourcesPreCICE,
  289.               sourcesBoost]
  290. )
  291.    
  292. bin = env.Program (
  293.     target = buildpath + '/binprecice',
  294.     source = [sourcesPreCICEMain,
  295.               sourcesBoost]
  296. )
  297.  
  298. Default(lib, bin)
  299. givenBuildTargets = map(str, BUILD_TARGETS)
  300. #print "Build targets before conversion:", buildtargets
  301. for i in range(len(givenBuildTargets)):
  302.     if givenBuildTargets[i] == "lib":
  303.         BUILD_TARGETS[i] = lib[0]
  304.     elif givenBuildTargets[i] == "bin":
  305.         BUILD_TARGETS[i] = bin[0]
  306.      
  307.  
  308. buildTargets = ""
  309. for target in map(str, BUILD_TARGETS):
  310.     if buildTargets != "":
  311.         buildTargets += ", "
  312.     buildTargets += target
  313.  
  314.  
  315. ##### Print build summary
  316.  
  317. print
  318. print "Targets:   " + buildTargets
  319. print "Buildpath: " + buildpath
  320. print
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement