Personal tools
User menu

Knowledge Base/CPP/log4cxx

From Thalesians

Jump to: navigation, search

Contents

Why Apache log4cxx?

Let us consider the alternatives. If you look for C++ logging libraries, you will probably discover

Alternatives

log4cplus

The stated purpose of this project is "to port the excellent Log for Java (log4j) logging library to C++" (just like Apache log4cxx). And "this project is now in Production status". The last release was performed on 28th March, 2009 (log4cplus V1.0.3), the next release is planned for October, 2009. Currently there is log4cplus V1.0.4. Looks like this project is activer and work is being done on it.

Whereas Log for Java was created by the Software Foundation, this project doesn't seem to be formally affiliated with Apache.

log4cpp

According to its creators, "log4cpp is library of C++ classes for flexible logging to files, syslog, IDSA and other destinations. It is modeled after the Log4j Java library, staying as close to their API as is reasonable".

One problem with this project is that the newest files on its SourceForge.net page were submitted on 3rd September, 2007 (log4cpp-1.0.tar.gz). Looks like no new releases have appeared since then.

"Boost Log"

We put "Boost Log" in quotes because it is not really Boost Log. At least, you won't find it here. The library was submitted to Boost by John Torjo but was rejected on 13th February, 2008: "February 13 - Logging Library Rejected - Awaiting resubmission for new review, John Torjo has already resubmitted and Gennadiy Rozental has again volunteered to manage the review". It is unclear whether the aforementioned new review has taken place; the library is not part of the standard Boost distribution. However, John has written "Boost Logging Library v2" which presumably will be reviewed and is maintained separately from Boost libraries. However, it looks like he is maintaining it single-handedly, at least at this stage.

Conclusion

We have also looked for other people's views on the subject of logging frameworks.

A very sensible question was submitted by Matthieu Labour to comp.lang.c++ (although ages ago, on 4th September, 2003): which of these logging frameworks is "best"? (Whatever "best" means, of course.) However, Kevin Goodsell and Alf P. Steinbach seized the occasion to indulge in a charming but pointless (as far as we are concerned!) discussion of what's off-topic and what isn't off-topic and the discussion quickly reduced to tedium and bureaucracy. So we stopped reading. (To be fair, perhaps Matthieu could have phrased his question better (avoiding the word "best"), and perhaps comp.lang.c++ is a wrong place to ask the question. However, no-one ever pointed out the right place and it looks like Kevin and Alf managed to deprive Matthieu of his enthusiasm — the question never surfaced elsewhere.)

Much later Andrew Cencini posted log4cxx / log4cplus and visual studio where he ultimately "moves to log4cxx as many seem to do". That was on 11th December, 2008.

Our own subjective conclusion is that log4cxx has several advantages over the other frameworks:

  • Like most other frameworks, it is modelled on Apache log4j. Its interface is very well thought out.
  • Unlike the rest, however, it is offered by Apache themselves, who seem to be in the best position to port log4j to C++ as they are the authors of log4j.
  • For the same reason a large number of people appear to be involved in this project.
  • The last check-in to http://svn.apache.org/viewvc/logging/log4cxx/trunk/ took place only two days ago (as of 26th August, 2009).
  • The feature set is rich. "Appenders exist for the console, files, GUI components, remote socket servers, NT Event Loggers, and remote UNIX Syslog daemons. It is also possible to log asynchronously" (as mentioned [http://logging.apache.org/log4cxx/index.html here).
  • It appears that other users (see above) have favoured log4cxx over other frameworks. Of course, our googling hasn't been exhaustive, and this statement is hardly scientific.

Therefore, we concluded, we should give log4cxx a go.

Building log4cxx on Windows

First, a few comments.

Why did we write this?

We found building log4cxx on Windows a bit of a nightmare.

One of the reasons is the proliferation of obsolete and/or incomplete build process documentation.

INSTALL

Consider, for example, the file INSTALL included in apache-log4cxx-0.10.0.zip. It tells us to use

Apache Ant 1.6.1 or later
   http://ant.apache.org

and

The following files placed in the lib directory:
    apr-1.2.2.tar.gz
    apr-util-1.2.2.tar.gz

If you try using (ant -v) this combination you will get the very unpleasant

--- Nested Exception ---
class net.sf.antcontrib.cpptasks.ide.ProjectDef doesn't support the nested "comment" element.
        at org.apache.tools.ant.IntrospectionHelper.throwNotSupported(IntrospectionHelper.java:447)
        at org.apache.tools.ant.UnknownElement.handleChildren(UnknownElement.java:349)
        at org.apache.tools.ant.UnknownElement.handleChild(UnknownElement.java:569)
        at org.apache.tools.ant.UnknownElement.handleChildren(UnknownElement.java:346)
        at org.apache.tools.ant.UnknownElement.configure(UnknownElement.java:198)
        at org.apache.tools.ant.UnknownElement.maybeConfigure(UnknownElement.java:160)
        at org.apache.tools.ant.Task.perform(Task.java:347)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.Target.performTasks(Target.java:385)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
        at org.apache.tools.ant.helper.SingleCheckExecutor.executeTargets(SingleCheckExecutor.java:38)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
        at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:416)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.Target.performTasks(Target.java:385)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
        at org.apache.tools.ant.Main.runBuild(Main.java:758)
        at org.apache.tools.ant.Main.startAnt(Main.java:217)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)

No good.

Online documentation

So one should ignore INSTALL and look at http://logging.apache.org/log4cxx/building/vstudio.html instead.

Currently (26th August, 2009), we are told to perform the following initial steps:

unzip apr-1.2.11-win32-src.zip
rename apr-1.2.11 apr
unzip apr-util-1.2.10-win32-src.zip
rename apr-util-1.2.10 apr-util
cd apache-log4cxx-0.10.0
configure
configure-aprutil

One of the requirements for building log4cxx is Microsoft Windows SDK. We used the latest version, Microsoft Windows SDK for Windows Server 2008 and .NET Framework V3.5 obtainable here. Despite the awkward naming, this framework supports Windows Server 2003, Windows Server 2008, Windows Vista, Windows XP; Visual Studio 2005 and Visual Studio 2008.

