Compiling with MSVC 2015 (static linkage)

yezezey edited this page Aug 8, 2016 · 3 revisions
Clone this wiki locally

This page describes how to compile 32-bit qBittorrent using MSVC 2015 under Windows. This is tested under Windows 7 SP1 64-bit but it should work the same under any other Windows version. Here the Community Edition of MSVC 2015 was used but any other edition must behave the same.

Table of Contents

What you will need:

Info that applies to all steps

  • Let's assume that the working directory for our compilation will be G:\QBITTORRENT
  • You need to use the 32-bit version of the compiler. All commands will be issued in that command shell. Open it via Start->All Programs->Visual Studio 2015->Visual Studio Tools->Windows Desktop Command Prompts->VS2015 x86 Native Tools Command Prompt
  • The above prompt will open and will use a path under the C:\ drive. If you want to use another drive for compilation (like mentioned above) you need to switch to that. Simply issuing G: (or any other drive letter) will switch there.
  • When you want to change paths in the prompt you do it by issuing cd new-path. NOTE: If the path starts with a different drive letter you need to switch to that first. The cd command doesn't do it automatically.
  • We will use 3 installation paths:
    • G:\QBITTORRENT\install_msvc\base will be used for installing all necessary libs except Qt5 and Qt4
    • G:\QBITTORRENT\install_msvc\base\qt4 will be used for installing qt4
    • G:\QBITTORRENT\install_msvc\base\qt5 will be used for installing qt5
  • The official builds use extra compiler/linker switches to make qbittorrent compatible with Windows XP. FYI, those extra things are:
    • Defining _USING_V110_SDK71_ (using the /D compiler switch)
    • Using the /SUBSYSTEM:WINDOWS",5.01" and /SUBSYSTEM:CONSOLE",5.01" switches (gui or console programs respectively)
    • Finally the /arch:IA32 compiler switch is used too. This isn't necessary for Windows XP compatibility. However, previous versions of qBittorent were built using MSVC 2008. That version defaulted to that option. Newer versions default to /arch:SSE2. Older CPUs that are still in use don't support that.
  • In general these compiler/linker flags will be used:
    • Compiler: -O1 -Oy- -GL -MT /arch:IA32
    • Linker: /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /DEBUG /OPT:REF /OPT:ICF /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT

Compiling Zlib

  • Extract the Zlib source inside our working dir.
  • Navigate to the Zlib source folder. eg cd G:\QBITTORRENT\zlib-1.2.8
  • Edit the win32/Makefile.msc file. Find the CFLAGS, WFLAGS and LDFLAGS variables and replace them with these:
 CFLAGS  = -nologo -O1 -Oy- -GL -MT /arch:IA32 $(LOC)
 WFLAGS  = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_USING_V110_SDK71_
 LDFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /DEBUG /OPT:REF /OPT:ICF /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
  • Issue the following commands:
 nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj"
  • Copy zlib.h, zconf.h, zlib.lib to our install dir.
 xcopy zlib.h G:\QBITTORRENT\install_msvc\base\include\
 xcopy zconf.h G:\QBITTORRENT\install_msvc\base\include\
 xcopy zlib.lib G:\QBITTORRENT\install_msvc\base\lib\

Compiling OpenSSL

  • Make sure you have installed perl and nasm.
  • Extract the OpenSSL source inside our working dir.
  • Navigate to the OpenSSL source folder. eg cd G:\QBITTORRENT\openssl-1.0.2g
  • Now we will build a static version of OpenSSL. Issue the following commands:
 perl Configure VC-WIN32 no-shared zlib no-zlib-dynamic threads --openssldir=C:\openssl --prefix=G:\QBITTORRENT\install_msvc\base -IG:\QBITTORRENT\install_msvc\base\include -LG:\QBITTORRENT\install_msvc\base\lib -D_USING_V110_SDK71_
 ms\do_nasm
  • NOTE: Using the --openssldir switch is very important. It controls the path that will get hardcoded into openssl when it looks for the file openssl.cnf. Otherwise openssl will use the prefix path. If that path is on any other drive other than C: it will cause weird problems for some of the end users. If users have assigned to G: (or any other letter you used) a card reader/cdrom/dvdrom that doesn't have a card/cd/dvd plugged in they will get a cryptic message saying There is no disk in the drive. Please insert a disk into drive G:. See issue #4190. So for that reason we use a dummy path under drive C: which is always available.
  • Edit the ms\nt.mak file and find the line that says:
 EX_LIBS=/libpath::\QBITTORRENT\install_msvc\base\lib ws2_32.lib gdi32.lib advapi32.lib crypt32.lib user32.lib zlib1.lib
  • Replace zlib1.lib with zlib.lib
  • Find the CFLAG variable and append:
  -O1 -Oy- -GL -MT /arch:IA32
  • Find line that says:
 LFLAGS=/nologo /subsystem:console /opt:ref /debug
  • And replace it with:
 LFLAGS=/NOLOGO /SUBSYSTEM:CONSOLE",5.01" /DYNAMICBASE /NXCOMPAT /LTCG /DEBUG /OPT:REF /OPT:ICF /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
  • Then issue the following:
 nmake -f ms\nt.mak
 nmake -f ms\nt.mak install

