Linking against a static Qt5 build using CMake

The previous post was the script I use to statically build Qt5 on Windows, but the real fun part is then linking an application using that version ! Here is the part of the CMake script I’m using (as usual, for reference)

For the moment I only build a basic Widgets application. As I use more modules / functionalities, I’ll update the script. Also please note that the very beginning (finding Qt) is tailored to my development setups, so you might need to update the paths (or provide CMake with a valid QT_DIR option)

Edit 2019-10-17: Since I removed accessibility from my build script, WindowsUIAutomationSupport is no longer needed as a dependency of the Windows integration plugin.

#
# Set to On to use a statically built version of Qt
#
set (QT_STATIC On)
if (QT_STATIC)
    set (QT_STATIC_SUFFIX "static/lib/cmake")
endif ()

#
# Find Qt.
#
find_path (QT_DIR Qt5
    HINTS
        # User set directory
        "${QT_DIR}"

        # My dev directories, depending on which machine I'm on
        "C:/Development/Libs/Qt/5.13.1"
        "D:/Development/Libs/Qt/5.13.1"
        "~/Development/Libs/Qt/5.13.1"

    PATH_SUFFIXES
        # As for the dev dirs, these are the suffixes to the CMake folder on the various machines I own.
        # Note that those are the default subfolder when installing Qt from its official installer.
        "${QT_STATIC_SUFFIX}"
        "msvc2017_64/lib/cmake"
        "gcc_64/lib/cmake"
        "clang_64/lib/cmake"
)

#
# Log / Error
#
if (NOT QT_DIR)
    message (FATAL_ERROR "Couldn't find Qt. Use QT_DIR variable to point to a valid Qt install.")
else ()
    message (STATUS "Found Qt in '${QT_DIR}'")
endif ()

#
# Find our Qt components
#
set (CMAKE_PREFIX_PATH ${QT_DIR})
find_package (Qt5 5
    COMPONENTS
        Widgets
    REQUIRED
)

#
# When using static build, exported Qt targets miss a awefull lot of dependencies (on Windows
# at least, didn't check the other platforms) so to avoid bothering, patch Qt5::Widgets
#
if (QT_STATIC)

    #
    # Set a few paths
    #
    set (QT_LIB_DIR "${QT_DIR}/..")
    set (QT_PLUGIN_DIR "${QT_DIR}/../../plugins")

    #
    # Qt5::QWindowsIntegrationPlugin
    # note that this target somehow is already there even if we didn't search for it in the
    # find_package command. And since it's mandatory to run the most basic Widgets application
    # on Windows ...
    #
    if (TARGET Qt5::QWindowsIntegrationPlugin)

        # find additional components needed by the windows platform plugin
        find_package (Qt5 5
            COMPONENTS
                EventDispatcherSupport
                FontDatabaseSupport
                ThemeSupport
            REQUIRED
        )

        # configure direct dependencies of the plugin
        target_link_libraries(Qt5::QWindowsIntegrationPlugin
            INTERFACE
                # Qt targets
                Qt5::EventDispatcherSupport
                Qt5::FontDatabaseSupport
                Qt5::ThemeSupport

                # Windows libs
                Dwmapi.lib
                Imm32.lib
                Wtsapi32.lib

                # The following is needed if you want to use the Windows vista style plugin.
                # If you provide your own style or CSS, you can comment out the following libs.
                ${QT_PLUGIN_DIR}/styles/qwindowsvistastyle.lib
                UxTheme.lib
        )

    endif ()

    #
    # Qt5::FontDatabaseSupport
    #
    if (TARGET Qt5::FontDatabaseSupport)

        target_link_libraries(Qt5::FontDatabaseSupport
            INTERFACE
                # Qt libs
                ${QT_LIB_DIR}/qtfreetype.lib
        )

    endif ()

    #
    # Qt5::Gui
    #
    if (TARGET Qt5::Gui)

        target_link_libraries(Qt5::Gui
            INTERFACE
                # Qt targets
                Qt5::QWindowsIntegrationPlugin

                # Qt libs
                ${QT_LIB_DIR}/qtlibpng.lib
        )

    endif ()

    #
    # Qt5::Core
    #
    if (TARGET Qt5::Core)

        target_link_libraries(Qt5::Core
            INTERFACE
                # Qt libs
                ${QT_LIB_DIR}/qtpcre2.lib

                # Windows libs
                Netapi32.lib
                Ws2_32.lib
                UserEnv.lib
                Version.lib
                Winmm.lib
        )

        target_compile_definitions (Qt5::Core
            INTERFACE
                # Remove debug stuff from Qt
                $<$<CONFIG:Release>:QT_NO_DEBUG>
                $<$<CONFIG:Release>:QT_NO_DEBUG_OUTPUT>
                $<$<CONFIG:Release>:QT_NO_INFO_OUTPUT>
                $<$<CONFIG:Release>:QT_NO_WARNING_OUTPUT>

                # Since Qt was built in release, we need to match it on Windows
                _ITERATOR_DEBUG_LEVEL=0
        )

    endif ()

