Project: userver (App Definition and Development / Streaming & Messaging)
File: build.md

The following CMake options are used by userver: | Option | Description | Default | |-|--|--| | USERVERFEATURECORE | Provide a core library with coroutines, otherwise build only `userver-universal` | ON | | USERVERFEATUREMONGODB | Provide asynchronous driver for MongoDB | ${USERVERISTHEROOTPROJECT} AND x86\ AND NOT \BSD | | USERVERFEATUREPOSTGRESQL | Provide asynchronous driver for PostgreSQL | ${USERVERISTHEROOTPROJECT} | | USERVERFEATUREREDIS | Provide asynchronous driver for Redis | ${USERVERISTHEROOTPROJECT} | | USERVERFEATURECLICKHOUSE | Provide asynchronous driver for ClickHouse | ${USERVERISTHEROOTPROJECT} AND x86\* | | USERVERFEATUREGRPC | Provide asynchronous driver for gRPC | ${USERVERISTHEROOTPROJECT} | | USERVERFEATUREKAFKA | Provide asynchronous driver for Apache Kafka | ${USERVERISTHEROOTPROJECT} | | USERVERFEATURERABBITMQ | Provide asynchronous driver for RabbitMQ (AMQP 0-9-1) | ${USERVERISTHEROOTPROJECT} | | USERVERFEATUREMYSQL | Provide asynchronous driver for MySQL/MariaDB | ${USERVERISTHEROOTPROJECT} | | USERVERFEATUREROCKS | Provide asynchronous driver for RocksDB | ${USERVERISTHEROOTPROJECT} | | USERVERFEATUREYDB | Provide asynchronous driver for YDB | ${USERVERISTHEROOTPROJECT} AND C++ standard >= 20 | | USERVERFEATUREUTEST | Provide 'utest' and 'ubench' for unit testing and benchmarking coroutines | ${USERVERFEATURECORE} | | USERVERFEATURECRYPTOPP_BLAKE2 | Provide wrappers for blake2 algorithms of crypto++ | ON | | USERVERFEATUREPATCH_LIBPQ | Apply patches to the libpq (add portals support), requires libpq.a | ON | | USERVERFEATURECRYPTOPPBASE64URL | Provide wrappers for Base64 URL decoding and encoding algorithms of crypto++ | ON | | USERVERFEATUREREDISHIMALLOC | Provide a `hi_malloc(unsigned long)` workaround | OFF | | USERVERFEATUREREDIS_TLS | SSL/TLS support for Redis driver | OFF | | USERVERFEATURESTACKTRACE | Allow capturing stacktraces using boost::stacktrace | OFF if platform is not \*BSD; ON otherwise | | USERVERFEATUREJEMALLOC | Use jemalloc memory allocator | ON | | USERVERFEATUREDWCAS | Require double-width compare-and-swap | ON | | USERVERFEATURETESTSUITE | Enable functional tests via testsuite | ON | | USERVERFEATUREGRPC_CHANNELZ | Enable Channelz for gRPC | ON for "sufficiently new" gRPC versions | | USERVERCHECKPACKAGE_VERSIONS | Check package versions | ON | | USERVER_SANITIZE | Build with sanitizers support, allows combination of values via 'val1 val2' | '' | | USERVERSANITIZEBLACKLIST | Path to file that is passed to the -fsanitize-blacklist option | '' | | USERVERUSELD | Linker to use, e.g. 'gold' or 'lld' | '' | | USERVER_LTO | Use link time optimizations | OFF | | USERVERLTOCACHE | Use LTO cache if present, disable for benchmarking build times | ON | | USERVERLTOCACHEDIR | LTO cache directory | `${CMAKECURRENTBINARYDIR}/.ltocache` | | USERVERLTOCACHESIZEMB | LTO cache size limit in MB | 6000 | | USERVERUSECCACHE | Use ccache if present, disable for benchmarking build times | ON | | USERVERCOMPILATIONTIME_TRACE | Generate Clang compilation time trace | OFF | | USERVERNOWERROR | Do not treat warnings as errors | ON | | USERVERPYTHONPATH | Path to the python3 binary for use in testsuite tests | python3 | | USERVERFEATUREERASELOGWITH_LEVEL | Logs of this and below levels are removed from

