views:

849

answers:

2

I'm investigating using SCons for our build process as we develop C++ for multiple platforms. I'm 99% of the way there in the build configuration, but I'm running into a VERY strange error on Windows having to do with the precompiled header file. Even stranger still is that it only happens on one project.

In the SConscript file for this project, I have the following to compile the PCH on windows:

if env['PLATFORM'] == 'win32':
    env['PCH'] = env.PCH('MyPCH-LSCommon.pch', 'Common/src/MyPCH.h')[0]
    env['PCHSTOP'] = '"MyPCH.h"'

I also have a compiler flag set to force include MyPCH.h on all files in the project:

if env['PLATFORM'] == 'win32':
    cxxflags = [ '/FI"MyPCH.h"' ]

Everything goes along and compiles absolutely fine. It isn't until the final DLL link stage that I get pages and pages of linker errors such as the following:

error LNK2001: unresolved external symbol "private: static class
boost::asio::detail::tss_ptr<class boost::asio::detail::call_stack<class 
boost::asio::detail::win_iocp_io_service>::context> boost::asio::detail::call_stack<class 
boost::asio::detail::win_iocp_io_service>::top_" 
(?top_@?$call_stack@Vwin_iocp_io_service@detail@asio@boost@@@detail@asio@boost@@0V?$tss_ptr@
Vcontext@?$call_stack@Vwin_iocp_io_service@detail@asio@boost@@@detail@asio@boost@@@234@A)

and:

     error LNK2001: unresolved external symbol "private: static class 
boost::asio::detail::winsock_init<2,0> boost::asio::detail::winsock_init<2,0>::instance_" 
(?instance_@?$winsock_init@$01$0A@@detail@asio@boost@@0V1234@A)

This is puzzling because none of the classes that I'm getting link warnings from don't even use boost::asio, although it is included in the precompiled header file and up the chain in some #includes.

Even more puzzling is that if I disable compilation of the precompiled header file, yet still force it's include, everything compiles and links just fine. It just takes freaking forever.

Does anyone have a clue as to what could be causing these linker errors?

Thanks in advance.

--- EDIT ---

Here's the command line that SCons is spitting out for building the PCH (Minus Include Paths):

    cl /nologo /W4 /Od /RTC1 /MDd /TP /EHsc /FD /RTC1 /RTCc /Gy /openmp /TP 
/Fd"\vc80.pdb" /nologo /Wp64 /wd4231 /wd4616 /errorReport:prompt /Zm256 /MDd /Od
/FI"CedrusPCH.h" /DOS_WINDOWS=OS_WINDOWS /D_WIN32 /DWIN32 /D_WIN32_WINNT=0X500 /D_WINDOWS 
/D_UNICODE /DBOOST_ALL_DYN_LINK /DBOOST_REGEX_DYN_LINK /DBOOST_LIB_DIAGNOSTIC 
/D_VC80_UPGRADE=0x710 /DUNICODE /DWXUSINGDLL /DwxUSE_SERVICE_DISCOVERY=1 /D_DEBUG /D_DEBUG 
/DSL_ENABLE_NETWORKING=1 /DWXMAKINGDLL_LSCOMMON /DSLSDK_USEDLL 
/c C:\Projects\licenser\Common\src\CedrusPCH.h /Foscons-out\dbg\obj\CedrusPCH-LSCommon.obj
/Yc"CedrusPCH.h" /Fpscons-out\dbg\obj\CedrusPCH-LSCommon.pch /ZI CedrusPCH.h

Here's the command line for a file being compiled (again minus include paths):

