building log4cxx under visual studio 2013

2019-04-13 02:35发布

问题:

I am trying to build log4cxx version 0.10.0 under Visual Studio 2013. I have done all the fixes as specified in building log4cxx in vs 2010 c++.

However, it is now failing at the link stage, when trying to create log4cxx.lib, with the following errors:

unresolved external symbol __InterlockedIncrement referenced in function _apr_atomic_inc32@4
unresolved external symbol __InterlockedExchangeAdd referenced in function _apr_atomic_add32@8
unresolved external symbol __InterlockedExchange referenced in function _apr_atomic_set32@8
unresolved external symbol __InterlockedDecrement referenced in function _apr_atomic_dec32@4
unresolved external symbol __InterlockedCompareExchange referenced in function _apr_atomic_cas32@12

According to MSDN, these function should be in kernel32.lib, and I have added this to the linker, with no effect. Looking at ht elib, this appears to contain _InterlockedIncrement (single underscore) and _imp_InterlockedIncrement

Does anyone know what I can do to get it working?

Also, the fix suggested in Building log4cxx with VS 2012 on Windows 7 does not make any different

回答1:

The procedure below is a complete process for building Log4CXX under VS2013, for both 32 and 64 bit builds. Note the 32 bit build has been very lightly tested, and the 64 bit build has been slightly more extensively tested (I.E, it's the version we're using).

  1. Download apache-log4cxx-0.10.0.zip, apr-x.y.z-win32.src.zip and apr-util-1.5.4-win32.src.zip, where x ,y and z are the latest versions.
  2. Extract contents to shared directory.
  3. Rename apr-x.y.z and apr-utls-x.y.z to remove the version numbers.
  4. Apply patches to files in log4cxx. See below.
  5. For the 32 bit version, patch apr\atomic\win32\apr_atomic.c.

    1. Replace all occurrences of defined(_M_IA64) || defined(_M_AMD64)) with defined(_M_IA64) || defined(_M_AMD64) || (_MSC_VER == 1800))

      This is only really a temporary fix, but it works.

  6. Run apache-log4cxx-0.10.0\configure.bat.
  7. Patch apr-util.
    1. In include\apu.hw, change APU_HAVE_APR_ICONV to be defined as 0.
    2. In include\apr_ldap.hw, change APR_HAS_LDAP to be defined as 0.
  8. Load apache-log4cxx-0.10.0\projects\log4cxx.dsw into Visual Studio 2013. You will be prompted to upgrade the projects. Accept, and wait for the conversion to complete. This will create log4cxx.sln which you should use next time you open the project
  9. Select menu option Build->Configuration Manager. Create x64 project contexts for log4cxx, both release and debug. Check the build box for these items.
  10. Upgrade projects where required. The previous step will cause this to be required for all the other projects.​ Right click on the project in Solution Explorer and select Upgrade VC++ compiler ....
  11. If you want your debug libraries to have a different file-name from the release, right click on the log4cxx project, and select properties.
    1. Select the Debug / All platforms configuration setup.
    2. Set Configuration Properties / General / Target name to have "_d" as end of file name.
    3. Set Linker / All Options / Output File to have "_d" as end of file name.
    4. Set Linker / All Options / Import Library​ to have "_d" as end of file name.
  12. Select the appropriate active solution configuration and platform in menu Build -> Configuration manager.
  13. Build the project.

Below is the patch required for log4cxx.