Possible values: trace, info, debug, warning, error | OFF | | USERVERDOWNLOADPACKAGES | Download missing third party packages and use the downloaded versions | ON | | USERVERPIPUSESYSTEMPACKAGES | Use system python packages inside venv | OFF | | USERVERPIPOPTIONS | Options for all pip calls | '' | | USERVERDOWNLOADPACKAGECARES | Download and setup c-ares if no c-ares of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGECCTZ | Download and setup cctz if no cctz of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGECLICKHOUSECPP | Download and setup clickhouse-cpp | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGECRYPTOPP | Download and setup CryptoPP if no CryptoPP of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGECURL | Download and setup libcurl if no libcurl of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGEFMT | Download and setup Fmt if no Fmt of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGEGBENCH | Download and setup gbench if no gbench of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGEGRPC | Download and setup gRPC if no gRPC of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGEGTEST | Download and setup gtest if no gtest of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGEPROTOBUF | Download and setup Protobuf if no Protobuf of matching version was found | ${USERVERDOWNLOADPACKAGEGRPC} | | USERVERDOWNLOADPACKAGEKAFKA | Download and setup librdkafka if no librdkafka matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERDOWNLOADPACKAGEYDBCPPSDK | Download and setup ydb-cpp-sdk if no ydb-cpp-sdk of matching version was found | ${USERVERDOWNLOAD_PACKAGES} | | USERVERFORCEDOWNLOAD_PACKAGES | Download all possible third-party packages even if there is an installed system package | OFF | | USERVER_INSTALL | Build userver for further installation | OFF | | USERVERISTHEROOTPROJECT | Contributor mode: build userver tests, samples and helper tools | auto-detects if userver is the top level project | | USERVERGOOGLECOMMONPROTOSTARGET | Name of cmake target preparing google common proto library | Builds userver-api-common-protos | | USERVERGOOGLECOMMON_PROTOS | Path to the folder with google common proto files | Downloads automatically | | USERVERPGSERVERINCLUDEDIR | Path to the folder with @ref POSTGRES_LIBS "PostgreSQL server headers", for example /usr/include/postgresql/15/server | autodetected | | USERVERPGSERVERLIBRARYDIR | Path to the folder with @ref POSTGRES_LIBS "PostgreSQL server libraries", for example /usr/lib/postgresql/15/lib | autodetected | | USERVERPGINCLUDEDIR | Path to the folder with @ref POSTGRESLIBS "PostgreSQL libpq headers", for example /usr/local/include | autodetected | | USERVERPGLIBRARYDIR | Path to the folder with @ref POSTGRESLIBS "PostgreSQL libpq libraries", for example /usr/local/lib | autodetected | | USERVERMYSQLALLOWBUGGYLIBMARIADB | Allows mysql driver to leak memory instead of aborting in some rare cases when linked against libmariadb3<3.3.4 | OFF | | USERVERDISABLEPHDRCACHE | Disable caching of dlphdr_info items, which interferes with dlopen | OFF | | USERVERDISABLERSEQ_ACCELERATION | Disable rseq-based optimizations, which may not work depending on kernel/glibc/distro/etc version | OFF for x86 Linux, ON otherwise | | USERVERFEATUREUBOOST_CORO | Build with vendored version of Boost.context and Boost.coroutine2, is needed for sanitizers builds | OFF for arm64 macOS, ON otherwise | To explicitly specialize the compiler use the cmake options `CMAKECCOMPILER` and `CMAKECXXCOMPILER`. For example to use clang-12 compiler install it and add the following options to cmake: `-DCMAKECXXCOMPILER=clang++-12 -DCMAKECCOMPILER=clang-12` @warning Using LTO can lead to . We don't recommend using `USERVER_LTO`. @anchor userver_libraries userver is split into multiple CMake libraries. | CMake target | CMake option to enable building the library | Component for install | Main documentation page | |-||--|-| | `userver-universal` | Always on | `universal` | @ref scripts/docs/en/index.md | | `userver-core` | `USERVERFEATURECORE` (`ON` by default) | `core` | @ref