cl /Foscons-out\dbg\obj\Licenser\src\secure\windows_crypto
\PlatformCryptoKeyProvider_wincrypt.obj /c C:\Projects\licenser\Licenser\src\secure
\windows_crypto\PlatformCryptoKeyProvider_wincrypt.cpp /nologo /W4 /Od /RTC1 /MDd /TP 
/EHsc /FD /RTC1 /RTCc /Gy /openmp /TP /Fd"\vc80.pdb" /nologo /Wp64 /wd4231 /wd4616 
/errorReport:prompt /Zm256 /MDd /Od /FI"CedrusPCH.h" /nologo /W4 /Od /RTC1 /MDd 
/DOS_WINDOWS=OS_WINDOWS /D_WIN32 /DWIN32 /D_WIN32_WINNT=0X500 /D_WINDOWS /D_UNICODE 
/DBOOST_ALL_DYN_LINK /DBOOST_REGEX_DYN_LINK /DBOOST_LIB_DIAGNOSTIC /D_VC80_UPGRADE=0x710 
/DUNICODE /DWXUSINGDLL /DwxUSE_SERVICE_DISCOVERY=1 /D_DEBUG /D_DEBUG 
/DSL_ENABLE_NETWORKING=1 /DWXMAKINGDLL_LSCOMMON /DSLSDK_USEDLL /D_USRDLL /D_WINDLL 
 /Yu"CedrusPCH.h" /Fpscons-out\dbg\obj\CedrusPCH-LSCommon.pch /ZI
PlatformCryptoKeyProvider_wincrypt.cpp

And finally, here's the link command line:

link /nologo /MACHINE:X86 /DEBUG -manifest /dll /out:scons-out\dbg\obj\LSCommon.dll 
/implib:scons-out\dbg\obj\LSCommon.lib /LIBPATH:scons-out\dbg\lib 
/LIBPATH:C:\Projects\licenser\scons-out\dbg\lib /LIBPATH:scons-out\dbg\obj 
/LIBPATH:. /LIBPATH:C:\Projects\licenser /LIBPATH:C:\Projects\licenser\scons-out\dbg\obj 
/LIBPATH:C:\Projects\wxWidgets\lib\vc_dll_vc8 /LIBPATH:C:\Projects\boost\install\lib 
"/LIBPATH:C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib" 
"/LIBPATH:C:\Program Files\Bonjour SDK\lib\win32" unicows.lib winmm.lib comctl32.lib 
rpcrt4.lib ws2_32.lib oleacc.lib kernel32.lib user32.lib gdi32.lib winspool.lib 
comdlg32.lib advapi32.lib shell32.lib oleacc.lib ole32.lib oleaut32.lib uuid.lib 
odbc32.lib odbccp32.lib boost_signals-vc80-mt-gd-1_39.lib boost_system-vc80-mt-gd-1_39.lib 
boost_date_time-vc80-mt-gd-1_39.lib boost_regex-vc80-mt-gd-1_39.lib 
boost_wserialization-vc80-mt-gd-1_39.lib boost_serialization-vc80-mt-gd-1_39.lib 
boost_thread-vc80-mt-gd-1_39.lib wxbase28ud.lib wxbase28ud_net.lib wxbase28ud_xml.lib 
wxmsw28ud_adv.lib wxmsw28ud_aui.lib wxmsw28ud_core.lib wxmsw28ud_html.lib wxmsw28ud_qa.lib 
wxmsw28ud_richtext.lib wxmsw28ud_xrc.lib LSBase.lib disphelper.lib Crypt32.lib 
/PDB:scons-out\dbg\obj\LSCommon.pdb /DEBUG 
scons-out\dbg\obj\Licenser\src\dll_template_instantiation_export_LSCommon.obj 
scons-out\dbg\obj\Licenser\src\secure\ConcreteMessageSigningAlgorithm_DSA_with_SHA1.obj 
scons-out\dbg\obj\Licenser\src\secure\CryptoObjectFactory.obj 
scons-out\dbg\obj\Licenser\src\secure\EntropyCalculation.obj 
scons-out\dbg\obj\Licenser\src\data\LSAccount.obj 
scons-out\dbg\obj\Licenser\src\data\LSAccountHistory.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSAccountHistoryRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSAccountRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\data\LSActivation.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSActivationRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\data\LSBlob.obj 
scons-out\dbg\obj\Licenser\src\data\LSCompositePrimaryKey.obj 
scons-out\dbg\obj\Licenser\src\data\LSDatabaseElementBase.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSDoActivateReplyPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSDoActivateRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSDoManualActivateReplyPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSDoManualActivateRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\data\LSLicense.obj 
scons-out\dbg\obj\Licenser\src\data\LSLicenseHistory.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSLicenseHistoryRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSLicenseRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSLoginReplyPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSLoginRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\data\LSMachine.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSMachineRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSNet.obj 
scons-out\dbg\obj\Licenser\src\data\LSPhyActivation.obj 
scons-out\dbg\obj\Licenser\src\data\deprecated_streamables\LSPhyActivation_LegacyStreamingHelper.obj 
scons-out\dbg\obj\Licenser\src\data\LSPrimaryKey.obj 
scons-out\dbg\obj\Licenser\src\data\LSPrimaryKeyDefinitions.obj 
scons-out\dbg\obj\Licenser\src\data\LSProduct.obj 
scons-out\dbg\obj\Licenser\src\data\LSProductHistory.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSProductHistoryRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSProductRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\data\LSSimplePrimaryKey.obj 
scons-out\dbg\obj\Licenser\src\data\LSUser.obj 
scons-out\dbg\obj\Licenser\src\data\LSUserHistory.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSUserHistoryRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSUserRequestPacket.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\streaming_versioning\StreamableClassInfoVersionTranslator.obj
scons-out\dbg\obj\Licenser\src\data\deprecated_streamables\LSProduct_deprecated_v_2.obj 
scons-out\dbg\obj\Licenser\src\secure\deprecated_streamables\DSA.obj 
scons-out\dbg\obj\Licenser\src\secure\deprecated_streamables\DSAKeyPair.obj 
scons-out\dbg\obj\Licenser\src\secure\deprecated_streamables\DSAPublicKey.obj 
scons-out\dbg\obj\Licenser\src\secure\deprecated_streamables\Hash.obj 
scons-out\dbg\obj\Licenser\src\secure\deprecated_streamables\SHA1.obj 
scons-out\dbg\obj\Licenser\src\server_daemon\LSActivationApprovalStrategy.obj 
scons-out\dbg\obj\Licenser\src\data\LSDatabaseElementT.obj 
scons-out\dbg\obj\Licenser\src\data\LSPairPrimaryKeyT.obj 
scons-out\dbg\obj\Licenser\src\data\LSSimplePrimaryKeyT.obj 
scons-out\dbg\obj\Licenser\src\secure\windows_crypto\PlatformCryptoKeyProvider_wincrypt.obj
scons-out\dbg\obj\Licenser\src\secure\windows_crypto\Scoped_RAII_AutoReleaseWincryptHandleFactory.obj

