senfscons: Add additional very simple build-helper for externel projects using SENF
g0dil [Mon, 7 Apr 2008 10:20:32 +0000 (10:20 +0000)]
Make wording on SENF_DEBUG more clear (hopefully ...)

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@788 270642c3-0616-0410-b53a-bc976706d245

Mainpage.dox
Scheduler/ClockService.hh
senf.dict
senfscons/Mainpage.dox
senfscons/senfutil.py [new file with mode: 0644]

index 77611d1..036a1e6 100644 (file)
 
     \section senf_compiler_options Compiler and Linker Options
 
-    If SENF is compiled in debug mode (SENF_DEBUG is defined), exception messages will
-    automatically include a stack backtrace. For this to work, you need to add the -rdynamic option
-    to all link commands. This feature depends on gcc and the GNU-libc.
-
-    It is <B>very important</B> that both the SENF library and the application using it are either
-    compiled with or without this compiler switch (-DSENF_DEBUG). Otherwise, the compiler will emit
-    error messages which might be hard to debug.
+    If SENF is compiled in debug mode (SENF_DEBUG is defined), exception messages will automatically
+    include a stack backtrace. For this to work, you need to add the -rdynamic option to all link
+    commands. This feature depends on gcc and the GNU-libc.
 
+    It is <B>very important</B> that both the SENF library and the application using it are compiled
+    \e both either with or without this compiler switch (-DSENF_DEBUG). Otherwise, the compiler will
+    emit error messages which might be hard to debug.
  */
 
 /** \page senf_build Building the SENF framework
     <tt>svn:externals</tt> for this) or a symbolic link to your SENF checkout.
 
     \code
-    import os.path, glob
+    import glob
 
     env = Environment(
 
 
     )
 
-    # If we have a symbolic link 'senf' pointing to our own senf build, use it (and assume
-    # it's in debug mode)
-    if os.path.exists('senf'):
-        print "\nUsing SENF in 'senf'\n"
-        env.Append(
-
-            CPPDEFINES = [ 'SENF_DEBUG' ],
-            LIBPATH    = [ 'senf' ],
-            CPPPATH    = [ 'senf/include' ],
-            CXXFLAGS   = [ '-O0', '-g', '-fno-inline' ],
-            LINKFLAGS  = [ '-g', '-rdynamic' ],
-
-        )
-        env.Execute([ 'scons -C senf libsenf.a' ])
-    else:
-        print "\nUsing system installed SENF\n"
-
-    # replace 'mytarget' with the name of your target executable
     env.Program(
         target = 'mytarget',
         source = glob.glob('*.cc'),
     );
     \endcode
 
-    This script automatically set's up the build correctly when using a self-compiled SENF in debug
-    mode (which is the default mode):
-    \li It links in all the required libraries in the correct order: First \c libsenf, then the
-        other needed libraries \c liberty, \c libboost_regex and \c libboost_iostreams.
-    \li It defines the <tt>SENF_DEBUG</tt> preprocessor symbol correctly
-    \li It correctly sets the include and library path
-    \li It adds sensible debug flags
-    \li It adds <tt>-rdynamic</tt> to the link command. This is needed to get a nice backtrace from
-        exceptions. 
-    \li It automatically rebuilds SENF if needed
+    When building against a self-built SENF which will probably be in debug mode, the '-DSENF_DEBUG'
+    option must be added to the compile command.
+
+    The most simple way to build using SENF is to use a very simple SCons helper which automatically
+    supports debug and final builds, uses SENF either centrally installed or locally built and has
+    some other nice features. See \ref senfutil for more info and an example for this utility.
 
     \see \ref senf_components \n
          \ref senf_overview
     \section libPPI libPPI: Packet Processing Infrastructure
 
     The Packet Processing Infrastructure implements a modular framework for implementing packet
-    oriented network applications. The library provides a larget set of pre-defined modules as well
+    oriented network applications. The library provides a large set of pre-defined modules as well
     as the necessary helpers to implement application specific processing modules.
 
     \see <a href="../../PPI/doc/html/index.html">libPPI API reference</a>
     \li senf::intrusive_refcount to simplify the implementation of classes usable with
         boost::intrusive_ptr
     \li boost::bind extensions
-    \li An interface to the \c g++ demangler integrated with type_info
+    \li An interface to the \c g++ de-mangler integrated with type_info
     \li Typedefs and rudimentary methods to simplify handling high-resolution time values
 
     \see <a href="../../Utils/doc/html/index.html">libUtils API reference</a>
     \li To interpret low level network packets, use the <a
         href="../../Packets/doc/html/index.html">Packets library</a>. This library will provide
         efficient and convenient access to all protocol fields. It supports parsing as well as
-        modifying and creating packets. It has default support for the most important internet
+        modifying and creating packets. It has default support for the most important Internet
         protocols and is highly extensible with new protocols.
     \li Go over the <a href="../../Utils/doc/html/index.html">Utils library</a>. It contains small
         helpers to simplify tasks like daemonization, exception handling, debugging and so on.
  */
 
 \f