endif ()

So this needs to be used after your project has been defined, and then you’ll be able the just add Qt5::Widgets to your target’s link libraries, and it should correctly link everything needed to run your Widgets application.

You’ll still need to manually import plugins though, and since the platform integration one is mandatory, here is how to do it (put that in your main compilation unit or wherever you want)

#if defined(QT_STATIC)

// needed to import statically linked plugins
#include <QtPlugin>

// The minimum plugin needed is the platform integration. Without it, the application just crashes on startup.
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);

// This one is for the Windows 'Vista' theme. As I wrote in the CMake part, this is
// optional if you plan on using your own CSS or style.
Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);

#endif

Qt5 static Windows build script

To avoid loosing the script I use to build Qt 5 on Windows, here is the latest version I’m using. Note that I’m compiling using Visual Studio 2019 and I disable things I don’t need to try to minimize build time.

Edit 2019-10-17: Removed accessibility and harfbuzz

@echo off

::
:: Configure Visual Studio 2019 Community for x64 build.
::
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64

::
:: Set Qt directory and set it as the current one.
::
set QT_DIR=C:\Development\Libs\Qt\5.13.1
pushd "%QT_DIR%\Src"

::
:: Configure Qt
::
call configure -release             ^
    -static                         ^
    -opensource -confirm-license    ^
    -prefix "%QT_DIR%/static"       ^
    -platform win32-msvc            ^
    -mp                             ^
    -c++std c++17                   ^
    -no-accessibility               ^
    -no-icu                         ^
    -no-harfbuzz                    ^
    -nomake examples                ^
    -nomake tests                   ^
    -skip qtwebengine               ^
    -skip qt3d

::
:: Build and install
::
nmake
nmake install

::
:: Restore the previous working directory
::
popd

Overwrite all git commit’s author

As a little post-it, here’s a script to amend author’s name and email of all commits of a repository. Use with care, it will override all commits, no matter what the original author is.

#!/bin/sh

if [ "$#" -ne 2 ]; then
	echo "usage: amend 'name' 'email'"
	exit 1
fi

git filter-branch -f --env-filter "
	GIT_AUTHOR_NAME='$1'
	GIT_AUTHOR_EMAIL='$2'
	GIT_COMMITTER_NAME='$1'
	GIT_COMMITTER_EMAIL='$2'
" HEAD

Credit: https://stackoverflow.com/a/750191/913135

Visual Studio 2017, CMake and launch settings

Long story short, documentation for CMake related features in Visual Studio 2017 sucks. It’s scattered among a ton of blog post where most of the code samples are outdated or contain errors. Here is an example launch.vs.json that I’m using for reference:

{
	"version": "0.2.1",
	"defaults": {},
	"configurations": [
		{
			"type": "Debug",
			"project": "CMakeLists.txt",
			"projectTarget": "foo.exe",
			"name": "foo.exe",

			// currentDir and not cwd like we can read in most examples ...
			"currentDir": "${workspaceRoot}",

			// this one is pretty straightforward
			"args": [ "arg0", "arg1" ],

			// env overwrites all the environment variables ...
			// separate vars by a null (\u0000) character. You can use existing env vars, see PATH
			"env": "TEST_ENV=foo\u0000HELLO=World\u0000PATH=${env.PATH};${workspaceRoot}"
		}
	]
}

Build / debug Blender with Visual Studio Code on Linux

Visual Studio Code is an open source and multiplatform IDE for code editing (and compiling, debugging, etc.) available here : https://code.visualstudio.com/