Also, the PCH header isn't explicitly included by each individual file, but on the command line options, I have /FI that force includes the PCH on every file compiled in the project.

+1  A: 

I seem to have solved my own problem. When precompiling the header file, cl.exe generates a .obj file. Because we're using boost's internal magic to automatically link to needed libraries on Windows and our boost header #includes are also in the precompiled header, those links are also included in the .obj file. Unfortunately, this .obj file is not added to the list of .obj files that need to be linked (to make a .dll in this case).

What got it working was manually appending the .obj file generated during compilation of the PCH to the LINKFLAGS argument. Doing this 100% completely solves the problem I've been having. Maybe it's time to update the msvc.py tool and send a patch into SCons!

Grant Limberg
I'm not sure I understand - the linker is generating an .obj file, which needs to be specified? Or is it that the linker command is missing a necessary .obj file that you have to include using the LINKFLAGS argument?
Michael Burr
Can you give some further details to how you solved this? E.g. how do you specify the LINKFLAGS argument?
Alex Black
It's an argument given to the Scons builder. eg.env.ComponentProgram( LINKFLAGS= myLinkFlagsList, CXXFLAGS= myCXXFlagsList,)
Grant Limberg
A: 

There are 2 defines when compiling that are there when building the pre-compiled headers:

/D_USRDLL
/D_WINDLL

As far as I know, these are MFC relics. I don't really know anything about them, but I wouldn't be surprised if wxWidgets had some dependencies on them. I doubt that Boost does (but I havn't looked, either).

Michael Burr
Five minutes late with the wrong answer - glad you solved your mystery.
Michael Burr