| | `userver-grpc` | `USERVERFEATUREGRPC` | `grpc` | @ref scripts/docs/en/userver/grpc.md | | `userver-mongo` | `USERVERFEATUREMONGODB` | `mongo` | @ref scripts/docs/en/userver/mongodb.md | | `userver-postgresql` | `USERVERFEATUREPOSTGRESQL` | `postgresql` | @ref pg_driver | | `userver-redis` | `USERVERFEATUREREDIS` | `redis` | @ref scripts/docs/en/userver/redis.md | | `userver-clickhouse` | `USERVERFEATURECLICKHOUSE` | `clickhouse` | @ref clickhouse_driver | | `userver-kafka` | `USERVERFEATUREKAFKA` | `kafka` | @ref scripts/docs/en/userver/kafka.md | | `userver-rabbitmq` | `USERVERFEATURERABBITMQ` | `rabbitmq` | @ref rabbitmq_driver | | `userver-mysql` | `USERVERFEATUREMYSQL` | `mysql` | @ref scripts/docs/en/userver/mysql/designanddetails.md | | `userver-rocks` | `USERVERFEATUREROCKS` | `rocks` | TODO | | `userver-ydb` | `USERVERFEATUREYDB` | `ydb` | TODO | For installed userver or Conan, cmake targets are named like `userver::{component}`, for instance: `userver::core`, `userver::mysql`, etc Make sure to: Enable the CMake options to build the libraries you need Link against the libraries The details vary depending on the method of building userver: `addsubsirectory(userver)` as used in @ref servicetemplates "service templates" @ref userver_cpm "CPM" @ref userver_conan "Conan" @ref userver_install "userver install" userver uses for downloading missing packages. By default, we first try to find the corresponding system package. With `USERVERFORCEDOWNLOAD_PACKAGES=ON`, no such attempt is made, and we skip straight to `CPMAddPackage`. This can be useful to guarantee that the build uses the latest (known to userver) versions of third-party packages. You can control the usage of CPM with `USERVERDOWNLOAD*` options. For example, `USERVERDOWNLOADPACKAGES=OFF` is useful for CI and other controlled environments to make sure that no download attempts are made, which ensures repeatability and the best CI build speed. For details on the download options, refer to documentation. Some advice: `CPMSOURCECACHE` helps to avoid re-downloads with multiple userver build modes or multiple CPM-using projects; `CPMUSENAMEDCACHEDIRECTORIES` (which userver enables by default) avoids junk library names shown in IDEs. @anchor userver_cpm userver itself can be downloaded and built using CPM. ```cmake CPMAddPackage( NAME userver VERSION (userver release version or git commit hash) GIT_TAG (userver release version or git commit hash) GITHUB_REPOSITORY userver-framework/userver OPTIONS "USERVERFEATUREGRPC ON" ) targetlinklibraries(${PROJECT_NAME} userver-grpc) ``` Make sure to enable the CMake options to build userver libraries you need, then link to those libraries. @see @ref userver_libraries @anchor service_templates There are prepared and ready to use service templates at the github: https://github.com/userver-framework/service_template https://github.com/userver-framework/pgservicetemplate https://github.com/userver-framework/pggrpcservice_template Just use the template to make your own service: Press the green "Use this template" button at the top of the github template page Clone the service `git clone your-service-repo && cd your-service-repo && git submodule update --init` Give a proper name to your service and replace all the occurrences of "*service_template" string with that name. Feel free to tweak, adjust or fully rewrite the source code of your service. For local development of your service either use the docker build and tests run via `make docker-test`; or install the build dependencies on your local system and adjust the `Makefile.local` file to provide \b platform-specific \b CMake options to the template: The service templates allow to kickstart the development of your production-ready service, but there can't be a repo for each and every combination of userver libraries. To use additional userver libraries, e.g. `userver-grpc`, add to the root `CMakeLists.txt`: ```cmake set(USERVERFEATUREGRPC ON CACHE BOOL "" FORCE) addsubdirectory(thirdparty/userver) targetlinklibraries(${PROJECT_NAME} userver-grpc) ``` @see @ref userver_libraries See @ref tutorial_services for minimal usage examples of various userver libraries. \b Dependencies: @ref

