asciidoc вместо markdown

This commit is contained in:
2019-06-02 00:08:41 +03:00
parent 71dd5de667
commit 82ae133e81
89 changed files with 3514 additions and 3122 deletions

View File

@ -1,38 +1,20 @@
---
title: "CMake: управление проектом"
category: Программирование
tags: программирование, cmake,
summary:
toc: yes
monofontoptions:
- Scale=0.6
...
= CMake: управление проектом
:category: Программирование
:tags: программирование, cmake,
<style type="text/css" rel="stylesheet">
table {
table-layout: fixed;
}
thead th:nth-child(1) {
width: 30%;
}
thead th:nth-child(2) {
width: 70%;
}</style>
:toc:
[TOC]
== Полезные ссылки
* https://github.com/onqtam/awesome-cmake[Каталог ссылок]
* https://cgold.readthedocs.io/en/latest/index.html[CGold: The
Hitchhikers Guide to the CMake]
### Полезные ссылки
* [Каталог ссылок](https://github.com/onqtam/awesome-cmake)
* [CGold: The Hitchhikers Guide to the CMake](https://cgold.readthedocs.io/en/latest/index.html)
### Структура каталогов проекта
== Структура каталогов проекта
Файлы проекта и результаты компиляции размещаются в каталогах:
```
....
└── cmex
├── _build
│ ├── Debug
@ -54,68 +36,72 @@ thead th:nth-child(2) {
│ └── lib
├── thirdparty
└── tools
```
....
Назначение каталогов приведено в таблице.
Каталог | Назначение
-------------------------|----------------------------------------------
`cmex/_build` | Результаты компиляции
`cmex/_build/Debug` | Результаты компиляции в режиме отладки
`cmex/_build/Release` | Результаты компиляции в режиме выпуска
`cmex/.git` | Репозиторий git
`cmex/cmake` | Файлы с дополнительными функциями для CMake
`cmex/cmake/cmlib` | Библиотека функций для CMake
`cmex/cmake/find` | Модули CMake для поиска внешних программ и библиотек
`cmex/cmake/etc` | Файлы настроек, используемые в CMake
`cmex/cmake/generators` | Генераторы проектов
`cmex/doc` | Документация для проекта
`cmake/files` | Каталог для дополнительных файлов
`cmake/files/etc` | Каталог для файлов настроек проекта
`cmake/files/share` | Каталог для неизменяемых файлов
`cmake/files/var` | Каталог для изменяемых файлов
`cmex/l10n` | Файлы переводов
`cmex/src` | Исходные тексты
`cmex/src/app` | Исходные тексты программ
`cmex/src/lib` | Исходные тексты библиотек
`cmex/thirdparty` | Исходные тексты сторонних проектов
`cmex/tools` | Дополнительные утилиты
[cols=",",options="header",]
|===
|Каталог |Назначение
|`cmex/_build` |Результаты компиляции
|`cmex/_build/Debug` |Результаты компиляции в режиме отладки
|`cmex/_build/Release` |Результаты компиляции в режиме выпуска
|`cmex/.git` |Репозиторий git
|`cmex/cmake` |Файлы с дополнительными функциями для CMake
|`cmex/cmake/cmlib` |Библиотека функций для CMake
|`cmex/cmake/find` |Модули CMake для поиска внешних программ и библиотек
|`cmex/cmake/etc` |Файлы настроек, используемые в CMake
|`cmex/cmake/generators` |Генераторы проектов
|`cmex/doc` |Документация для проекта
|`cmake/files` |Каталог для дополнительных файлов
|`cmake/files/etc` |Каталог для файлов настроек проекта
|`cmake/files/share` |Каталог для неизменяемых файлов
|`cmake/files/var` |Каталог для изменяемых файлов
|`cmex/l10n` |Файлы переводов
|`cmex/src` |Исходные тексты
|`cmex/src/app` |Исходные тексты программ
|`cmex/src/lib` |Исходные тексты библиотек
|`cmex/thirdparty` |Исходные тексты сторонних проектов
|`cmex/tools` |Дополнительные утилиты
|===
Каталог `_build` создаётся, чтобы избежать попадания получаемых во время
сборки файлов в иерархию основного проекта.
Запись результатов сборки проекта внутрь иерархии каталогов с исходными текстами
приводит к засорению формируемыми на этапе сборки файлами, которые затрудняют
разработку, поиск в оригинальных файлах и мешают ориентироваться в проекте.
При работе с несколькими типами сборки, например, отладка и выпуск, появляется
необходимость корректного полного удаления результатов предыдущего тип сборки.
сборки файлов в иерархию основного проекта. Запись результатов сборки
проекта внутрь иерархии каталогов с исходными текстами приводит к
засорению формируемыми на этапе сборки файлами, которые затрудняют
разработку, поиск в оригинальных файлах и мешают ориентироваться в
проекте. При работе с несколькими типами сборки, например, отладка и
выпуск, появляется необходимость корректного полного удаления
результатов предыдущего тип сборки.
### Начало проекта
== Начало проекта
В каталоге `cmex` нужно создать файл `CMakeLists.txt`:
```cmake
[source,cmake]
----
# Минимальная версия Cmake
cmake_minimum_required(VERSION 3.3)
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(cmex VERSION 0.2.0 LANGUAGES C CXX)
```
----
Значение версии следует формировать согласно правилам
[семантического версионирования](https://semver.org/lang/ru/).
https://semver.org/lang/ru/[семантического версионирования].
В каталог `cmake/cmlib` установить субмодуль CMLib, содержащий функции для CMake:
В каталог `cmake/cmlib` установить субмодуль CMLib, содержащий функции
для CMake:
```
....
git submodule add ssh://git@gitlab-server/root/cmlib cmake/cmlib
```
....
и подключить в файле `CMakeLists.txt`:
```cmake
[source,cmake]
----
# В каталоге cmake/cmlib находятся файлы с библиотечными функциями
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmlib)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/cmlib)
@ -125,19 +111,19 @@ endif()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/find)
include(CMLibCommon)
```
----
В файле `cmake/etc/organization.txt` записать название
организации, которой принадлежит проект:
В файле `cmake/etc/organization.txt` записать название организации,
которой принадлежит проект:
```
....
ORG, Inc.
```
....
В файле `cmake/etc/cpack_ignore.txt` перечислить шаблоны
для исключения из архива, создаваемого целью `dist`. Например:
В файле `cmake/etc/cpack_ignore.txt` перечислить шаблоны для исключения
из архива, создаваемого целью `dist`. Например:
```
....
cmake/lib/.git$
.git$
files/var
@ -146,82 +132,86 @@ CMakeLists.txt.user
\\\\..*\\\\.bak$
\\\\..*\\\\.tmp$
\\\\..*\\\\.swp$
```
....
Чтобы проверить корректность файла `CMakeLists.txt`, нужно создать
каталог `_build` в каталоге `cmex`, перейти в него и выполнить команды:
Чтобы проверить корректность файла `CMakeLists.txt`, нужно создать каталог
`_build` в каталоге `cmex`, перейти в него и выполнить команды:
```sh
[source,sh]
----
cmake ..
make
```
----
### Поиск системных библиотек
== Поиск системных библиотек
Системные библиотеки можно искать с помощью программы `pkgconfig`,
которая хранит базу данных параметров, включающую пути к заголовочным
файлами и перечни библиотек, необходимых для компоновки.
Сначала производится наличие модуля `PkgConfig`, в котором определена
функция `pkg_check_modules`, которая и осуществляет поиск. Например,
для поиска библиотек `gsl`, `fftw3` и `udev` можно написать:
файлами и перечни библиотек, необходимых для компоновки. Сначала
производится наличие модуля `PkgConfig`, в котором определена функция
`pkg_check_modules`, которая и осуществляет поиск. Например, для поиска
библиотек `gsl`, `fftw3` и `udev` можно написать:
```cmake
[source,cmake]
----
# Поиск библиотек с помощью pkgconfig
find_package(PkgConfig)
pkg_check_modules(GSL REQUIRED gsl)
pkg_check_modules(FFTW3 REQUIRED fftw3)
pkg_check_modules(UDEV udev)
```
----
Если системная библиотека поставляется без файла описания для `pkgconfig`,
то для её поиска может быть написан специальный модуль для `CMake`,
который вызывается функцией `find_package`. Кроме того функция `find_package`
может возвращать дополнительные значения, например, пути к исполняемым файлам.
Если системная библиотека поставляется без файла описания для
`pkgconfig`, то для её поиска может быть написан специальный модуль для
`CMake`, который вызывается функцией `find_package`. Кроме того функция
`find_package` может возвращать дополнительные значения, например, пути
к исполняемым файлам.
```cmake
[source,cmake]
----
# Поиск с помощью функции find_package
find_package(LibXml2)
find_package(CURL)
```
----
Если для библиотеки нет модуля, выполняющего её поиск, то можно
произвести поиск с помощью функции `find_library`. Например,
```cmake
[source,cmake]
----
# Поиск библиотеки с помощью функции find_library
find_library(MATHGL mgl PATHS /usr/lib /usr/lib/x86_64-linux-gnu)
find_library(MATHGLQT5 mgl-qt5 PATHS /usr/lib /usr/lib/x86_64-linux-gnu)
```
----
### Автоматически генерируемый заголовочный файл
== Автоматически генерируемый заголовочный файл
На этапе конфигурирования проекта можно создать файл, в который будут
записаны параметры, полученные на данной стадии. В библиотеке CMLib
присутствует функция `cmlib_config_hpp_generate()`, создающая файл
`${CMAKE_BUILD_DIR}/include/config.hpp`, в который записывается
информация о имени и версии проекта, дате и типе сборки.
информация о имени и версии проекта, дате и типе сборки.
```cmake
[source,cmake]
----
# Автоматически генерируемый заголовочный файл
cmlib_config_hpp_generate()
```
----
== Базовая библиотека
### Базовая библиотека
В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла
`CMakeLists.txt` в подкаталоге `src/lib`:
В файле `cmex/CMakeLists.txt` должна быть строка, включающая
поиск файла `CMakeLists.txt` в подкаталоге `src/lib`:
```cmake
[source,cmake]
----
add_subdirectory(src/libcmex)
```
----
В каталоге `cmex/src/libcmex` нужно создать файл `cmex.hpp`:
```cpp
[source,cpp]
----
#ifndef LIBCMEX_CMEX_HPP_
#define LIBCMEX_CMEX_HPP_
@ -230,21 +220,23 @@ add_subdirectory(src/libcmex)
int32_t cmex_init(int32_t i);
#endif // LIBCMEX_CMEX_HPP_
```
----
файл `cmex.cpp`:
```cpp
[source,cpp]
----
#include "cmex.hpp"
int32_t cmex_init(int32_t i = 0) {
return i;
return i;
}
```
----
и файл `CMakeLists.txt`:
```cmake
[source,cmake]
----
# Название основной цели и имя библиотеки в текущем каталоге
set(current_target cmex)
@ -274,21 +266,22 @@ if(BUILD_SHARED_LIBS)
endif()
install(FILES ${CMAKE_BINARY_DIR}/include/config.hpp ${current_target_headers}
COMPONENT headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${current_target})
```
----
== Базовое приложение
### Базовое приложение
В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла
`CMakeLists.txt` в подкаталоге `src/cmex`:
В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла `CMakeLists.txt`
в подкаталоге `src/cmex`:
```cmake
[source,cmake]
----
add_subdirectory(src/cmex)
```
----
В каталоге `cmex/src/cmex` нужно создать файл `main.cpp`:
```cpp
[source,cpp]
----
#include "compiler_features.hpp"
#include "config.hpp"
@ -297,18 +290,18 @@ add_subdirectory(src/cmex)
#include "cmex.hpp"
int main(int argc, char **argv) {
std::cout << CMEX_COMPILER_VERSION_MAJOR << std::endl; // Значение из compiler_features.hpp
std::cout << BUILD_TYPE << std::endl; // Значение из config.hpp
std::cout << CMEX_VERSION_STR << std::endl; // Значение из config.hpp
std::cout << cmex_init(4) << std::endl; // Функция из внутренней библиотеки
return 0;
std::cout << CMEX_COMPILER_VERSION_MAJOR << std::endl; // Значение из compiler_features.hpp
std::cout << BUILD_TYPE << std::endl; // Значение из config.hpp
std::cout << CMEX_VERSION_STR << std::endl; // Значение из config.hpp
std::cout << cmex_init(4) << std::endl; // Функция из внутренней библиотеки
return 0;
}
```
----
и файл `CMakeLists.txt`:
```cmake
[source,cmake]
----
# Название основной цели в текущем каталоге
set(current_target cmex_app)
@ -343,15 +336,15 @@ target_link_libraries(${current_target} cmex_static)
# Правила для установки
install(TARGETS ${current_target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
```
----
### Подключение внешнего проекта
== Подключение внешнего проекта
В каталоге `cmex/thirdparty` нужно создать каталог `cmext` с проектом,
состоящим из файлов `cmext.hpp`:
```c
[source,c]
----
#ifndef CMEXT_CMEXT_HPP_
#define CMEXT_CMEXT_HPP_
@ -360,21 +353,23 @@ install(TARGETS ${current_target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
int32_t cmext_init(int32_t i);
#endif
```
----
`cmext.cpp`:
```c
[source,c]
----
#include "cmext.hpp"
int32_t cmext_init(int32_t i = 0) {
return i;
return i;
}
```
----
и `CMakeLists.txt`:
```cmake
[source,cmake]
----
cmake_minimum_required(VERSION 3.3)
project(cmext)
@ -382,13 +377,14 @@ include(GNUInstallDirs)
add_library(cmext cmext.cpp)
install(TARGETS cmext ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES cmext.hpp COMPONENT headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME})
```
----
В файле `cmex/CMakeLists.txt` нужно подключить стандартный модуль
`ExternalProject` и описать правила для его загрузки, настройки,
компиляции и установки для сопряжения с текущим проектом:
```cmake
[source,cmake]
----
# Подключение внешних проектов
include(ExternalProject)
@ -400,36 +396,41 @@ ExternalProject_Add(cmext
BUILD_BYPRODUCTS <INSTALL_DIR>/lib/libcmext.a
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_BUILD_TYPE=Release
)
```
----
Вызовы этих функций нужно сделать до функций `add_subdirectories`,
чтобы в подключенных подкаталогах можно было использовать цель `cmext`
для определения зависимостей.
Вызовы этих функций нужно сделать до функций `add_subdirectories`, чтобы
в подключенных подкаталогах можно было использовать цель `cmext` для
определения зависимостей.
В файле `cmex/src/cmex/CMakeLists.txt` нужно подключить внешний проект `cmext`:
В файле `cmex/src/cmex/CMakeLists.txt` нужно подключить внешний проект
`cmext`:
```cmake
[source,cmake]
----
# Зависимость от библиотеки из внешнего проекта проекта
add_dependencies(${current_target} cmext)
```
----
```cmake
[source,cmake]
----
# Добавление каталога, в который устанавливаются заголовочные файлы от внешнего
# проекта cmext, к списку путей для поиска заголовочных файлов
target_include_directories(${current_target} PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include/cmext>)
```
----
```cmake
[source,cmake]
----
# Библиотека из внешнего проекта cmext
target_link_libraries(${current_target} ${CMAKE_BINARY_DIR}/lib/libcmext.a)
```
----
Для проверки работоспособности в файле `cmex/src/cmex/main.cpp` нужно вызвать
функцию `cmext_init` из библиотеки, предоставляемой внешним проектом.
Например:
Для проверки работоспособности в файле `cmex/src/cmex/main.cpp` нужно
вызвать функцию `cmext_init` из библиотеки, предоставляемой внешним
проектом. Например:
```cpp
[source,cpp]
----
#include "compiler_features.hpp"
#include "config.hpp"
@ -456,43 +457,44 @@ int main(int argc, char **argv) {
// Функция из внешней библиотеки
qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl;
return 0;
return 0;
}
```
----
== Qt5
### Qt5
Для поиска необходимых компонентов Qt5 нужно в файл
`cmex/CMakeLists.txt` добавить строки:
Для поиска необходимых компонентов Qt5 нужно в файл `cmex/CMakeLists.txt`
добавить строки:
```cmake
[source,cmake]
----
find_package(Qt5 COMPONENTS Core Network Gui Widgets DBus Concurrent Sql REQUIRED)
```
----
Библиотека CMLib автоматически подключает вызов препроцессора `moc`
и компилятора ресурсов `rcc`, если цель использует модуль `Core`, и
Библиотека CMLib автоматически подключает вызов препроцессора `moc` и
компилятора ресурсов `rcc`, если цель использует модуль `Core`, и
вызывает компилятор файлов описания интерфейса, если цель использует
модуль `Widgets`.
### Консольное приложение
== Консольное приложение
В файл `cmex/src/cmex/CMakeLists.txt` добавить строки:
```cmake
[source,cmake]
----
# Qt5
qt_translation(TARGET ${current_target} TS_DIR ${CMAKE_SOURCE_DIR}/l10n LANGUAGES ru_RU)
target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_compile_options(${current_target} PUBLIC "${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
target_link_libraries(${current_target} Qt5::Core)
```
----
Для проверки работоспособности подключения Qt5 файл `cmex/src/cmex/main.cpp`
нужно заменить на:
Для проверки работоспособности подключения Qt5 файл
`cmex/src/cmex/main.cpp` нужно заменить на:
```cpp
[source,cpp]
----
#include "compiler_features.hpp"
#include "config.hpp"
@ -509,13 +511,13 @@ QTextStream& qStdOut()
}
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
QTranslator translator;
QCoreApplication app(argc, argv);
QTranslator translator;
if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm")))
{
app.installTranslator(&translator);
}
if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm")))
{
app.installTranslator(&translator);
}
// Значение из compiler_features.hpp
qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl;
// Значение из config.hpp
@ -527,30 +529,32 @@ int main(int argc, char **argv) {
// Функция из внешней библиотеки
qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl;
return 0;
return 0;
}
```
----
После сборки проекта в каталоге `cmex/l10n` появится файл `cmex_app_ru_RU.ts`,
в котором нужно отредактировать переводы с помощью программы `linguist`.
После сохранения переводов проект нужно пересобрать, файл переводов в
скопилированном виде будет встроен в исполняемый файл `cmex`, а доступ
к нему будет осуществляться с помощью кода:
После сборки проекта в каталоге `cmex/l10n` появится файл
`cmex_app_ru_RU.ts`, в котором нужно отредактировать переводы с помощью
программы `linguist`. После сохранения переводов проект нужно
пересобрать, файл переводов в скопилированном виде будет встроен в
исполняемый файл `cmex`, а доступ к нему будет осуществляться с помощью
кода:
```cpp
if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm")))
{
app.installTranslator(&translator);
}
```
[source,cpp]
----
if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm")))
{
app.installTranslator(&translator);
}
----
== Графическое приложение
### Графическое приложение
Для создания минимального графического приложения нужно создать файл
описания интерфейса `cmex/src/cmex/my_main_window.ui`:
Для создания минимального графического приложения нужно создать
файл описания интерфейса `cmex/src/cmex/my_main_window.ui`:
```xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MyMainWindow</class>
@ -571,11 +575,12 @@ int main(int argc, char **argv) {
<resources/>
<connections/>
</ui>
```
----
заголовочный файл `cmex/src/cmex/my_main_window.hpp`:
```cpp
[source,cpp]
----
#ifndef CMEX_MY_MAIN_WINDOW_HPP_
#define CMEX_MY_MAIN_WINDOW_HPP_
@ -583,18 +588,20 @@ int main(int argc, char **argv) {
#include "ui_my_main_window.h"
class MyMainWindow : public QWidget, private Ui::MyMainWindow {
Q_OBJECT
public:
MyMainWindow(QWidget* parent = 0);
virtual ~MyMainWindow();
Q_OBJECT
public:
MyMainWindow(QWidget* parent = 0);
virtual ~MyMainWindow();
};
#endif /* CMEX_MY_MAIN_WINDOW_HPP_ */
```
----
и файл с реализацией конструктора и деструктора `cmex/src/cmex/my_main_window.cpp`:
и файл с реализацией конструктора и деструктора
`cmex/src/cmex/my_main_window.cpp`:
```cpp
[source,cpp]
----
#include "my_main_window.hpp"
MyMainWindow::MyMainWindow(QWidget* parent) {
@ -604,12 +611,13 @@ MyMainWindow::MyMainWindow(QWidget* parent) {
MyMainWindow::~MyMainWindow() {
}
```
----
Для отображения графического окна нужно заменить файл
`cmex/src/cmex/main.cpp` на:
```cpp
[source,cpp]
----
#include "compiler_features.hpp"
#include "config.hpp"
@ -628,13 +636,13 @@ QTextStream& qStdOut()
}
int main(int argc, char **argv) {
QApplication app(argc, argv);
QTranslator translator;
QApplication app(argc, argv);
QTranslator translator;
if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm")))
{
app.installTranslator(&translator);
}
if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm")))
{
app.installTranslator(&translator);
}
// Значение из compiler_features.hpp
qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl;
@ -647,16 +655,17 @@ int main(int argc, char **argv) {
// Функция из внешней библиотеки
qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl;
MyMainWindow* mmw = new MyMainWindow();
mmw->show();
return app.exec();
MyMainWindow* mmw = new MyMainWindow();
mmw->show();
return app.exec();
}
```
----
В файле `cmex/src/cmex/CMakeLists.txt` добавить новые файлы
к списку файлов, используемых для компиляции:
В файле `cmex/src/cmex/CMakeLists.txt` добавить новые файлы к списку
файлов, используемых для компиляции:
```cmake
[source,cmake]
----
set(current_target_sources
main.cpp
my_main_window.cpp
@ -665,51 +674,51 @@ set(current_target_sources
set(current_target_uis
my_main_window.ui
)
```
----
```cmake
[source,cmake]
----
# Цель для создания исполняемого файла
add_executable(${current_target} ${current_target_sources} ${current_target_uis})
```
----
и добавить строки для подключения графических библиотек Qt5
и соответствующих им заголовочных файлов:
и добавить строки для подключения графических библиотек Qt5 и
соответствующих им заголовочных файлов:
```cmake
[source,cmake]
----
target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Gui_INCLUDE_DIRS})
target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Widgets_INCLUDE_DIRS})
target_link_libraries(${current_target} Qt5::Gui)
target_link_libraries(${current_target} Qt5::Widgets)
```
----
Во время сборки проекта в файл переводов `cmex/l10n/cmex_app_ru_RU.ts`
будут добавлены повые строки, их нужно перевести с помощью `linguist`
и снова скомпилировать проект.
будут добавлены повые строки, их нужно перевести с помощью `linguist` и
снова скомпилировать проект.
### Удаление установленных файлов
== Удаление установленных файлов
В библиотеку CMLib добавлена цель `uninstall`, позволяющая удалить
файлы, перечисленные в файле `${CMAKE_BUILD_DIR}/install_manifest.txt`.
### Архивирование проекта
== Архивирование проекта
Стандарный модуль `CPack` осуществляет архивирование проекта. В файле
`cproj/cmake/etc/cpack_ignore.txt` определён список типовых масок файлов для
исключения из архива:
`cproj/cmake/etc/cpack_ignore.txt` определён список типовых масок файлов
для исключения из архива:
```
....
.git$
files/var
CMakeLists.txt.user
~$
\\\\..*\\\\.bak$
\\\\..*\\\\.tmp$
\\\\..*\\\\.bak$
\\\\..*\\\\.swp$
```
\\\\..*\\\\.o$
....
По умолчанию цель для упаковки проекта называется `package_source`.
В библиотеке CMLib определены значения основных параметров, а также
По умолчанию цель для упаковки проекта называется `package_source`. В
библиотеке CMLib определены значения основных параметров, а также
дополнительная цель `dist`.

View File

@ -0,0 +1,38 @@
= Intel Parallel Studio: установка в образ для чтения
:category: Linux/Программы
:tags: Linux, Intel, компилятор, C++,
Для установки и использования Intel Parallel Studio в сжатом образе
доступном только для чтения необходимо:
[arabic]
. Скачать
https://software.intel.com/en-us/parallel-studio-xe[дистрибутив] и
распаковать его.
. Скачать файл link:files/parallel-studio/silent.cfg[`silent.cfg`] и
скопировать его в полученный каталог.
. Если есть файл лицензии `parallel_studio.lic`, скопировать его в
каталог `/opt/intel/licenses`.
. Добавить полномочия для сбора статистики:
[source,sh]
----
sudo setcap cap_sys_ptrace=eip /opt/intel/vtune_amplifier/bin64/amplxe-cl
sudo setcap cap_sys_ptrace=eip /opt/intel/vtune_amplifier/bin64/amplxe-perf
----
[arabic, start=5]
. От суперпользователя установить в каталог `/opt/intel` командой
`sudo ./install.sh -s silent.cfg`.
. Создать образ
`mksquashfs /opt/intel/* /home/user/intel.sfs -comp xz -Xbcj x86 -all-root -b 512K`
. Удалить содержимое каталога `/opt/intel`.
. Подмонтировать образ:
`mount -t squashfs /home/user/intel.sfs /opt/intel`
. Добавить в файл `/home/user/.bashrc` строки:
[source,sh]
----
source /opt/intel/bin/compilervars.sh intel64
source /opt/intel/vtune_amplifier/amplxe-vars.sh
----

View File

@ -1,22 +0,0 @@
---
title: "Intel Parallel Studio: установка в образ для чтения"
category: Linux/Программы
tags: Linux, Intel, компилятор, C++
summary:
...
Для установки и использования Intel Parallel Studio
в сжатом образе доступном только для чтения необходимо:
1. Скачать [дистрибутив](https://software.intel.com/en-us/parallel-studio-xe) и распаковать его.
2. Скачать файл [`silent.cfg`](files/parallel-studio/silent.cfg) и скопировать его в полученный каталог.
3. Если есть файл лицензии `parallel_studio.lic`, скопировать его в каталог `/opt/intel/licenses`.
4. От суперпользователя установить в каталог `/opt/intel` командой `sudo ./install.sh -s silent.cfg`.
5. Создать образ `mksquashfs /opt/intel/* /home/user/intel.sfs -comp xz -Xbcj x86 -all-root -b 512K`
6. Удалить содержимое каталога `/opt/intel`.
7. Подмонтировать образ: `mount -t squashfs /home/user/intel.sfs /opt/intel`
8. Добавить в файл `/home/user/.bashrc` строки:
```sh
source /opt/intel/bin/compilervars.sh intel64
source /opt/intel/vtune_amplifier/amplxe-vars.sh
```

View File

@ -1,59 +1,62 @@
---
title: "PVS-Studio"
category: Программирование
tags: программирование, C, C++, отладка,
summary:
toc: yes
...
= PVS-Studio
:category: Программирование
:tags: программирование, C, C++, отладка,
[TOC]
:toc:
### Информация и лицензия
== Информация и лицензия
[PVS-Studio](https://www.viva64.com/ru/pvs-studio/) — это инструмент для
статического анализа исходного кода программ, написанных на языках С, C++.
https://www.viva64.com/ru/pvs-studio/[PVS-Studio] — это инструмент для
статического анализа исходного кода программ, написанных на языках С,
C++.
Для использования в Linux нужно чтобы в каталоге `~/.config/PVS-Studio`
находился лицензионный ключ или в начале исходных файлов с расширениями
`*.c`, `*.cpp`, `*.cxx` и т.п. [присутствовали строки](https://www.viva64.com/ru/b/0457/)
`*.c`, `*.cpp`, `*.cxx` и т.п.
https://www.viva64.com/ru/b/0457/[присутствовали строки]
```
....
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
```
....
### Настройка и компиляция проекта
== Настройка и компиляция проекта
Полное руководство для работы в Linux находится
[здесь](https://www.viva64.com/ru/m/0036/), а ниже приведён список типовых команд.
https://www.viva64.com/ru/m/0036/[здесь], а ниже приведён список типовых
команд.
Настройка проекта для CMake:
```sh
[source,sh]
----
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On <src-tree-root>
```
----
Сборка проекта с помощью `make`:
```sh
[source,sh]
----
pvs-studio-analyzer trace -- make -j$(nproc)
```
----
Настройка и сборка проекта с использованием Ninja:
```sh
[source,sh]
----
cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=On <src-tree-root>
ninja -t compdb
```
----
### Анализ проекта
== Анализ проекта
Для анализа проектов используется утилита `pvs-studio-analyzer`. По умолчанию
включены только диагностики общего назначения (General Analysis, GA).
Включить дополнительные правила можно с помощью опции `-a`:
Для анализа проектов используется утилита `pvs-studio-analyzer`. По
умолчанию включены только диагностики общего назначения (General
Analysis, GA). Включить дополнительные правила можно с помощью опции
`-a`:
```
....
-a [MODE], --analysis-mode [MODE]
MODE defines the type of warnings:
1 - 64-bit errors;
@ -64,45 +67,50 @@ ninja -t compdb
32 - MISRA.
Modes can be combined by adding the values
Default: 4
```
....
Выбор типов предупреждений осуществляется на основе побитовой маски из
приведенных выше типов. Чтобы выполнить анализ, исключив проверки MISRA,
нужно выполнить
```sh
[source,sh]
----
pvs-studio-analyzer analyze -a 29 -j$(nproc) -o pvs.log
```
----
Составление отчёта для просмотра в Qt Creator:
```sh
[source,sh]
----
plog-converter -t tasklist -o pvs.tasks pvs.log
```
----
При составлении отчёта уровень детализации можно изменять с помощью ключа
`-a` (`--analyzer`), который производит фильтрацию предупреждений согласно
маске, которая имеет вид `MessageType:MessageLevels`, где `MessageType`
может принимать один из следующих типов: `GA`, `OP`, `64`, `CS`, `MISRA`,
а `MessageLevels` может принимать значения от `1` до `3`.
При составлении отчёта уровень детализации можно изменять с помощью
ключа `-a` (`--analyzer`), который производит фильтрацию предупреждений
согласно маске, которая имеет вид `MessageType:MessageLevels`, где
`MessageType` может принимать один из следующих типов: `GA`, `OP`, `64`,
`CS`, `MISRA`, а `MessageLevels` может принимать значения от `1` до `3`.
Возможна комбинация разных масок через `;`. Например, при составлении
отчёта для просмотра в формате HTML можно повысить уровень детализации:
```sh
[source,sh]
----
plog-converter -t fullhtml -a "GA:1,2,3;64:1;OP:1,2;CS:1,2" -o html pvs.log
```
----
Составление отчёта для редактора Vim:
```sh
[source,sh]
----
plog-converter -a "GA:1,2" -t errorfile -o pvs.err pvs.log
```
----
Для просмотра отчёта в редакторе Vim нужно открыть файл `pvs.err` и выполнить команды:
Для просмотра отчёта в редакторе Vim нужно открыть файл `pvs.err` и
выполнить команды:
```vim
[source,vim]
----
:set makeprg=cat\ % " выбор программы для компиляции в текущей сессии
:silent make " имитация сборки
:cw " открытие результатов в нижнем окне
```
----

View File

@ -0,0 +1,36 @@
= Подбор ключей компиляции GCC
:category: Программирование
:tags: программирование, C, C++, отладка, оптимизация,
Подбор ключей компиляции основан на измерениях характеристик во время
выполнения программы. На первом этапе создаётся исполняемый файл
`program`, в который включается информация для профилировки. Ключ
`-fprofile-generate=data/pgo` указывает, что нужно собирать информацию и
сохранять в каталог `data/pgo`. Компиляцию следует выполнять в
последовательном режиме.
[source,sh]
----
env CXXFLAGS='-fprofile-generate=data/pgo' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"
make -j1
----
После компиляцию программу следует выполнить, придерживаясь типичного
сценария использования.
[source,sh]
----
./program
----
Скомпилировать программу с использованием полученной статистики. Для
многопоточной программы следует указать флаг `-fprofile-correction`,
чтобы скорректировать данные, которые могут неустойчивыми из-за
пропусков обновлений счётчиков. Компиляцию следует выполнять в
последовательном режиме.
[source,sh]
----
env CXXFLAGS='-fprofile-use=data/pgo -fprofile-correction' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"
make -j1
----

View File

@ -1,35 +0,0 @@
---
title: "Подбор ключей компиляции GCC"
category: Программирование
tags: программирование, C, C++, отладка, оптимизация,
summary:
...
Подбор ключей компиляции основан на измерениях характеристик во
время выполнения программы. На первом этапе создаётся исполняемый
файл `program`, в который включается информация для профилировки.
Ключ `-fprofile-generate=data/pgo` указывает, что нужно собирать
информацию и сохранять в каталог `data/pgo`. Компиляцию следует
выполнять в последовательном режиме.
```sh
env CXXFLAGS='-fprofile-generate=data/pgo' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"
make -j1
```
После компиляцию программу следует выполнить, придерживаясь
типичного сценария использования.
```sh
./program
```
Скомпилировать программу с использованием полученной статистики.
Для многопоточной программы следует указать флаг `-fprofile-correction`,
чтобы скорректировать данные, которые могут неустойчивыми из-за пропусков
обновлений счётчиков. Компиляцию следует выполнять в последовательном режиме.
```sh
env CXXFLAGS='-fprofile-use=data/pgo -fprofile-correction' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"
make -j1
```

View File

@ -0,0 +1,77 @@
= Профилирование кода
:category: Программирование
:tags: программирование, отладка, производительность, профилирование, gprof,
== Общее описание
Чтобы профилировать приложения, компилируемые http://gcc.gnu.org[GCC],
необходимо добавлять флаг `-fno-omit-frame-pointer` и, желательно, `-g`.
== quickstack
Утилита для отслеживания стеков вызовов функций
https://github.com/yoshinorim/quickstack[quicktrack]. Пример
использования:
[source,sh]
----
quickstack -f -p $(pidof application)
----
== perf
Утилита профилирования для ядра Linux (находится в дереве его исходных
текстов в каталоге `tools/perf`).
[source,sh]
----
perf record --call-graph dwarf -- ./application
perf report -g graph --no-children
----
Полезные ссылки:
* https://perf.wiki.kernel.org/index.php/Main_Page[Официальная страница]
* https://stackoverflow.com/questions/1777556/alternatives-to-gprof/10958510#10958510[Примеры]
* http://www.brendangregg.com/perf.html[Примеры]
== oprofile
[source,sh]
----
opcontrol --setup --vmlinux=/boot/vmlinux-`uname -r`
----
== Systemtap
https://eax.me/systemtap/[Установка и простые примеры использования
SystemTap]
== Valgrind
https://eax.me/valgrind/[Хорошая статья] об использовании Valgrind для
поиска утечек, а также о взаимодействии с GDB.
В версии 3.15 добавление инструмент профилирования кучи DHAT (Dynamic
Heap Analysis Tool), позволяющий отследить все запросы на распределения
памяти в куче и выявить утечки ресурсов, места излишне большой
активности при работе с кучей, неиспользованные выделения памяти,
краткосрочные выделения и неэффективное размещение данных в куче.
[source,sh]
----
valgrind --tool=dhat ./application
----
== gperftools
== Разное
* https://eax.me/c-cpp-profiling/[Профилирование кода на C/C++ в Linux и
FreeBSD]
* http://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-level-cpu-profiling-linux/[Примеры]
== Графическое отображение
* http://www.brendangregg.com/flamegraphs.html[Flame Graphs]
* https://github.com/jrfonseca/gprof2dot[gprof2dot]

View File

@ -1,79 +0,0 @@
---
title: "Профилирование кода"
category: Программирование
tags: программирование, отладка, производительность, профилирование, gprof,
summary:
...
## Общее описание
Чтобы профилировать приложения, компилируемые [GCC](http://gcc.gnu.org),
необходимо добавлять флаг `-fno-omit-frame-pointer` и, желательно, `-g`.
## quickstack
Утилита для отслеживания стеков вызовов функций [quicktrack](https://github.com/yoshinorim/quickstack).
Пример использования:
```sh
quickstack -f -p $(pidof application)
```
## perf
Утилита профилирования для ядра Linux (находится в дереве его исходных текстов
в каталоге `tools/perf`).
```sh
perf record --call-graph dwarf -- ./application
perf report -g graph --no-children
```
Полезные ссылки:
* [Официальная страница](https://perf.wiki.kernel.org/index.php/Main_Page)
* [Примеры](https://stackoverflow.com/questions/1777556/alternatives-to-gprof/10958510#10958510)
* [Примеры](http://www.brendangregg.com/perf.html)
## oprofile
```sh
opcontrol --setup --vmlinux=/boot/vmlinux-`uname -r`
```
## Systemtap
[Установка и простые примеры использования SystemTap](https://eax.me/systemtap/)
## Valgrind
[Хорошая статья](https://eax.me/valgrind/) об использовании Valgrind для поиска
утечек, а также о взаимодействии с GDB.
В версии 3.15 добавление инструмент профилирования кучи DHAT (Dynamic
Heap Analysis Tool), позволяющий отследить все запросы на распределения
памяти в куче и выявить утечки ресурсов, места излишне большой активности
при работе с кучей, неиспользованные выделения памяти, краткосрочные
выделения и неэффективное размещение данных в куче.
```sh
valgrind --tool=dhat ./application
```
## gperftools
## Разное
* [Профилирование кода на C/C++ в Linux и FreeBSD](https://eax.me/c-cpp-profiling/)
* [Примеры](http://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-level-cpu-profiling-linux/)
## Графическое отображение
* [Flame Graphs](http://www.brendangregg.com/flamegraphs.html)
* [gprof2dot](https://github.com/jrfonseca/gprof2dot)

View File

@ -1,33 +1,33 @@
---
title: "Статический анализ кода"
category: Программирование
tags: программирование, отладка, cppcheck, iwyu, clang-tidy, cpplint, clazy,
summary:
...
= Статический анализ кода
:category: Программирование
:tags: программирование, отладка, cppcheck, iwyu, clang-tidy, cpplint, clazy,
## Общее описание
== Общее описание
Ниже приведены утилиты для проверки кода на C++ и примеры их настройки и использования
совместно с [CMake](https://cmake.org/).
Ниже приведены утилиты для проверки кода на C++ и примеры их настройки и
использования совместно с https://cmake.org/[CMake].
### [clang-tidy](http://clang.llvm.org/extra/clang-tidy/)
=== http://clang.llvm.org/extra/clang-tidy/[clang-tidy]
Установка:
```sh
[source,sh]
----
sudo apt-get install clang-tidy-6.0
```
----
Использование:
```sh
[source,sh]
----
cmake "-DCMAKE_CXX_CLANG_TIDY=/usr/bin/clang-tidy-6.0" path/to/source
```
----
В каталоге проекта нужно создать файл `.clang-tidy` в формате YAML со списком
выполняемых проверок. Например:
В каталоге проекта нужно создать файл `.clang-tidy` в формате YAML со
списком выполняемых проверок. Например:
```yaml
[source,yaml]
----
---
Checks: '-*,
clang-diagnostic-*,
@ -42,91 +42,97 @@ CheckOptions:
- key: readability-identifier-naming.ClassMemberCase
value: camelBack
...
```
----
Пример файла `.clang-tidy`, в котором перечислены все правила для проверки
именования идентификаторов приведён [здесь](https://git.246060.ru/f1x1t/clang-tidy-readability-identifier-naming).
Пример файла `.clang-tidy`, в котором перечислены все правила для
проверки именования идентификаторов приведён
https://git.246060.ru/f1x1t/clang-tidy-readability-identifier-naming[здесь].
### CppCheck
=== CppCheck
Установка:
```sh
[source,sh]
----
sudo apt-get install cppcheck
```
----
Использование:
```sh
[source,sh]
----
cmake "-DCMAKE_CXX_CPPCHECK=/usr/bin/cppcheck;--std=c++11" path/to/source
```
----
This will run /usr/bin/cppcheck;std=c++11″ source=/path/to/source/file.cxx on each c++ file in the project being built.
This will run /usr/bin/cppcheck;std=c++11″
source=/path/to/source/file.cxx on each c++ file in the project being
built.
### CppLint
=== CppLint
Установка:
```sh
[source,sh]
----
sudo apt-get install python3-cpplint
```
----
Использование:
```sh
[source,sh]
----
cmake "-DCMAKE_CXX_CPPLINT=/usr/bin/cpplint;--linelength=79" path/to/source
```
----
```sh
[source,sh]
----
make -j24 2>&1 1>/dev/null | ../cpplint2tasks.pl > 222.tasks
```
----
This will run /usr/local/bin/cpplint linelength=79 on each c++ file in the project being built.
This will run /usr/local/bin/cpplint linelength=79 on each c++ file in
the project being built.
### IWYU
=== IWYU
Установка:
```sh
[source,sh]
----
sudo apt-get install iwyu
```
----
Использование:
```sh
[source,sh]
----
cmake "-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=/usr/bin/iwyu;--transitive_includes_only" ..
```
----
This will run /usr/bin/iwyu transitive_includes_only on each c++ file
in the project being built.
This will run /usr/bin/iwyu transitive_includes_only on each c++ file in the project being built.
=== LWYU
### LWYU
```sh
[source,sh]
----
cmake -DCMAKE_LINK_WHAT_YOU_USE=TRUE ..
```
### Clazy
----
=== Clazy
Установка:
```sh
[source,sh]
----
sudo apt-get install clazy clang-6.0
```
----
Использование:
```sh
[source,sh]
----
CLAZY_CHECKS=level2 cmake -DCMAKE_CXX_COMPILER=clazy ..
CLANGXX=clang++-6.0 make
```
### PVS-Studio
----
=== PVS-Studio