Compiling Boost

  • Extract the Boost sources in the working dir.
  • Navigate to the Boost source folder. eg cd G:\QBITTORRENT\boost_1_60_0
  • Now you will need to bootstrap Boost so it will build b2.exe(previously bjam.exe). Issue the following command:
 bootstrap.bat 
  • Compile a static version of Boost. Issue the following command. Replace N in -j N with the number of CPU cores you have or how many threads you want b2 to use when compiling:
 b2 -q --with-system --toolset=msvc-14.0 variant=release link=static runtime-link=static debug-symbols=on include="G:\QBITTORRENT\install_msvc\base\include" library-path="G:\QBITTORRENT\install_msvc\base\lib" --prefix="G:\QBITTORRENT\install_msvc\base" define=_USING_V110_SDK71_ define=BOOST_ASIO_DISABLE_CONNECTEX define=BOOST_USE_WINAPI_VERSION=0x0501 cxxflags=/arch:IA32 --hash -j N
  • Install (it take a while to copy the numerous files):
 b2 -q --with-system --toolset=msvc-14.0 variant=release link=static runtime-link=static debug-symbols=on include="G:\QBITTORRENT\install_msvc\base\include" library-path="G:\QBITTORRENT\install_msvc\base\lib" --prefix="G:\QBITTORRENT\install_msvc\base" define=_USING_V110_SDK71_ define=BOOST_ASIO_DISABLE_CONNECTEX define=BOOST_USE_WINAPI_VERSION=0x0501 cxxflags=/arch:IA32 --hash -j N install

Compiling Libtorrent

  • Extract the Libtorrent sources in the working dir.
  • Navigate to the Libtorrent source folder. eg cd G:\qBittorrent\libtorrent-rasterbar-1.0.9
  • Copy the b2.exe from the Boost directory to the Libtorrent directory
 copy ..\boost_1_60_0\b2.exe b2.exe
  • Compile a static version of Libtorrent. Issue the following command. Replace N in -j N with the number of CPU cores you have or how many threads you want b2 to use when compiling:
 b2 -q --without-python --toolset=msvc-14.0 variant=release link=static runtime-link=static debug-symbols=on encryption=openssl logging=none geoip=off resolve-countries=off dht=on boost=source character-set=unicode boost-link=static -sBOOST_ROOT="G:\qBittorrent\boost_1_60_0" include="G:\QBITTORRENT\install_msvc\base\include" library-path="G:\QBITTORRENT\install_msvc\base\lib" --prefix="G:\QBITTORRENT\install_msvc\base" define=_USING_V110_SDK71_ define=BOOST_ASIO_DISABLE_CONNECTEX define=BOOST_USE_WINAPI_VERSION=0x0501 cxxflags=/arch:IA32 --hash -j N
  • Install:
 b2 -q --without-python --toolset=msvc-14.0 variant=release link=static runtime-link=static debug-symbols=on encryption=openssl logging=none geoip=off resolve-countries=off dht=on boost=source character-set=unicode boost-link=static -sBOOST_ROOT="G:\qBittorrent\boost_1_60_0" include="G:\QBITTORRENT\install_msvc\base\include" library-path="G:\QBITTORRENT\install_msvc\base\lib" --prefix="G:\QBITTORRENT\install_msvc\base" define=_USING_V110_SDK71_ define=BOOST_ASIO_DISABLE_CONNECTEX define=BOOST_USE_WINAPI_VERSION=0x0501 cxxflags=/arch:IA32 --hash -j 12 install