What happens if we use apr-1.2.11-win32-src.zip and apr-util-1.2.10-win32-src.zip with this version of the Microsoft Windows SDK?

If we follow the steps in http://logging.apache.org/log4cxx/building/vstudio.html and attempt to build the project apr from Visual Studio 2005 we first get

multicast.c
I:\dev\apr\network_io\unix\multicast.c(137) : error C2079: 'mip' uses undefined struct 'group_source_req'
I:\dev\apr\network_io\unix\multicast.c(168) : error C2224: left of '.gsr_interface' must have struct/union 
type
I:\dev\apr\network_io\unix\multicast.c(168) : warning C4013: 'find_if_index' undefined; assuming extern 
returning int
I:\dev\apr\network_io\unix\multicast.c(169) : error C2224: left of '.gsr_group' must have struct/union type
I:\dev\apr\network_io\unix\multicast.c(169) : error C2224: left of '.gsr_group' must have struct/union type
I:\dev\apr\network_io\unix\multicast.c(169) : error C2198: 'memcpy' : too few arguments for call
I:\dev\apr\network_io\unix\multicast.c(170) : error C2224: left of '.gsr_source' must have struct/union type
I:\dev\apr\network_io\unix\multicast.c(170) : error C2224: left of '.gsr_source' must have struct/union type
I:\dev\apr\network_io\unix\multicast.c(170) : error C2198: 'memcpy' : too few arguments for call

Other people have experienced this. There is even a fix:

Index: include/apr.hw
===================================================================
--- include/apr.hw	(revision 606596)
+++ include/apr.hw	(working copy)
@@ -78,7 +78,10 @@
 
 /* Restrict the server to a subset of Windows 2000 header files by default
  */
-#define _WIN32_WINNT 0x0500
+ *
+ * In order to use the MCAST API - 0x0501 is required!
+ */
+#define _WIN32_WINNT 0x0501 /* _WIN32_WINNT_WINXP */
 #endif
 #ifndef NOUSER
 #define NOUSER
@@ -217,7 +220,7 @@
 #define APR_HAVE_IN_ADDR        1
 #define APR_HAVE_INET_ADDR      1
 #define APR_HAVE_INET_NETWORK   0
-#define APR_HAVE_IPV6           0
+#define APR_HAVE_IPV6           1
 #define APR_HAVE_MEMMOVE        1
 #define APR_HAVE_SETRLIMIT      0
 #define APR_HAVE_SIGACTION      0
Index: network_io/unix/multicast.c
===================================================================
--- network_io/unix/multicast.c	(revision 606596)
+++ network_io/unix/multicast.c	(working copy)
@@ -117,13 +117,13 @@
 #if APR_HAVE_IPV6
     struct ipv6_mreq mip6;
 #endif
