aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md238
1 files changed, 143 insertions, 95 deletions
diff --git a/README.md b/README.md
index 74cc49c6..d9f50f0a 100644
--- a/README.md
+++ b/README.md
@@ -7,15 +7,16 @@
[![release](https://img.shields.io/github/release/quotient-im/libQuotient/all.svg)](https://github.com/quotient-im/libQuotient/releases/latest)
[![](https://img.shields.io/cii/percentage/1023.svg?label=CII%20best%20practices)](https://bestpractices.coreinfrastructure.org/projects/1023/badge)
![](https://img.shields.io/github/commit-activity/y/quotient-im/libQuotient.svg)
-[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/quotient-im/libQuotient.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/quotient-im/libQuotient/context:cpp)
-[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
+![CI Status](https://img.shields.io/github/workflow/status/quotient-im/libQuotient/CI)
+![Sonar Tech Debt](https://img.shields.io/sonar/tech_debt/quotient-im_libQuotient?server=https%3A%2F%2Fsonarcloud.io)
+![Sonar Coverage](https://img.shields.io/sonar/coverage/quotient-im_libQuotient?server=https%3A%2F%2Fsonarcloud.io)
+![Matrix](https://img.shields.io/matrix/quotient:matrix.org?logo=matrix)
The Quotient project aims to produce a Qt5-based SDK to develop applications
for [Matrix](https://matrix.org). libQuotient is a library that enables client
applications. It is the backbone of
[Quaternion](https://github.com/quotient-im/Quaternion),
-[NeoChat](https://matrix.org/docs/projects/client/neo-chat) and
-other projects.
+[NeoChat](https://matrix.org/docs/projects/client/neo-chat) and other projects.
Versions 0.5.x and older use the previous name - libQMatrixClient.
## Contacts
@@ -28,72 +29,85 @@ If you find what looks like a security issue, please use instructions
in SECURITY.md.
## Getting and using libQuotient
-Depending on your platform, the library can come as a separate package.
-Recent releases of Debian and openSUSE, e.g., already have the package
-(under the old name). If your Linux repo doesn't provide binary package
-(either libqmatrixclient - older - or libquotient - newer), or you're
-on Windows or macOS, your best bet is to build the library from the source
-and bundle it with your application.
+Depending on your platform, the library can be obtained from a package
+management system. Recent releases of Fedora, Debian and openSUSE already have
+it. Alternatively, you can build the library from the source and bundle it with
+your application, as described below.
### Pre-requisites
- A recent Linux, macOS or Windows system (desktop versions are known to work;
mobile operating systems where Qt is available might work too)
- - Recent enough Linux examples: Debian Buster; Fedora 28; openSUSE Leap 15;
- Ubuntu Bionic Beaver.
-- Qt 5 (either Open Source or Commercial), 5.9 or higher;
- 5.12 is recommended, especially if you use qmake
-- A build configuration tool (CMake is recommended, qmake is supported):
- - CMake 3.10 or newer (from your package management system or
- [the official website](https://cmake.org/download/))
- - or qmake (comes with Qt)
-- A C++ toolchain with _reasonably complete_ C++17 support:
- - GCC 7 (Windows, Linux, macOS), Clang 6 (Linux), Apple Clang 10 (macOS)
- and Visual Studio 2017 (Windows) are the oldest officially supported.
-- Any build system that works with CMake and/or qmake should be fine:
- GNU Make, ninja (any platform), NMake, jom (Windows) are known to work.
+ - Recent enough Linux examples: Debian Bullseye; Fedora 35;
+ openSUSE Leap 15.4; Ubuntu 22.04 LTS.
+- Qt 5.15 or 6 (experimental, as of libQuotient 0.7) - either Open Source or
+ Commercial
+- CMake 3.16 or newer
+- A C++ toolchain that supports at least some subset of C++20 (concepts,
+ in particular):
+ - GCC 11 (Windows, Linux, macOS), Clang 11 (Linux), Apple Clang 12 (macOS)
+ and Visual Studio 2019 (Windows) are the oldest officially supported.
+- If using E2EE (beta, as of libQuotient 0.7):
+ - libolm 3.2.5 or newer (the latest 3.x strongly recommended)
+ - OpenSSL (1.1.x is known to work; 3.x should likely work too).
+- Any build system that works with CMake should be fine:
+ GNU Make and ninja on any platform, NMake and jom on Windows are known to work.
+ Ninja is recommended.
#### Linux
-Just install things from the list above using your preferred package manager. If your Qt package base is fine-grained you might want to run cmake/qmake and look at error messages. The library is entirely offscreen (QtCore and QtNetwork are essential) but it also depends on QtGui in order to handle avatar thumbnails.
+Just install things from the list above using your preferred package manager.
+If your Qt package base is fine-grained you might want to run cmake and look
+at error messages. The library is entirely offscreen but aside from QtCore and
+QtNetwork it also depends on QtGui in order to handle avatar thumbnails.
#### macOS
-`brew install qt5` should get you a recent Qt5. If you plan to use CMake, you will need to tell it about the path to Qt by passing `-DCMAKE_PREFIX_PATH=$(brew --prefix qt5)`
+`brew install qt5` should get you a recent Qt5. You may need to add the output
+of `brew --prefix qt5` to `CMAKE_PREFIX_PATH` (see below) to make CMake aware
+of the Qt location.
+
+If using E2EE, you need to perform the same dance for libolm and openssl.
#### Windows
-Install Qt5, using their official installer; if you plan to build with CMake,
-make sure to tick the CMake box in the list of installed components.
-
-The commands in further sections imply that cmake/qmake is in your PATH,
-otherwise you have to prepend those commands with actual paths. As an option
-it's a good idea to run a `qtenv2.bat` script that can be found in
-`C:\Qt\<Qt version>\<toolchain>\bin` (assuming you installed Qt to `C:\Qt`);
-the only thing it does is adding necessary paths to PATH. You might not want
-to run that script on system startup but it's very handy to setup
-the environment before building. For CMake you can alternatively point
-`CMAKE_PREFIX_PATH` to your Qt installation and leave PATH unchanged; but
-in that case you'll have to supply the full path to CMake when calling it.
+Install Qt5 using their official installer; make sure to tick the CMake box
+in the list of installed components unless you already have it installed.
+
+The commands in further sections imply that cmake is in your PATH, otherwise
+you have to prepend those commands with actual paths. It's a good idea to run
+a `qtenv2.bat` script that can be found in `C:\Qt\<Qt version>\<toolchain>\bin`
+(assuming you installed Qt to `C:\Qt`) if you're building from the command line;
+the script adds necessary paths to PATH. You might not want to run that script
+on system startup but it's very handy to setup the environment before building.
+Alternatively you can add the Qt path to `CMAKE_PREFIX_PATH` and leave PATH
+unchanged.
+
+If you're trying out E2EE, you will also need libolm and OpenSSL. Unfortunately,
+neither project provides official binary libraries for Windows. libolm can
+be compiled from the sources (available at ) using the same toolchain
+(CMake+MSVC). It's not recommended to compile OpenSSL yourself; instead, use
+one of the "OpenSSL for Windows" links in
+[unofficial list on the project Wiki](https://wiki.openssl.org/index.php/Binaries).
+
### Using the library
-If you use CMake, `find_package(Quotient)` sets up the client code to use
-libQuotient, assuming the library development files are installed. There's no
-documented procedure to use a preinstalled library with qmake; consider
-introducing a submodule in your source tree and build it along with the rest
-of the application for now. Note also that qmake is no more supported
-in libQuotient 0.7 so you should really think of moving over to CMake.
+If you're just starting a project using libQuotient from scratch, you can copy
+`quotest/CMakeLists.txt` to your project and change `quotest` to your
+project name. If you already have an existing CMakeLists.txt, you need to insert
+a `find_package(Quotient REQUIRED)` line to an appropriate place in it (use
+`find_package(Quotient)` if libQuotient is not a hard dependency for you) and
+then add `Quotient` to your `target_link_libraries()` line.
Building with dynamic linkage is only tested on Linux at the moment and is
a recommended way of linking your application with libQuotient on this platform.
Static linkage is the default on Windows/macOS; feel free to experiment
with dynamic linking and submit PRs if you get reusable results.
-[Quotest](tests), the test application that comes with libQuotient, includes
-most common use cases such as sending messages, uploading files,
-setting room state etc.; for more extensive usage check out the source code
-of [Quaternion](https://github.com/quotient-im/Quaternion)
-(the reference client of Quotient) or
-[NeoChat](https://invent.kde.org/network/neochat).
-
-To ease the first step, `tests/CMakeLists.txt` is a good starting point
-for your own CMake-based project using libQuotient.
+As for the actual API usage, a (very basic) overview can be found at
+[the respective wiki page](https://github.com/quotient-im/libQuotient/wiki/libQuotient-overview).
+Beyond that, looking at [Quotest](quotest) - the test application that comes
+with libQuotient - may help you with most common use cases such as sending
+messages, uploading files, setting room state etc. For more extensive usage
+feel free to check out (and copy, with appropriate attribution) the source code
+of [Quaternion](https://github.com/quotient-im/Quaternion) (the reference client
+for libQuotient) or [NeoChat](https://invent.kde.org/network/neochat).
## Building the library
[The source code is at GitHub](https://github.com/quotient-im/libQuotient).
@@ -102,28 +116,32 @@ along with submodules is strongly recommended. If you want to hack on
the library as a part of another project (e.g. you are working on Quaternion
but need to do some changes to the library code), it makes sense
to make a recursive check out of that project (in this case, Quaternion)
-and update the library submodule (also recursively) to its master branch.
+and update the library submodule (also recursively) within the appropriate
+branch. Be mindful of API compatibility restrictions: e.g., Quaternion 0.0.95
+will not build with the master branch of libQuotient.
Tags consisting of digits and periods represent released versions; tags ending
with `-betaN` or `-rcN` mark pre-releases. If/when packaging pre-releases,
it is advised to replace a dash with a tilde.
-### CMake-based
-In the root directory of the project sources:
+The following commands issued in the root directory of the project sources:
```shell script
mkdir build_dir
cd build_dir
cmake .. # [-D<cmake-variable>=<value>...], see below
cmake --build . --target all
```
-This will get you the compiled library in `build_dir` inside your project
-sources. Static builds are tested on all supported platforms, building
-the library as a shared object (aka dynamic library) is supported on Linux
-and macOS but is very likely to be broken on Windows.
-
-The first CMake invocation configures the build. You can pass CMake variables,
-such as `-DCMAKE_PREFIX_PATH="path1;path2;..."` and
-`-DCMAKE_INSTALL_PREFIX=path` here if needed.
+will get you a compiled library in `build_dir` inside your project sources.
+Static builds are tested on all supported platforms, building the library as
+a shared object (aka dynamic library) is supported on Linux and macOS but is
+very likely to be broken on Windows.
+
+Before proceeding, double-check that you have installed development libraries
+for all prerequisites above. CMake will stop and tell you if something's missing.
+
+The first CMake invocation above configures the build. You can pass CMake
+variables (such as `-DCMAKE_PREFIX_PATH="path1;path2;..."` and
+`-DCMAKE_INSTALL_PREFIX=path`) here if needed.
[CMake documentation](https://cmake.org/cmake/help/latest/index.html)
(pick the CMake version at the top of the page that you use) describes
the standard variables coming with CMake. On top of them, Quotient introduces:
@@ -137,9 +155,17 @@ the standard variables coming with CMake. On top of them, Quotient introduces:
to get the contents of `#quotient:matrix.org`; this is being fixed in
[#401](https://github.com/quotient-im/libQuotient/issues/401).
- `Quotient_ENABLE_E2EE=<ON/OFF>`, `OFF` by default - enable work-in-progress
- E2EE code in the library. Do NOT use this: as of 0.6, the code is very
- incomplete and leaks memory; 0.7 will have a different E2EE implementation.
-- `MATRIX_DOC_PATH` and `GTAD_PATH` - these two variables are used to point
+ E2EE code in the library. As of 0.6, this code is very incomplete and buggy;
+ you should NEVER use it. In 0.7, the enabled code is beta-quality and is
+ generally good for trying the technology and API but really not for
+ mission-critical applications.
+
+ Switching this on will define `Quotient_E2EE_ENABLED` macro (note
+ the difference from the CMake switch) for compiler invocations on all
+ Quotient and Quotient-dependent (if it uses `find_package(Quotient)`)
+ code; so you can use `#ifdef Quotient_E2EE_ENABLED` to guard the code using
+ E2EE parts of Quotient.
+- `MATRIX_SPEC_PATH` and `GTAD_PATH` - these two variables are used to point
CMake to the directory with the matrix-doc repository containing API files
and to a GTAD binary. These two are used to generate C++ files from Matrix
Client-Server API description made in OpenAPI notation. This is not needed
@@ -151,38 +177,60 @@ You can install the library with CMake:
cmake --build . --target install
```
This will also install cmake package config files; once this is done, you
-should be able to use [`tests/CMakeLists.txt`](tests/CMakeLists.txt) to compile quotest
+should be able to use [`quotest/CMakeLists.txt`](quotest/CMakeLists.txt) to compile quotest
with the _installed_ library. Installation of the `quotest` binary
along with the rest of the library can be skipped
by setting `Quotient_INSTALL_TESTS` to `OFF`.
-### qmake-based (deprecated)
-The library provides a .pri file with an intention to be included from a bigger project's .pro file. As a starting point you can use `quotest.pro` that will build a minimal example of library usage for you. In the root directory of the project sources:
-```shell script
-qmake quotest.pro
-make all
-```
-This will get you `debug/quotest` and `release/quotest`
-console executables that login to the Matrix server at matrix.org with
-credentials of your choosing (pass the username and password as arguments),
-run a sync long-polling loop and do some tests of the library API. Note that
-qmake didn't really know about C++17 until Qt 5.12 so if your Qt is older
-you may have quite a bit of warnings during the compilation process.
-
-Installing the standalone library with qmake has not been implemented.
-
## Troubleshooting
#### Building fails
-If `cmake` fails with...
-```
-CMake Warning at CMakeLists.txt:11 (find_package):
- By not providing "FindQt5Widgets.cmake" in CMAKE_MODULE_PATH this project
- has asked CMake to find a package configuration file provided by
- "Qt5Widgets", but CMake did not find one.
-```
-...then you need to set the right `-DCMAKE_PREFIX_PATH` variable, see above.
+- If `cmake` fails with
+ ```
+ CMake Warning at CMakeLists.txt:11 (find_package):
+ By not providing "FindQt5Widgets.cmake" in CMAKE_MODULE_PATH this project
+ has asked CMake to find a package configuration file provided by
+ "Qt5Widgets", but CMake did not find one.
+ ```
+ then you need to set the right `-DCMAKE_PREFIX_PATH` variable, see above.
+
+- If `cmake` fails with a message similar to:
+ ```
+ CMake Error at /usr/lib64/cmake/Qt6Core/Qt6CoreVersionlessTargets.cmake:37 (message):
+ Some (but not all) targets in this export set were already defined.
+
+ Targets Defined: Qt::Core
+
+ Targets not yet defined: Qt::CorePrivate
+ ```
+ then you likely have both Qt 5 and Qt 6 on your system, and your client code
+ uses a different major version than Quotient. Make sure you use the client
+ version that matches libQuotient (e.g. you can't configure Quaternion 0.0.95
+ with libQuotient 0.7 in Qt 6 mode).
+
+- If you use GCC and get an "unknown declarator" compilation error in the file
+`qtconcurrentthreadengine.h` - unfortunately, it is an actual error in Qt 5.15
+sources, see https://bugreports.qt.io/browse/QTBUG-90568 (or
+https://bugreports.qt.io/browse/QTBUG-91909). The Qt company did not make
+an open source release with the fix, therefore:
+
+ - if you're on Linux - try to use Qt from your package management system, as
+ most likely this bug is already fixed in the packages
+ - if you're on Windows, or if you have to use Qt (5.15) from download.qt.io
+ for any other reason, you should apply the fix to Qt sources: locate
+ the file (the GCC error message tells exactly where it is), find the line
+ with the (strange-looking) `ThreadEngineStarter` constructor definition:
+ ```cplusplus
+ ThreadEngineStarter<void>(ThreadEngine<void> \*_threadEngine)
+ ```
+ and remove the template specialisation from the constructor name so that it
+ looks like
+ ```cplusplus
+ ThreadEngineStarter(ThreadEngine<void> \*_threadEngine)
+ ```
+ This will fix your build (and any other build involving QtConcurrent from
+ this installation of Qt - the fix is not specific to Quotient in any way).
#### Logging configuration
@@ -191,11 +239,11 @@ libQuotient uses Qt's logging categories to make switching certain types of logg
quotient.<category>.<level>=<flag>
```
where
-- `<category>` is one of: `main`, `jobs`, `jobs.sync`, `events`, `events.state`
- (covering both the "usual" room state and account data), `events.messages`,
- `events.ephemeral`, `e2ee` and `profiler` (you can always find the full list
- in `lib/logging.cpp`)
-- `<level>` is one of `debug`, `info`, and `warning`
+- `<category>` is one of: `main`, `jobs`, `jobs.sync`, `jobs.thumbnail`,
+ `events`, `events.state` (covering both the "usual" room state and account
+ data), `events.messages`, `events.ephemeral`, `e2ee` and `profiler` (you can
+ always find the full list in `lib/logging.cpp`);
+- `<level>` is one of `debug`, `info`, and `warning`;
- `<flag>` is either `true` or `false`.
`*` can be used as a wildcard for any part between two dots, and semicolon is used for a separator. Latter statements override former ones, so if you want to switch on all debug logs except `jobs` you can set