I wanted to see if I could build, run and debug Blender using this IDE, and the anwser is : yes. Here is how to do it.

Get Blender’s sources and dependencies

Based on : https://wiki.blender.org/index.php/Dev:Doc/Building_Blender/Linux/Generic_Distro/CMake. Here are the commands I used :

mkdir blender-git
cd blender-git
git clone --recursive https://git.blender.org/blender.git

This will get the main Blender sources. It’s quite fast, but depending on your internet connection speed, it can take a few minutes.

The next part is a lot longer : it will retrieve everything needed to build the third party libraries, and then build them. Depending on your computer it can be very long, so be patient. And check regularly, because it might ask for your password more than once !

cd ..
mkdir -p deps/src
mkdir -p deps/install
./blender/build_files/build_environment/install_deps.sh \
    --with-all \
    --source <path_to_blender-git>/deps/src \
    --install <path_to_blender-git>/deps/install

<path_to_blender-git> must be an absolute path to your blender-git folder. Note that you must also create the deps/src and deps/install folders prior to calling install_deps.sh, or else you might have some errors telling you that you don’t have the rights to create folders.

Install Visual Studio Code

Once you’ve installed Visual Studio Code, install the following addons :

  • C/C++ (Microsoft) – C/C++ support. Required
  • CMake (twxs) – CMake syntax coloring, code completion, etc. Optional but useful if you have to modify a CMake script file
  • CMake Tools (vector-of-bool) – Add Configure/Build features based on CMake. Required

Note that CMake Tools plugin requires CMake version 3.7.1 or greater, with server mode enabled (if you installed a recent prebuilt version from the CMake website, it should be enabled by default. But if you build your own, make sure it’s enabled)

Configure Blender’s project

Now, open Visual Studio Code, and open the blender-git/blender folder. If CMake Tools worked correctly, the status bar should look like this:

Before going further, we will setup the project to configure CMake to use the dependencies. Open the Preferences, then select “Workspace Settings” to only modify the Blender’s project settings. In this settings file, add the following options (there are comments in case you’re wondering what they do) :

// Place your settings in this file to overwrite default and user settings.
{
    //
    // This is where the build system will create intermediate files
    // I like to keep this out of my source folder to avoid
    // unintentionally commiting them :)
    //
    "cmake.buildDirectory": "${workspaceRoot}/../build", 

    //
    // This will setup the install path path. This option is needed
    // because Blender needs to deploy all its scripts files, and
    // this is not done during building, but during install.
    // So we need to setup this, and run CMake: Install once
    // before being able to debug. Note that this little complexity
    // is due to the way Blender is built/deployed
    //
    "cmake.installPrefix": "${workspaceRoot}/../build/bin",

    //
    // Options sent to CMake when it's configured. Those are the
    // options found in BUILD_NOTES.txt, converted to JSON format.
    // I didn't put all of them here, so copy from your own file.
    //
    "cmake.configureSettings": {
        "WITH_CODEC_SNDFILE": "ON",
        "PYTHON_VERSION": "3.5",
        "PYTHON_ROOT_DIR": "<blender-git>/deps/install/python-3.5",
        "WITH_OPENCOLORIO": "ON",
        "OPENCOLORIO_ROOT_DIR": "<blender-git>/deps/install/ocio"

        //
        // The rest of the options.
        // Don't forget to copy them !!
        //
    }
}

Notice that the options in BUILD_NOTES.txt are not formatted the same way as CMake Tools want, so you need to format them like in the example above.

Also note that even though you can have the -DWITH_OPENCOLLADA=ON option, install_deps.sh seems to forget to add the path to OpenCollada, so you need to add it yourself. Just add the following option:

"OPENCOLLADA_ROOT_DIR": "<blender-git>/deps/install/opencollada",

Now, click on the status bar on the "CMake: No Project: Unconfigured" part. It should pop a dropdown on the upper part of VSCode looking like this:

Just select debug, and when CMake’s done working, go to the Debug panel of VSCode. On the upper left corner, you should see this :

Since you haven’t configured the debug session, it’s perfectly normal :) Click on the little "No Configuration" dropdown, and you should see this :

Select C++ (GDB/LLDB) and it should create and open a launch.json file. The last step is to configure it. In my setup, it looks like this (the parts with a comment are the ones to might want to modify) :

