wiki/Compiling-with-MSVC-2019-(static-linkage).mediawiki

189 lines
20 KiB
Plaintext

This page describes how to compile 32-bit and 64-bit qBittorrent using MSVC 2019 under Windows. This is tested under Windows 10 64-bit but it should work the same under any other Windows version. Here the Community Edition of MSVC 2019 was used but any other edition must behave the same.
=== What you will need: ===
* The MSVC 2019 compiler. The free [https://visualstudio.microsoft.com/vs/community/ Community Edition] will do fine.
* A [https://www.perl.org/ Perl language] interpreter. [http://strawberryperl.com/ Strawberry Perl] will do fine.
* Latest release of the [https://www.nasm.us/ NASM assembler].
* Latest release of [https://www.zlib.net/ Zlib].
* Latest release of [https://www.openssl.org/source/ OpenSSL] (1.1.1 branch).
* Latest release of the [https://www.boost.org/ Boost libraries].
* Latest release of [https://www.libtorrent.org/ libtorrent(rasterbar)] (1.2.x branch).
* Latest release of the [https://download.qt.io/official_releases/qt/ Qt libraries] source.
** Choose the latest release, and then download the .tar.xz or .zip file under the 'single' directory. For example, 5.15.1 may be found [https://download.qt.io/official_releases/qt/5.15/5.15.1/single/ here].
** '''Note''': This is a massive source tree, with many small files, and will take some time to decompress.
* Latest release of qBittorrent (clone the repository or download the source tarball of the latest release). Typically you want either the latest stable release or the latest master commit, for the latest fixes and improvements.
* [https://download.qt.io/official_releases/qtcreator/ Qt Creator].
=== Info that applies to all steps ===
* Let's assume that the working directory for our compilation will be <code>G:\QBITTORRENT</code>
* For 32-bit or 64-bit you need to use the appropriate version of the compiler. All commands will be issued from the appropriate compiler command prompt. Open it via <code>Start->All Programs->Visual Studio 2019->Visual Studio Tools->VC</code>. For '''32-bit''' use <code>x86 Native Tools Command Prompt for VS 2019</code> and for '''64-bit''' use <code>x64 Native Tools Command Prompt for VS 2019</code>
* The above prompt will open and will use a path under the <code>C:\</code> drive. If you want to use another drive for compilation (like mentioned above) you need to switch to that. Simply issuing <code>G:</code> (or any other drive letter) will switch there.
* When you want to change paths in the prompt you do it by issuing <code>cd new-path</code>. '''NOTE:''' If the path starts with a different drive letter you need to switch to that first. The <code>cd</code> command doesn't do it automatically.
* We will use 2 installation paths
: '''32-bit:'''
:* <code>G:\QBITTORRENT\install_msvc32\base</code> will be used for installing all necessary libs except Qt
:* <code>G:\QBITTORRENT\install_msvc32\base\qt5</code> will be used for installing Qt
: '''64-bit:'''
:* <code>G:\QBITTORRENT\install_msvc64\base</code> will be used for installing all necessary libs except Qt
:* <code>G:\QBITTORRENT\install_msvc64\base\qt5</code> will be used for installing Qt
* In general these compiler/linker flags will be used (at some places below there are deviations):
** '''Compiler (32-bit):''' -O1 -Oy- -Gy -Gw -GL -MT
** '''Compiler (64-bit):''' -O1 -Gy -Gw -GL -MT
** '''Linker:''' /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /DEBUG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
=== Compiling Zlib ===
* Extract the Zlib source inside our working dir.
* Navigate to the Zlib source folder. eg <code>cd G:\QBITTORRENT\zlib-1.2.11</code>
* Edit the '''win32/Makefile.msc''' file. Find the CFLAGS, ASFLAGS and LDFLAGS variables and replace them with these:
32-bit: CFLAGS = -nologo -O1 -Oy- -Gy -Gw -GL -MT $(LOC)
64-bit: CFLAGS = -nologo -O1 -Gy -Gw -GL -MT $(LOC)
LDFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
: From ASFLAGS delete "/Zi"
* Issue the following command:
nmake -f win32/Makefile.msc
* Copy zlib.h, zconf.h, zlib.lib to our install dir.
:'''32-bit'''
xcopy zlib.h G:\QBITTORRENT\install_msvc32\base\include\
xcopy zconf.h G:\QBITTORRENT\install_msvc32\base\include\
xcopy zlib.lib G:\QBITTORRENT\install_msvc32\base\lib\
:'''64-bit'''
xcopy zlib.h G:\QBITTORRENT\install_msvc64\base\include\
xcopy zconf.h G:\QBITTORRENT\install_msvc64\base\include\
xcopy zlib.lib G:\QBITTORRENT\install_msvc64\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 <code>cd G:\QBITTORRENT\openssl-1.1.1g</code>
* Now we will build a static version of OpenSSL. Issue the following commands:
:'''32-bit'''
perl Configure VC-WIN32 no-shared no-zlib no-zlib-dynamic threads --release --openssldir=C:\openssl --prefix=G:\QBITTORRENT\install_msvc32\base -IG:\QBITTORRENT\install_msvc32\base\include -LG:\QBITTORRENT\install_msvc32\base\lib --with-zlib-lib=G:\QBITTORRENT\install_msvc32\base\lib\zlib.lib
:'''64-bit'''
perl Configure VC-WIN64A no-shared no-zlib no-zlib-dynamic threads --release --openssldir=C:\openssl --prefix=G:\QBITTORRENT\install_msvc64\base -IG:\QBITTORRENT\install_msvc64\base\include -LG:\QBITTORRENT\install_msvc64\base\lib --with-zlib-lib=G:\QBITTORRENT\install_msvc64\base\lib\zlib.lib
* '''NOTE:''' Using the <code>--openssldir</code> switch is very important. It controls the path that will get hardcoded into openssl when it looks for the file <code>openssl.cnf</code>. 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 <code>There is no disk in the drive. Please insert a disk into drive G:</code>. See issue [https://github.com/qbittorrent/qBittorrent/issues/4190 #4190]. So for that reason we use a dummy path under drive C: which is always available.
* Edit the generated ''makefile'' file.
* At the end of the CFLAGS variable append:
:'''32-bit'''
-Oy- -Gy -Gw -GL -MT
:'''64-bit'''
-Gy -Gw -GL -MT
: Don't use "-O1" because it makes one openssl test fail which might indicate a general problem with the openssl build
* Find the LDFLAGS variable and replace it with:
LDFLAGS=/NOLOGO /SUBSYSTEM:CONSOLE /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
* Then issue the following:
nmake
nmake test
* Because we substituted the LDFLAGS variable and removed the "/debug" switch, *.pdb files weren't generated. The next command expects to find one at "apps/openssl.pdb". So we just create a dummy file with that name. The easiest way is to make a copy of <code>openssl.exe</code> (exists in the same subfolder) and rename it to <code>openssl.pdb</code>.
* Issue command:
nmake install_sw
* Delete the dummy <code>openssl.pdb</code> from where it was copied to (adjust for 64-bit):
G:\QBITTORRENT\install_msvc32\base\bin\openssl.pdb
=== Compiling Boost ===
* Extract the Boost sources in the working dir.
* Navigate to the Boost source folder. eg <code>cd G:\QBITTORRENT\boost_1_73_0</code>
* 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 <code>-j N</code> with the number of CPU cores you have or how many threads you want b2 to use when compiling:
:'''32-bit'''
b2 -q --with-system --with-date_time --toolset=msvc-14.2 variant=release link=static runtime-link=static include="G:\QBITTORRENT\install_msvc32\base\include" library-path="G:\QBITTORRENT\install_msvc32\base\lib" define=BOOST_ASIO_DISABLE_CONNECTEX cxxflags="-O1 -Oy- -Gy -Gw -GL" linkflags="/NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO" --hash -j N
:'''64-bit'''
b2 -q --with-system --with-date_time --toolset=msvc-14.2 address-model=64 variant=release link=static runtime-link=static include="G:\QBITTORRENT\install_msvc64\base\include" library-path="G:\QBITTORRENT\install_msvc64\base\lib" --prefix="G:\QBITTORRENT\install_msvc64\base" cxxflags="-O1 -Gy -Gw -GL" linkflags="/NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO" --hash -j N
=== Compiling Libtorrent ===
* Extract the Libtorrent sources in the working dir.
* Navigate to the Libtorrent source folder. eg <code>cd G:\QBITTORRENT\libtorrent-rasterbar-1.2.10</code>
* Copy the b2.exe from the Boost directory to the Libtorrent directory
copy ..\boost_1_73_0\b2.exe b2.exe
* Set the following two shell variables, so that boost knows where its build system is:
set BOOST_ROOT=G:\QBITTORRENT\boost_1_73_0
set BOOST_BUILD_PATH=G:\QBITTORRENT\boost_1_73_0\tools\build
* Compile a static version of Libtorrent. Issue the following command. Replace N in <code>-j N</code> with the number of CPU cores you have or how many threads you want b2 to use when compiling:
:'''32-bit'''
b2 -q --without-python --toolset=msvc-14.2 variant=release link=static runtime-link=static debug-symbols=on encryption=on crypto=openssl openssl-version=1.1 logging=off dht=on windows-version=win7 boost-link=static -sBOOST_ROOT="G:\QBITTORRENT\boost_1_73_0" include="G:\QBITTORRENT\install_msvc32\base\include" include="G:\QBITTORRENT\boost_1_73_0" library-path="G:\QBITTORRENT\install_msvc32\base\lib" library-path="G:\QBITTORRENT\boost_1_73_0\stage\lib" --prefix="G:\QBITTORRENT\install_msvc32\base" define=BOOST_ASIO_DISABLE_CONNECTEX cxxflags="-O1 -Oy- -Gy -Gw -GL" linkflags="/NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO" --hash -j N
:'''64-bit'''
b2 -q --without-python --toolset=msvc-14.2 address-model=64 variant=release link=static runtime-link=static debug-symbols=on encryption=on crypto=openssl openssl-version=1.1 logging=off dht=on windows-version=win7 boost-link=static -sBOOST_ROOT="G:\QBITTORRENT\boost_1_73_0" include="G:\QBITTORRENT\install_msvc64\base\include" include="G:\QBITTORRENT\boost_1_73_0" library-path="G:\QBITTORRENT\install_msvc64\base\lib" library-path="G:\QBITTORRENT\boost_1_73_0\stage\lib" --prefix="G:\QBITTORRENT\install_msvc64\base" cxxflags="-O1 -Gy -Gw -GL" define=BOOST_ASIO_DISABLE_CONNECTEX linkflags="/NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO" --hash -j N
* Install:
:'''32-bit'''
b2 -q --without-python --toolset=msvc-14.2 variant=release link=static runtime-link=static debug-symbols=on encryption=on crypto=openssl openssl-version=1.1 logging=off dht=on windows-version=win7 boost-link=static -sBOOST_ROOT="G:\QBITTORRENT\boost_1_73_0" include="G:\QBITTORRENT\install_msvc32\base\include" include="G:\QBITTORRENT\boost_1_73_0" library-path="G:\QBITTORRENT\install_msvc32\base\lib" library-path="G:\QBITTORRENT\boost_1_73_0\stage\lib" --prefix="G:\QBITTORRENT\install_msvc32\base" define=BOOST_ASIO_DISABLE_CONNECTEX cxxflags="-O1 -Oy- -Gy -Gw -GL" linkflags="/NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO" --hash -j N install
:'''64-bit'''
b2 -q --without-python --toolset=msvc address-model=64 variant=release link=static runtime-link=static debug-symbols=on encryption=on crypto=openssl openssl-version=1.1 logging=off dht=on windows-version=win7 boost-link=static -sBOOST_ROOT="G:\QBITTORRENT\boost_1_73_0" include="G:\QBITTORRENT\install_msvc64\base\include" include="G:\QBITTORRENT\boost_1_73_0" library-path="G:\QBITTORRENT\install_msvc64\base\lib" library-path="G:\QBITTORRENT\boost_1_73_0\stage\lib" --prefix="G:\QBITTORRENT\install_msvc64\base" cxxflags="-O1 -Gy -Gw -GL" define=BOOST_ASIO_DISABLE_CONNECTEX linkflags="/NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO" --hash -j N install
=== Compiling Qt5 ===
* Extract the Qt sources in the working dir.
* Navigate to the Qt source folder. eg <code>cd G:\QBITTORRENT\qt-everywhere-src-5.14.2</code>
* 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:
:'''32-bit'''
QMAKE_CFLAGS_RELEASE = -O1 -Oy- -Gy -Gw -GL -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O1 -Oy- -Gy -Gw -GL -MT -Zi
:'''64-bit'''
QMAKE_CFLAGS_RELEASE = -O1 -Gy -Gw -GL -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O1 -Gy -Gw -GL -MT -Zi
:'''32bit and 64-bit'''
QMAKE_CFLAGS_DEBUG = -Zi -MTd
QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT /LTCG
QMAKE_LFLAGS_RELEASE = /DEBUG /OPT:REF /OPT:ICF=5 /MANIFEST:EMBED /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT
QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF /OPT:ICF=5 /INCREMENTAL:NO
* Issue the following command:
:'''32-bit'''
configure -prefix G:\QBITTORRENT\install_msvc32\qt5 -I G:\QBITTORRENT\install_msvc32\base\include -L G:\QBITTORRENT\install_msvc32\base\lib -platform win32-msvc -release -opensource -confirm-license -strip -no-shared -static -static-runtime -ltcg -make libs -make tools -nomake examples -no-compile-examples -no-dbus -no-icu -system-zlib -openssl-linked -no-gtk -no-opengl -no-opengles3 -no-angle -no-sql-sqlite -no-sql-odbc -no-sqlite -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquickcontrols -skip qtquickcontrols2 -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns ZLIB_LIBS="-lzlib" OPENSSL_LIBS="-lzlib -llibcrypto -llibssl -lgdi32 -luser32 -lws2_32 -lAdvapi32 -lCrypt32"
:'''64-bit'''
configure -prefix G:\QBITTORRENT\install_msvc64\qt5 -I G:\QBITTORRENT\install_msvc64\base\include -L G:\QBITTORRENT\install_msvc64\base\lib -platform win32-msvc -release -opensource -confirm-license -strip -no-shared -static -static-runtime -ltcg -make libs -make tools -nomake examples -no-compile-examples -no-dbus -no-icu -system-zlib -openssl-linked -no-gtk -no-opengl -no-opengles3 -no-angle -no-sql-sqlite -no-sql-odbc -no-sqlite -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquickcontrols -skip qtquickcontrols2 -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns ZLIB_LIBS="-lzlib" OPENSSL_LIBS="-lzlib -llibcrypto -llibssl -lgdi32 -luser32 -lws2_32 -lAdvapi32 -lCrypt32"
* Now you have 2 choices for compiling. Using <code>nmake</code> or <code>jom</code>. 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 [https://download.qt.io/official_releases/jom/ 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
=== Install and Configure Qt Creator ===
* Just follow the installer instructions for the installation.
* Launch Qt Creator and select Tools->Options...
* Select the '''Kits''' 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_msvc32\qt5\bin\qmake.exe''' or '''G:\QBITTORRENT\install_msvc64\qt5\bin\qmake.exe'''
* Name it something meaningful like "Qt5 msvc x32" or "Qt5 msvc x64"
* Apply the changes
* Click the '''Kits''' tab
* Click the '''Add''' button. Choose a name eg Qt5 msvc2019 x32. 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 if you choose the 32-bit version of Qt and the equivalent for 64-bit. 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 <code>qbittorrent.pro</code> file in <code>G:\QBITTORRENT\qBittorrent</code>
* From the Window that pops up select the Qt version you added above and specify '''release''' version. You can also select where qBittorrent will be built if you want.
* If you're compiling the 4.2.x branch with MSVC2019:
:* Navigate down to <code>src/gui/Sources</code> in the Qt Creator folder tree on the left.
:* Open <code>fspathedit.cpp</code>.
:* At the end of the header inclusions at beginning of that file, add this line:
:::<code>#include <stdexcept></code>
:* and save your changes.
* Navigate to <code>G:\QBITTORRENT\qBittorrent</code> in Windows Explorer, and rename the <code>conf.pri.windows</code> file to <code>conf.pri</code> (or make a copy of it with that name). You'll have to change a few paths here so that qBittorrent successfully builds and links.
::: '''NOTE:''' The paths below use the proper pathnames for a 64-bit build. Make sure you adjust them if you are building for a 32-bit target. Moreover, there are some notes in <code>conf.pri</code> itself that provide for alternative configurations that are worth paying attention to, but are not covered here. Keeping that in mind:
:* Edit the first INCLUDEPATH to look like this (adjust for actual boost version):
INCLUDEPATH += $$quote(G:/QBITTORRENT/boost_1_73_0)
:* Edit the second INCLUDEPATH to look like this:
INCLUDEPATH += $$quote(G:/QBITTORRENT/install_msvc64/base/include)
:* Edit the third INCLUDEPATH to look like this:
INCLUDEPATH += $$quote(G:/QBITTORRENT/install_msvc64/qt5/include)
:* Delete the lines with the rest of the INCLUDEPATH variables
:* Edit the first LIBS to look like this (adjust for actual boost version):
LIBS += $$quote(-LG:/QBITTORRENT/boost_1_73_0/stage/lib)
:* Edit the second LIBS to look like this:
LIBS += $$quote(-LG:/QBITTORRENT/install_msvc64/base/lib)
:* Edit the third LIBS to look like this:
LIBS += $$quote(-LG:/QBITTORRENT/install_msvc64/qt5/lib)
:* Delete the nearby lines with the rest of the LIBS variables that '''expect paths'''
:* Look for the LIBS variables that take the lib names of libboost_system.
:**These lines may mention the <code>libtorrent</code> library as well on versions earlier than the 4.3.x branch; just leave that alone if it is present.
:**Adjust the filename of the <code>libboost_system</code> library. Its full name will vary based on the boost version, build-system, and target architecture, among other things. In our example, it can be found under <code>G:/QBITTORRENT/boost_1_73_0/stage/lib</code>.
:***For example, if you've built an x64 build of boost 1.73.0 with MSVC2019, it should be <code>libboost_system-vc142-mt-s-x64-1_73.lib</code>
:** '''Additionally''', if you are building 4.3.x or later, you must '''also''' specify the correct filename of the <code>libboost_date_time</code> library here. You can find out what it is by looking in the same directory that the <code>libboost_system</code> library is.
:* If you are compiling the 4.2.x branch rather than the latest master commit, find the following line
:::<code>LIBS += libeay32.lib ssleay32.lib</code>
::*and replace it with:
:::<code>LIBS += libcrypto.lib libssl.lib</code>
:* Save your changes.
* Select Build->Build Project "qbittorrent"
* After the compilation ends you should have ''qbittorrent.exe'' in <code><build folder>\src\release</code>. "build folder" is where you chose qBittorrent to be built in the popup window.
** If you didn't specify a build directory earlier, then by default, the build folder will be a new directory that's the same depth as--''not under''--your source directory, and may look something like this: <code>build-qbittorrent-Desktop_x86_windows_msvc2019_pe_64bit-Release</code>.