+// :vim:textwidth=100
 // Local Variables:
 // mode: c++
 // fill-column: 100
-// :vim:textwidth=100
 // c-file-style: "senf"
 // indent-tabs-mode: nil
 // ispell-local-dictionary: "american"
index 255fcbe..e0e3939 100644 (file)
@@ -84,6 +84,13 @@ namespace senf {
             in the normal case (no clock skew) and still encapsulate the dependency on legacy C
             headers. Using the senf::singleton mixin ensures, that the instance is constructed
             before main even when instance() is not called.
+
+        \bug There is a deadlock condition between ClockService and the streaming of Boost.DateTime
+            values: Boost.DateTime seems to call tzset() whenever writing a date/time value (ugh)
+            and since tzset changes basic date/time values, it seems to block gettimeofday() which
+            leads to the SIGLARM handler blocking indefinitely. Resolution either a) find out, why
+            tzset() of all functions is called or b) move the ClockService heartbeat functionality
+            into the Scheduler.
       */
     class ClockService
         : singleton<ClockService>
index 00e57e0..755321b 100644 (file)
--- a/senf.dict
+++ b/senf.dict
@@ -39,9 +39,11 @@ bund
 calculateChecksum
 callback
 callbacks
+CapitalziedLettersToSeparateWords
 catched
 cb
 cc
+cci
 cd
 cerr
 cfi
@@ -64,8 +66,14 @@ ConnectedCommunicationPolicy
 ConnectedRawV
 ConnectedUDPv
 const
+CPPDEFINES
+CPPPATH
 createAfter
 createBefore
+ct
+cti
+CXXFLAGS
+daemonization
 DatagramSection
 DataPacket
 dd
@@ -89,6 +97,7 @@ dontinclude
 dox
 doxyfile
 doxygen
+DSENF
 DSMCCSection
 dt
 ElementParser
@@ -98,6 +107,7 @@ endif
 endl
 ENOFILE
 enum
+env
 eof
 EPIPE
 epoll
@@ -139,6 +149,7 @@ findPrev
 fixme
 fixvariant
 flurgle
+fno
 fokus
 foo
 fooCallback
@@ -178,6 +189,8 @@ html
 http
 iana
 ias
+iberty
+IDE
 IdleEvent
 ietf
 ifndef
@@ -190,6 +203,7 @@ init
 initHeadSize
 initSize
 inline
+inlines
 InputConnector
 inputSocket
 Institut
@@ -202,6 +216,7 @@ IOEvent
 IOEventInfo
 ios
 iostream
+iostreams
 ip
 IpChecksum
 IpTypes
@@ -212,13 +227,22 @@ IPX
 isock
 iterator
 jens
+jkaeber
 join
 key
 li
+libboost
 libc
 libcwd
 libPacket
 libPackets
+LIBPATH
+libPPI
+libScheduler
+libsenf
+libSocket
+libUtils
+LINKFLAGS
 LinkScope
 ListB
 ListN
@@ -232,6 +256,7 @@ mainpage
 mixin
 mkdir
 MPEGDVBBundle
+mpp
 multicast
 mycommand
 mydir
@@ -241,6 +266,7 @@ MyNodeType
 MyParser
 myserver
 MySpecialObject
+mytarget
 MyVariant
 MyVariantPolicy
 MyVector
@@ -261,6 +287,7 @@ NodeCreateTraits
 noinit
 noroute
 nothrow
+nUsing
 ob
 ObjectDirectory
 offene
@@ -287,6 +314,7 @@ PacketData
 PacketImpl
 PacketInterpreter
 PacketInterpreterBase
+packetized
 packetparser
 PacketParser
 PacketParserBase
@@ -348,6 +376,7 @@ RawINetProtocol
 RawV
 rdynamic
 refcount
+regex
 registerEvent
 registerPacket
 registerPacketType
@@ -364,6 +393,7 @@ Satelitenkommunikation
 SConfig
 scons
 SCons
+SConstruct
 ScopedDirectory
 ScopeId
 screenshot
@@ -491,6 +521,8 @@ Ver
 vlanId
 VLanId
 VoidPacketParser
+Wno
+Woverloaded
 WrapException
 www
 xmlsoft