Compiling Qt5

  • You don't need Qt5 if you're going to use Qt4 and vice versa.
  • Extract the Qt sources in the working dir.
  • Navigate to the Qt source folder. eg cd G:\QBITTORRENT\qt-everywhere-opensource-src-5.5.1
  • Now we will build a static version of Qt and make it as small as possible.
  • Open qtbase/mkspecs/common/msvc-desktop.conf and replace the relevant lines with:
 DEFINES += UNICODE WIN32 _USING_V110_SDK71_
 QMAKE_CFLAGS_RELEASE = -O1 -Oy- -GL -MT /arch:IA32
 QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi
 QMAKE_CFLAGS_DEBUG = -Zi -MTd
 QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG
 QMAKE_LFLAGS_RELEASE = /DEBUG /OPT:REF /OPT:ICF /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO
 QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE",5.01"
 QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS",5.01"
  • Find the line that says greaterThan(MSC_VER, 1699) => disable and disable these 2 lines(needed for Windows XP compatibility):
  QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE@QMAKE_SUBSYSTEM_SUFFIX@
  QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS@QMAKE_SUBSYSTEM_SUFFIX@
  • Issue the following command:
 configure -prefix G:\QBITTORRENT\install_msvc\qt5 -I G:\QBITTORRENT\install_msvc\base\include -L G:\QBITTORRENT\install_msvc\base\lib -platform win32-msvc2015 -release -opensource -confirm-license -c++11 -static -largefile -no-sql-sqlite -no-qml-debug -system-zlib -openssl-linked -make libs -make tools -nomake examples -no-icu -strip -no-dbus -no-opengl -no-angle -no-sse2 -no-sse3 -no-sse4.1 -no-sse4.2 -no-ssse3 -no-avx -no-avx2 -no-audio-backend -no-wmf-backend -no-native-gestures -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtconnectivity -skip qtdeclarative -skip qtdoc -skip qtenginio -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmacextras -skip qtmultimedia -skip qtquick1 -skip qtquickcontrols -skip qtscript -skip qtsensors -skip qtserialport -skip qtsvg -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebkit -skip qtwebkit-examples -skip qtwebsockets -skip qtwinextras -skip qtx11extras -skip qtxmlpatterns ZLIB_LIBS="-lzlib"
  • Now you have 2 choices for compiling. Using nmake or jom. nmake uses only one core for compilation. That means that the qt compilation will take hours. On the other hand jom can use multiple cores/threads for faster compilation. Download it from here. Extract the jom.exe to the qt source dir and just issue(N number of cores/threads to use):
 jom -j N
  • Now install:
 jom -j N install

Compiling Qt4

  • You don't need Qt4 if you're going to use Qt5 and vice versa.
  • Extract the Qt sources in the working dir.
  • Navigate to the Qt source folder. eg cd G:\QBITTORRENT\qt-everywhere-opensource-src-4.8.7
  • Now we will build a static version of Qt and make it as small as possible.
  • Open src/corelib/global/qglobal.h and find this segment:
#if defined(Q_CC_MSVC) && !defined(Q_CC_INTEL)
#  if defined(__cplusplus)
#    if _MSC_VER >= 1600
       /* C++11 features supported in VC10 = VC2010: */