-#if MCAST_JOIN_SOURCE_GROUP
+#ifdef GROUP_FILTER_SIZE
     struct group_source_req mip;
     int ip_proto;
 #endif
 
     if (source != NULL) {
-#if MCAST_JOIN_SOURCE_GROUP
+#ifdef GROUP_FILTER_SIZE
         if (sock_is_ipv4(sock)) {
             ip_proto = IPPROTO_IP;
         }

(But in our case the original line looks like

#define _WIN32_WINNT 0x0400

which means that we are looking at an even older version of apr.)

Having applied this fix we get a huge number of errors like the following:

nteventlogappender.cpp
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(91) : warning C4005: 'AF_IPX' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(460) : see previous definition of 
'AF_IPX'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(127) : warning C4005: 'AF_MAX' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(479) : see previous definition of 
'AF_MAX'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(163) : warning C4005: 'SO_DONTLINGER' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(402) : see previous definition of 
'SO_DONTLINGER'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(207) : error C2011: 'sockaddr' : 'struct' type 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(485) : see declaration of 'sockaddr'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(385) : error C2143: syntax error : missing '}' 
before 'constant'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(385) : error C2143: syntax error : missing ';' 
before 'constant'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(385) : error C2059: syntax error : 'constant'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(438) : error C2143: syntax error : missing ';' 
before '}'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(438) : error C4430: missing type specifier - 
int assumed. Note: C++ does not support default-int
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(438) : error C4430: missing type specifier - 
int assumed. Note: C++ does not support default-int
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(519) : warning C4005: 'IN_CLASSA' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(287) : see previous definition of 
'IN_CLASSA'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(525) : warning C4005: 'IN_CLASSB' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(293) : see previous definition of 
'IN_CLASSB'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(531) : warning C4005: 'IN_CLASSC' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(299) : see previous definition of 
'IN_CLASSC'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(542) : warning C4005: 'INADDR_ANY' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(304) : see previous definition of 
'INADDR_ANY'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(544) : warning C4005: 'INADDR_BROADCAST' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(306) : see previous definition of 
'INADDR_BROADCAST'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2def.h(578) : error C2011: 'sockaddr_in' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(312) : see declaration of 
'sockaddr_in'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(132) : error C2011: 'fd_set' : 'struct' type 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(68) : see declaration of 'fd_set'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(167) : warning C4005: 'FD_SET' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(102) : see previous definition of 
'FD_SET'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(176) : error C2011: 'timeval' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(111) : see declaration of 'timeval'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(232) : error C2011: 'hostent' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(167) : see declaration of 'hostent'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(245) : error C2011: 'netent' : 'struct' type 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(180) : see declaration of 'netent'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(252) : error C2011: 'servent' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(187) : see declaration of 'servent'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(264) : error C2011: 'protoent' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(199) : see declaration of 'protoent'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(360) : error C2011: 'WSAData' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(322) : see declaration of 'WSAData'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(458) : error C2011: 'sockproto' : 'struct' 
type redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(494) : see declaration of 'sockproto'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(500) : error C2011: 'linger' : 'struct' type 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(531) : see declaration of 'linger'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(513) : warning C4005: 'SOMAXCONN' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(544) : see previous definition of 
'SOMAXCONN'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(542) : warning C4005: 'FD_READ' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(562) : see previous definition of 
'FD_READ'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(545) : warning C4005: 'FD_WRITE' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(563) : see previous definition of 
'FD_WRITE'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(548) : warning C4005: 'FD_OOB' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(564) : see previous definition of 
'FD_OOB'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(551) : warning C4005: 'FD_ACCEPT' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(565) : see previous definition of 
'FD_ACCEPT'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(554) : warning C4005: 'FD_CONNECT' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(566) : see previous definition of 
'FD_CONNECT'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(557) : warning C4005: 'FD_CLOSE' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(567) : see previous definition of 
'FD_CLOSE'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1527) : error C2375: 'accept' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(735) : see declaration of 'accept'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1548) : error C2375: 'bind' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(740) : see declaration of 'bind'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1567) : error C2375: 'closesocket' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(745) : see declaration of 
'closesocket'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1586) : error C2375: 'connect' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(747) : see declaration of 'connect'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1607) : error C2375: 'ioctlsocket' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(752) : see declaration of 
'ioctlsocket'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1628) : error C2375: 'getpeername' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(757) : see declaration of 
'getpeername'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1649) : error C2375: 'getsockname' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(762) : see declaration of 
'getsockname'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1672) : error C2375: 'getsockopt' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(767) : see declaration of 
'getsockopt'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1693) : error C2375: 'htonl' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(774) : see declaration of 'htonl'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1710) : error C2375: 'htons' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(776) : see declaration of 'htons'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1728) : error C2375: 'inet_addr' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(778) : see declaration of 'inet_addr'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1745) : error C2375: 'inet_ntoa' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(780) : see declaration of 'inet_ntoa'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1763) : error C2375: 'listen' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(782) : see declaration of 'listen'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1781) : error C2375: 'ntohl' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(786) : see declaration of 'ntohl'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1798) : error C2375: 'ntohs' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(788) : see declaration of 'ntohs'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1818) : error C2375: 'recv' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(790) : see declaration of 'recv'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1843) : error C2375: 'recvfrom' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(796) : see declaration of 'recvfrom'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1869) : error C2375: 'select' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(804) : see declaration of 'select'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1893) : error C2375: 'send' : redefinition; 
different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(811) : see declaration of 'send'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1918) : error C2375: 'sendto' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(817) : see declaration of 'sendto'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1944) : error C2375: 'setsockopt' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(825) : see declaration of 
'setsockopt'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1966) : error C2375: 'shutdown' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(832) : see declaration of 'shutdown'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(1986) : error C2375: 'socket' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(836) : see declaration of 'socket'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2009) : error C2375: 'gethostbyaddr' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(843) : see declaration of 
'gethostbyaddr'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2029) : error C2375: 'gethostbyname' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(848) : see declaration of 
'gethostbyname'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2047) : error C2375: 'gethostname' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(850) : see declaration of 
'gethostname'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2067) : error C2375: 'getservbyport' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(854) : see declaration of 
'getservbyport'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2087) : error C2375: 'getservbyname' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(858) : see declaration of 
'getservbyname'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2106) : error C2375: 'getprotobynumber' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(862) : see declaration of 
'getprotobynumber'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2124) : error C2375: 'getprotobyname' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(864) : see declaration of 
'getprotobyname'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2145) : error C2375: 'WSAStartup' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(868) : see declaration of 
'WSAStartup'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2163) : error C2375: 'WSACleanup' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(872) : see declaration of 
'WSACleanup'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2180) : error C2375: 'WSASetLastError' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(874) : see declaration of 
'WSASetLastError'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2197) : error C2375: 'WSAGetLastError' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(876) : see declaration of 
'WSAGetLastError'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2214) : error C2375: 'WSAIsBlocking' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(878) : see declaration of 
'WSAIsBlocking'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2231) : error C2375: 'WSAUnhookBlockingHook' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(880) : see declaration of 
'WSAUnhookBlockingHook'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2248) : error C2375: 'WSASetBlockingHook' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(882) : see declaration of 
'WSASetBlockingHook'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2265) : error C2375: 'WSACancelBlockingCall' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(884) : see declaration of 
'WSACancelBlockingCall'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2287) : error C2375: 'WSAAsyncGetServByName' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(886) : see declaration of 
'WSAAsyncGetServByName'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2314) : error C2375: 'WSAAsyncGetServByPort' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(894) : see declaration of 
'WSAAsyncGetServByPort'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2340) : error C2375: 
'WSAAsyncGetProtoByName' : redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(902) : see declaration of 
'WSAAsyncGetProtoByName'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2365) : error C2375: 
'WSAAsyncGetProtoByNumber' : redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(909) : see declaration of 
'WSAAsyncGetProtoByNumber'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2390) : error C2375: 'WSAAsyncGetHostByName' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(916) : see declaration of 
'WSAAsyncGetHostByName'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2417) : error C2375: 'WSAAsyncGetHostByAddr' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(923) : see declaration of 
'WSAAsyncGetHostByAddr'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2440) : error C2375: 'WSACancelAsyncRequest' 
: redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(932) : see declaration of 
'WSACancelAsyncRequest'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(2461) : error C2375: 'WSAAsyncSelect' : 
redefinition; different linkage
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(934) : see declaration of 
'WSAAsyncSelect'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(3910) : error C2059: syntax error : '}'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(3910) : error C2143: syntax error : missing 
';' before '}'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock2.h(3910) : error C2059: syntax error : '}'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(39) : error C2143: syntax error : missing 
';' before '{'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(39) : error C2447: '{' : missing function 
header (old-style formal list?)
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(119) : warning C4005: 'IP_TOS' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(352) : see previous definition of 
'IP_TOS'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(120) : warning C4005: 'IP_TTL' : macro 
redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(351) : see previous definition of 
'IP_TTL'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(121) : warning C4005: 'IP_MULTICAST_IF' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(346) : see previous definition of 
'IP_MULTICAST_IF'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(122) : warning C4005: 'IP_MULTICAST_TTL' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(347) : see previous definition of 
'IP_MULTICAST_TTL'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(123) : warning C4005: 'IP_MULTICAST_LOOP' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(348) : see previous definition of 
'IP_MULTICAST_LOOP'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(124) : warning C4005: 'IP_ADD_MEMBERSHIP' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(349) : see previous definition of 
'IP_ADD_MEMBERSHIP'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(125) : warning C4005: 'IP_DROP_MEMBERSHIP' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(350) : see previous definition of 
'IP_DROP_MEMBERSHIP'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2ipdef.h(126) : warning C4005: 'IP_DONTFRAGMENT' : 
macro redefinition
        C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\winsock.h(353) : see previous definition of 