{
    "version": "0.2.0",
    "configurations": [
        {
            //
            // the name of this configuration. Choose what you want
            //
            "name": "Debug",
            "type": "cppdbg",
            "request": "launch",

            //
            // Point to Blender's executable.
            //
            "program": "${workspaceRoot}/../build/bin/blender",
            "args": [],
            "stopAtEntry": false,

            //
            // Execute in the same folder as Blender's executable.
            //
            "cwd": "${workspaceRoot}/../build/bin",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "setupCommands": [
                 {
                     "description": "Enable pretty-printing for gdb",
                     "text": "-enable-pretty-printing",
                     "ignoreFailures": true
                 }
            ]
        }
    ]
}

Running / Debugging

And now, building is as simple as using the CMake: Build command (or even better, just F7 by default :p)

Just run a CMake: Install once to install all needed scripts into the folder where Blender’s executable is built, and you’re good to go. You only need to install when you do a clean/rebuild. If you only build Blender’s exe, you don’t need to re-install everytime :)

And debugging is as simple as putting a breakpoint where you want, and hitting F5. Well, provided it’s C/C++ source. To debug the Python scripts I don’t really know how that would work in VSCode since I never tried. But that might be the subject of a next article, if it’s feasible :)

Conclusion

It was my first time using Visual Studio Code, and I must say I’m very impressed by the ease of use and feature set ! Out of the box, it has Git support, and through the embedded extension manager you can enable C/C++ building/debugging/etc., CMake support, etc. with only a few clicks !

And then the setup part is completely straightforward ! You have a .vscode folder in your project containing the various .json setting files, and in each of those files, autocompletion works like a charm so you can easily find what you want, without even having to bother looking online for documentation / help !! (in my first tests, I was on an old computer where I had to specify the path to my custom CMake, and the path to my custom GDB, and I found them in a few seconds without having to leave the IDE)

Anyway, I highly recommend you to give a try to this software, CMake support is almost perfect (I still have to delete the build folder manually whenever I want to change the options CMake was configured with, but other than that, perfect) and building / debugging is fast, intuitive, user friendly and powerful.

Fontainebleau

Deux petites vidéos pour deux WE de grimpe, avec :

  • Renversement Dialectique (7a)
  • La Memel (7a+)
  • Free Hug (7b)
  • Noir Désir gauche (7b)
  • Dark Room (7a+)

Change default location of Visual Studio’s intellisense databases

A small post-it on how to change the default location of intellisense databases for Visual Studio. By default, those huge .sdf files (which get updated again and again) are stored next to your project location.

If you’re working on an SSD, or on a slow USB drive, you might want to avoid storing those databases at their usual location (or just to avoid having huge files around, or whatever other reason)

To do that, just go to Tools > Options then on the Text Editor > C/C++ > Advanced tab, locate the section Fallback Location. Here, Always use Fallback Location will need to be set to true to tell Visual Studio to always use the Fallback Location (which you can then set to any folder you want, or leave empty if you want to use the windows temp folder)

You can now close Visual Studio, remove your sdf files, launch it again. It will prompt you about your fallback location, but you just have to click OK and don’t forget to check the Don’t Prompt Me Again checkbox to avoid this at every launch. Tadaaa, no more sdf files next to your projects !

[Source]

Apremont Ouest

Beau ciel bleu et grosse collante pour un après-midi à Apremont. Et quelques belles croix :

  • Tailler en Pièce (7a)
  • Onde de Choc (7b)
  • Fleurs de Rhum (7a+)
  • Crazy Horse (7b)

Starring Carlos la Machina, Chukky le sac à pouf cool, et moiself.

Compiling ICU with Visual Studio 2013

In my previous post on how to build Qt on Windows, I explained how to build Qt for Windows, using Visual Studio 2010 and prebuilt ICU libraries. If we want to build Qt with Visual Studio 2013, we’ll need to build ICU ourself, and here’s how :

  • Download ICU sources from here : http://site.icu-project.org/download
  • Unzip in C:\ (you will have a C:\icu folder with C:\icu\readme.html (among others))
  • Go into C:\icu\source\common\unicode, edit platform.h and add the following somewhere at the beginning. It’s needed if you want to build Qt :
#define U_CHARSET_IS_UTF8 1
  • Go into C:\icu and create a build.bat file, with the following content and run it :
@echo off

