Supporting x64 and Win32 within one solution
Preface
The typical programmer will face a build problem to compile an application for Win32 and for x64 platforms. The .sln 's and .vcproj 's which are generated from .dsw 's and .dsp 's support only Win32. However, you can add x64 support to the project files. If you have read the description in INSTALL-MSW.txt you know that you only need to go to the 'Build' menu and choose 'Configuration Manager...' and add 'x64'. But if you now build Win32 libraries and x64 libraries you'll end up having several linker errors and a mixed set of libraries (some for Win32 and some for x64).
This problem can be solved if you edit build/msw/*.vcproj (all of them) and the file include/msvc/wx/setup.h.
Editing *.vcproj in the directory build/msw:
An alternative
Notice that instead of changing .vcproj files you may also simply build wxWidgets from the command line using nmake. Then it is enough to simply use TARGET_CPU=amd64 on nmake command line to build the 64 bit version. Of course, you still will be able to use the IDE for your own projects.
Changing them with gawk.exe
If you have gawk.exe, you can use it to make the needed changes. Go into the directory build/msw and create following two files. Than execute VC2005_MultiTargetSupport.bat if you use cmd.exe or VC2005_MultiTargetSupport.sh if you use cygwin.
VC2005_MultiTargetSupport.awk
{ PlatformPath = "\\$(PlatformName)" split ("vc_lib vc_dll vc_mswu vc_mswuniv vc_mswunivu vc_mswunivddll vc_mswdll vc_mswunivdll vc_msw vc_mswudll vc_mswunivudll vc_mswunivud vc_mswunivd vc_mswuddll vc_mswud vc_mswddll vc_mswd vc_mswunivuddll", wxNames) for (name in wxNames) { while (0!=match($0, "^(.*)([^[:alnum:]_])"wxNames[name]"([^[:alnum:]_])(.*)$", text ) ) { $0 = text[1] text[2] wxNames[name] "DONTFINDMEAGAIN" PlatformPath text[3] text[4] } gsub("DONTFINDMEAGAIN", "") } print $0 }
VC2005_MultiTargetSupport.bat
@echo off for %%I in (*.vcproj) do ren %%I %%I.old && gawk -f VC2005_MultiTargetSupport.awk %%I.old > %%I rem for %%I in (*.vcproj) do gawk -f wxExtender.awk %%I > %%I.new
VC2005_MultiTargetSupport.sh
for i in *.vcproj; do mv $i $i.old gawk -f VC2005_MultiTargetSupport.awk $i.old > $i done
Changing them manually
If you don't have gawk.exe, prepare for half an hour of work!
Please add the string
\$(PlatformName)
after each occurence of following strings:
vc_lib vc_dll vc_mswu vc_mswuniv vc_mswunivu vc_mswunivddll vc_mswdll vc_mswunivdll vc_msw vc_mswudll vc_mswunivudll vc_mswunivud vc_mswunivd vc_mswuddll vc_mswud vc_mswddll vc_mswd vc_mswunivuddll
You should end up having changed the lines which begin with one of these xml names (.vcproj files are xml files):
OutputDirectory IntermediateDirectory TypeLibraryName AdditionalIncludeDirectories PrecompiledHeaderFile AssemblerListingLocation ObjectFile ProgramDataBaseFileName AdditionalIncludeDirectories AdditionalDependencies OutputFile AdditionalLibraryDirectories ProgramDatabaseFile ImportLibrary OutputFile
Here is an example of how such a change would look alike:
<Configuration Name="DLL Unicode Debug|Win32" OutputDirectory=".\..\..\lib\vc_dll\$(PlatformName)" IntermediateDirectory=".\vc_mswuddll\$(PlatformName)\adv" ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="1" > ... <Tool Name="VCMIDLTool" PreprocessorDefinitions="WIN32,_USRDLL,DLL_EXPORTS,_DEBUG,__WXMSW__,__WXDEBUG__,_UNICODE,WXUSINGDLL,WXMAKINGDLL_ADV" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\..\..\lib\vc_dll\$(PlatformName)/wx_adv.tlb" HeaderFileName="" /> <Tool Name="VCCLCompilerTool" AdditionalOptions="/EHsc " Optimization="0" AdditionalIncludeDirectories="..\..\lib\vc_dll\$(PlatformName)\mswud,..\..\include,..\..\src\tiff,..\..\src\jpeg,..\..\src\png,..\..\src\zlib,..\..\src\regex,..\..\src\expat\lib" PreprocessorDefinitions="WIN32;_USRDLL;DLL_EXPORTS;_DEBUG;__WXMSW__;__WXDEBUG__;WXUSINGDLL;WXMAKINGDLL_ADV" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" RuntimeTypeInfo="true" UsePrecompiledHeader="2" PrecompiledHeaderThrough="wx/wxprec.h" PrecompiledHeaderFile="vc_mswuddll\$(PlatformName)\wxprec_advdll.pch" AssemblerListingLocation=".\vc_mswuddll\$(PlatformName)\adv/" ObjectFile=".\vc_mswuddll\$(PlatformName)\adv/" ProgramDataBaseFileName="..\..\lib\vc_dll\$(PlatformName)\wxmsw270ud_adv_vc_custom.pdb" WarningLevel="4" SuppressStartupBanner="true" DebugInformationFormat="3" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" PreprocessorDefinitions="_DEBUG,__WXMSW__,__WXDEBUG__,_UNICODE,WXDLLNAME=wxmsw270ud_adv_vc_custom,WXUSINGDLL,WXMAKINGDLL_ADV" Culture="1033" AdditionalIncludeDirectories="..\..\lib\vc_dll\$(PlatformName)\mswud;..\..\include;..\..\src\tiff;..\..\src\jpeg;..\..\src\png;..\..\src\zlib;..\..\src\regex;..\..\src\expat\lib" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" AdditionalDependencies="wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib wxregexud.lib wxexpatd.lib winmm.lib comctl32.lib rpcrt4.lib wsock32.lib odbc32.lib ..\..\lib\vc_dll\$(PlatformName)\wxmsw27ud_html.lib ..\..\lib\vc_dll\$(PlatformName)\wxbase27ud_xml.lib ..\..\lib\vc_dll\$(PlatformName)\wxmsw27ud_core.lib ..\..\lib\vc_dll\$(PlatformName)\wxbase27ud.lib" OutputFile="..\..\lib\vc_dll\$(PlatformName)\wxmsw270ud_adv_vc_custom.dll" LinkIncremental="2" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\lib\vc_dll\$(PlatformName)" GenerateDebugInformation="true" ProgramDatabaseFile=".\..\..\lib\vc_dll\$(PlatformName)/wxmsw270ud_adv_vc_custom.pdb" ImportLibrary="..\..\lib\vc_dll\$(PlatformName)\wxmsw27ud_adv.lib" TargetMachine="1" /> <Tool Name="VCALinkTool" /> ... <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\..\..\lib\vc_dll\$(PlatformName)/wx_adv.bsc" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCAppVerifierTool" ... <Tool Name="VCPostBuildEventTool" /> </Configuration>
Again: These changes have to be done to all *.vcproj! Yes, this is a lot of work. Maybe someone can write a script which works with tools which are included by default in Windows (like VBScript or similar).
Changing mostly automatic using Visual Studio
This method only works if you solely use wxWidgets (2.9+) statically using the Debug or Release configuration. It requires a lot less manual work than the previous method.
Make the following three replacements using Visual Studio's "Replace in Files" option (Ctrl+Shift+H, or Edit > Find and Replace > Replace in Files) to all wx_vc9*.vcproj (assuming you use Visual Studio 2008, if not then replace with 7 or 8 as needed) files in build\msw\:
Replace:
OutputDirectory="..\..\lib\vc_lib"
with:
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
Replace:
lib\vc_lib\
with:
lib\vc_lib\$(PlatformName)\
Replace:
vc_msw
with:
$(PlatformName)\vc_msw
Editing setup.h in the directory include/msvc/wx:
Replace the single line:
#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, wxARCH_SUFFIX, _lib)
with these multiple lines:
#ifdef _M_X64 #define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, _lib, /x64) #else #define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, _lib, /Win32) #endif
The below changes to setup.h are not needed.
Editing setup.h in the directory include/msvc/wx:
NB: you don't need to do this with wxWidgets 2.9 in which msvc/wx/setup.h was modified to use the correct paths out of the box, the instructions below are for wxWidgets 2.8 only!
(There are several files named setup.h in the wxWidgets directory tree. Please be careful to modify the correct one.)
It's difficult to describe what you need to do now. In this case examples are better than words, so here it goes:
The unmodified setup.h might look like this
... #ifdef WXUSINGDLL #ifdef _DEBUG #include "../../../lib/vc_dll/mswud/wx/setup.h" #else #include "../../../lib/vc_dll/mswu/wx/setup.h" #endif #else #ifdef _DEBUG #include "../../../lib/vc_lib/mswud/wx/setup.h" #else #include "../../../lib/vc_lib/mswu/wx/setup.h" #endif #endif ... #else // !_UNICODE #ifdef WXUSINGDLL #ifdef _DEBUG #include "../../../lib/vc_dll/mswd/wx/setup.h" #else #include "../../../lib/vc_dll/msw/wx/setup.h" #endif #else // static lib #ifdef _DEBUG #include "../../../lib/vc_lib/mswd/wx/setup.h" #else #include "../../../lib/vc_lib/msw/wx/setup.h" #endif #endif // shared/static
The modified setup.h must look like this
... #ifdef WXUSINGDLL #ifdef _DEBUG #ifdef _WIN64 #include "../../../lib/vc_dll/x64/mswud/wx/setup.h" #else #include "../../../lib/vc_dll/Win32/mswud/wx/setup.h" #endif #else #ifdef _WIN64 #include "../../../lib/vc_dll/x64/mswu/wx/setup.h" #else #include "../../../lib/vc_dll/Win32/mswu/wx/setup.h" #endif #endif #else #ifdef _DEBUG #ifdef _WIN64 #include "../../../lib/vc_lib/x64/mswud/wx/setup.h" #else #include "../../../lib/vc_lib/Win32/mswud/wx/setup.h" #endif #else #ifdef _WIN64 #include "../../../lib/vc_lib/x64/mswu/wx/setup.h" #else #include "../../../lib/vc_lib/Win32/mswu/wx/setup.h" #endif #endif #endif ... #else // !_UNICODE #ifdef WXUSINGDLL #ifdef _DEBUG #ifdef _WIN64 #include "../../../lib/vc_dll/x64/mswd/wx/setup.h" #else #include "../../../lib/vc_dll/Win32/mswd/wx/setup.h" #endif #else #ifdef _WIN64 #include "../../../lib/vc_dll/x64/msw/wx/setup.h" #else #include "../../../lib/vc_dll/Win32/msw/wx/setup.h" #endif #endif #else // static lib #ifdef _DEBUG #ifdef _WIN64 #include "../../../lib/vc_lib/x64/mswd/wx/setup.h" #else #include "../../../lib/vc_lib/Win32/mswd/wx/setup.h" #endif #else #ifdef _WIN64 #include "../../../lib/vc_lib/x64/msw/wx/setup.h" #else #include "../../../lib/vc_lib/Win32/msw/wx/setup.h" #endif #endif #endif // shared/static ...
Automatic Python script
Ian Mallett provides the following Python script that makes all the changes automatically. Standard disclaimer.
import os #CHANGE THIS!!! dir_prefix = "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/wxWidgets-2.9.4/" for dirname, dirnames, filenames in os.walk(dir_prefix+"build/msw/"): for filename in filenames: if filename.startswith("wx_vc9") and filename.endswith(".vcproj"): path = dirname + filename file = open(path,"r") data = file.read() file.close() data = data.replace( "OutputDirectory=\"..\\..\\lib\\vc_lib\"", "OutputDirectory=\"$(PlatformName)\\$(ConfigurationName)\"" ) data = data.replace( "OutputDirectory=\"..\\..\\lib\\vc_dll\"", "OutputDirectory=\"$(PlatformName)\\$(ConfigurationName)\"" ) data = data.replace( "lib\\vc_lib\\", "lib\\vc_lib\\$(PlatformName)\\" ) data = data.replace( "lib\\vc_dll\\", "lib\\vc_dll\\$(PlatformName)\\" ) data = data.replace( "vc_msw", "$(PlatformName)\\vc_msw" ) data = data.replace( #Must come after the others "AdditionalLibraryDirectories=\"..\\..\\lib\\vc_dll\"", "AdditionalLibraryDirectories=\"..\\..\\lib\\vc_dll\\$(Platform)\"" ) file = open(path,"w") file.write(data) file.close() file = open(dir_prefix+"include/msvc/wx/setup.h","r") data = file.read() file.close() data = data.replace( "#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, wxARCH_SUFFIX, _dll)", """#ifdef _M_X64 \t#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, _dll, /x64) #else \t#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, _dll, /Win32) #endif""" ) data = data.replace( "#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, wxARCH_SUFFIX, _lib)", """#ifdef _M_X64 \t#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, _lib, /x64) #else \t#define wxLIB_SUBDIR wxCONCAT3(wxCOMPILER_PREFIX, _lib, /Win32) #endif""" ) file = open(dir_prefix+"include/msvc/wx/setup.h","w") file.write(data) file.close()
Final Notes
I have done this with the HEAD version of CVS and it works. Unfortunately, I don't know if the samples will compile and link seamless with these changes. If they don't work, you will need to change the project file similar to above.