4

我正在調查使用SCons構建過程,因爲我們正在爲多種平臺開發C++。我在構建配置中的99%的方式,但我遇到了一個非常 Windows上的奇怪的錯誤與預編譯頭文件。更奇怪的是,它只發生在一個項目上。SCons,Boost :: ASIO,Windows預編譯頭文件和鏈接程序錯誤

在該項目的SConscript文件,我有以下的編譯PCH在Windows上:

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

我也有設置強制編譯器標誌包括MyPCH.h項目中的所有文件:

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

一切順利,編譯絕對好。它不是直到最後的DLL鏈接階段,我得到的鏈接錯誤頁面和頁面,如下所示:

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_" 
([email protected][email protected][email protected]@[email protected]@@@[email protected]@[email protected]@[email protected] 
[email protected][email protected][email protected]@[email protected]@@@[email protected]@[email protected]@@[email protected]) 

和:

 error LNK2001: unresolved external symbol "private: static class 
boost::asio::detail::winsock_init<2,0> boost::asio::detail::winsock_init<2,0>::instance_" 
([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]) 

這是令人費解,因爲沒有課的,我儘管它包含在預編譯頭文件中,並且在一些#includes中包含在鏈中,但即使使用boost :: asio也沒有獲得鏈接警告。

更令人費解的是,如果我禁用了預編譯頭文件的編譯,但仍然強制它的包含,一切編譯和鏈接都很好。它只是永遠嚇壞了。

有沒有人有線索可能導致這些鏈接錯誤?

在此先感謝。

---編輯---

下面是SCons的是隨地吐痰建設的PCH(減號包括路徑)命令行:

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 

下面是一個文件的命令行正在編制(再次減去包括路徑):

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 

最後,這裏的鏈接命令行:

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 

此外,PCH頭沒有明確包含在每個單獨的文件中,但是在命令行選項中,我有/ FI,強制在項目中編譯的每個文件中包含PCH。

+0

你能展示一些正在用來調用編譯器和鏈接器的示例命令行嗎? cl.exe命令行上的/ D宏定義是否始終完全相同?在包含任何其他頭文件之前,所有源文件都包含預編譯頭文件? – 2009-06-16 04:19:24

+0

已添加示例命令行 – 2009-06-16 16:44:10

回答

2

我似乎已經解決了我自己的問題。預編譯頭文件時,cl.exe會生成一個.obj文件。因爲我們使用boost的內部魔法來自動鏈接到Windows上所需的庫,並且我們的boost頭文件包含在預編譯頭文件中,所以這些鏈接也包含在.obj文件中。不幸的是,這個.obj文件沒有被添加到需要鏈接的.obj文件列表中(在這種情況下生成一個.dll)。

它的工作原理是手動將編譯PCH期間生成的.obj文件附加到LINKFLAGS參數。這樣做完全解決了我一直存在的問題。也許是時候更新msvc.py工具並將補丁發送到SCons!

+0

我不確定我是否理解 - 鏈接器正在生成需要指定的.obj文件?或者,鏈接器命令是否缺少必須使用LINKFLAGS參數包含的必需.obj文件? – 2009-06-17 01:14:28

0

有編譯時有沒有建立預編譯的頭時,2個定義:

/D_USRDLL 
/D_WINDLL 

據我所知,這些都是MFC文物。我真的不知道他們的任何事情,但如果wxWidgets對他們有依賴關係,我不會感到驚訝。我懷疑Boost的確如此(但我也沒有看過)。