#      define Q_COMPILER_AUTO_FUNCTION
#      define Q_COMPILER_AUTO_TYPE
#      define Q_COMPILER_DECLTYPE
#      define Q_COMPILER_LAMBDA
#      define Q_COMPILER_RVALUE_REFS
//  MSVC's library has std::initializer_list, but the compiler does not support the braces initialization
//#      define Q_COMPILER_INITIALIZER_LISTS
#    endif
#  endif
#endif
Uncomment //# define Q_COMPILER_INITIALIZER_LISTS (remove the // characters). MSVC 2015 supports initializer lists but qt 4.8.7 is old and its config files reflect that.
  • Open mkspecs/win32-msvc2015/qmake.conf and replace the relevant lines with:
 DEFINES += UNICODE WIN32 _USING_V110_SDK71_
 QMAKE_CFLAGS_RELEASE = -O1 -Oy- -GL -MT /arch:IA32
 QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi
 QMAKE_CFLAGS_DEBUG = -Zi -MTd
 QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG
 QMAKE_LFLAGS_RELEASE = /DEBUG /OPT:REF /OPT:ICF /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO
 QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE",5.01"
 QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS",5.01"
  • Open src\3rdparty\zlib_dependency.pri and replace zdll.lib with zlib.lib
  • Do the same for src\tools\bootstrap\bootstrap.pri
  • Issue the following commands:
 configure.exe -prefix G:\QBITTORRENT\install_msvc\qt4 -I G:\QBITTORRENT\install_msvc\base\include -L G:\QBITTORRENT\install_msvc\base\lib -debug-and-release -opensource -static -ltcg -fast -system-zlib -no-qt3support -no-opengl -no-openvg -no-dsp -no-vcproj -no-dbus -no-phonon -no-phonon-backend -no-multimedia -no-audio-backend -no-webkit -no-script -no-scripttools -no-declarative -no-declarative-debug -mp -arch windows -qt-style-windowsxp -nomake examples -nomake demos -platform win32-msvc2015 -openssl-linked -largefile
 bin\qmake.exe projects.pro QT_BUILD_PARTS="libs translations"
  • Copy the mkspecs folder under G:\QBITTORRENT\install_msvc\qt4. Stupid Qt4 tries to look for the mkspecs under that path instead of its source dir.
  • Now you have 2 choices for compiling. Using nmake or jom. nmake uses only one core for compilation. That means that the qt compilation will take hours. On the other hand jom can use multiple cores/threads for faster compilation. Download it from here. Extract the jom.exe to the qt source dir and just issue(N number of cores/threads to use):
 jom -j N
  • Now install:
 jom -j N install
  • Now you need to do some cleaning up because Qt4 is stupid again. Find a program that can search and replace strings inside files. Make it search for all files ending in .pri under G:\QBITTORRENT\install_msvc\qt4. Make it search for the strings /LIBPATH:G:\\QBITTORRENT\\install_msvc\\base\\lib and g:\\QBITTORRENT\\qt-everywhere-opensource-src-4.8.7\\lib\\ and replace them with an empty string(ie delete them).

Install and Configure Qt Creator

  • Just follow the installer instructions for the installation.
  • Launch Qt Creator and select Tools->Options...
  • Select the Build & Run item from the left and select the Qt Versions tab.
  • Click the Add... button and select the qmake.exe you just build. It should be in G:\QBITTORRENT\install_msvc\qt5\bin\qmake.exe or G:\QBITTORRENT\install_msvc\qt4\bin\qmake.exe
  • Name it something meaningful like "Qt5 msvc"
  • Apply the changes
  • Click the Kits tab
  • Click the Add button. Choose a name eg Qt5 msvc2015. Also choose a Qt version and a compiler from the drop down menus. Be sure to select the 32-bit(x86) version of the compiler. Click Apply.
  • If you have configured multiple kits, then select the one you want as default and click the button Make Default and click OK. Otherwise, just close the dialog now.

Compiling qBittorrent

  • Extract the qBittorrent sources in the working dir.
  • Launch Qt Creator and open the qbittorrent.pro file in G:\QBITTORRENT\qbittorrent-3.3.3
  • From the Window that pops up select the Qt version you added above and specify release version. Also check the Use Shadow Building checkbox. You can also select where qBittorrent will be built if you want.
  • Open the winconf.pri file and adjust the paths. Disregard most of the file comments(read next step).
  • Edit the first INCLUDEPATH to look like this:
 INCLUDEPATH += $$quote(G:/qBittorrent/install_msvc/base/include)
  • Edit the second INCLUDEPATH to look like this(adjust for actual boost name):
 INCLUDEPATH += $$quote(G:/qBittorrent/install_msvc/base/include/boost-1_60)
  • Comment the other 2 INCLUDEPATH lines by putting # in front of them.
  • Edit the first LIBS to look like this:
 LIBS += $$quote(-LG:/qBittorrent/install_msvc/base/lib)
  • Comment the other 3 LIBS lines by putting # in front of them.
  • Open the winconf-msvc.pri file and adjust the filename of the lib of Boost.
  • Select Build->Build All
  • After the compilation ends you should have qbittorrent.exe in <build></build>\src\release. "build folder" is where you chose qBittorrent to be build in the popup window.