Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added scons build scripts.

  • Loading branch information...
commit 75d7795aacaddcafb05f7126c7ba34474b806d26 1 parent 46442f4
George Sudarkoff authored
420 SConstruct
View
@@ -0,0 +1,420 @@
+# -*- mode: python; -*-
+# build file for Domus
+# requires scons: http://www.scons.org
+# type 'scons' to build
+
+# This file, SConstruct, configures the build environment, and then delegates
+# to several, subordinate SConscript files, which describe specific build
+# rules.
+
+EnsureSConsVersion( 1, 1, 0 )
+
+import os
+import sys
+import types
+from buildscripts import utils
+
+import libdeps
+
+# --- options ----
+
+options = {}
+
+def add_option( name, help , nargs , contibutesToVariantDir , dest=None ):
+
+ if dest is None:
+ dest = name
+
+ AddOption( "--" + name ,
+ dest=dest,
+ type="string",
+ nargs=nargs,
+ action="store",
+ help=help )
+
+ options[name] = { "help" : help ,
+ "nargs" : nargs ,
+ "contibutesToVariantDir" : contibutesToVariantDir ,
+ "dest" : dest }
+
+def get_option( name ):
+ return GetOption( name )
+
+def has_option( name ):
+ x = get_option( name )
+ if x is None:
+ return False
+
+ if x == False:
+ return False
+
+ if x == "":
+ return False
+
+ return True
+
+
+def get_variant_dir():
+
+ a = []
+
+ for name in options:
+ o = options[name]
+ if not has_option( o["dest"] ):
+ continue
+ if not o["contibutesToVariantDir"]:
+ continue
+
+ if o["nargs"] == 0:
+ a.append( name )
+ else:
+ x = get_option( name )
+ x = re.sub( "[,\\\\/]" , "_" , x )
+ a.append( name + "_" + x )
+
+ s = "#build/${PYSYSPLATFORM}/"
+
+ if len(a) > 0:
+ a.sort()
+ s += "/".join( a ) + "/"
+ else:
+ s += "normal/"
+ return s
+
+# linking options
+add_option( "release" , "release build" , 0 , True )
+add_option( "static" , "fully static build" , 0 , True )
+
+# base compile flags
+add_option( "64" , "force 64 bit" , 0 , True , "force64" )
+add_option( "32" , "force 32 bit" , 0 , True , "force32" )
+
+add_option( "cpppath", "Include path if you have headers in a nonstandard directory" , 1 , True )
+add_option( "libpath", "Library path if you have libraries in a nonstandard directory" , 1 , True )
+
+# dev options
+add_option( "d", "debug build no optimization, etc..." , 0 , True , "debugBuild" )
+
+add_option( "use-system-boost", "use system version of boost libraries", 0, True )
+add_option( "use-system-all" , "use all system libraries", 0 , True )
+
+# don't run configure if user calls --help
+if GetOption('help'):
+ Return()
+
+# --- environment setup ---
+
+variantDir = get_variant_dir()
+
+def print_local_info():
+ import sys, SCons
+ print( "scons version: " + SCons.__version__ )
+ print( "python version: " + " ".join( [ `i` for i in sys.version_info ] ) )
+
+print_local_info()
+
+boostLibs = [ "program_options" ]
+
+nix = False
+linux = False
+linux64 = False
+darwin = False
+force32 = has_option( "force32" )
+force64 = has_option( "force64" )
+if not force64 and not force32 and os.getcwd().endswith( "domus-64" ):
+ force64 = True
+ print( "*** assuming you want a 64-bit build b/c of directory *** " )
+
+release = has_option( "release" )
+static = has_option( "static" )
+
+debugBuild = has_option( "debugBuild" )
+
+env = Environment( BUILD_DIR=variantDir,
+ tools=["default"],
+ PYSYSPLATFORM=os.sys.platform,
+ )
+
+
+libdeps.setup_environment( env )
+
+extraLibPlaces = []
+
+env['EXTRACPPPATH'] = []
+env['EXTRALIBPATH'] = []
+
+def add_extra_libs( s ):
+ for x in s.split(","):
+ env.Append( EXTRACPPPATH=[ x + "/include" ] )
+ env.Append( EXTRALIBPATH=[ x + "/lib" ] )
+ env.Append( EXTRALIBPATH=[ x + "/lib64" ] )
+ extraLibPlaces.append( x + "/lib" )
+
+# ---- other build setup -----
+
+platform = os.sys.platform
+if "uname" in dir(os):
+ processor = os.uname()[4]
+else:
+ processor = "i386"
+
+if force32:
+ processor = "i386"
+if force64:
+ processor = "x86_64"
+
+env['PROCESSOR_ARCHITECTURE'] = processor
+
+def filter_exists(paths):
+ return filter(os.path.exists, paths)
+
+if "darwin" == os.sys.platform:
+ darwin = True
+ platform = "osx" # prettier than darwin
+
+ if env["CXX"] is None:
+ print( "YO" )
+ if os.path.exists( "/usr/bin/g++-4.2" ):
+ env["CXX"] = "g++-4.2"
+
+ nix = True
+
+ if force64:
+ env.Append( EXTRACPPPATH=["/usr/64/include"] )
+ env.Append( EXTRALIBPATH=["/usr/64/lib"] )
+ if installDir == DEFAULT_INSTALL_DIR and not distBuild:
+ installDir = "/usr/64/"
+ else:
+ env.Append( EXTRACPPPATH=filter_exists(["/sw/include" , "/opt/local/include"]) )
+ env.Append( EXTRALIBPATH=filter_exists(["/sw/lib/", "/opt/local/lib"]) )
+
+elif os.sys.platform.startswith("linux"):
+ linux = True
+ platform = "linux"
+
+ env.Append( LIBS=['m'] )
+
+ if os.uname()[4] == "x86_64" and not force32:
+ linux64 = True
+ nixLibPrefix = "lib64"
+ env.Append( EXTRALIBPATH=["/usr/lib64" , "/lib64" ] )
+ env.Append( LIBS=["pthread"] )
+
+ force64 = False
+
+ if force32:
+ env.Append( EXTRALIBPATH=["/usr/lib32"] )
+
+ nix = True
+
+ if static:
+ env.Append( LINKFLAGS=" -static " )
+
+else:
+ print( "No special config for [" + os.sys.platform + "] which probably means it won't work" )
+
+env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+if nix:
+ # -Winvalid-pch Warn if a precompiled header (see Precompiled Headers) is found in the search path but can't be used.
+ env.Append( CPPFLAGS="-fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch" )
+
+ if linux:
+ env.Append( CPPFLAGS=" -Werror -pipe " )
+ if not has_option('clang'):
+ env.Append( CPPFLAGS=" -fno-builtin-memcmp " ) # glibc's memcmp is faster than gcc's
+
+ env.Append( CPPDEFINES="_FILE_OFFSET_BITS=64" )
+ env.Append( CXXFLAGS=" -Wnon-virtual-dtor -Woverloaded-virtual" )
+ env.Append( LINKFLAGS=" -fPIC -pthread -rdynamic" )
+ env.Append( LIBS=[] )
+
+ #make scons colorgcc friendly
+ env['ENV']['HOME'] = os.environ['HOME']
+ try:
+ env['ENV']['TERM'] = os.environ['TERM']
+ except KeyError:
+ pass
+
+ if debugBuild:
+ env.Append( CPPFLAGS=" -O0 -fstack-protector " );
+ env['ENV']['GLIBCXX_FORCE_NEW'] = 1; # play nice with valgrind
+ else:
+ env.Append( CPPFLAGS=" -O3 " )
+ #env.Append( CPPFLAGS=" -fprofile-generate" )
+ #env.Append( LINKFLAGS=" -fprofile-generate" )
+ # then:
+ #env.Append( CPPFLAGS=" -fprofile-use" )
+ #env.Append( LINKFLAGS=" -fprofile-use" )
+
+ if force64:
+ env.Append( CFLAGS="-m64" )
+ env.Append( CXXFLAGS="-m64" )
+ env.Append( LINKFLAGS="-m64" )
+
+ if force32:
+ env.Append( CFLAGS="-m32" )
+ env.Append( CXXFLAGS="-m32" )
+ env.Append( LINKFLAGS="-m32" )
+
+try:
+ umask = os.umask(022)
+except OSError:
+ pass
+
+commonFiles = []
+serverOnlyFiles = []
+
+env['DOMUS_COMMON_FILES'] = commonFiles
+env['DOMUS_SERVER_ONLY_FILES' ] = serverOnlyFiles
+
+env.Append( CPPPATH=['$EXTRACPPPATH'],
+ LIBPATH=['$EXTRALIBPATH'] )
+
+# --- check system ---
+
+def getSysInfo():
+ return " ".join( os.uname() )
+
+def do_configure( myenv , shell=False ):
+ conf = Configure(myenv)
+ myenv["LINKFLAGS_CLEAN"] = list( myenv["LINKFLAGS"] )
+ myenv["LIBS_CLEAN"] = list( myenv["LIBS"] )
+
+ if 'CheckCXX' in dir( conf ):
+ if not conf.CheckCXX():
+ print( "c++ compiler not installed!" )
+ Exit(1)
+
+ if nix and not shell:
+ if not conf.CheckLib( "stdc++" ):
+ print( "can't find stdc++ library which is needed" );
+ Exit(1)
+
+ def my_check_lib( poss , failIfNotFound=False , staticOnly=False):
+
+ if type( poss ) != types.ListType :
+ poss = [poss]
+
+ allPlaces = [];
+ allPlaces += extraLibPlaces
+ if nix and release:
+ allPlaces += myenv.subst( myenv["LIBPATH"] )
+ if not force64:
+ allPlaces += [ "/usr/lib" , "/usr/local/lib" ]
+
+ for p in poss:
+ for loc in allPlaces:
+ fullPath = loc + "/lib" + p + ".a"
+ if os.path.exists( fullPath ):
+ myenv.Append( _LIBFLAGS='${SLIBS}',
+ SLIBS=" " + fullPath + " " )
+ return True
+
+ if release and failIfNotFound:
+ print( "ERROR: can't find static version of: " + str( poss ) + " in: " + str( allPlaces ) )
+ Exit(1)
+
+ res = not staticOnly and conf.CheckLib( poss )
+ if res:
+ return True
+
+ if failIfNotFound:
+ print( "can't find or link against library " + str( poss ) + " in " + str( myenv["LIBPATH"] ) )
+ print( "see config.log for more information" )
+ Exit(1)
+
+ return False
+
+ if has_option('use-system-all') or has_option('use-system-boost'):
+ if not conf.CheckCXXHeader( "boost/filesystem/operations.hpp" ):
+ print( "can't find boost headers" )
+ Exit(1)
+
+ # this will add it if it exists and works
+ my_check_lib( [ "boost_system-mt", "boost_system" ] )
+
+ for b in boostLibs:
+ l = "boost_" + b
+ my_check_lib( [ l + "-mt" , l ] , release or not shell)
+
+ if not conf.CheckCXXHeader( "execinfo.h" ):
+ myenv.Append( CPPDEFINES=[ "NOEXECINFO" ] )
+
+ return conf.Finish()
+
+env = do_configure( env )
+
+# ---- Docs ----
+def build_docs(env, target, source):
+ """Generate documentation.
+ """
+ from buildscripts import docs
+ docs.main()
+
+env.Alias("docs", [], [build_docs])
+env.AlwaysBuild("docs")
+
+# ---- astyle ----
+def astyle( env , target , source ):
+ """Re-formatt the source code
+ """
+ res = utils.execsys( "astyle --version" )
+ res = " ".join(res)
+ if res.count( "2." ) == 0:
+ print( "astyle 2.x needed, found:" + res )
+ Exit(-1)
+
+ files = utils.getAllSourceFiles()
+ files = filter( lambda x: not x.endswith( ".c" ) , files )
+
+ cmd = "astyle --options=domus_astyle " + " ".join( files )
+ res = utils.execsys( cmd )
+ print( res[0] )
+ print( res[1] )
+
+env.Alias( "style" , [] , [ astyle ] )
+env.AlwaysBuild( "style" )
+
+# ---- CONVENIENCE ----
+
+def tabs( env, target, source ):
+ """Check for TABS in C++ source files
+ """
+ from subprocess import Popen, PIPE
+ from re import search, match
+ diff = Popen( [ "git", "diff", "-U0", "origin/master", "master" ], stdout=PIPE ).communicate()[ 0 ]
+ sourceFile = False
+ for line in diff.split( "\n" ):
+ if match( "diff --git", line ):
+ sourceFile = not not search( "\.(h|hpp|c|cpp)\s*$", line )
+ if sourceFile and match( "\+ *\t", line ):
+ return True # TODO: Return a proper error message ("TAB in %s" % line)
+ return False
+
+env.Alias( "checkSource", [], [ tabs ] )
+env.AlwaysBuild( "checkSource" )
+
+def git_push( env, target, source ):
+ """Push to the tracking remote branch.
+ """
+ import subprocess
+ return subprocess.call( [ "git", "push" ] )
+
+# TODO: Add running smoke tests here
+env.Alias( "push", [ ".", "checkSource" ], git_push )
+env.AlwaysBuild( "push" )
+
+# The following symbols are exported for use in subordinate SConscript files.
+# Ideally, the SConscript files would be purely declarative. They would only
+# import build environment objects, and would contain few or no conditional
+# statements or branches.
+#
+# Currently, however, the SConscript files do need some predicates for
+# conditional decision making that hasn't been moved up to this SConstruct file,
+# and they are exported here, as well.
+Export("env")
+Export("has_option")
+Export("getSysInfo")
+Export("darwin linux nix")
+
+env.SConscript( 'src/SConscript', variant_dir=variantDir, duplicate=False )
0  buildscripts/__init__.py
View
No changes.
70 buildscripts/docs.py
View
@@ -0,0 +1,70 @@
+"""
+Build docs.
+"""
+
+import os
+import shutil
+import subprocess
+
+import markdown
+
+
+def clean_dir(dir):
+ try:
+ shutil.rmtree(dir)
+ except:
+ pass
+ os.makedirs(dir)
+
+
+def convert_dir(source, dest):
+ """
+ Convert markdown files to html.
+ """
+
+ clean_dir(dest)
+
+ for x in os.listdir(source + "/"):
+ if not x.endswith(".md"):
+ continue
+
+ with open("%s/%s" % (source, x)) as f:
+ raw = f.read()
+
+ html = markdown.markdown(raw)
+ print(x)
+
+ with open("%s/%s" % (dest, x.replace(".md", ".html")), 'w') as o:
+ o.write(html)
+
+
+def gen_cplusplus(dir):
+ clean_dir(dir)
+ clean_dir("docs/doxygen")
+
+ # Silence the noisy Doxygen...
+ with open("/dev/null") as null:
+ subprocess.call(["doxygen", "doxygenConfig"], stdout=null, stderr=null)
+
+ os.rename("docs/doxygen/html", dir)
+
+
+def version():
+ """Get the server version from doxygenConfig.
+ """
+ with open("doxygenConfig") as f:
+ for line in f.readlines():
+ if line.startswith("PROJECT_NUMBER"):
+ return line.split("=")[1].strip()
+
+
+def main():
+ v = version()
+ print("Generating server docs in docs/internal/%s" % v)
+ convert_dir("docs", "docs/internal/%s" % v)
+ print("Generating C++ docs in docs/cplusplus/%s" % v)
+ gen_cplusplus("docs/cplusplus/%s" % v)
+
+
+if __name__ == "__main__":
+ main()
155 buildscripts/utils.py
View
@@ -0,0 +1,155 @@
+
+import re
+import socket
+import time
+import os
+import os.path
+import itertools
+import subprocess
+import sys
+# various utilities that are handy
+
+def getAllSourceFiles( arr=None , prefix="." ):
+ if arr is None:
+ arr = []
+
+ for x in os.listdir( prefix ):
+ if x.startswith( "." ) or x.startswith( "pcre-" ) or x.startswith( "32bit" ) or x.startswith( "mongodb-" ) or x.startswith("debian") or x.startswith( "mongo-cxx-driver" ):
+ continue
+ full = prefix + "/" + x
+ if os.path.isdir( full ) and not os.path.islink( full ):
+ getAllSourceFiles( arr , full )
+ else:
+ if full.endswith( ".cpp" ) or full.endswith( ".hpp" ) or full.endswith( ".h" ) or full.endswith( ".c" ):
+ arr.append( full )
+
+ return arr
+
+
+def getGitBranch():
+ if not os.path.exists( ".git" ):
+ return None
+
+ version = open( ".git/HEAD" ,'r' ).read().strip()
+ if not version.startswith( "ref: " ):
+ return version
+ version = version.split( "/" )
+ version = version[len(version)-1]
+ return version
+
+def getGitBranchString( prefix="" , postfix="" ):
+ t = re.compile( '[/\\\]' ).split( os.getcwd() )
+ if len(t) > 2 and t[len(t)-1] == "mongo":
+ par = t[len(t)-2]
+ m = re.compile( ".*_([vV]\d+\.\d+)$" ).match( par )
+ if m is not None:
+ return prefix + m.group(1).lower() + postfix
+ if par.find("Nightly") > 0:
+ return ""
+
+ b = getGitBranch()
+ if b == None or b == "master":
+ return ""
+ return prefix + b + postfix
+
+def getGitVersion():
+ if not os.path.exists( ".git" ):
+ return "nogitversion"
+
+ version = open( ".git/HEAD" ,'r' ).read().strip()
+ if not version.startswith( "ref: " ):
+ return version
+ version = version[5:]
+ f = ".git/" + version
+ if not os.path.exists( f ):
+ return version
+ return open( f , 'r' ).read().strip()
+
+def execsys( args ):
+ import subprocess
+ if isinstance( args , str ):
+ r = re.compile( "\s+" )
+ args = r.split( args )
+ p = subprocess.Popen( args , stdout=subprocess.PIPE , stderr=subprocess.PIPE )
+ r = p.communicate()
+ return r;
+
+def getprocesslist():
+ raw = ""
+ try:
+ raw = execsys( "/bin/ps -ax" )[0]
+ except Exception,e:
+ print( "can't get processlist: " + str( e ) )
+
+ r = re.compile( "[\r\n]+" )
+ return r.split( raw )
+
+def removeIfInList( lst , thing ):
+ if thing in lst:
+ lst.remove( thing )
+
+def findVersion( root , choices ):
+ for c in choices:
+ if ( os.path.exists( root + c ) ):
+ return root + c
+ raise "can't find a version of [" + root + "] choices: " + choices
+
+def choosePathExist( choices , default=None):
+ for c in choices:
+ if c != None and os.path.exists( c ):
+ return c
+ return default
+
+def filterExists(paths):
+ return filter(os.path.exists, paths)
+
+def ensureDir( name ):
+ d = os.path.dirname( name )
+ if not os.path.exists( d ):
+ print( "Creating dir: " + name );
+ os.makedirs( d )
+ if not os.path.exists( d ):
+ raise "Failed to create dir: " + name
+
+def distinctAsString( arr ):
+ s = set()
+ for x in arr:
+ s.add( str(x) )
+ return list(s)
+
+def which(executable):
+ if sys.platform == 'win32':
+ paths = os.environ.get('Path', '').split(';')
+ else:
+ paths = os.environ.get('PATH', '').split(':')
+
+ for path in paths:
+ path = os.path.expandvars(path)
+ path = os.path.expanduser(path)
+ path = os.path.abspath(path)
+ executable_path = os.path.join(path, executable)
+ if os.path.exists(executable_path):
+ return executable_path
+
+ return executable
+
+def find_python(min_version=(2, 5)):
+ # if this script is being run by py2.5 or greater,
+ # then we assume that "python" points to a 2.5 or
+ # greater python VM. otherwise, explicitly use 2.5
+ # which we assume to be installed.
+ version = re.compile(r'[Pp]ython ([\d\.]+)', re.MULTILINE)
+ binaries = ('python27', 'python2.7', 'python26', 'python2.6', 'python25', 'python2.5', 'python')
+ for binary in binaries:
+ try:
+ out, err = subprocess.Popen([binary, '-V'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ for stream in (out, err):
+ match = version.search(stream)
+ if match:
+ versiontuple = tuple(map(int, match.group(1).split('.')))
+ if versiontuple >= (2, 5):
+ return which(binary)
+ except:
+ pass
+
+ raise Exception('could not find suitable Python (version >= %s)' % '.'.join(min_version))
213 site_scons/libdeps.py
View
@@ -0,0 +1,213 @@
+"""Extension to SCons providing advanced static library dependency tracking.
+
+These modifications to a build environment, which can be attached to
+StaticLibrary and Program builders via a call to setup_environment(env),
+cause the build system to track library dependencies through static libraries,
+and to add them to the link command executed when building programs.
+
+For example, consider a program 'try' that depends on a lib 'tc', which in
+turn uses a symbol from a lib 'tb' which in turn uses a library from 'ta'.
+Without this package, the Program declaration for "try" looks like this:
+
+Program('try', ['try.c', 'path/to/${LIBPREFIX}tc${LIBSUFFIX}',
+ 'path/to/${LIBPREFIX}tc${LIBSUFFIX}',
+ 'path/to/${LIBPREFIX}tc${LIBSUFFIX}',])
+
+With this library, we can instead write the following
+
+Program('try', ['try.c'], LIBDEPS=['path/to/tc'])
+StaticLibrary('tc', ['c.c'], LIBDEPS=['path/to/tb'])
+StaticLibrary('tb', ['b.c'], LIBDEPS=['path/to/ta'])
+StaticLibrary('ta', ['a.c'])
+
+And the build system will figure out that it needs to link libta.a and libtb.a
+when building 'try'.
+"""
+
+# Copyright (c) 2010, Corensic Inc., All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import os
+
+import SCons.Errors
+import SCons.Scanner
+import SCons.Util
+
+class DependencyCycleError(SCons.Errors.UserError):
+ """Exception representing a cycle discovered in library dependencies."""
+
+ def __init__(self, first_node ):
+ super(DependencyCycleError, self).__init__()
+ self.cycle_nodes = [first_node]
+
+ def __str__(self):
+ return " => ".join(str(n) for n in self.cycle_nodes)
+
+def __get_libdeps(node, env_var):
+ """Given a SCons Node, return its library dependencies.
+
+ Computes the dependencies if they're not already cached.
+ """
+
+ cached_var_name = env_var + '_cached'
+
+ if not hasattr(node.attributes, cached_var_name):
+ setattr(node.attributes, cached_var_name, __compute_libdeps(node, env_var))
+ return getattr(node.attributes, cached_var_name)
+
+def __compute_libdeps(node, env_var):
+ """Recursively identify all library dependencies for a node."""
+
+ if getattr(node.attributes, 'libdeps_exploring', False):
+ raise DependencyCycleError(node)
+
+ env = node.get_env()
+ deps = set()
+ node.attributes.libdeps_exploring = True
+ try:
+ try:
+ for child in env.Flatten(env.get(env_var, [])):
+ if not child:
+ continue
+ deps.add(child)
+ deps.update(__get_libdeps(child, env_var))
+
+ except DependencyCycleError, e:
+ if len(e.cycle_nodes) == 1 or e.cycle_nodes[0] != e.cycle_nodes[-1]:
+ e.cycle_nodes.append(node)
+ raise
+ finally:
+ node.attributes.libdeps_exploring = False
+
+ return deps
+
+def update_scanner(builder):
+ """Update the scanner for "builder" to also scan library dependencies."""
+
+ old_scanner = builder.target_scanner
+
+ if old_scanner:
+ path_function = old_scanner.path_function
+ def new_scanner(node, env, path=()):
+ result = set(old_scanner.function(node, env, path))
+ result.update(__get_libdeps(node, 'LIBDEPS'))
+ result.update(__get_libdeps(node, 'SYSLIBDEPS'))
+ return sorted(result)
+ else:
+ path_function = None
+ def new_scanner(node, env, path=()):
+ result = set(__get_libdeps(node, 'LIBDEPS'))
+ result.update(__get_libdeps(node, 'SYSLIBDEPS'))
+ return sorted(result)
+
+ builder.target_scanner = SCons.Scanner.Scanner(function=new_scanner,
+ path_function=path_function)
+
+def get_libdeps(source, target, env, for_signature):
+ """Implementation of the special _LIBDEPS environment variable.
+
+ Expands to the library dependencies for a target.
+ """
+
+ if for_signature:
+ return []
+ target = env.Flatten([target])
+ return list(__get_libdeps(target[0], 'LIBDEPS'))
+
+def get_libdeps_objs(source, target, env, for_signature):
+ objs = set()
+ for lib in get_libdeps(source, target, env, for_signature):
+ objs.update(lib.sources_set)
+ return list(objs)
+
+def get_libdeps_special_sun(source, target, env, for_signature):
+ x = get_libdeps(source, target, env, for_signature )
+ return x + x + x
+
+def get_syslibdeps(source, target, env, for_signature):
+ if for_signature:
+ return[]
+ deps = list(__get_libdeps(target[0], 'SYSLIBDEPS'))
+ return deps
+
+def libdeps_emitter(target, source, env):
+ """SCons emitter that takes values from the LIBDEPS environment variable and
+ converts them to File node objects, binding correct path information into
+ those File objects.
+
+ Emitters run on a particular "target" node during the initial execution of
+ the SConscript file, rather than during the later build phase. When they
+ run, the "env" environment's working directory information is what you
+ expect it to be -- that is, the working directory is considered to be the
+ one that contains the SConscript file. This allows specification of
+ relative paths to LIBDEPS elements.
+
+ This emitter also adds LIBSUFFIX and LIBPREFIX appropriately.
+ """
+
+ libdep_files = []
+ lib_suffix = env.subst('$LIBSUFFIX', target=target, source=source)
+ lib_prefix = env.subst('$LIBPREFIX', target=target, source=source)
+ for dep in env.Flatten([env.get('LIBDEPS', [])]):
+ full_path = env.subst(str(dep), target=target, source=source)
+ dir_name = os.path.dirname(full_path)
+ file_name = os.path.basename(full_path)
+ if not file_name.startswith(lib_prefix):
+ file_name = '${LIBPREFIX}' + file_name
+ if not file_name.endswith(lib_suffix):
+ file_name += '${LIBSUFFIX}'
+ libdep_files.append(env.File(os.path.join(dir_name, file_name)))
+
+ env['LIBDEPS'] = libdep_files
+
+ return target, source
+
+def setup_environment(env):
+ """Set up the given build environment to do LIBDEPS tracking."""
+
+ try:
+ env['_LIBDEPS']
+ except KeyError:
+ env['_LIBDEPS'] = '$_LIBDEPS_LIBS'
+
+ # TODO: remove this
+ # this is a horrible horrible hack for
+ # for 32-bit solaris
+ if "uname" in dir(os) and os.uname()[1] == "sun32b":
+ env['_LIBDEPS_LIBS'] = get_libdeps_special_sun
+ else:
+ env['_LIBDEPS_LIBS'] = get_libdeps
+
+ env['_LIBDEPS_OBJS'] = get_libdeps_objs
+ env['_SYSLIBDEPS'] = ' ${_stripixes(LIBLINKPREFIX, SYSLIBDEPS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)} '
+ env['_SHLIBDEPS'] = '$SHLIBDEP_GROUP_START ${_concat(SHLIBDEPPREFIX, __env__.subst(_LIBDEPS, target=TARGET, source=SOURCE), SHLIBDEPSUFFIX, __env__, target=TARGET, source=SOURCE)} $SHLIBDEP_GROUP_END'
+
+ env['LIBDEPS'] = SCons.Util.CLVar()
+ env['SYSLIBDEPS'] = SCons.Util.CLVar()
+ env.Append(LIBEMITTER=libdeps_emitter,
+ PROGEMITTER=libdeps_emitter,
+ SHLIBEMITTER=libdeps_emitter)
+ env.Prepend(_LIBFLAGS=' $LINK_LIBGROUP_START $_LIBDEPS $LINK_LIBGROUP_END $_SYSLIBDEPS ')
+ for builder_name in ('Program', 'SharedLibrary', 'LoadableModule'):
+ try:
+ update_scanner(env['BUILDERS'][builder_name])
+ except KeyError:
+ pass
6 src/SConscript
View
@@ -0,0 +1,6 @@
+# -*- mode: python; -*-
+#
+# This is the principle SConscript file, invoked by the SConstruct. Its job is
+# to delegate to any and all per-module SConscript files.
+
+SConscript( [ 'domus/SConscript', ] )
49 src/domus/SConscript
View
@@ -0,0 +1,49 @@
+# -*- mode: python; -*-
+
+# This SConscript describes build rules for the "domus" project.
+
+import os
+from buildscripts import utils
+
+Import("env")
+Import("has_option")
+Import("getSysInfo")
+Import("darwin linux nix")
+
+def setupBuildInfoFile( env, target, source, **kw ):
+ version = utils.getGitVersion()
+ sysInfo = getSysInfo()
+ contents = '\n'.join([
+ '#include <iostream>',
+ '#include <string>',
+ '#include <boost/version.hpp>',
+ 'namespace domus { const char * gitVersion(){ return "' + version + '"; } }',
+ 'namespace domus { std::string sysInfo(){ return "' + sysInfo + ' BOOST_LIB_VERSION=" BOOST_LIB_VERSION; } }',
+ ])
+
+ contents += '\n\n';
+
+ out = open( str( target[0] ) , 'wb' )
+ try:
+ out.write( contents )
+ finally:
+ out.close()
+
+env.AlwaysBuild( env.Command( 'buildinfo.cpp', [], setupBuildInfoFile ) )
+
+# --- SOURCE FILES ---
+serverOnlyFiles = [ "buildinfo.cpp",
+ "domus.cpp"
+ ]
+
+serverOnlyFiles += env['DOMUS_COMMON_FILES']
+
+
+# --- TARGETS ---
+
+# main target
+domusd = env.Install( '#/', env.Program( "domusd", serverOnlyFiles,
+ LIBDEPS=[],
+ _LIBDEPS='$_LIBDEPS_OBJS' ) )
+
+Default( domusd )
Please sign in to comment.
Something went wrong with that request. Please try again.