::
:: setup Visual Studio 2013 environment for x64 builds
::
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64

::
:: build
::
msbuild source\allinone\allinone.sln /m /target:Build /property:Configuration=Release;Platform=x64
msbuild source\allinone\allinone.sln /m /target:Build /property:Configuration=Debug;Platform=x64

This will build ICU in x64. You can run the same script again and remove the “x86_amd64” argument to the vcvarsall.bat script, and change the Platform property to Win32 to build ICU in x86.

Building Qt from sources on Windows

Building Qt is not in itself difficult. But building Qt on Windows, and with QtWebkit can become quite the challenge. So here is a little tutorial on how I did it.

Configuration

First of all, you’ll need a lot of stuff correctly installed. Keep in mind that the paths to the following tools should appear in your PATH env var. Some installers will update it for you, for others you’ll need to add it personally.

So the first thing you’ll want to install is this great tool : Rapid Env Editor. Be careful though, the big Download button on the download page is NOT the one you want to click ! You don’t have to go to the download section, you have download links in the header on the upper right :) (I made the mistake, thus this warning)

Now the list of stuff you to install :

Now, time to get the sources / libraries :

  • Qt (Get the source zip)
  • ICU (Get the package corresponding to your compiler. Currently only Visual Studio 2010, you’ll need to build from sources to get a version corresponding to Visual Studio 2013)

Extract Qt and ICU somewhere on your disk. I recommend you to put that in a short path, such as C:\Qt and C:\ICU. See Troobleshooting section for the reason why :)

Building

Once everything’s installed and the paths to the tools in your PATH env var, you’re ready to build.

Go into the Qt sources root folder, then create a file name build_Qt_x64.bat (for instance) and copy the following into it :

@echo off

::
:: Remember the source path (where the Qt sources are, e.g. where this file is)
::
set sourcepath=%cd%

::
:: The following part should be updated to reflect your build environment
::

:: this will setup Visual Studio so that we can use it in command line
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86_amd64

:: where we want to install Qt
set installpath=C:\Qt_x64

:: set the path where icu's lib was installed
set icupath=C:\icu
set icusuffix=64

::
:: Setup the configuration
::

set configuration= -opensource -confirm-license -debug-and-release
set configuration= %configuration% -prefix "%installpath%"
set configuration= %configuration% -c++11 -mp -opengl desktop
set configuration= %configuration% -icu -I "%icupath%\include" -L "%icupath%\lib%icusuffix%"
set configuration= %configuration% -no-compile-examples -nomake tests -nomake examples -no-accessibility
set configuration= %configuration% -skip qtwebkit-examples

::
:: Cleanup previous install
::

if exist "%installpath%" ( echo Removing "%installpath%" )
if exist "%installpath%" ( rmdir /Q /S "%installpath%" )
if not exist "%installpath%" ( echo Creating "%installpath%" )
if not exist "%installpath%" ( mkdir "%installpath%" )

::
:: Update the path with a few access to dlls, tools, etc.
::

set path=%installpath%\qtbase\lib;%path%
set path=%icupath%\bin%icusuffix%;%path%
set path=%sourcepath%\GnuWin32\bin;%path%

::
:: Configure.
::

pushd "%installpath%"
call "%sourcepath%\configure" %configuration% -platform win32-msvc2010

::
:: And build
::

nmake
nmake install
nmake clean

popd

Now you can build by opening a command line on the root folder, and by typing the following :

build_Qt_x64.bat
nmake
nmake install
nmake clean

The first line is quite fast (a few minutes) and the second can take a whole night :) The 2 last are quite long too, but it’s reasonable (a few hours max)

Troubleshooting

Hopefully everything will work well, but here are a few problems that you might encounter. I’ll update this part if needed.

fatal error U1095

One of the compilation command line is too long. The solution (which worked for me) is to ove the Qt and ICU to short folders, such as (for instance) C:\Qt and C:\ICU

fatal error U1077

This has to do with ICU. You shouldn’t get this if you’re building with Visual Studio 2010. If you’re using Visual Studio 2012 or 2013, see this post about building ICU (thanks Mihai :p)

Release x64 crashes when all other versions work

This one I discovered very recently, and updated the build script. It’s due to a bug in the Visual Studio 2010 compiler for x64, when you use link time code generation (the -ltcg option) So the solution is to not use this option :)

References