'IP_DONTFRAGMENT'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(750) : error C2061: syntax error : 
identifier 'MULTICAST_MODE_TYPE'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(757) : error C2065: 'PIP_MSFILTER' : 
undeclared identifier
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(757) : error C2146: syntax error : missing 
';' before identifier 'Filter'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(757) : error C2065: 'Filter' : undeclared 
identifier
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(759) : error C2065: 'SourceCount' : 
undeclared identifier
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(760) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(760) : error C2065: 'SourceList' : 
undeclared identifier
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(760) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(761) : error C3861: 'WSASetLastError': 
identifier not found
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(765) : error C2065: 'IP_MSFILTER' : 
undeclared identifier
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(765) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(766) : error C2146: syntax error : missing 
';' before identifier 'HeapAlloc'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(768) : error C3861: 'WSASetLastError': 
identifier not found
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(772) : error C2227: left of 
'->imsf_multiaddr' must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(773) : error C2227: left of 
'->imsf_interface' must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(774) : error C2227: left of '->imsf_fmode' 
must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(774) : error C2065: 'FilterMode' : 
undeclared identifier
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(775) : error C2227: left of '->imsf_numsrc' 
must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(778) : error C2227: left of '->imsf_slist' 
must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(778) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(795) : error C2061: syntax error : 
identifier 'MULTICAST_MODE_TYPE'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(802) : error C2146: syntax error : missing 
';' before identifier 'Filter'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(805) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(805) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(806) : error C3861: 'WSASetLastError': 
identifier not found
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(810) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(811) : error C2146: syntax error : missing 
';' before identifier 'HeapAlloc'
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(813) : error C3861: 'WSASetLastError': 
identifier not found
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(817) : error C2227: left of 
'->imsf_multiaddr' must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(818) : error C2227: left of 
'->imsf_interface' must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(819) : error C2227: left of '->imsf_numsrc' 
must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(827) : error C2227: left of '->imsf_slist' 
must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(827) : error C2070: ''unknown-type'': 
illegal sizeof operand
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(828) : error C2227: left of '->imsf_numsrc' 
must point to class/struct/union/generic type
        type is ''unknown-type''
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(830) : error C2227: left of '->imsf_fmode' 
must point to class/struct/union/generic type
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\ws2tcpip.h(830) : fatal error C1003: error count 
exceeds 100; stopping compilation

All this means that winsock.h and winsock2.h are both being included and there can be only one!

The correct instructions

Building log4cxx

Rather than patching apr or Microsoft Windows SDK we attempt to use the latest versions of apr and apr-util where these problems have been fixed. (Spoiler: it works!)

(Is it obvious that we should be using the latest versions, you may ask? In our opinion, not at all!)

Thus the correct instructions (as of 26th August, 2009) are as follows.

Prerequisites
GnuWin32

We will need sed and some other *nix tools — their Windows ports. We use GnuWin32 which we have under

  • C:\Programs\Win32\GnuWin32\

which you can download using GetGnuWin32.

This has sed, among other things.

Important: You should add

  • C:\Programs\Win32\GnuWin32\bin\

(or wherever sed.exe lives) to your PATH environment variable.

Windows SDK

Windows SDK is a prerequisite. We are using Windows SDK for Windows Server 2008 and .NET Framework 3.5, obtainable from

Once you have installed the SDK using setup.exe, you will see its files (typically) under

  • "C:\Program Files\Microsoft SDKs\Windows\v6.1\"

Important: In order to make the header files visible to the C++ compiler, you should add

  • /I"C:\Program Files\Microsoft SDKs\Windows\v6.1\Include" /I"C:\Program Files\Microsoft Visual Studio 8\VC\include"

to your CL environment variable.

APR

