Add -u support to scons target@host support
[senf.git] / SConstruct
index a5de9b2..d8c0510 100644 (file)
@@ -1,6 +1,6 @@
 # -*- python -*-
 
-import sys, glob, os.path, fnmatch
+import sys, os.path, fnmatch
 import SENFSCons, senfutil
 
 ###########################################################################
@@ -12,15 +12,7 @@ env.Decider('MD5-timestamp')
 env.EnsureSConsVersion(1,2)
 
 # Load all the local SCons tools
-env.Tool('Doxygen')
-env.Tool('Dia2Png')
-env.Tool('PkgDraw')
-env.Tool('InstallSubdir')
-env.Tool('CopyToDir')
-env.Tool('Boost')
-env.Tool('CombinedObject')
-env.Tool('PhonyTarget')
-env.Tool('InstallDir')
+senfutil.loadTools(env)
 
 env.Help("""
 Additional top-level build targets:
@@ -39,19 +31,28 @@ linklint       Check links of doxygen documentation with 'linklint'
 fixlinks       Fix broken links in doxygen documentation
 all_valgrinds  Run all tests under valgrind/memcheck
 lcov           Generate test coverage output in doc/lcov and lcov.info
+
+You may execute targets on a remote host (if the directory layout is the same)
+by calling
+
+    scons <target>@[<user>@]<host>
 """)
 
 env.Append(
-   ENV                    = { 'PATH' : os.environ.get('PATH'), 'HOME' : os.environ.get('HOME') },
-   CLEAN_PATTERNS         = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*',
-                              '*.gcno', '*.gcda', '*.gcov' ],
-
-   CPPPATH                = [ '#' ],
-   LOCALLIBDIR            = '#',
+   ENV                    = { 'PATH' : os.environ.get('PATH'), 
+                              'HOME' : os.environ.get('HOME'),
+                              'SSH_AGENT_PID': os.environ.get('SSH_AGENT_PID'),
+                              'SSH_AUTH_SOCK': os.environ.get('SSH_AUTH_SOCK') },
+   CLEAN_PATTERNS         = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*' ],
+
+   BUILDDIR               = '${FLAVOR and "#/build/$FLAVOR" or "#"}',
+   CPPPATH                = [ '$BUILDDIR', '#' ],
+   LOCALLIBDIR            = '$BUILDDIR',
    LIBPATH                = [ '$LOCALLIBDIR' ],
    LIBS                   = [ '$LIBSENF$LIBADDSUFFIX', 'rt', '$BOOSTREGEXLIB', 
                               '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ], 
    TEST_EXTRA_LIBS        = [  ],
+   VALGRINDARGS           = [ '--num-callers=50' ],
 
    PREFIX                 = '#/dist',
    LIBINSTALLDIR          = '$PREFIX${syslayout and "/lib" or ""}',
@@ -98,9 +99,14 @@ env.SetDefault(
     LIBSENF           = "senf",
     LCOV              = "lcov",
     GENHTML           = "genhtml",
-    SCONS             = "./tools/scons -j$CONCURRENCY_LEVEL",
+    SCONSBIN          = env.File("#/tools/scons"),
+    SCONSARGS          = [ '-Q', '-j$CONCURRENCY_LEVEL', 'debug=$debug', 'final=$final' ],
+    SCONS             = "@$SCONSBIN $SCONSARGS",
     CONCURRENCY_LEVEL = env.GetOption('num_jobs') or 1,
     TOPDIR            = env.Dir('#').abspath,
+    LIBADDSUFFIX      = '${FLAVOR and "_$FLAVOR" or ""}',
+    OBJADDSUFFIX      = '${LIBADDSUFFIX}',
+    FLAVOR            = '',
 )
 
 # Set variables from command line
@@ -120,7 +126,7 @@ if not os.path.exists("doclib/Doxyfile.local"):
 
 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
    and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
-    env.Execute([ "scons prepare" ])
+    env.Execute([ "$SCONS prepare" ])
 
 # Load SConscripts
 
@@ -128,7 +134,10 @@ SConscriptChdir(0)
 SConscript("debian/SConscript")
 SConscriptChdir(1)
 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
-SConscript("senf/SConscript")
+if env.subst('$BUILDDIR') == '#':
+    SConscript("SConscript")
+else:
+    SConscript("SConscript", variant_dir=env.subst('$BUILDDIR'), src_dir='#', duplicate=False)
 SConscript("Examples/SConscript")
 SConscript("HowTos/SConscript")
 SConscript("doclib/SConscript")
@@ -136,20 +145,6 @@ SConscript("doclib/SConscript")
 ###########################################################################
 # Define build targets
 
-#### libsenf.a
-libsenf = env.Library("$LOCALLIBDIR/${LIBSENF}${LIBADDSUFFIX}", env['ALLOBJECTS'])
-env.Default(libsenf)
-env.Install('$LIBINSTALLDIR', libsenf)
-
-def create(target, source, env): 
-    file(str(target[0]), 'w').write(source[0].get_contents()+"\n")
-env['BUILDERS']['CreateFile'] = Builder(action = create)
-
-conf = env.CreateFile("${LOCALLIBDIR}/${LIBSENF}${LIBADDSUFFIX}.conf", 
-                      env.Value(env.subst("$_CPPDEFFLAGS")))
-env.Default(conf)
-env.Install('$CONFINSTALLDIR', conf)
-
 #### install_all, default, all_tests, all
 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
                                     'site_scons/senfutil.py',
@@ -169,11 +164,12 @@ env.PhonyTarget('prepare', [], [])
 #### valgrind
 for test in env.FindAllBoostUnitTests():
     stamp = env.Command(test[0].dir.File('.test-valgrind.stamp'), 
-                        [ test[0].dir.File('.test.bin'), test ],
+                        [ test[0].dir.File('.test.bin'), 'tools/valgrind.sup' ],
                         [ """valgrind --tool=memcheck 
                                       --error-exitcode=99 
-                                      --suppressions=tools/valgrind.sup 
-                                          $SOURCE $BOOSTTESTARGS;
+                                      --suppressions=${SOURCES[1]}
+                                      $VALGRINDARGS
+                                          ${SOURCES[0]} $BOOSTTESTARGS;
                              [ $$? -ne 99 ] || exit 1""".replace("\n"," "),
                           Touch("$TARGET") ])
     alias = env.Command(test[0].dir.File('valgrind'), stamp, [ env.NopAction() ])
@@ -181,23 +177,43 @@ for test in env.FindAllBoostUnitTests():
 
 ### lcov
 env.PhonyTarget('lcov', [], [
-        '$SCONS debug=1 CCFLAGS+="-fprofile-arcs -ftest-coverage" LIBS+="gcov" all_tests',
-        '$LCOV --directory $TOPDIR/senf --capture --output-file /tmp/senf_lcov.info --base-directory $TOPDIR',
+        '$SCONS debug=1 BUILDDIR="#/build/lcov" CCFLAGS+="-fprofile-arcs -ftest-coverage" LIBS+="gcov" all_tests',
+        '$LCOV --follow --directory $TOPDIR/build/lcov/senf --capture --output-file /tmp/senf_lcov.info --base-directory $TOPDIR',
         '$LCOV --output-file lcov.info --remove /tmp/senf_lcov.info "*/include/*" "*/boost/*" "*.test.*" ',
         '$GENHTML --output-directory doc/lcov --title all_tests lcov.info',
         'rm /tmp/senf_lcov.info' ])
-
+if env.GetOption('clean'): 
+    env.Clean('lcov', [ os.path.join(path,f)
+                        for path, subdirs, files in os.walk('.')
+                        for pattern in ('*.gcno', '*.gcda', '*.gcov')
+                        for f in fnmatch.filter(files,pattern) ] + 
+                      [ 'lcov.info', env.Dir('doc/lcov'), env.Dir('build/lcov') ])
+    
 #### clean
-env.Clean('all', '.prepare-stamp')
-env.Clean('all', libsenf)
-env.Clean('all', env.Dir('dist'))
-env.Clean('all', 'lcov.info')
+env.Clean('all', ('.prepare-stamp', env.Dir('dist'), env.Dir('build')))
+if env.GetOption('clean') : env.Depends('all', ('lcov', 'all_valgrinds'))
 
-if env.GetOption('clean'):
+if env.GetOption('clean') and 'all' in BUILD_TARGETS:
     env.Clean('all', [ os.path.join(path,f)
                        for path, subdirs, files in os.walk('.')
                        for pattern in env['CLEAN_PATTERNS']
                        for f in fnmatch.filter(files,pattern) ])
+    # Disable writing to the deleted .sconsign file
+    import SCons.SConsign
+    SCons.SConsign.write = lambda : None
 
 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
     Execute(Touch(".prepare-stamp"))
+
+### execute targets on remote hosts
+for target in COMMAND_LINE_TARGETS:
+    if '@' in target:
+        realtarget, host = target.split('@',1)
+        cwd=env.GetLaunchDir()
+        home=os.environ['HOME']+'/'
+        if cwd.startswith(home) : cwd = cwd[len(home):]
+        args = [ '$SCONSARGS' ]
+        if env.GetLaunchDir() != os.getcwd():
+            args.append('-u')
+        env.PhonyTarget(target, [], [ "ssh $HOST scons $SCONSARGS -C $DIR $RTARGET" ],
+                        HOST=host, RTARGET=realtarget, DIR=cwd, SCONSARGS=args)