index 9b915dc..5c81984 100644 (file)
@@ -34,6 +34,61 @@ namespace senfscons {
     of pre- and postprocessing (which is integrated with the provided Doxygen builder) to fix some
     doxygen problems and generate a (IMHO) more readable layout.
 
+    \section senfutil Building Projects using SENF
+
+    When building projects using senf, SENFSCons has a very simple helper module \ref senfutil to
+    make the building of libraries utilizing senf simpler:
+    \code
+    import sys
+    sys.path.extend(('senf/senfscons','/usr/lib/senf/senfscons'))
+    import os.path, glob, senfutil
+
+    env = Environment()
+
+    senfutil.SetupForSENF( env )
+
+    env.Append(
+
+        LIBS            = [ ],
+        CXXFLAGS        = [ '-Wall', '-Woverloaded-virtual' ],
+        LINKFLAGS       = [ ],
+
+        CXXFLAGS_debug  = [ ],
+        LINKFLAGS_debug = [ ],
+        LOGLEVELS_debug = [ 'senf::log::Debug||VERBOSE' ],
+
+        CXXFLAGS_final  = [ '-O3' ],
+        LINKFLAGS_final = [ ],
+        LOGLEVELS_final = [ ],
+
+        SENF_BUILDOPTS  = [ ],
+
+    )
+
+    env.Default(
+        env.Program( target = 'udpforward',
+                     source = glob.glob('*.cc') )
+    )
+
+    env.Clean(DEFAULT_TARGETS, [ 'udpforward.log', 'udpforward.pid' ])
+    \endcode
+
+    This example builds a simple binary from a number of source files (all '.cc' files). It links
+    against the SENF library and automatically sets all the correct compiler options using
+    <tt>senfutil.SetupForSENF( env )</tt>.
+
+    This script automatically uses a SENF installation either symlinked or imported into the current
+    project in directory 'senf' or, if this directory does not exist, a globaly installed SENF. A
+    locally installed SENF is automatically recompiled if needed. Parallel building is also
+    supported.
+
+    This script automatically supports the \c final and \c LOGLEVELS command line parameters. The
+    LOGLEVELS parameter uses a much more readable syntax than SENF_LOG_CONF:
+    <pre>
+    $ scons -j2 final=1 \
+          LOGLEVELS='senf::log::Debug||IMPORTANT myapp::Transactions|mytrans::Area|VERBOSE'
+    </pre>
+
     \section layout The Project Layout
 
     A Project using the SENFSCons infrastructure will always use a consistent directory layout. The
diff --git a/senfscons/senfutil.py b/senfscons/senfutil.py
new file mode 100644 (file)
index 0000000..a0954a8
--- /dev/null
@@ -0,0 +1,59 @@
+import os.path
+from SCons.Script import *
+
+###########################################################################
+# This looks much more complicated than it is: We do three things here:
+# a) switch between final or debug options
+# b) parse the LOGLEVELS parameter into the correct SENF_LOG_CONF syntax
+# c) check for a local SENF, set options accordingly and update that SENF if needed
+
+def SetupForSENF(env):
+    env.Append( LIBS           = [ 'senf', 'iberty', 'boost_regex', 'boost_iostreams' ],
+                CXXFLAGS       = [ '-Wno-long-long',
+                                   '${"$CXXFLAGS_"+(final and "final" or "debug")}' ],
+                LINKFLAGS      = [ '${"$LINKFLAGS_"+(final and "final" or "debug")}' ],
+                SENF_BUILDOPTS = [ '-j%s' % (env.GetOption('num_jobs') or "1") ],
+                CXXFLAGS_debug  = [ '-O0', '-g', '-fno-inline' ],
+                LINKFLAGS_debug = [ '-g', '-rdynamic' ],
+                )
+
+    # Parse LOGLEVELS parameter
+    def parseLogOption(value):
+        stream, area, level = ( x.strip() for x in value.strip().split('|') )
+        stream = ''.join('(%s)' % x for x in stream.split('::') )
+        if area : area = ''.join( '(%s)' % x for x in elts[1].split('::') )
+        else    : area = '(_)'
+        return '(( %s,%s,%s ))' % (stream,area,level)
+
+    def expandLogOption(target, source, env, for_signature):
+        return ' '.join( parseLogOption(x) for x in env.subst('$LOGLEVELS').split() )
+
+    # Add command-line options: 'LOGLEVELS' and 'final'
+    opts = Options()
+    opts.Add( 'LOGLEVELS', 'Special log levels. Syntax: <stream>|[<area>]|<level> ...',
+              '${"$LOGLEVELS_"+(final and "final" or "debug")}' )
+    opts.Add( BoolOption('final', 'Build final (optimized) build', False) )
+    opts.Update(env)
+
+    print env.subst('$LOGLEVELS')
+
+    if env.subst('$LOGLEVELS'):
+        env.Append( expandLogOption=expandLogOption )
+        env.Append( CPPDEFINES = { 'SENF_LOG_CONF': '$expandLogOption' } )
+
+    env.Help(opts.GenerateHelpText(env))
+
+    # If we have a symbolic link (or directory) 'senf', we use it as our
+    # senf repository
+    if os.path.exists('senf'):
+        print "\nUsing SENF in './senf'\n"
+        env.Append( LIBPATH = [ 'senf' ],
+                    CPPPATH = [ 'senf/include' ],
+                    SENF_BUILDOPTS = [ '${final and "final=1" or None}' ],
+                    CPPDEFINES = [ '${not(final) and "SENF_DEBUG" or None}' ] )
+
+        env.Default(
+            env.AlwaysBuild(
+                env.Command('senf/libsenf.a', [],  [ 'scons -C senf $SENF_BUILDOPTS libsenf.a' ])))
+    else:
+        print '\nUsing global SENF\n'