"The mission of the Apache Portable Runtime (APR) project is to create and maintain software libraries that provide a predictable and consistent interface to underlying platform-specific implementations" (http://apr.apache.org/). In each case, both APR and APR-UTIL are required.

Choose a directory (we chose I:\dev\apache-log4cxx-0.10.0\) and download

to this directory.

Preparation

Then, from this directory:

unzip apr-1.3.8-win32-src.zip
rename apr-1.3.8 apr
unzip apr-util-1.3.9-win32-src.zip
rename apr-util-1.3.9 apr-util
cd apache-log4cxx-0.10.0
configure
configure-aprutil

configure.bat copies the prefabricated log4cxx.hw and private/log4cxx_private.hw over to log4cxx.h and private/log4cxx_private.h.

configure-aprutil.bat uses sed to modify apu.hw and apr_ldap.hw to disable APR-Iconv and LDAP which are not necessary for log4cxx and problematic to build. If sed is not available, the modifications would be trivial to do in any text editor.

Use the Win32 source zips for APR and APR-Util to preserve the required line endings for the project files. Directories need to be renamed to "apr" and "apr-util" respectively.

Building log4cxx.dll

Open I:/dev/apache-log4cxx-0.10.0/projects/log4cxx.dsw with Microsoft Visual Studio 2005. You will be asked to convert the *.dsw Microsoft Visual Studio 6 project files to the *.sln and *.vcproj Microsoft Visual Studio 2005 project files. Agree to this, and continue.

Select "Debug" from the configuration drop-down list. Then Build > Build Solution. This should produce

  • I:\dev\apache-log4cxx-0.10.0\projects\Debug\log4cxx.dll

Select "Release" from the configuration drop-down list. Then Build > Build Solution. This should produce

  • I:\dev\apache-log4cxx-0.10.0\projects\Release\log4cxx.dll

Building log4cxx test suite

Prerequisites
Environment Variables

We are about to change the environment variables. For changes to take effect, close Visual Studio 2005.

Go to Control Panel > System > Advanced > Environment Variables and set the system variables

TOTO=wonderful
key1=value1
key2=value2
*nix tools

You need gzip, zip and sed to run the tests. They must be on your PATH.

But if you have installed GnuWin32 as we advised you will find all of these under

  • C:\Programs\Win32\GnuWin32\bin\
Building the test suite

Open I:\dev\apache-log4cxx-0.10.0\projects\testsuite.dsw. You will be asked to convert the project to Visual Studio 2005. Confirm this in the dialog boxes.

Select "Debug" from the configuration drop-down list. Then Build > Build Solution. This should produce

  • I:\dev\apache-log4cxx-0.10.0\projects\Debug\testsuite.exe

Select "Release" from the configuration drop-down list. Then Build > Build Solution. This should produce

  • I:\dev\apache-log4cxx-0.10.0\projects\Release\testsuite.exe
Running the test suite

Right-click on the testsuite project in Solution Explorer. Click on "Set as StartUp Project".

Right-click on the testsuite project (again). Click on "Properties". Select Congfiguration: "All Configurations". Under Configuration Properties > Debugging set Working Directory to ../src/test/resources. Click OK.

From the menu, Debug > Start Without Debugging.

Building log4cxx on Linux

We found it easier to build log4cxx on Linux. Maybe this is because we learned some lessons from the Windoes build. In each case we decided to document the procedure.

The original document by Apache can be found here:

Note that there are some differences between our procedure and theirs. We didn't have to sudo make install anything in order to get this to work. This may be useful, particularly if you are not a sudoer or do not have root access.

Prerequisites

System

We have built log4cxx on

  • Linux V2.4.21

using

  • gcc V3.2.3
  • GNU Make V3.79.1

gcc must be on the PATH.

APR

We downloaded

to

  • /home/paul/dev

Building APR

The following steps should build APR:

cd /home/paul/dev
gzip -d apr-1.3.8.tar.gz
tar xvf apr-1.3.8.tar
cd apr-1.3.8
./configure
make
make check

The last command should show something like

...
testsockopt         : SUCCESS
teststr             : SUCCESS
teststrnatcmp       : SUCCESS
testtable           : SUCCESS
testtemp            : SUCCESS
testthread          : SUCCESS
testtime            : SUCCESS
testud              : SUCCESS
testuser            : SUCCESS
testvsn             : SUCCESS
All tests passed.
ia32make[1]: Leaving directory `/home/paul/dev/apr-1.3.8/test'

This should have produced

  • /home/paul/dev/apr-1.3.8/.libs/libapr-1.a

Building APR Util

We used the following sequence:

cd ..
gzip -d apr-util-1.3.9.tar.gz
tar xvf apr-util-1.3.9.tar
cd apr-util-1.3.9
./configure --with-apr=../apr-1.3.8
make
make check

The last command should produce something like

...
testmd5             : SUCCESS
testdbd             : SUCCESS
testdate            : SUCCESS
testmemcache        : SUCCESS
testxml             : SUCCESS
testxlate           : SUCCESS
testrmm             : SUCCESS
testdbm             : SUCCESS
testqueue           : SUCCESS
testreslist         : SUCCESS
All tests passed.

This should have produced

  • /home/paul/dev/apr-util-1.3.9/.libs/libaprutil-1.a

Building log4cxx

Finally,

cd ..
unzip apache-log4cxx-0.10.0.zip
cd apache-log4cxx-0.10.0
./configure --with-apr=../apr-1.3.8 --with-apr-util=../apr-util-1.3.9
make
make check

The last command should produce

testcase3           : SUCCESS
All tests passed.
../cpp/testsuite -v testcase4
LC_CTYPE: C
testcase4           : SUCCESS
All tests passed.
ia32make[3]: Leaving directory `/home/paul/dev/apache-log4cxx-0.10.0/src/test/resources'
ia32make[3]: Entering directory `/home/paul/dev/apache-log4cxx-0.10.0/src/test'
ia32make[3]: Nothing to be done for `check-am'.
ia32make[3]: Leaving directory `/home/paul/dev/apache-log4cxx-0.10.0/src/test'
ia32make[2]: Leaving directory `/home/paul/dev/apache-log4cxx-0.10.0/src/test'
ia32make[2]: Entering directory `/home/paul/dev/apache-log4cxx-0.10.0/src'
ia32make[2]: Nothing to be done for `check-am'.
ia32make[2]: Leaving directory `/home/paul/dev/apache-log4cxx-0.10.0/src'
ia32make[1]: Leaving directory `/home/paul/dev/apache-log4cxx-0.10.0/src'
ia32make[1]: Entering directory `/home/paul/dev/apache-log4cxx-0.10.0'
ia32make[1]: Nothing to be done for `check-am'.
ia32make[1]: Leaving directory `/home/paul/dev/apache-log4cxx-0.10.0'

if we succeeded.

This should have produced

  • /home/paul/dev/apache-log4cxx-0.10.0/src/main/cpp/.libs/liblog4cxx.a

Using Apache log4cxx

Here are some basic examples.

Don't worry if you see log4j in these examples. We are still on the C++ territory; the authors decided to stay faithful to the original log4j implementation, hence the names.

BasicConfigurator

  1. #include <log4cxx/logger.h>
  2. #include <log4cxx/basicconfigurator.h>
  3.  
  4. #include <tchar.h>
  5.  
  6. using namespace log4cxx;
  7.  
  8. LoggerPtr logger(Logger::getRootLogger());
  9.  
  10. int _tmain(int argc, _TCHAR* argv[])
  11. {
  12. BasicConfigurator::configure();
  13.  
  14. LOG4CXX_DEBUG(logger, _T("This is a debug message"));
  15. LOG4CXX_INFO(logger, _T("This is an info message"));
  16. LOG4CXX_WARN(logger, _T("This is a warn message"));
  17. LOG4CXX_ERROR(logger, _T("This is an error message"));
  18. LOG4CXX_FATAL(logger, _T("This is a fatal message"));
  19.  
  20. return 0;
  21. }

This produced the output

0 [0x00000dd4] DEBUG root null - This is a debug message
0 [0x00000dd4] INFO root null - This is an info message
0 [0x00000dd4] WARN root null - This is a warn message
0 [0x00000dd4] ERROR root null - This is an error message
0 [0x00000dd4] FATAL root null - This is a fatal message

Modifying BasicConfigurator configuration

It is possible to tweak the configuration produced by BasicConfigurator::configure. Here is an example.

  1. #include <log4cxx/logger.h>
  2. #include <log4cxx/basicconfigurator.h>
  3. #include <log4cxx/patternlayout.h>
  4.  
  5. #include <tchar.h>
  6.  
  7. using namespace log4cxx;
  8.  
  9. LoggerPtr logger(Logger::getRootLogger());
  10.  
  11. int _tmain(int argc, _TCHAR* argv[])
  12. {
  13. BasicConfigurator::configure();
  14.  
  15. LoggerPtr logger(Logger::getRootLogger());
  16. logger->setLevel(Level::getInfo());
  17. AppenderList appenders(logger->getAllAppenders());
  18. appenders[0]->setLayout(new PatternLayout(LOG4CXX_STR("%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p [%t] (%F:%L) - %m%n")));
  19.  
  20. LOG4CXX_DEBUG(logger, _T("This is a debug message"));
  21. // The above line should have no effect as we have done
  22. // logger->setLevel(Level::getInfo());
  23. LOG4CXX_INFO(logger, _T("This is an info message"));
  24. LOG4CXX_WARN(logger, _T("This is a warn message"));
  25. LOG4CXX_ERROR(logger, _T("This is an error message"));
  26. LOG4CXX_FATAL(logger, _T("This is a fatal message"));
  27.  
  28. return 0;
  29. }

DOMConfigurator

The source file:

  1. #include <log4cxx/logger.h>
  2. #include <log4cxx/xml/domconfigurator.h>
  3.  
  4. #include <tchar.h>
  5.  
  6. using namespace log4cxx;
  7. using namespace log4cxx::xml;
  8.  
  9. LoggerPtr logger(Logger::getRootLogger());
  10.  
  11. int _tmain(int argc, _TCHAR* argv[])
  12. {
  13. DOMConfigurator::configure("DevLogConfig.xml");
  14.  
  15. LOG4CXX_DEBUG(logger, _T("This is a debug message"));
  16. LOG4CXX_INFO(logger, _T("This is an info message"));
  17. LOG4CXX_WARN(logger, _T("This is a warn message"));
  18. LOG4CXX_ERROR(logger, _T("This is an error message"));
  19. LOG4CXX_FATAL(logger, _T("This is a fatal message"));
  20.  
  21. return 0;
  22. }

The configuration file, DevLogConfig.xml:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <root>
  5. <priority value="all" />
  6. <appender-ref ref="ConsoleAppender" />
  7. </root>
  8.  
  9. <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
  10. <param name="Target" value="System.out" />
  11. <layout class="org.apache.log4j.PatternLayout">
  12. <param name="ConversionPattern" value="%5p [%t] (%F:%L) - %m%n" />
  13. </layout>
  14. </appender>
  15. </log4j:configuration>

The output:

DEBUG [0x000012a4] (.\proto-log4cxx.cpp:15) - This is a debug message
 INFO [0x000012a4] (.\proto-log4cxx.cpp:16) - This is an info message
 WARN [0x000012a4] (.\proto-log4cxx.cpp:17) - This is a warn message
ERROR [0x000012a4] (.\proto-log4cxx.cpp:18) - This is an error message
FATAL [0x000012a4] (.\proto-log4cxx.cpp:19) - This is a fatal message

Note that we have chosen to call our appender ConsoleAppender by specifying

<appender name="ConsoleAppender" ...

Of course, we could have called it something else. (But the class tells us what implements the appender, so it has to be org.apache.log4j.ConsoleAppender.)

FileAppender

Of course, more often than not, we need to log to a file. We don't need to change any code. Just update DevLogConfig.xml in the example above to

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <root>
  5. <priority value="all" />
  6. <appender-ref ref="ConsoleAppender" />
  7. <appender-ref ref="FileAppender" />
  8. </root>
  9.  
  10. <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
  11. <param name="Target" value="System.out" />
  12. <layout class="org.apache.log4j.PatternLayout">
  13. <param name="ConversionPattern" value="%5p [%t] (%F:%L) - %m%n" />
  14. </layout>
  15. </appender>
  16.  
  17. <appender name="FileAppender" class="org.apache.log4j.FileAppender">
  18. <param name="File" value="C:/MyApp.log" />
  19. <param name="Append" value="true" />
  20. <layout class="org.apache.log4j.PatternLayout">
  21. <param name="ConversionPattern" value="%5p [%t] (%F:%L) - %m%n" />
  22. </layout>
  23. </appender>
  24. </log4j:configuration>

This will produce the output

DEBUG [0x00000990] (.\proto-log4cxx.cpp:15) - This is a debug message
 INFO [0x00000990] (.\proto-log4cxx.cpp:16) - This is an info message
 WARN [0x00000990] (.\proto-log4cxx.cpp:17) - This is a warn message
ERROR [0x00000990] (.\proto-log4cxx.cpp:18) - This is an error message
FATAL [0x00000990] (.\proto-log4cxx.cpp:19) - This is a fatal message

both on the console and in C:/MyApp.log. Of course, it's the same in both cases only because we are using identical ConversionPattern in the two appenders.

ConversionPattern

This is a good time to discuss the ConversionPattern. We were using

%5p [%t] (%F:%L) - %m%n

to get:

%5p   %t           (%F                 :%L) - %m                     %n
 INFO [0x00000990] (.\proto-log4cxx.cpp:16) - This is an info message

But we could try something fancier, such as

%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p [%t] (%F:%L) - %m%n

which would give us

2009-08-27 14:00:50,259 31 INFO  [0x00000b28] (.\proto-log4cxx.cpp:16) - This is an info message

Here is this line along with the conversion pattern, side by side:

%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p  [%t        ] (%F                 :%L) - %m                     %n
   2009-08-27 14:00:50,259  31 INFO  [0x00000b28] (.\proto-log4cxx.cpp:16) - This is an info message

We could use a brief conversion pattern in our ConsoleAppender and a more comprehensive one in our FileAppender:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <root>
  5. <priority value="all" />
  6. <appender-ref ref="ConsoleAppender" />
  7. <appender-ref ref="FileAppender" />
  8. </root>
  9.  
  10. <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
  11. <param name="Target" value="System.out" />
  12. <layout class="org.apache.log4j.PatternLayout">
  13. <param name="ConversionPattern" value="%r %-5p - %m%n" />
  14. </layout>
  15. </appender>
  16.  
  17. <appender name="FileAppender" class="org.apache.log4j.FileAppender">
  18. <param name="File" value="C:/MyApp.log" />
  19. <param name="Append" value="true" />
  20. <layout class="org.apache.log4j.PatternLayout">
  21. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p [%t] (%F:%L) - %m%n" />
  22. </layout>
  23. </appender>
  24. </log4j:configuration>

On the screen, we'll see

46 DEBUG - This is a debug message
46 INFO  - This is an info message
46 WARN  - This is a warn message
46 ERROR - This is an error message
62 FATAL - This is a fatal message

But in C:/MyApp.log we'll have more information:

2009-08-27 14:04:44,618 46 DEBUG [0x00001584] (.\proto-log4cxx.cpp:15) - This is a debug message
2009-08-27 14:04:44,618 46 INFO  [0x00001584] (.\proto-log4cxx.cpp:16) - This is an info message
2009-08-27 14:04:44,618 46 WARN  [0x00001584] (.\proto-log4cxx.cpp:17) - This is a warn message
2009-08-27 14:04:44,618 46 ERROR [0x00001584] (.\proto-log4cxx.cpp:18) - This is an error message
2009-08-27 14:04:44,634 62 FATAL [0x00001584] (.\proto-log4cxx.cpp:19) - This is a fatal message

The conversion characters, like "%r" (which is, by the way, the number of milliseconds elapsed since the start of the application until the creation of the logging event) are documented here.

Reconfiguring log4cxx dynamically

Is it possible to reconfigure log4cxx on the fly after it has already been configured? Apparently it is.

Code:

  1. #include <log4cxx/logger.h>
  2. #include <log4cxx/basicconfigurator.h>
  3. #include <log4cxx/xml/domconfigurator.h>
  4.  
  5. #include <tchar.h>
  6.  
  7. using namespace log4cxx;
  8. using namespace log4cxx::xml;
  9.  
  10. LoggerPtr logger(Logger::getRootLogger());
  11.  
  12. int _tmain(int argc, _TCHAR* argv[])
  13. {
  14. // First, use BasicConfigurator
  15. BasicConfigurator::configure();
  16.  
  17. LOG4CXX_DEBUG(logger, _T("This is a debug message"));
  18. LOG4CXX_INFO(logger, _T("This is an info message"));
  19. LOG4CXX_WARN(logger, _T("This is a warn message"));
  20. LOG4CXX_ERROR(logger, _T("This is an error message"));
  21. LOG4CXX_FATAL(logger, _T("This is a fatal message"));
  22.  
  23. // Now, reconfigured using DOMConfigurator
  24. DOMConfigurator::configure("DevLogConfig.xml");
  25.  
  26. LOG4CXX_DEBUG(logger, _T("This is a debug message"));
  27. LOG4CXX_INFO(logger, _T("This is an info message"));
  28. LOG4CXX_WARN(logger, _T("This is a warn message"));
  29. LOG4CXX_ERROR(logger, _T("This is an error message"));
  30. LOG4CXX_FATAL(logger, _T("This is a fatal message"));
  31.  
  32. return 0;
  33. }

Output:

0 [0x00001110] DEBUG root null - This is a debug message
0 [0x00001110] INFO root null - This is an info message
0 [0x00001110] WARN root null - This is a warn message
0 [0x00001110] ERROR root null - This is an error message
0 [0x00001110] FATAL root null - This is a fatal message
31 DEBUG - This is a debug message
31 INFO  - This is an info message
31 WARN  - This is a warn message
31 ERROR - This is an error message
31 FATAL - This is a fatal message

Detecting user name and directory; system properties

In production, the process may not have the permission to access C:/MyApp.log. It is more sensible to place it under the user's home directory:

"C:\Documents and Settings\paul\MyApp.log"

But how do we know, in our DevLogConfig.xml where it is at runtime?

Also, it may be useful to output the username as part of our message, particularly in multi-user systems.

We can use the properties ${user.home} and ${user.name}:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <root>
  5. <priority value="all" />
  6. <appender-ref ref="ConsoleAppender" />
  7. <appender-ref ref="FileAppender" />
  8. </root>
  9.  
  10. <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
  11. <param name="Target" value="System.out" />
  12. <layout class="org.apache.log4j.PatternLayout">
  13. <param name="ConversionPattern" value="%r %-5p - %m%n" />
  14. </layout>
  15. </appender>
  16.  
  17. <appender name="FileAppender" class="org.apache.log4j.FileAppender">
  18. <param name="File" value="${user.home}/MyApp.log" />
  19. <param name="Append" value="true" />
  20. <layout class="org.apache.log4j.PatternLayout">
  21. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  22. </layout>
  23. </appender>
  24. </log4j:configuration>

In summary, the Logsystem properties that <tt>log4cxx supports are:

  • java.io.tmpdir — the temporary directory, something like C:/Documents and Settings/paul/Local Settings/Temp
  • user.dir — the user's current directory (not home directory!)
  • user.home — the user's home directory, something like C:/Documents and Settings/paul/Local Settings/Temp
  • user.name — the username, something like paul

Logging to Windows NT/XP/etc. Event Log

Simply add a org.apache.log4j.nt.NTEventLogAppender log appender to DevLogConfig.xml which we use in the above examples:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <root>
  5. <priority value="all" />
  6. <appender-ref ref="ConsoleAppender" />
  7. <appender-ref ref="FileAppender" />
  8. <appender-ref ref="NTEventLogAppender" />
  9. </root>
  10.  
  11. <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
  12. <param name="Target" value="System.out" />
  13. <layout class="org.apache.log4j.PatternLayout">
  14. <param name="ConversionPattern" value="%r %-5p - %m%n" />
  15. </layout>
  16. </appender>
  17.  
  18. <appender name="FileAppender" class="org.apache.log4j.FileAppender">
  19. <param name="File" value="${user.home}/MyApp.log" />
  20. <param name="Append" value="true" />
  21. <layout class="org.apache.log4j.PatternLayout">
  22. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  23. </layout>
  24. </appender>
  25.  
  26. <appender name="NTEventLogAppender" class="org.apache.log4j.nt.NTEventLogAppender">
  27. <param name="Source" value="MyApp" />
  28. <layout class="org.apache.log4j.PatternLayout">
  29. <param name="ConversionPattern" value="%r %-5p [%t] (%F:%L) - %m%n" />
  30. </layout>
  31. </appender>
  32. </log4j:configuration>

You should now be able to view the logged events in Event Viewer (Control Panel > Administrative Tools > Event Viewer), under the Event Viewer (Local) > Application log.

We can add a threshold to the NTEventLogAppender definition so only the WARN, ERROR, and FATAL level events get logged. In order to do this, we amend the corresponding appender section as follows:

  1. ...
  2. <appender name="NTEventLogAppender" class="org.apache.log4j.nt.NTEventLogAppender">
  3. <param name="Threshold" value="WARN" />
  4. <param name="Source" value="MyApp" />
  5. <layout class="org.apache.log4j.PatternLayout">
  6. <param name="ConversionPattern" value="%r %-5p [%t] (%F:%L) - %m%n" />
  7. </layout>
  8. </appender>
  9. ...

Rolling file appenders

Here is an example size-based rolling file appender:

  1. ...
  2. <appender name="SizeBasedRollingFileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
  3. <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
  4. <param name="MaxFileSize" value="100KB" />
  5. </triggeringPolicy>
  6. <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
  7. <param name="FileNamePattern" value="${user.home}/MyApp-%i.log" />
  8. <param name="MaxIndex" value="10" />
  9. </rollingPolicy>
  10. <layout class="org.apache.log4j.PatternLayout">
  11. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  12. </layout>
  13. </appender>
  14. ...

and a time-based rolling file appender:

  1. ...
  2. <appender name="TimeBasedRollingFileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
  3. <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
  4. <param name="FileNamePattern" value="${user.home}/MyApp-%d{yyyy-MM-dd_HH_mm}.log" />
  5. </rollingPolicy>
  6.  
  7. <layout class="org.apache.log4j.PatternLayout">
  8. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  9. </layout>
  10. </appender>
  11. ...

A new log file will be created every minute. If you want it created every hour, simply replace the line

<param name="FileNamePattern" value="${user.home}/MyApp-%d{yyyy-MM-dd_HH_mm}.log" />

with

<param name="FileNamePattern" value="${user.home}/MyApp-%d{yyyy-MM-dd_HH}.log" />

The rest is pretty self-explanatory.

A Summary So Far

We have mentioned quite a few different appenders and techniques, so it's probably a good idea to examine a configuration file that includes all/most of them. Here it is:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <root>
  5. <priority value="all" />
  6. <appender-ref ref="ConsoleAppender" />
  7. <appender-ref ref="FileAppender" />
  8. <appender-ref ref="SizeBasedRollingFileAppender" />
  9. <appender-ref ref="TimeBasedRollingFileAppender" />
  10. <appender-ref ref="NTEventLogAppender" />
  11. </root>
  12.  
  13. <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
  14. <param name="Target" value="System.out" />
  15. <layout class="org.apache.log4j.PatternLayout">
  16. <param name="ConversionPattern" value="%r %-5p - %m%n" />
  17. </layout>
  18. </appender>
  19.  
  20. <appender name="FileAppender" class="org.apache.log4j.FileAppender">
  21. <param name="File" value="${user.home}/MyApp.log" />
  22. <param name="Append" value="true" />
  23. <layout class="org.apache.log4j.PatternLayout">
  24. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  25. </layout>
  26. </appender>
  27.  
  28. <appender name="SizeBasedRollingFileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
  29. <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
  30. <param name="MaxFileSize" value="100KB" />
  31. </triggeringPolicy>
  32. <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
  33. <param name="FileNamePattern" value="${user.home}/MyApp-%i.log"/>
  34. <param name="MaxIndex" value="10"/>
  35. </rollingPolicy>
  36. <layout class="org.apache.log4j.PatternLayout">
  37. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  38. </layout>
  39. </appender>
  40.  
  41. <appender name="TimeBasedRollingFileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
  42. <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
  43. <param name="FileNamePattern" value="${user.home}/MyApp-%d{yyyy-MM-dd_HH_mm}.log"/>
  44. </rollingPolicy>
  45.  
  46. <layout class="org.apache.log4j.PatternLayout">
  47. <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %r %-5p ${user.name} [%t] (%F:%L) - %m%n" />
  48. </layout>
  49. </appender>
  50.  
  51. <appender name="NTEventLogAppender" class="org.apache.log4j.nt.NTEventLogAppender">
  52. <param name="Threshold" value="WARN" />
  53. <param name="Source" value="MyApp" />
  54. <layout class="org.apache.log4j.PatternLayout">
  55. <param name="ConversionPattern" value="%r %-5p [%t] (%F:%L) - %m%n" />
  56. </layout>
  57. </appender>
  58. </log4j:configuration>
  • This page was last modified on 6 October 2009, at 15:46.
  • This page has been accessed 50,006 times.