"third_party/userver/scripts/docs/en/deps/ubuntu-22.04.md" Dependencies could be installed via: ``` bash sudo apt install --allow-downgrades -y $(cat third_party/userver/scripts/docs/en/deps/ubuntu-22.04.md | tr '\n' ' ') ``` The Docker image `ghcr.io/userver-framework/ubuntu-22.04-userver-pg:latest` provides a container with all the build dependencies, PostgreSQL and userver preinstalled and with a proper setup of PPAs with databases, compilers, tools. To run it just use a command like ``` docker run --rm -it --network ip6net --entrypoint bash ghcr.io/userver-framework/ubuntu-22.04-userver-pg:latest ``` The Docker image `ghcr.io/userver-framework/ubuntu-22.04-userver:latest` provides a container with all the build dependencies and userver preinstalled and with a proper setup of PPAs with databases, compilers, tools. To run it just use a command like ``` docker run --rm -it --network ip6net --entrypoint bash ghcr.io/userver-framework/ubuntu-22.04-userver:latest ``` The Docker image `ghcr.io/userver-framework/ubuntu-22.04-userver-base:latest` provides a container with all the build dependencies preinstalled and with a proper setup of PPAs with databases, compilers and tools. To run it just use a command like ``` docker run --rm -it --network ip6net --entrypoint bash ghcr.io/userver-framework/ubuntu-22.04-userver-base:latest ``` After that, install the databases and compiler you are planning to use via `apt install` and start developing. @note The above image is build from `scripts/docker/ubuntu-22.04-pg.dockerfile`, `scripts/docker/ubuntu-22.04.dockerfile` and `scripts/docker/base-ubuntu-22.04.dockerfile` respectively. See `scripts/docker/` directory and @ref scripts/docker/Readme.md for more inspiration on building your own custom docker containers. The userver framework is . To create a VM with preinstalled userver just click the "Create VM" button and pay for the Cloud hardware usage. After that the VM is ready to use. SSH to it and use `find_package(userver REQUIRED)` in the `CMakeLists.txt` to use the preinstalled userver framework. If there a need to update the userver in the VM do the following: ``` bash sudo apt remove userver-* cd /app/userver sudo git checkout develop sudo git pull sudo ./scripts/buildandinstall_all.sh ``` \b Dependencies: @ref scripts/docs/en/deps/ubuntu-21.10.md "third_party/userver/scripts/docs/en/deps/ubuntu-21.10.md" Dependencies could be installed via: ``` bash sudo apt install --allow-downgrades -y $(cat third_party/userver/scripts/docs/en/deps/ubuntu-21.10.md | tr '\n' ' ') ``` \b Dependencies: @ref scripts/docs/en/deps/ubuntu-20.04.md "third_party/userver/scripts/docs/en/deps/ubuntu-20.04.md" Dependencies could be installed via: ``` bash sudo apt install --allow-downgrades -y $(cat third_party/userver/scripts/docs/en/deps/ubuntu-20.04.md | tr '\n' ' ') ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DUSERVERFEATURECRYPTOPPBLAKE2=0 -DUSERVERFEATUREREDISHI_MALLOC=1 ``` \b Dependencies: @ref scripts/docs/en/deps/ubuntu-18.04.md "third_party/userver/scripts/docs/en/deps/ubuntu-18.04.md" Dependencies could be installed via: ``` bash sudo apt install --allow-downgrades -y $(cat third_party/userver/scripts/docs/en/deps/ubuntu-18.04.md | tr '\n' ' ') ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DCMAKECXXCOMPILER=g++-8 -DCMAKECCOMPILER=gcc-8 -DUSERVERFEATURECRYPTOPP_BLAKE2=0 \ -DUSERVERFEATURECRYPTOPPBASE64URL=0 -DUSERVERFEATUREGRPC=0 -DUSERVERFEATUREPOSTGRESQL=0 \ -DUSERVERFEATUREMONGODB=0 -DUSERVERUSELD=gold ``` \b Dependencies: @ref scripts/docs/en/deps/debian-11.md "third_party/userver/scripts/docs/en/deps/debian-11.md" \b Dependencies: @ref scripts/docs/en/deps/debian-11.md "third_party/userver/scripts/docs/en/deps/debian-11.md" (same as above) \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DCMAKECFLAGS='-DFILEOFFSETBITS=64' -DCMAKECXXFLAGS='-DFILEOFFSETBITS=64' ``` \b Dependencies: @ref scripts/docs/en/deps/fedora-36.md "third_party/userver/scripts/docs/en/deps/fedora-35.md" Fedora dependencies could be installed via: ``` bash sudo dnf install -y $(cat third_party/userver/scripts/docs/en/deps/fedora-35.md | tr '\n' ' ') ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DUSERVERFEATURESTACKTRACE=0 -DUSERVERFEATUREPATCH_LIBPQ=0 ``` \b Dependencies: @ref scripts/docs/en/deps/fedora-36.md "third_party/userver/scripts/docs/en/deps/fedora-36.md" Fedora dependencies could be installed via: ``` bash sudo dnf install -y $(cat third_party/userver/scripts/docs/en/deps/fedora-36.md | tr '\n' ' ') ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DUSERVERFEATURESTACKTRACE=0 -DUSERVERFEATUREPATCH_LIBPQ=0 ``` \b Dependencies: @ref scripts/docs/en/deps/gentoo.md "third_party/userver/scripts/docs/en/deps/gentoo.md" Dependencies could be installed via: ``` bash sudo emerge --ask --update --oneshot $(cat scripts/docs/en/deps/gentoo.md | tr '\n' ' ') ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DUSERVERCHECKPACKAGEVERSIONS=0 -DUSERVERFEATURE_GRPC=0 \ -DUSERVERFEATURECLICKHOUSE=0 ``` \b Dependencies: @ref scripts/docs/en/deps/arch.md

Using an AUR helper (pikaur in this example) the dependencies could be installed as: ``` bash pikaur -S $(cat third_party/userver/scripts/docs/en/deps/arch.md | sed 's/^makepkg|//g' | tr '\n' ' ') ``` Without AUR: ``` bash sudo pacman -S $(cat third_party/userver/scripts/docs/en/deps/arch.md | grep -v -- 'makepkg|' | tr '\n' ' ') cat third_party/userver/scripts/docs/en/deps/arch.md | grep -oP '^makepkg\|\K.*' | while read ;\ do \ DIR=$(mktemp -d) ;\ git clone https://aur.archlinux.org/$REPLY.git $DIR ;\ pushd $DIR ;\ yes|makepkg -si ;\ popd ;\ rm -rf $DIR ;\ done ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DUSERVERFEATUREPATCH_LIBPQ=0 ``` \b Dependencies: @ref scripts/docs/en/deps/macos.md "third_party/userver/scripts/docs/en/deps/macos.md". At least MacOS 10.15 required with and . Dependencies could be installed via: ```bash brew install $(cat third_party/userver/scripts/docs/en/deps/macos.md | tr '\n' ' ') ``` \b Recommended \b Makefile.local: ``` CMAKECOMMONFLAGS += -DCMAKEBUILDTYPE=Release -DCMAKEEXPORTCOMPILE_COMMANDS=ON \ -DUSERVERNOWERROR=1 -DUSERVERCHECKPACKAGE_VERSIONS=0 \ -DUSERVERFEATUREREDISHIMALLOC=1 \ -DUSERVERFEATURECRYPTOPPBLAKE2=0 -DUSERVERDOWNLOADPACKAGECRYPTOPP=1 \ -DUSERVERFEATURECLICKHOUSE=0 \ -DUSERVERFEATURERABBITMQ=0 \ -DOPENSSLROOTDIR=$(brew --prefix openssl) \ -DUSERVERPGLIBRARYDIR=$(pgconfig --libdir) -DUSERVERPGINCLUDEDIR=$(pgconfig --includedir) \ -DUSERVERPGSERVERLIBRARYDIR=$(pgconfig --pkglibdir) -DUSERVERPGSERVERINCLUDEDIR=$(pgconfig --includedir-server) ``` After that the `make test` would build and run the service tests. @warning MacOS is recommended only for development as it may have performance issues in some cases. userver works well on modern POSIX platforms. Follow the cmake hints for the installation of required packets and experiment with the CMake options. Feel free to provide a PR with instructions for your favorite platform at https://github.com/userver-framework/userver. If there's a strong need to build \b only the userver and run its tests, then see @ref scripts/docs/en/userver/tutorial/build_userver.md @anchor userver_install You can install userver globally and then use it from anywhere with `find_package`. Make sure to use the same build mode as for your service, otherwise subtle linkage issues will arise. To install userver build it with `USERVER_INSTALL=ON` flags in `Debug` and `Release` modes: ``` cmake -S./ -B./build_debug \ -DCMAKEBUILDTYPE=Debug \ -DUSERVER_INSTALL=ON \ -DUSERVER_SANITIZE="ub addr" \ -GNinja cmake -S./ -B./build_release \ -DCMAKEBUILDTYPE=Release \ -DUSERVER_INSTALL=ON \ -GNinja cmake --build build_debug/ cmake --build build_release/ cmake --install build_debug/ cmake --install build_release/ ``` Next, write ``` find_package(userver REQUIRED COMPONENTS core postgresql grpc redis clickhouse mysql rabbitmq mongo) ``` in your `CMakeLists.txt`. Choose only the necessary components. @see @ref userver_libraries Finally, link your source with userver component. For instance: ``` targetlinklibraries(${PROJECTNAME}objs PUBLIC userver::postgresql) ``` Done! You can use installed userver. Link `mariadbclient` additionally for mysql component: ``` targetlinklibraries(${PROJECTNAME}-mysqlobjs PUBLIC userver::mysql mariadbclient) ``` @anchor POSTGRES_LIBS If CMake option `USERVERFEATUREPATCH_LIBPQ` is on, then the same developer version of libpq, libpgport and libpgcommon libraries should be available on the system. If there are multiple versions of those libraries use USERVERPG* CMake options to aid the build system in finding the right version. You could also install any version of the above libraries by explicitly pinning the version. For example in Debian/Ubuntu pinning to version 14 could be done via the following commands: ``` sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7FCC7D46ACCC4CF8 echo "deb https://apt-archive.postgresql.org/pub/repos/apt jammy-pgdg-archive main" | sudo tee /etc/apt/sources.list.d/pgdg.list sudo apt update sudo mkdir -p /etc/apt/preferences.d printf "Package: postgresql-14\nPin: version 14.5*\nPin-Priority: 1001\n" | sudo tee -a /etc/apt/preferences.d/postgresql-14 printf "Package: postgresql-client-14\nPin: version 14.5*\nPin-Priority: 1001\n" | sudo tee -a /etc/apt/preferences.d/postgresql-client-14 sudo apt install --allow-downgrades -y postgresql-14 postgresql-client-14 printf "Package: libpq5\nPin: version 14.5*\nPin-Priority: 1001\n" | sudo tee -a /etc/apt/preferences.d/libpq5 printf "Package: libpq-dev\nPin: version 14.5*\nPin-Priority: 1001\n"| sudo tee -a /etc/apt/preferences.d/libpq-dev sudo apt install --allow-downgrades -y libpq5 libpq-dev ``` @htmlonly <div class="bottom-nav"> @endhtmlonly @ref scripts/docs/en/userver/supportedplatforms.md | @ref scripts/docs/en/userver/deployenv.md @htmlonly </div> @endhtmlonly