diff -r .\archives\apache-log4cxx-0.10.0/src/main/cpp/loggingevent.cpp .\build_official_2\apache-log4cxx-0.10.0/src/main/cpp/loggingevent.cpp
127c127
< LoggingEvent::KeySet LoggingEvent::getMDCKeySet() const
---
> KeySet LoggingEvent::getMDCKeySet() const
129c129
<         LoggingEvent::KeySet set;
---
>         KeySet set;
188c188
< LoggingEvent::KeySet LoggingEvent::getPropertyKeySet() const
---
> KeySet LoggingEvent::getPropertyKeySet() const
190c190
<         LoggingEvent::KeySet set;
---
>         KeySet set;
diff -r .\archives\apache-log4cxx-0.10.0/src/main/cpp/propertiespatternconverter.cpp .\build_official_2\apache-log4cxx-0.10.0/src/main/cpp/propertiespatternconverter.cpp
62c62
<       LoggingEvent::KeySet keySet(event->getMDCKeySet());
---
>       KeySet keySet(event->getMDCKeySet());
64c64
<       for(LoggingEvent::KeySet::const_iterator iter = keySet.begin();
---
>       for(KeySet::const_iterator iter = keySet.begin();
diff -r .\archives\apache-log4cxx-0.10.0/src/main/cpp/xmllayout.cpp .\build_official_2\apache-log4cxx-0.10.0/src/main/cpp/xmllayout.cpp
104,105c104,105
<             LoggingEvent::KeySet propertySet(event->getPropertyKeySet());
<             LoggingEvent::KeySet keySet(event->getMDCKeySet());
---
>             KeySet propertySet(event->getPropertyKeySet());
>             KeySet keySet(event->getMDCKeySet());
109c109
<                 for (LoggingEvent::KeySet::const_iterator i = keySet.begin();
---
>                 for (KeySet::const_iterator i = keySet.begin();
123c123
<             for (LoggingEvent::KeySet::const_iterator i2 = propertySet.begin();
---
>             for (KeySet::const_iterator i2 = propertySet.begin();
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/asyncappender.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/asyncappender.h
52a53
>       LOG4CXX_LIST_DEF(LoggingEventList, log4cxx::spi::LoggingEventPtr);
197c198
<                 LOG4CXX_LIST_DEF(LoggingEventList, log4cxx::spi::LoggingEventPtr);
---
>                 
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/bytearrayinputstream.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/bytearrayinputstream.h
38a39
>         LOG4CXX_LIST_DEF(ByteList, unsigned char);
42c43
<               LOG4CXX_LIST_DEF(ByteList, unsigned char);
---
>               
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/bytearrayoutputstream.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/bytearrayoutputstream.h
40a41
>         LOG4CXX_LIST_DEF(ByteList, unsigned char);
44c45
<                  LOG4CXX_LIST_DEF(ByteList, unsigned char);
---
>                  
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/simpledateformat.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/simpledateformat.h
45a46
>         LOG4CXX_LIST_DEF(PatternTokenList, log4cxx::helpers::SimpleDateFormatImpl::PatternToken*);
78c79
<                   LOG4CXX_LIST_DEF(PatternTokenList, log4cxx::helpers::SimpleDateFormatImpl::PatternToken*);
---
>                   
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/socketoutputstream.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/helpers/socketoutputstream.h
35c35
< 
---
>               LOG4CXX_LIST_DEF(ByteList, unsigned char);
53c53
<                         LOG4CXX_LIST_DEF(ByteList, unsigned char);
---
>                         

diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/net/sockethubappender.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/net/sockethubappender.h
105c105
< 
---
>               LOG4CXX_LIST_DEF(ObjectOutputStreamList, log4cxx::helpers::ObjectOutputStreamPtr);
115c115
<                         LOG4CXX_LIST_DEF(ObjectOutputStreamList, log4cxx::helpers::ObjectOutputStreamPtr);
---
>                         
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/net/telnetappender.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/net/telnetappender.h
67c67,69
<         class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
---
>           typedef log4cxx::helpers::SocketPtr Connection;
>           LOG4CXX_LIST_DEF(ConnectionList, Connection);
>           class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
134,135d135
<                         typedef log4cxx::helpers::SocketPtr Connection;
<                         LOG4CXX_LIST_DEF(ConnectionList, Connection);
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/patternlayout.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/patternlayout.h
326a327,328
>       LOG4CXX_LIST_DEF(LoggingEventPatternConverterList, log4cxx::pattern::LoggingEventPatternConverterPtr);
>       LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
337c339
<                 LOG4CXX_LIST_DEF(LoggingEventPatternConverterList, log4cxx::pattern::LoggingEventPatternConverterPtr);
---
>                 
343c345
<                 LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
---
>                 

diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/rolling/rollingpolicybase.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/rolling/rollingpolicybase.h
44a45,46
>       LOG4CXX_LIST_DEF(PatternConverterList, log4cxx::pattern::PatternConverterPtr);
>       LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
60c62
<           LOG4CXX_LIST_DEF(PatternConverterList, log4cxx::pattern::PatternConverterPtr);
---
>           
66c68
<           LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
---
>           
diff -r .\archives\apache-log4cxx-0.10.0/src/main/include/log4cxx/spi/loggingevent.h .\build_official_2\apache-log4cxx-0.10.0/src/main/include/log4cxx/spi/loggingevent.h
54a55
>               LOG4CXX_LIST_DEF(KeySet, LogString);
155c156
<                         LOG4CXX_LIST_DEF(KeySet, LogString);
---
>       


回答2:

The cause of the linking errors is the APR (Apache Portable Runtime) library.

In the file atomic\win32\apr_atomic.c, there are calls to the various interlocked functions, in the form:

#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
    return InterlockedIncrement(mem) - 1;
#else
    return ((apr_atomic_win32_ptr_fn)InterlockedIncrement)(mem) - 1;
#endif

where apr_atomic_win32_ptr_fn is defined as

typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_fn)
(apr_uint32_t volatile *);

As the compiler is building a 32 bit executable, the second call is used. This cast causes the compiler not to recognise InterlockedIncrement as a built in, and generate a call to __InterlockedIncrement(), rather than the expected intrinsic.

As a temporary fix, I have edited the calls to use the same call as the 64 bit version.



回答3:

The following worked for me with respect to log4cxx:

VS2013 APR link issue