From: g0dil Date: Sat, 20 Jan 2007 23:45:42 +0000 (+0000) Subject: Again some doc-build fixes X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=70256cc93f59f5d2c9b3428775a181e5e225bfc5;p=senf.git Again some doc-build fixes Extend the CSS rules some more for advanced browsers (probably everyone except IE) Finish FileHandle documentation Complete SocketHandle documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@181 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/SConstruct b/SConstruct index c3cd824..ca3fad0 100644 --- a/SConstruct +++ b/SConstruct @@ -23,7 +23,7 @@ SConscript(glob.glob("*/SConscript")) SENFSCons.StandardTargets(env) SENFSCons.GlobalTargets(env) SENFSCons.Doxygen(env) -SENFSCons.DoxyXRef(env, env.Alias('all_docs')[0].sources, +SENFSCons.DoxyXRef(env, HTML_HEADER = '#/doclib/doxy-header-overview.html', HTML_FOOTER = '#/doclib/doxy-footer.html') diff --git a/Socket/FileHandle.cc b/Socket/FileHandle.cc index 687bde7..c482e6d 100644 --- a/Socket/FileHandle.cc +++ b/Socket/FileHandle.cc @@ -20,7 +20,9 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// Definition of non-inline non-template functions +/** \file + \brief senf::FileHandle non-inline non-template implementation + */ #include "FileHandle.hh" //#include "FileHandle.ih" @@ -76,6 +78,9 @@ prefix_ void senf::FileBody::blocking(bool status) if (::fcntl(fd(), F_SETFL, flags) < 0) throw SystemException(errno); } +/* We don't take POLLIN/POLLOUT as argument to avoid having to include + sys/poll.h in the .cci file (and therefore indirectly into the .hh + and then every file which uses FileHandle) */ prefix_ bool senf::FileBody::pollCheck(int fd, bool incoming, bool block) const { diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci index f69d3e0..0fc5f3e 100644 --- a/Socket/FileHandle.cci +++ b/Socket/FileHandle.cci @@ -20,7 +20,9 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// Definition of inline non-template functions +/** \file + \brief senf::FileHandle inline non-template implementation + */ //#include "FileHandle.ih" diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh index 9a8c7e7..d2c93b6 100644 --- a/Socket/FileHandle.hh +++ b/Socket/FileHandle.hh @@ -20,6 +20,10 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** \file + \brief senf::FileHandle public header + */ + #ifndef HH_FileHandle_ #define HH_FileHandle_ 1 @@ -105,19 +109,27 @@ namespace senf { bool eof() const; ///< Check EOF condition /**< Depending on the socket type, this might never return \p - true */ + true. + + This member is somewhat problematic performance wise if + called frequently since it relies on virtual + functions. However, since the eof() handling is extremely + protocol dependent, a policy based implementation does not + seam feasible. */ bool valid() const; ///< Check filehandle validity /**< Any operation besides valid() will fail on an invalid FileHandle */ bool boolean_test() const; ///< Short for valid() && ! eof() /**< This is called when using a FileHandle instance in a boolen - context */ + context + + See the performance comments for the eof() member */ int fd() const; ///< Return the raw FileHandle - static FileHandle cast_static(FileHandle handle); ///< \internal - static FileHandle cast_dynamic(FileHandle handle); ///< \internal + static FileHandle cast_static(FileHandle handle); /**< \internal */ + static FileHandle cast_dynamic(FileHandle handle); /**< \internal */ protected: explicit FileHandle(std::auto_ptr body); diff --git a/Socket/FileHandle.ih b/Socket/FileHandle.ih index 9ca832d..24c0528 100644 --- a/Socket/FileHandle.ih +++ b/Socket/FileHandle.ih @@ -20,6 +20,10 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** \file + \brief senf::FileHandle internal header + */ + #ifndef IH_FileHandle_ #define IH_FileHandle_ 1 @@ -32,7 +36,29 @@ namespace senf { - /** \brief + /** \brief senf::FileHandle referenced body + + \internal + + The senf::FileBody class formes the body part of the handle/body structure of the FileHandle + interface. It manages the FileHandle data and is referenced by senf::FileHandle. It is + automatically managed using reference counting. + + Since the senf::FileHandle class forwards most calls directly to the underlying + senf::FileBody instance, most members are documented in senf::FileHandle. + + \section filebody_new Writing senf::FileBody derived classes + + It is possible to write customized senf::FileBody derived body implementations. This + implementation can then be used be a senf::FileHandle derived class to customize the + FileHandle behavior. Handling the body directly by the handle class ensures, that no invalid + handles can be created (a senf::FileHandle derived handle expecting a specific body type but + pointing to a different body type). + + To customize the behavior, a virtual interface is provided. This interface only covers some + basic funcionality which is only used infrequently during the lifetime of a FileHandle + instance. + */ class FileBody : public senf::intrusive_refcount @@ -47,7 +73,11 @@ namespace senf { ///\name Structors and default members ///@{ - explicit FileBody(int fd=-1); + explicit FileBody(int fd=-1); ///< Create new instance + /**< You need to pass a real file descriptor to this + constructor not some arbitrary id even if you overload + all the virtual members. If the file descriptor is -1 the + resulting body/handle is not valid() */ virtual ~FileBody(); // no copy @@ -77,11 +107,23 @@ namespace senf { /////////////////////////////////////////////////////////////////////////// // Virtual interface for subclasses to override - virtual void v_close(); - virtual void v_terminate(); - virtual bool v_eof() const; - virtual bool v_valid() const; - + virtual void v_close(); ///< Called to close the file descriptor + /**< You should probably always call the global ::close() + function in this member, however you might want to do + some additional cleanup here. If the operation fails, you + are allowed to throw (preferably a + senf::SystemException). + + \throws senf::SystemException */ + virtual void v_terminate(); ///< Called to forcibly close the file descriptor + /**< This member is called by the destructor (and by + terminate()) to close the descriptor. This member must \e + never throw, it should probably just ignore error + conditions (there's not much else you can do) */ + virtual bool v_eof() const; ///< Called by eof() + virtual bool v_valid() const; ///< Called by valid() + /**< This member is only called, if the file descriptor is + not -1 */ protected: @@ -100,4 +142,5 @@ namespace senf { // Local Variables: // mode: c++ // c-file-style: "senf" +// fill-column: 100 // End: diff --git a/Socket/SocketHandle.cc b/Socket/SocketHandle.cc index 3f8a0ce..f2225a8 100644 --- a/Socket/SocketHandle.cc +++ b/Socket/SocketHandle.cc @@ -20,7 +20,9 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// Definition of non-inline non-template functions +/** \file + \brief senf::SocketHandle non-inline non-template implementation + */ #include "SocketHandle.hh" #include "SocketHandle.ih" @@ -85,7 +87,8 @@ namespace { } } -prefix_ bool senf::detail::StateMapOrdering::operator()(std::string a1, std::string a2) +prefix_ bool senf::detail::StateMapOrdering::operator()(std::string const & a1, + std::string const & a2) const { std::string::iterator i1 (a1.begin()); diff --git a/Socket/SocketHandle.cci b/Socket/SocketHandle.cci index 60a5220..e138ec2 100644 --- a/Socket/SocketHandle.cci +++ b/Socket/SocketHandle.cci @@ -20,7 +20,9 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// Definition of inline non-template functions +/** \file + \brief senf::SocketHandle inline non-template implementation + */ #include "SocketHandle.ih" diff --git a/Socket/SocketHandle.ct b/Socket/SocketHandle.ct index 0082ffb..eac4a09 100644 --- a/Socket/SocketHandle.ct +++ b/Socket/SocketHandle.ct @@ -20,7 +20,9 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// Definition of non-inline template functions +/** \file + \brief senf::SocketHandle non-inline template implementation + */ #include "SocketHandle.ih" diff --git a/Socket/SocketHandle.cti b/Socket/SocketHandle.cti index f573e43..e93ec63 100644 --- a/Socket/SocketHandle.cti +++ b/Socket/SocketHandle.cti @@ -20,7 +20,9 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// Definition of inline template functions +/** \file + \brief senf::SocketHandle inline template implementation + */ #include "SocketHandle.ih" diff --git a/Socket/SocketHandle.hh b/Socket/SocketHandle.hh index 7304ff1..8f10b4a 100644 --- a/Socket/SocketHandle.hh +++ b/Socket/SocketHandle.hh @@ -20,6 +20,10 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** \file + \brief senf::SocketHandle public header + */ + #ifndef HH_SocketHandle_ #define HH_SocketHandle_ 1 @@ -36,10 +40,26 @@ namespace senf { - /** \brief + /** \brief basic SocketHandle supporting protocol and policy abstraction + + The senf::SocketHandle class introduces the two abstraction layers of the socket + library. senf::SocketHandle does \e not provide socket functions it only provides the + infrastructure necessary to support both, the protocol and the policy interface. + + senf::SocketHandle takes the socket policy as a template argument. senf::SocketHandle also + introduces the protocol class. However, the class has no public constructors (see the + derived classes senf::ProtocolClientSocketHandle and senf::ProtocolServerSocketHandle). + + The most important functionality provided by senf::SocketHandle is the conversion + constructor. This allows to implicitly convert between compatible socket handle types as + specified by the socket policy. The conversion constructor is defined in such a way, that + only valid conversions are possible (see the implementation source for a more complete + discussion). - \todo Create a SocketHandleBase class and move some non-Policy - dependent code there + \note This class is \e not meant to be used as a base-class outside the library + implementation; The protected interface is for internal use only. + + \todo Create a SocketHandleBase class and move some non-Policy dependent code there */ template class SocketHandle @@ -51,6 +71,12 @@ namespace senf { typedef SocketPolicy Policy; + /** \brief Check policy compatibility + + IsCompatible is a template meta-function which will check some other socket policy for + conversion compatibility. This check is used in the senf::SocketPolicy implementation to + restrict the conversion operator. + */ template struct IsCompatible : public boost::enable_if< SocketPolicyIsBaseOf, @@ -66,45 +92,137 @@ namespace senf { // default destructor // conversion constructors + template SocketHandle(SocketHandle other, typename IsCompatible::type * = 0); + ///< Convert from other socket handle checking policy + ///< compatibility ///@} /////////////////////////////////////////////////////////////////////////// template typename IsCompatible::type const & operator=(SocketHandle other); - - static SocketHandle cast_static(FileHandle handle); - static SocketHandle cast_dynamic(FileHandle handle); + ///< Assign from other socket handle checking policy + ///< compatibility void state(SocketStateMap & map, unsigned lod=0); + ///< Inquire state information of socket handle + /**< The map argument (a string to string mapping) will be + filled with information coverning the current state of + the socket. The information provided depends on the + socket protocol. The amount of information returned can + be controlled using the \p lod value. + + See senf::SocketProtocol::state() for more information, + how the Information is generated. + + \param map string to string mapping to be filled with + state information + \param lod level of detail requesten. The interpretation + of this value is protocol specific */ std::string dumpState(unsigned lod=0); + ///< Format complete state information as string + /**< Formats the complete state map value and returns it as + a single multi-line string. */ protected: explicit SocketHandle(std::auto_ptr protocol, bool isServer); + ///< Initialize SocketHandle providing the protocol + /**< \param protocol Protocol class of the protocol + implemented by this socket handle + \param isServer \c true, if this SocketHandle instance + implements a server handle, \c false otherwise */ SocketHandle(FileHandle other, bool isChecked); - - SocketBody & body(); - SocketBody const & body() const; + ///< Initialize SocketHandle from arbitrary checked + ///< FileHandle + /**< This constructor is used to support up- and downcasting + of SocketHandle instances. + + \warning It is absolutely necessary to ensure, that the + FileHandle passed in is \e really a SocketHandle holding + a SocketBody (and not a simple FileBody) + instance. Additionally. the SocketPolicy absolutely must + be compatible. + + \param other FileHandle to assign + \param isChecked has to be \c true + + \todo Answer, why the heck I need the \c isChecked + parameter ?? + */ + + SocketBody & body(); ///< Access socket body + /**< This member replaces the corresponding FileHandle + member and returns an appropriately cast body reference */ + SocketBody const & body() const; ///< Access socket body in const context + /**< This member replaces the corresponding FileHandle + member and returns an appropriately cast body reference */ SocketProtocol const & protocol() const; + ///< Access protocol class + + void assign(FileHandle other); /**< \internal */ - void assign(FileHandle other); + public: + static SocketHandle cast_static(FileHandle handle); + static SocketHandle cast_dynamic(FileHandle handle); private: }; + /** \brief Write stream status dump to output stream + + Write senf::SocketHandle::dumpState() to \c os + + \related senf::SocketHandle + */ template std::ostream & operator<<(std::ostream & os, SocketHandle handle); + /** \brief static socket (down-)cast + + This function is like \c static_cast but for socket handles. It allows to downcast any + FileHandle to any SocketHandle (and its derived types). static_socket_cast will \e not check + the validity of the cast, it will assume, that the cast is valid. + + The function will however check, that the cast is possible. Casting between (at compile + time) known incompatible types (like casting a SocketHandle with a communication policy of + ConnectedCommunicationPolicy to a SocketHandle with UnconnectedCommunicationPolicy will fail + at compile time). + + \warning + If the type you cast to is not really a compatible socket handle type you will get undefined + behavior, probably your program will crash (You will get an assertion in debug builds). + + \related senf::SocketHandle + */ template Target static_socket_cast(Source handle); + /** \brief dynamic socket (down-)cast + + This function is like \c dynamic_cast but for socket handles. It is a runtime typechecked + version of static_socket_cast. + + \throws std::bad_cast You have tried to perform an invalid down- or crosscast. + + \related senf::SocketHandle + */ template Target dynamic_socket_cast(Source handle); + /** \brief dynamically check cast validity + + This function will check, wether the given cast is valid. This is the same as checking, that + dynamic_socket_cast does not throw. + + This member is needed, since there is no 'null' SocketHandle (comparable to a null pointer) + which could be returned by a non-throwing variant of dynamic_socket_cast. + + \related senf::SocketHandle + */ template bool check_socket_cast(Source handle); } @@ -119,4 +237,5 @@ namespace senf { // Local Variables: // mode: c++ // c-file-style: "senf" +// fill-column: 100 // End: diff --git a/Socket/SocketHandle.ih b/Socket/SocketHandle.ih index 5ad2b99..c72b54d 100644 --- a/Socket/SocketHandle.ih +++ b/Socket/SocketHandle.ih @@ -20,6 +20,10 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** \file + \brief senf::SocketHandle internal header + */ + #ifndef IH_SocketHandle_ #define IH_SocketHandle_ 1 @@ -38,65 +42,141 @@ namespace senf { namespace detail { + /** \brief String supporting automatic type conversion + + The ConvertibleString class is used to simplify creating a text representation of + arbitrary values. ConvertibleString is an ordinary string with an additional constructor + which allows constructing the string from any arbitrary, streamable type. + + \note It is generally not advisable to derive from the standard library container + classes. However, in this concrete case, the derivation is safe since only the + additional functionality is added. It is absolutely safe to convert the derived class + back to the base type. + */ class ConvertibleString : public std::string { public: ConvertibleString(); - ConvertibleString(bool v); + ConvertibleString(bool v); ///< Bool conversion constructor + /**< The bool conversion is defined explicitly to use a + specialized representation (the strings 'true' and + 'false') */ template ConvertibleString(T const & other); - template - ConvertibleString & operator+= (ConvertibleString const & other); - }; - - struct StateMapOrdering - : public std::binary_function - { - bool operator()(std::string a1, std::string a2) const; - }; - + ///< Conversion constructor + /**< This constructor will assign the string from any + arbitrary type. It will use boost::lexical_cast to + convert the argument to its string representation. */ + + template + ConvertibleString & operator+= (ConvertibleString const & other); + ///< Add additional values with separator + /**< This operator facilitates the representation of + multiple values in a single string. Each value is first + converted to a string (using the type conversion + machinery of C++ and the ConvertibleString conversion + constructors). It is then appended to the current string + with ', ' as a separator (if the current string is + non-empty). */ + }; + + /** \brief Special ordering for the SocketStateMap + \internal + + This special ordering will sort 'hierarchical' strings correctly. A hierarchical string + in this context is a string like a path- or hostname with '.' as the hierarchical + separator. + */ + struct StateMapOrdering + : public std::binary_function + { + bool operator()(std::string const & a1, std::string const & a2) const; + }; + } typedef std::map< std::string, detail::ConvertibleString, detail::StateMapOrdering > SocketStateMap; namespace detail { - std::string dumpState(SocketStateMap const & map); + /** \brief Helper to convert SocketStateMap to multiline string representation + \internal + */ + std::string dumpState(SocketStateMap const & map); } + /** \brief senf::SocketHandle referenced body + + \internal + + senf::SocketBody is the extended (relatively to senf::FileBody) body of + senf::SocketHandle. Every SocketHandle must have a SocketBody as it's body (and not a simple + FileBody). The casting and conversion operators defined will ensure this if used + properly. If this invariant is violated, your Program will probably crash. + */ class SocketBody - : public FileBody + : public FileBody { public: - /////////////////////////////////////////////////////////////////////////// - // Types - - typedef boost::intrusive_ptr ptr; - - /////////////////////////////////////////////////////////////////////////// - ///\name Structors and default members - ///@{ - - explicit SocketBody(std::auto_ptr protocol, bool isServer); - SocketBody(std::auto_ptr protocol, bool isServer, int fd); - - // no copy - // no conversion constructors - - ///@} - /////////////////////////////////////////////////////////////////////////// - - SocketProtocol const & protocol() const; - bool isServer(); - - void state(SocketStateMap & map, unsigned lod); + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::intrusive_ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + SocketBody(std::auto_ptr protocol, bool isServer); + /**< + \param protocol Protocol class implementing the desired + protocol + \param isServer \c true, if this socket is a server + socket, false otherwise */ + SocketBody(std::auto_ptr protocol, bool isServer, int fd); + /**< + \param protocol Protocol class implementing the desired + protocol + \param isServer \c true, if this socket is a server + socket, false otherwise + \param fd socket file descriptor */ + + // no copy + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + SocketProtocol const & protocol() const; + ///< Access the protocol instance + bool isServer(); ///< Check socket type + /**< \return \c true, if this is a server socket, \c false + otherwise */ + + void state(SocketStateMap & map, unsigned lod); + /**< \todo Move state into a virtual body member (which is + ok, since SocketBody already has virtual members). This + makes in unnecessary to reimplement dumpState and state + in every SocketHandle derived class */ private: - virtual void v_close(); - virtual void v_terminate(); - virtual bool v_eof() const; - - boost::scoped_ptr protocol_; - bool isServer_; + virtual void v_close(); ///< Close socket + /**< This override will automatically \c shutdown() the + socket whenever it is closed. + \throws senf::SystemException */ + virtual void v_terminate(); ///< Forcibly close socket + /**< This override will automatically \c shutfown() the + socket whenever it is called. Additionally it will + disable SO_LINGER to ensure, that v_terminate will not + block. Like the overriden method, this member will ignore + failures and will never throw. It therefore safe to be + called from a destructor. */ + virtual bool v_eof() const; ///< Check for eof condition + /**< Since the eof check for sockets is very protocol + dependent, this member will forward the call to + senf::SocketPolicy::eof() */ + + boost::scoped_ptr protocol_; + bool isServer_; }; } @@ -108,4 +188,5 @@ namespace senf { // Local Variables: // mode: c++ // c-file-style: "senf" +// fill-column: 100 // End: diff --git a/doclib/senf.css b/doclib/senf.css index e2086c9..f5f2de4 100644 --- a/doclib/senf.css +++ b/doclib/senf.css @@ -106,25 +106,6 @@ div.tabs ul li a:hover, div.tabs ul li#current a { background-color: #EDE497; } -div.nav { - width: auto; - background-color: white; - border: none; - border-bottom: 1px solid #AF9D00; - padding: 5px 0; - margin: 0; -} - -div.qindex { - width: auto; - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - padding: 2px; - line-height: 140%; -} - #footer { clear: both; padding: 4px 10px 4px 142px; @@ -187,74 +168,88 @@ table.senf th { font-weight: bold; } -dl.bug { +dl.bug, dl.fixme, dl.todo, dl.idea { border: 1px solid #EE0000; border-left-width: 4px; background-color: #FFDDDD; padding: 0 10px; } -dl:contains("Bug:") { +dl:contains("Bug:"), dl:contains("Fix:"), dl:contains("Todo:"), dl:contains("Idea:") { border: 1px solid #CC8888; - padding: 5px; + padding: 4px; background-color: #FFEEEE; color: #666666; + font-size: 6px; + line-height: 6px; + overflow: hidden; + height: 6px; +} + +dl:contains("Bug:"):hover, dl:contains("Fix:"):hover, +dl:contains("Todo:"):hover, dl:contains("Idea:"):hover { + line-height: inherit; + font-size: inherit; + height: auto; } -dl:contains("Bug:") a { +dl:contains("Bug:") a, dl:contains("Fix:") a, dl:contains("Todo:") a, dl:contains("Idea:") a { color: #6666FF; } dl.fixme { - border: 1px solid #EEEE00; - border-left-width: 4px; + border-color: #EEEE00; background-color: #FFFFDD; - padding: 0 10px; } dl:contains("Fix:") { - border: 1px solid #CCCC88; - padding: 5px; + border-color: #CCCC88; background-color: #FFFFEE; - color: #666666; -} - -dl:contains("Fix:") a { - color: #6666FF; } dl.todo { - border: 1px solid #00AA00; - border-left-width: 4px; + border-color: #00AA00; background-color: #DDFFDD; - padding: 0 10px; } dl:contains("Todo:") { - border: 1px solid #88CC88; - padding: 5px; + border-color: #88CC88; background-color: #EEFFEE; - color: #666666; -} - -dl:contains("Todo:") a { - color: #6666FF; } dl.idea { - border: 1px solid #AAAAAA; - border-left-width: 4px; + border-color: #AAAAAA; background-color: #EEEEEE; - padding: 0 10px; } dl:contains("Idea:") { - border: 1px solid #CCCCCC; - padding: 5px; + border-color: #CCCCCC; background-color: #F8F8F8; - color: #666666; } -dl:contains("Idea:") a { - color: #6666FF; -} \ No newline at end of file +table { + width: 100%; +} + +div.ah { + margin-right: 10px; +} + +div.nav { + width: auto; + background-color: white; + border: none; + border-bottom: 1px solid #AF9D00; + padding: 5px 0; + margin: 0; +} + +div.qindex { + width: auto; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px 0; + padding: 2px; + line-height: 140%; +} diff --git a/senfscons/Doxygen.py b/senfscons/Doxygen.py index bd493a3..9e8f1c6 100644 --- a/senfscons/Doxygen.py +++ b/senfscons/Doxygen.py @@ -15,6 +15,34 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# I have been fighting 4 problems in this implementation: +# - A Directory target will *not* call any source scanners +# - A Directory target will interpret the directory contents as +# sources not targets. This means, that if a command creates that +# directory plus contents, the target will never be up-to-date +# (since the directory contents will change with every call of +# scons) +# - Theres a bug in SCons which will produce an error message for +# directory targets if dir.sources is not set explicitly +# - the first argument to env.Clean() must be the command line target, +# with which the scons was invoked. This does not help to add +# aditional files or directories to be cleaned if you don't know +# that target (it's not possible to say 'if you clean this file, +# also clean that one' hich is, what I had expected env.Clean to +# do). +# +# Together, these problems have produced several difficulties. I have +# solved them by +# - Adding an (empty) stamp file as a (file) target. This target will +# cause source scanners to be invoked +# - Adding the documentation directory as a target (so it will be +# cleaned up which env.Clean doesn't help me to do), but *only* if +# scons is called to with the -c option +# - Setting dir.sources to the known source-list to silence the error +# message whenever a directory is added as a target +# +# You will find all this in the DoxyEmitter + import os, sys, traceback import os.path import glob @@ -165,23 +193,18 @@ def DoxyEmitter(source, target, env): out_dir = data["OUTPUT_DIRECTORY"] dir = env.Dir( os.path.join(source[0].dir.abspath, out_dir) ) dir.sources = source - targets.append(dir) + if env.GetOption('clean'): targets.append(dir) else: out_dir = '.' # add our output locations for (k, v) in output_formats.iteritems(): if data.get("GENERATE_" + k, v[0]).upper() == "YES": - # Grmpf ... need to use a File object here. The problem is, that - # Dir.scan() is implemented to just return the directory entries - # and does *not* invoke the source-file scanners .. ARGH !! dir = env.Dir( os.path.join(source[0].dir.abspath, out_dir, data.get(k + "_OUTPUT", v[1])) ) - # This is needed to silence the (wrong) 'Multiple ways to - # build the same target' message dir.sources = source node = env.File( os.path.join(dir.abspath, k.lower()+".stamp" ) ) targets.append(node) - targets.append(dir) + if env.GetOption('clean'): targets.append(dir) if data.has_key("GENERATE_TAGFILE"): targets.append(env.File( os.path.join(source[0].dir.abspath, data["GENERATE_TAGFILE"]) )) diff --git a/senfscons/SENFSCons.py b/senfscons/SENFSCons.py index 91bac5b..d2e0c48 100644 --- a/senfscons/SENFSCons.py +++ b/senfscons/SENFSCons.py @@ -218,7 +218,8 @@ def DoxyXRef(env, docs=None, "sed -e 's/\\$$title/$TITLE/g' -e 's/\\$$projectname/Overview/g' ${SOURCES[%d]} >> $TARGET" % (HTML_HEADER and 3 or 2)) - xref = env.Command("doc/html/xref.html", sources, commands) + xref = env.Command("doc/html/xref.html", sources, commands, + TITLE = TITLE) env.Alias('all_docs',xref) return xref