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

View File

@ -0,0 +1,49 @@
= Построение профиля местности в QGis
:category: Картография
:tags: картография, qgis, sxf, shp, gdal,
[arabic]
. В главном меню QGis *Слой* — *Добавить слой* — *Добавить векторный
слой* выбрать и открыть файл с векторным слоем, например, `map.sxf`.
. Среди слоёв выбрать слой с рельефом местности и типом геометрии
`LineString`.
image:qgis-heights/1.png[Слои карты]
[arabic, start=3]
. На панели *Панель слоёв* правой кнопкой мыши щелкнуть на слое,
содержащем данные о высотах, и выбрать *Фильтр…*.
. Построить выражение выбирающие только данные с высотами, например,
`"CLNAME" ILIKE '%ГОРИЗОНТАЛИ ОСНОВ%'` и нажить *OK*.
. На панели *Панель слоёв* правой кнопкой мыши щелкнуть на слое,
содержащем данные о высотах, и выбрать *Сохранить как…*. Появившийся
новый слой *heights* следует удалить.
. В появившемся диалоговом окне выбрать имя выходного файла, например,
`heights`.
image:qgis-heights/2.png[Имя выходного файла]
[arabic, start=7]
. В каталоге `/home/a/work/map` выполнить команду, которая в файле
`heights.shp` из слоя `heights` берёт данные о высотах из поля `SC_4` и
генерирует матрицу высот размером 2000 на 2000 в формате BMP. Настойки
алгоритма посторения матрицы можно изменять с помощью параметра `-a`:
[source,sh]
----
gdal_grid -a invdist:power=3.0:smoothing=1.0 -outsize 2000 2000 -of BMP -ot Byte -zfield SC_4 -l heights heights.shp heights.bmp
----
[arabic, start=8]
. После построения матрицы её можно импортировать в QGis как растровый
слой, для этого в главном меню QGis *Слой* — *Добавить слой* — *Добавить
растровый слой* нужно выбрать и открыть файл `heights.bmp`. В результате
на панели *Панель слоёв* появится растровый слой *heights*.
. С помощью модуля Profile Tool можно построить профиль местности. В
главном меню нужно выбрать *Модуль* — *Profile Tool* — *Terrain
profile*.
. На панели *Панель слоёв* нужно перенести растровый слой *heights* в
конец списка, выделить его и на панели *Profile Tool* нажать *Add
Layer*. После этого на карте можно строить профили местности.
image:qgis-heights/3.png[Матрица высот]

View File

@ -1,51 +0,0 @@
---
title: "Построение профиля местности в QGis"
category: Картография
tags: картография, qgis, sxf, shp, gdal,
summary:
...
1) В главном меню QGis **Слой****Добавить слой****Добавить векторный слой**
выбрать и открыть файл с векторным слоем, например, `map.sxf`.
2) Среди слоёв выбрать слой с рельефом местности и типом геометрии `LineString`.
![Слои карты](images/qgis-heights/1.png)
3) На панели **Панель слоёв** правой кнопкой мыши щелкнуть на слое,
содержащем данные о высотах, и выбрать **Фильтр...**.
4) Построить выражение выбирающие только данные с высотами, например,
`"CLNAME" ILIKE '%ГОРИЗОНТАЛИ ОСНОВ%'` и нажить **OK**.
5) На панели **Панель слоёв** правой кнопкой мыши щелкнуть на слое,
содержащем данные о высотах, и выбрать **Сохранить как...**. Появившийся
новый слой **heights** следует удалить.
6) В появившемся диалоговом окне выбрать имя выходного файла, например, `heights`.
![Имя выходного файла](images/qgis-heights/2.png)
7) В каталоге `/home/a/work/map` выполнить команду, которая в файле
`heights.shp` из слоя `heights` берёт данные о высотах из поля `SC_4`
и генерирует матрицу высот размером 2000 на 2000 в формате BMP.
Настойки алгоритма посторения матрицы можно изменять с помощью параметра `-a`:
```sh
gdal_grid -a invdist:power=3.0:smoothing=1.0 -outsize 2000 2000 -of BMP -ot Byte -zfield SC_4 -l heights heights.shp heights.bmp
```
8) После построения матрицы её можно импортировать в QGis как растровый
слой, для этого в главном меню QGis **Слой****Добавить слой**
**Добавить растровый слой** нужно выбрать и открыть файл `heights.bmp`.
В результате на панели **Панель слоёв** появится растровый слой **heights**.
9) С помощью модуля Profile Tool можно построить профиль местности. В главном
меню нужно выбрать **Модуль****Profile Tool****Terrain profile**.
10) На панели **Панель слоёв** нужно перенести растровый слой **heights**
в конец списка, выделить его и на панели **Profile Tool** нажать **Add Layer**.
После этого на карте можно строить профили местности.
![Матрица высот](images/qgis-heights/3.png)

View File

@ -0,0 +1 @@
{"checksum":"81886ef1b8d31cdb2b865473bbeb2cf9","width":671,"height":550}

View File

@ -0,0 +1 @@
{"checksum":"e76d88ee3db613b3f806d8c773281fdc","width":685,"height":363}

View File

@ -0,0 +1,29 @@
= Git: автоматическое сохранение в репозиторий
:category: Программирование
:tags: программирование, git,
Скрипт https://github.com/elnull/gitwatch[gitwatch] позволяет
отслеживать изменения в каталоге с помощью программы `inotifywait` и
фиксировать их в репозиторий. Для работы скрипта необходимо установить
пакет `inotify-tools`. Если нужно следить за каталогом `/home/user/dir`
и записывать историю изменений в `/home/user/repo/dir`, то нужно
инициализировать репозиторий:
[source,sh]
----
git init --bare /home/user/repo/dir
----
добавить шаблоны исключаемых файлов:
[source,sh]
----
printf '*.[oa]\n*.swp\n*~\n/.git' >> /home/user/repo/dir/info/exclude
----
и запустить скрипт:
[source,sh]
----
./gitwatch.sh -g /home/user/repo/dir /home/user/dir
----

View File

@ -1,27 +0,0 @@
---
title: "Git: автоматическое сохранение в репозиторий"
category: Программирование
tags: программирование, git,
...
Скрипт [gitwatch](https://github.com/elnull/gitwatch) позволяет отслеживать
изменения в каталоге с помощью программы `inotifywait` и фиксировать их в
репозиторий. Для работы скрипта необходимо установить пакет `inotify-tools`.
Если нужно следить за каталогом `/home/user/dir` и записывать историю
изменений в `/home/user/repo/dir`, то нужно инициализировать репозиторий:
```sh
git init --bare /home/user/repo/dir
```
добавить шаблоны исключаемых файлов:
```sh
printf '*.[oa]\n*.swp\n*~\n/.git' >> /home/user/repo/dir/info/exclude
```
и запустить скрипт:
```sh
./gitwatch.sh -g /home/user/repo/dir /home/user/dir
```

View File

@ -1,20 +1,16 @@
---
title: "Git: замена адреса подмодуля"
category: Программирование
tags: программирование, git,
monofontoptions:
- Scale=0.7
...
= Git: замена адреса подмодуля
:category: Программирование
:tags: программирование, git,
Если у подмодуля, находящегося в каталоге `thirdparty/example` нужно
заменить адрес синхронизации и имя используемой ветки, то в каталоге
с файлом `.gitmodules`, в котором содержится информация об этом подмодуле,
заменить адрес синхронизации и имя используемой ветки, то в каталоге с
файлом `.gitmodules`, в котором содержится информация об этом подмодуле,
нужно выполнить команды:
```sh
[source,sh]
----
git config --file=.gitmodules submodule.thirdparty/example.url https://github.com/username/ABC.git
git config --file=.gitmodules submodule.thirdparty/example.branch new-branch-name
git submodule sync --recursive
git submodule update --init --recursive --remote
```
----

View File

@ -0,0 +1,391 @@
= Git: основные команды
:category: Программирование
:tags: программирование, git
== Ссылки
* https://githowto.com/ru/changes_not_files[GitHowTo]
* https://git-scm.com/book/ru/v2[ProGit]
* https://github.com/maxliscia/git-pocket[Git Pocket Guide]
== Установка
В Debian/Ubuntu:
[source,sh]
----
sudo apt-get install git
----
== Термины
[width="100%",cols="16%,17%,67%",options="header",]
|===
|Термин |Англ |Определение
|Рабочий каталог |working tree, working directory |Набор файлов в
текущем каталоге
|Репозиторий |repository, repo |Контейнер, хранящий историю изменений
файлов проекта
|Индекс |index, staging area |Область между рабочим каталогом и
репозиторием, в которой осуществляется подготовка к фиксации
|SHA-1 |SHA-1 |Уникальный идентификатор, отражающий информацию об
истории
|Ветка |branch |Именованная последовательность в истории изменений
|Фиксация (коммит) |commit |Набор файлов, записанных в историю
одновременно
|`HEAD` |`HEAD` |Имя ссылки на последнюю фиксацию в текущей ветке
|Метка |tag |Именованная ссылка на некоторую фиксацию в истории
|===
== Состояния
Файлы в рабочем каталоге могут отслеживаться системой контроля версий
(tracked) или нет (untracked). Отслеживаемые файлы, которые на диаграмме
обозначены зелёным фоном, могут быть неизменёнными (unmodified),
изменёнными (modified) или подготовленными к фиксации (staged).
[plantuml]
----
@startuml
participant untracked as "Неотслеживамые\n(untracked)"
box "Отслеживаемые"
participant staged as "Подготовленные к фиксации\n(staged)" #55FF55
participant unmodified as "Неизменённые\n(unmodified)" #99FF99
participant modified as "Изменённые\n(modified)" #77FF77
end box
untracked -> staged : git add
staged -> unmodified : git commit
unmodified -> modified : редактирование
modified -> staged : git add
modified -> untracked: git rm --cached
unmodified -> untracked: git rm --cached
staged -> untracked: git rm --cached
@enduml
----
Основные команды, осуществляющие взаимодействие между рабочим каталогом,
индексом, локальным и удалённым репозиторием, приведены на диаграмме
ниже.
[plantuml]
----
@startuml
participant workspace as "Рабочий каталог\n(working dir)"
participant index as "Индекс\n(index)" #77FF77
participant local as "Локальный репозиторий\n(local repository)" #FF7777
participant remote as "Удалённый репозиторий\n(remote repository)" #7777FF
workspace -> local : git commit -a
workspace -> index : git add (-u)
index -> local : git commit
local -> remote : git push
== Обновление с сервера ==
remote -> workspace : git pull (rebase)
remote -> local : fetch
== Откат изменений ==
local -[#red]> workspace : git checkout HEAD
index -[#red]> workspace : git checkout
== Сравнение ==
local -[#blue]> workspace : git diff HEAD
index -[#blue]> workspace : git diff
@enduml
----
== Настройка
[width="100%",cols="16%,38%,46%",options="header",]
|===
|Команда |Ключи |Описание
|`git config` |`--global user.name "John Doe"` |Имя текущего
пользователя
|`git config` |`--global user.email "mail@example.com"` |Почта текущего
пользователя
|`git config` |`--list` |Вывод текущей конфигурации
|`git config` |`--global --list` |Вывод глобальной конфигурации
|===
== Инициализация
[width="100%",cols="19%,27%,54%",options="header",]
|===
|Команда |Ключи |Описание
|`git init` |`<dir>` |Создать пустой репозиторий в каталоге `<dir>`
|`git clone` |`<giturl>` `<dir>` |Создать в каталоге `<dir>` копию
репозитория, находящегося по адресу `<giturl>`
|`git clone` |`--recursive <giturl>` `<dir>` |Создать в каталоге `<dir>`
копию репозитория, находящегося по адресу `<giturl>`, с учётом
подмодулей
|===
== Подмодули
[width="100%",cols="19%,27%,54%",options="header",]
|===
|Команда |Ключи |Описание
|`git submodule` |`add <giturl> <dir>` |Добавить в каталог `<dir>`
текущего рапозитория подмодуль, находящийся по адресу `<giturl>`
|`git submodule` |`update --recursive --remote` |Обновить подмодули
|`git submodule` |`sync --recursive` |Заменить адреса подмодулей на
указанные в файле `.gitmodules`
|===
Удаление подмодуля:
[source,sh]
----
git submodule deinit <path/to/submodule>
git rm <path/to/submodule>
----
== Фиксация
[width="100%",cols="19%,27%,54%",options="header",]
|===
|Команда |Ключи |Описание
|`git add` |`<filename>` |Подготовить файл `<filename>` к фиксации
|`git commit` | |Зафиксировать подготовленные файлы
|`git commit` |`-a` |Зафиксировать все отслеживаемые файлы, которые были
изменены
|`git rm` |`<filename>` |Удалить файл из индекса и рабочего каталога
|`git rm` |`-f <filename>` |Force deletion of files from disk
|`git rm` |`--cached <filename>` |Untrack file (without deleting)
|===
== Информация
[width="100%",cols="20%,20%,60%",options="header",]
|===
|Команда |Ключи |Описание
|`git status` |`-s` |Вывод информации о рабочем каталоге в
краткой форме
|`git log` |`--oneline` |Вывод журнала изменений в краткой форме
|`git ls-files` | |Вывод списка отслеживаемых и подготовленных файлов
|===
== $push branches (see tags for pushing tags)
[cols=",,",options="header",]
|===
|Команда |Ключи |Описание
|`git push` |`<remotename> <branchname>` |Push branch to remote
|`git push` |`<remotename> --all` |Push all branches to remote
|`git push` |`--d <remotename> <branchname>` |`--delete` remote branch
|===
== $remote
* Remote connections are like bookmarks named after remote repos
* `git clone` automatically creates a remote connection usually called
`origin`
[width="100%",cols="36%,26%,38%",options="header",]
|===
|Команда |Ключи |Описание
|`git remote` |`-v` |List remote repository endpoints
|`git branch` |`-r` |List remote repository branches
|`git remote` |`add <name> <url>` |Create namespaced connection to a
remote repository
|`git remote` |`rename <oldname> <newname>` |Rename connection
|`git remote` |`rm <name>` |Remove connection
|`git remote` |`add origin <url>` |Set remote origin
|===
Reference: https://git-scm.com/docs/git-remote
*Remove remote origin:*
[source,shell]
----
# Remove `origin` settings from .git/config
git remote rm origin
# Remove `FETCH_HEAD` which still points to remote
git rm .git/FETCH_HEAD
----
== $fetch-pull
[cols=",,",options="header",]
|===
|Команда |Ключи |Описание
|`git fetch` |`<remote>` |Fetch all branches from remote (without merge)
|`git fetch` |`<remote> <branch>` |Fetch specific branch
|`git merge` |`<remote>/<branch>` |Merge fetched remote
|`git pull` |`<remote>` |Fetch and merge in one command
|===
Reference: https://git-scm.com/docs/git-fetch,
https://git-scm.com/docs/git-pull
== $branch
[cols=",,",options="header",]
|===
|Команда |Ключи |Описание
|`git branch` | |List branches
|`git branch` |`<branchname>` |Create new branch
|`git checkout` |`<sha-1>` |Switch to branch, or commit
|`git branch` |`-m <branchname> <newname>` |Rename branch
|`git merge` |`<branchname>` |Merge changes from `<branchname>` to
current branch
|`git branch` |`-d <branchname>` |`--delete` branch
|===
Reference: https://git-scm.com/docs/git-branch
== $diff
[cols=",,",options="header",]
|===
|Команда |Ключи |Описание
|`git diff` | |Compare *`working directory`* and *`index`*
| |`-cached` |Compare *`index`* and *`latest commit`*
| |`HEAD` |Compare *`latest commit`* and *`working directory`*
| |`--stat` |Optional short format
| |`<sha-1> <sha-1>` |2 points in time to compare
| |`<dir> | <file>` |Compare whole directory or limit to file
|===
Reference: https://git-scm.com/docs/git-diff
*Examples:*
[source,shell]
----
## compare changes made to README.md between working tree (default) and latest commit (HEAD)
$ git diff --stat HEAD ./path/README.md
## compare changes made to README.md between 2 specific points in time (e.g. 2 commits)
$ git diff --stat a649900 24bdd58 ./path/README.md
----
== $tag
[width="100%",cols="36%,26%,38%",options="header",]
|===
|Команда |Ключи |Описание
|`git tag` | |List tags
|`git tag` |`<v1.0.0>` |Create tag, from latest commit, lightweight
|`git tag` |`-a <v1.0.0> -m "<msg>"` |Create tag, with `--annotate`,
from latest commit
|`git tag` |`-a <v1.0.0> -m "<msg>" <SHA-1>` |Create tag, with
`--annotate`, from specific commit
|`git tag` |`-d <v1.1.0>` |`--delete` tag
|`git show` |`<v1.0.0>` |Show tag data and message
|`git checkout` |`<v1.0.0>` |Switch to specific point tag (not editable)
|`git push` |`<remote> <tag>` |Push specific tag to `<remote>`
(recommended)
|`git push` |`<remote> --tags` |Push all tags to `<remote>` (only if
necessary)
|===
Инициализация репозитория в каталоге `dir`:
[source,sh]
----
git init dir
----
Клонирование репозитория `repo`, принадлежащего пользователю `user`, с
сервера `gitlab.2` в каталог `dir`:
[source,sh]
----
git clone git@gitlab.2:user/repo.git dir
----
Просмотр состояния рабочего каталога и репозитория:
[source,sh]
----
git status
----
Краткая форма вывода состояния:
[source,sh]
----
git status -s
----
Добавление файла `README.md` под версионный контроль и подготовка к
фиксации:
[source,sh]
----
git add README.md
----
Удаление файла `README.md` из индекса репозитория:
[source,sh]
----
git rm --cached README.md
----
Зафиксировать файлы, подготовленные к фиксации:
[source,sh]
----
git commit
----
Зафиксировать все отслеживаемые файлы, которые были изменены:
[source,sh]
----
git commit -a
----
Отправить все ветки репозитория на сервер с меткой `origin`:
[source,sh]
----
git push origin
----

View File

@ -1,311 +0,0 @@
---
title: "Git: основные команды"
category: Программирование
tags: программирование, git
monofontoptions:
- Scale=0.8
...
<style type="text/css" rel="stylesheet">
table { table-layout: fixed;}
</style>
## Ссылки
* [GitHowTo](https://githowto.com/ru/changes_not_files)
* [ProGit](https://git-scm.com/book/ru/v2)
* [Git Pocket Guide](https://github.com/maxliscia/git-pocket)
## Установка
В Debian/Ubuntu:
```sh
sudo apt-get install git
```
## Термины
| Термин | Англ | Определение |
| ------ | ------ | ----------------------- |
| Рабочий каталог | working tree, working directory | Набор файлов в текущем каталоге |
| Репозиторий | repository, repo | Контейнер, хранящий историю изменений файлов проекта |
| Индекс | index, staging area | Область между рабочим каталогом и репозиторием, в которой осуществляется подготовка к фиксации |
| SHA-1 | SHA-1 | Уникальный идентификатор, отражающий информацию об истории |
| Ветка | branch | Именованная последовательность в истории изменений |
| Фиксация (коммит) | commit | Набор файлов, записанных в историю одновременно |
| `HEAD` | `HEAD` | Имя ссылки на последнюю фиксацию в текущей ветке |
| Метка | tag | Именованная ссылка на некоторую фиксацию в истории |
## Состояния
Файлы в рабочем каталоге могут отслеживаться системой контроля версий
(tracked) или нет (untracked). Отслеживаемые файлы, которые на диаграмме
обозначены зелёным фоном, могут быть неизменёнными (unmodified),
изменёнными (modified) или подготовленными к фиксации (staged).
```plantuml
@startuml
participant untracked as "Неотслеживамые\n(untracked)"
box "Отслеживаемые"
participant staged as "Подготовленные к фиксации\n(staged)" #55FF55
participant unmodified as "Неизменённые\n(unmodified)" #99FF99
participant modified as "Изменённые\n(modified)" #77FF77
end box
untracked -> staged : git add
staged -> unmodified : git commit
unmodified -> modified : редактирование
modified -> staged : git add
modified -> untracked: git rm --cached
unmodified -> untracked: git rm --cached
staged -> untracked: git rm --cached
@enduml
```
Основные команды, осуществляющие взаимодействие между рабочим каталогом,
индексом, локальным и удалённым репозиторием, приведены на диаграмме ниже.
```plantuml
@startuml
participant workspace as "Рабочий каталог\n(working dir)"
participant index as "Индекс\n(index)" #77FF77
participant local as "Локальный репозиторий\n(local repository)" #FF7777
participant remote as "Удалённый репозиторий\n(remote repository)" #7777FF
workspace -> local : git commit -a
workspace -> index : git add (-u)
index -> local : git commit
local -> remote : git push
== Обновление с сервера ==
remote -> workspace : git pull (rebase)
remote -> local : fetch
== Откат изменений ==
local -[#red]> workspace : git checkout HEAD
index -[#red]> workspace : git checkout
== Сравнение ==
local -[#blue]> workspace : git diff HEAD
index -[#blue]> workspace : git diff
@enduml
```
## Настройка
| Команда | Ключи | Описание |
| ---- | ---------- | ------------ |
| `git config` | `--global user.name "John Doe"` | Имя текущего пользователя |
| `git config` | `--global user.email "mail@example.com"` | Почта текущего пользователя |
| `git config` | `--list` | Вывод текущей конфигурации |
| `git config` | `--global --list` | Вывод глобальной конфигурации |
## Инициализация
| Команда | Ключи | Описание |
| ---- | ------ | ------------ |
| `git init` | `<dir>` | Создать пустой репозиторий в каталоге `<dir>` |
| `git clone` | `<giturl>` `<dir>` | Создать в каталоге `<dir>` копию репозитория, находящегося по адресу `<giturl>` |
| `git clone` | `--recursive <giturl>` `<dir>` | Создать в каталоге `<dir>` копию репозитория, находящегося по адресу `<giturl>`, с учётом подмодулей |
## Подмодули
| Команда | Ключи | Описание |
| ---- | ------ | ------------ |
| `git submodule` | `add <giturl> <dir>` | Добавить в каталог `<dir>` текущего рапозитория подмодуль, находящийся по адресу `<giturl>` |
| `git submodule` | `update --recursive --remote` | Обновить подмодули |
| `git submodule` | `sync --recursive` | Заменить адреса подмодулей на указанные в файле `.gitmodules` |
Удаление подмодуля:
```sh
git submodule deinit <path/to/submodule>
git rm <path/to/submodule>
```
## Фиксация
| Команда | Ключи | Описание |
| ---- | ------ | ------------ |
| `git add` | `<filename>` | Подготовить файл `<filename>` к фиксации |
| `git commit` | | Зафиксировать подготовленные файлы |
| `git commit` | `-a` | Зафиксировать все отслеживаемые файлы, которые были изменены |
| `git rm` | `<filename>` | Удалить файл из индекса и рабочего каталога |
| `git rm` | `-f <filename>` | Force deletion of files from disk |
| `git rm` | `--cached <filename>` | Untrack file (without deleting) |
## Информация
| Команда | Ключи | Описание |
| ---- | ---- | ------------ |
| `git status` | `-s` | Вывод информации о рабочем каталоге в краткой форме |
| `git log` | `--oneline` | Вывод журнала изменений в краткой форме |
| `git ls-files` | | Вывод списка отслеживаемых и подготовленных файлов |
## $push branches (see tags for pushing tags)
| Команда | Ключи | Описание |
| ---- | ------ | ------------ |
| `git push` | `<remotename> <branchname>` | Push branch to remote |
| `git push` | `<remotename> --all` | Push all branches to remote |
| `git push` | `--d <remotename> <branchname>` | `--delete` remote branch |
## $remote
- Remote connections are like bookmarks named after remote repos
- `git clone` automatically creates a remote connection usually called `origin`
| Команда | Ключи | Описание |
|---------|-------|----------|
| `git remote` | `-v` | List remote repository endpoints |
| `git branch` | `-r` | List remote repository branches |
| `git remote` | `add <name> <url>` | Create namespaced connection to a remote repository |
| `git remote` | `rename <oldname> <newname>` | Rename connection |
| `git remote` | `rm <name>` | Remove connection |
| `git remote` | `add origin <url>` | Set remote origin |
Reference: https://git-scm.com/docs/git-remote
**Remove remote origin:**
```shell
# Remove `origin` settings from .git/config
git remote rm origin
# Remove `FETCH_HEAD` which still points to remote
git rm .git/FETCH_HEAD
```
## $fetch-pull
| Команда | Ключи | Описание |
|---------|-------|----------|
| `git fetch` | `<remote>` | Fetch all branches from remote (without merge) |
| `git fetch` | `<remote> <branch>` | Fetch specific branch |
| `git merge` | `<remote>/<branch>` | Merge fetched remote |
| `git pull` | `<remote>` | Fetch and merge in one command |
Reference: https://git-scm.com/docs/git-fetch, https://git-scm.com/docs/git-pull
## $branch
| Команда | Ключи | Описание |
|---------|-------|----------|
| `git branch` | | List branches |
| `git branch` | `<branchname>` | Create new branch |
| `git checkout` | `<sha-1>` | Switch to branch, or commit |
| `git branch` | `-m <branchname> <newname>` | Rename branch |
| `git merge` | `<branchname>` | Merge changes from `<branchname>` to current branch |
| `git branch` | `-d <branchname>` | `--delete` branch |
Reference: https://git-scm.com/docs/git-branch
## $diff
| Команда | Ключи | Описание |
|---------|-------|----------|
| `git diff` | | Compare **`working directory`** and **`index`** |
| | `-cached` | Compare **`index`** and **`latest commit`** |
| | `HEAD` | Compare **`latest commit`** and **`working directory`** |
| | `--stat` | Optional short format |
| | `<sha-1> <sha-1>` | 2 points in time to compare |
| | `<dir> | <file>` | Compare whole directory or limit to file |
Reference: https://git-scm.com/docs/git-diff
**Examples:**
```shell
## compare changes made to README.md between working tree (default) and latest commit (HEAD)
$ git diff --stat HEAD ./path/README.md
## compare changes made to README.md between 2 specific points in time (e.g. 2 commits)
$ git diff --stat a649900 24bdd58 ./path/README.md
```
## $tag
| Команда | Ключи | Описание |
|---------|-------|----------|
| `git tag` | | List tags |
| `git tag` | `<v1.0.0>` | Create tag, from latest commit, lightweight |
| `git tag` | `-a <v1.0.0> -m "<msg>"` | Create tag, with `--annotate`, from latest commit |
| `git tag` | `-a <v1.0.0> -m "<msg>" <SHA-1>` | Create tag, with `--annotate`, from specific commit |
| `git tag` | `-d <v1.1.0>` | `--delete` tag |
| `git show` | `<v1.0.0>` | Show tag data and message |
| `git checkout` | `<v1.0.0>` | Switch to specific point tag (not editable) |
| `git push` | `<remote> <tag>` | Push specific tag to `<remote>` (recommended) |
| `git push` | `<remote> --tags` | Push all tags to `<remote>` (only if necessary) |
Инициализация репозитория в каталоге `dir`:
```sh
git init dir
```
Клонирование репозитория `repo`, принадлежащего пользователю `user`,
с сервера `gitlab.2` в каталог `dir`:
```sh
git clone git@gitlab.2:user/repo.git dir
```
Просмотр состояния рабочего каталога и репозитория:
```sh
git status
```
Краткая форма вывода состояния:
```sh
git status -s
```
Добавление файла `README.md` под версионный контроль и подготовка
к фиксации:
```sh
git add README.md
```
Удаление файла `README.md` из индекса репозитория:
```sh
git rm --cached README.md
```
Зафиксировать файлы, подготовленные к фиксации:
```sh
git commit
```
Зафиксировать все отслеживаемые файлы, которые были изменены:
```sh
git commit -a
```
Отправить все ветки репозитория на сервер с меткой `origin`:
```sh
git push origin
```

View File

@ -0,0 +1,10 @@
= Git: распаковка объекта
:category: Программирование
:tags: программирование, git,
В случае повреждения репозитория можно восстановить отдельные объекты,
которые сохраняются в формате zlib. Пример команды:
....
perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' < 1234567890abcdef1234567890abcdef012345 > file
....

View File

@ -1,14 +0,0 @@
---
title: "Git: распаковка объекта"
category: Программирование
tags: программирование, git,
monofontoptions:
- Scale=0.7
...
В случае повреждения репозитория можно восстановить отдельные
объекты, которые сохраняются в формате zlib. Пример команды:
```
perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' < 1234567890abcdef1234567890abcdef012345 > file
```

View File

@ -1,26 +1,26 @@
---
title: "Git: репозиторий на переносном устройстве"
category: Программирование
tags: программирование, git,
...
= Git: репозиторий на переносном устройстве
:category: Программирование
:tags: программирование, git,
Создание репозитория для нового проекта:
```sh
[source,sh]
----
ln -s /media/user/usbdisk/git /home/user/work/usbdisk/git
git --bare init /home/user/work/usbdisk/git/project.git
cd /home/user/work/projects
git clone /home/user/work/usbdisk/git/project.git
cd project
git remote set-url usb file:///home/user/work/usbdisk/git/project.git/
```
----
Добавление нового удалённого репозитория к существующему проекту:
```sh
[source,sh]
----
ln -s /media/user/usbdisk/git /home/user/work/usbdisk/git
git --bare init /home/user/work/usbdisk/git/project.git
cd /home/user/work/projects/project
git remote add usb file:///home/user/work/usbdisk/git/project.git
git push --set-upstream usb master
```
----

View File

@ -0,0 +1,29 @@
= Git: частичная копия репозитория
:category: Программирование
:tags: программирование, git,
Если проект очень большой, а следить нужно только за малой его частью,
можно создать частичную копию репозитория. Допустим, по адресу
`git://localhost/project.git` находится большой проект, в котором
интересует только последнее состояние каталогов `src/driver` и
`include/driver`. Сначала нужно создать пустой репозиторий и подготовить
его для получения только необходимых файлов:
[source,sh]
----
git init project
cd project
git remote add origin git://localhost/project.git
git config core.sparsecheckout true
echo "src/driver/*" >> .git/info/sparse-checkout
echo "include/driver/*" >> .git/info/sparse-checkout
----
После этого можно получать частичную копию проекта, а, добавив ключ
`--depth=1`, указать, что синхронизироваться должно только текущее
состояние файлов без учёта истории.
[source,sh]
----
git pull --depth=1 origin master
----

View File

@ -1,31 +0,0 @@
---
title: "Git: частичная копия репозитория"
category: Программирование
tags: программирование, git,
summary:
...
Если проект очень большой, а следить нужно только за малой
его частью, можно создать частичную копию репозитория.
Допустим, по адресу `git://localhost/project.git` находится
большой проект, в котором интересует только последнее
состояние каталогов `src/driver` и `include/driver`.
Сначала нужно создать пустой репозиторий и подготовить его
для получения только необходимых файлов:
```sh
git init project
cd project
git remote add origin git://localhost/project.git
git config core.sparsecheckout true
echo "src/driver/*" >> .git/info/sparse-checkout
echo "include/driver/*" >> .git/info/sparse-checkout
```
После этого можно получать частичную копию проекта,
а, добавив ключ `--depth=1`, указать, что синхронизироваться
должно только текущее состояние файлов без учёта истории.
```sh
git pull --depth=1 origin master
```

View File

@ -0,0 +1,38 @@
= GitLab: выполнение по расписанию
:category: Программирование
:tags: программирование, gitlab, git,
После помещения изменений (push) на сервер следует выполнять только
задачи, не требующие много ресурсов. Ресурсоёмкие задачи можно отложить
на время минимальной нагрузки сервера. Для этого нужно:
* в секциях файла `.gitlab-ci.yml`, запускающих задачи с высокой
нагрузкой, добавить
[source,yaml]
----
only:
- schedules
----
подробнее это описано
https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified[здесь]
* в веб-интерфейсе в меню *CI/CD* / *Расписания* добавить *Новое
расписание* и назначить исполнение задачи на время, когда нагрузка на
сервер минимальна.
Для пропуска запланированной задачи в исполняемый скрипт нужно добавить
проверку условия запуска. Например, чтобы отменить запуск компиляции,
если за последний день (86400 секунд) не было изменений, можно оформить
`.gitlab-ci.yml` примерно так:
[source,yaml]
----
nightly-job:
only:
- schedules
script:
- "[ $(($(date +%s)-$(git log -1 --date=format:%s --format=%cd))) -gt 86400 ] && exit 0"
- make
----

View File

@ -1,36 +0,0 @@
---
title: "GitLab: выполнение по расписанию"
category: Программирование
tags: программирование, gitlab, git,
...
После помещения изменений (push) на сервер следует выполнять только задачи,
не требующие много ресурсов. Ресурсоёмкие задачи можно отложить на время
минимальной нагрузки сервера. Для этого нужно:
* в секциях файла `.gitlab-ci.yml`, запускающих задачи с высокой нагрузкой,
добавить
```yaml
only:
- schedules
```
подробнее это описано [здесь](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified)
* в веб-интерфейсе в меню **CI/CD** / **Расписания** добавить **Новое расписание**
и назначить исполнение задачи на время, когда нагрузка на сервер минимальна.
Для пропуска запланированной задачи в исполняемый скрипт нужно добавить
проверку условия запуска. Например, чтобы отменить запуск компиляции,
если за последний день (86400 секунд) не было изменений, можно оформить
`.gitlab-ci.yml` примерно так:
```yaml
nightly-job:
only:
- schedules
script:
- "[ $(($(date +%s)-$(git log -1 --date=format:%s --format=%cd))) -gt 86400 ] && exit 0"
- make
```

View File

@ -1,33 +1,31 @@
---
title: "Установка и настройка GitLab в LXC"
category: Программирование
tags: программирование, gitlab, git, lxc, контейнеры, ubuntu,
summary:
toc: yes
...
= Установка и настройка GitLab в LXC
:category: Программирование
:tags: программирование, gitlab, git, lxc, контейнеры, ubuntu,
[TOC]
:toc:
Установка выполняется в операционной системе Ubuntu Bionic.
### LXC
== LXC
Создание базового контейнера:
```sh
[source,sh]
----
lxc-create -t download -n bionic-base -- --dist ubuntu --release bionic --arch amd64
```
----
Создание контейнеров для GitLab и GitLab Runner:
```sh
[source,sh]
----
lxc-copy -n bionic-base -N gitlab-bionic -s
lxc-copy -n bionic-base -N gitlab-runner-bionic -s
```
----
Файл `/var/lib/lxc/gitlab-bionic/config`:
```
....
# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
@ -50,11 +48,11 @@ lxc.autodev = 1
lxc.pty.max = 16384
lxc.cgroup.devices.allow = c 10:200 rwm
lxc.mount.entry = /dev/net dev/net none bind,create=dir
```
....
Файл `/var/lib/lxc/gitlab-runner-bionic/config`:
```
....
# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
@ -82,65 +80,67 @@ lxc.autodev = 1
lxc.pty.max = 16384
lxc.cgroup.devices.allow = c 10:200 rwm
lxc.mount.entry = /dev/net dev/net none bind,create=dir
```
....
### GitLab
== GitLab
Установить GitLab:
```sh
[source,sh]
----
sudo lxc-start -n gitlab-bionic
sudo lxc-attach -n gitlab-bionic
sudo apt install curl
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo apt install gitlab-ce
```
----
Отредактировать файл `/etc/locale.gen` и сгенерировать локали для системы:
Отредактировать файл `/etc/locale.gen` и сгенерировать локали для
системы:
```sh
[source,sh]
----
sudo locale-gen
```
----
Отредактировать файл `/etc/gitlab/gitlab.rb` и выполнить:
```sh
[source,sh]
----
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart
```
----
### GitLab Runner и Docker
== GitLab Runner и Docker
Установить GitLab Runner:
```sh
[source,sh]
----
sudo lxc-start -n runner-bionic
sudo lxc-attach -n runner-bionic
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt install gitlab-runner docker.io
sudo gitlab-runner register
```
----
Во время установки ввести токен приведённый на странице `admin/runners`,
а в качестве исполнителя задач `docker`.
Для работы Docker внутри контейнера нужно удалить AppArmor:
```sh
[source,sh]
----
sudo apt purge apparmor
```
----
Внутри контейнера для Docker желательно использовать драйвер `btrfs`
cat /etc/docker/daemon.json
Внутри контейнера для Docker желательно использовать драйвер `btrfs` cat
/etc/docker/daemon.json
{
"storage-driver": "btrfs"
}
\{ ``storage-driver'': ``btrfs'' }
== Ссылки
### Ссылки
* [GitLab Runner](https://docs.gitlab.com/runner/register/index.html)
* [Runners](https://docs.gitlab.com/ee/ci/runners/)
* [Gitlab-CI](https://habr.com/ru/company/southbridge/blog/306596/)
* https://docs.gitlab.com/runner/register/index.html[GitLab Runner]
* https://docs.gitlab.com/ee/ci/runners/[Runners]
* https://habr.com/ru/company/southbridge/blog/306596/[Gitlab-CI]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
= Библиотеки для C, C++
:category: Программирование
:tags: программирование, C, C++, Qt,
:toc:
== C
* http://nanomsg.org[nanomsg]: сетевое взаимодействие
* https://noping.cc[oping]: работа с ICMP-пакетами
* https://github.com/xianyi/OpenBLAS[openblas]: оптимизированная версия
https://ru.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms[BLAS]
== C++
* https://github.com/nlohmann/json[JSON]
* https://github.com/fmtlib/fmt[fmtlib]: форматирование строк
* https://github.com/gabime/spdlog[spdlog]: журналирование
* https://github.com/skystrife/cpptoml[cpptoml]: чтение
https://github.com/toml-lang/toml[TOML]
* https://github.com/martinmoene/gsl-lite/[gsl-lite]: реализация
рекомедаций https://github.com/isocpp/CppCoreGuidelines[C++ Core
Guidelines]
* http://www.holoborodko.com/pavel/mpfr[mpfrc++]: C++ интерфейс для
https://www.mpfr.org/[MPFR]
== Qt
* https://github.com/sjinks/qt_signalwatcher[Обработка сигналов UNIX]

View File

@ -1,30 +0,0 @@
---
title: "Библиотеки для C, C++"
category: Программирование
tags: программирование, C, C++, Qt,
summary:
toc: yes
...
[TOC]
### C
* [nanomsg](http://nanomsg.org): сетевое взаимодействие
* [oping](https://noping.cc): работа с ICMP-пакетами
* [openblas](https://github.com/xianyi/OpenBLAS): оптимизированная версия
[BLAS](https://ru.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms)
### C++
* [JSON](https://github.com/nlohmann/json)
* [fmtlib](https://github.com/fmtlib/fmt): форматирование строк
* [spdlog](https://github.com/gabime/spdlog): журналирование
* [cpptoml](https://github.com/skystrife/cpptoml): чтение [TOML](https://github.com/toml-lang/toml)
* [gsl-lite](https://github.com/martinmoene/gsl-lite/): реализация рекомедаций [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines)
* [mpfrc++](http://www.holoborodko.com/pavel/mpfr): C++ интерфейс для [MPFR](https://www.mpfr.org/)
### Qt
* [Обработка сигналов UNIX](https://github.com/sjinks/qt_signalwatcher)

View File

@ -0,0 +1,156 @@
= Работа с датами и временем
:category: Программирование
:tags: программирование, время, часы, дата,
:toc:
== Временные шкалы
В идеале системы учёта времени должны обладать тремя характеристиками:
[arabic]
. _точность_ (время базируется на атомном стандарте, каждая секунда
отсчитывается как секунда в системе СИ, нет високосных секунд, переводов
на зимнее или летнее время и т.п.);
. _простота_ (каждый '`день`' состоит из 86400 "`секунд`");
. _календарные дни_ (дни календаря точно соответствуют вращению Земли).
На практике есть возможность выбрать шкалу только с двумя
характеристиками из трёх.
[arabic]
. точность и календарные дни. Примером такой шкалы является UTC, в
которой отсчёт дней и секунд ведётся разными методами (секунды
исчисляются по атомному стандарту, а дни по суточному вращению Земли), а
соответствие достигается вводом _секунды координации_;
. календарные дни и простота. Примером такой шкалы является POSIX (IEEE
Std 1003.1-1988), в которой день всегда равен 86400 секундам;
. точность и простота. Этими характеристиками обладают технические шкалы
(атомные часы, GPS), в которых не важен учёт дней.
== Классы времени
Время можно условно поделить на два класса: физическое и гражданское.
[arabic]
. _Физическое_ время представляет собой точки на непрерывной шкале,
такую концепцию достаточно точно отражает UTC, если можно пренебречь
_секундой координации_ (дополнительная секунда, добавляемая к UTC 30
июня или 31 декабря для согласования со средним солнечным временем UT1.
В этот момент время условно обозначается как 23:59:60, а на шкале UTC
две секунды отображаются как одна).
. _Гражданское_ время представляется полями (год, месяц, число, час,
минута, секунда, доли секунды, а также временная зона и календарь,
который по умолчанию считается Григорианским).
Почти всегда существует возможность однозначно перевести физическое
время в гражданское и наоборот, но при этом следует различать их
свойства и применение (ближайшая аналогия — массивы байтов и символьные
строки).
Основная проблема состоит в том, что в обычном употреблении не всегда
можно сделать вывод о том, какой класс времени подразумевается, и
гражданское время меняется на основании юридических актов (указов,
постановлений и т.п.), что приводит к неоднозначности при планировании
событий.
== Обработка на компьютере
=== Хранение и отображение
Для ссылки на момент во времени необходимо использовать единую шкалу, на
которой нет разрывов, связанных с летним временем. Примером стандарта
времени с такой шкалой является UTC. Локальное или местное время для
таких целей не подходит, так как на его шкале имеются разрывы и
неоднозначности, связанные с переходами на летнее время и обратно.
Если нужно сохранить значение локального времени, то необходимо
сохранить также смещение относительно UTC, чтобы временную отметку можно
было интерпретировать однозначно. Необходимо помнить, что местное время
может отличаться от UTC на интервал не кратный часу (например, в
Нидерландах с 1909-05-01 по 1937-06-30 смещение времени от UTC
составляло 19 минут и 32.13 секунд).
Правила хранения и отображения времени:
[arabic]
. Время всегда хранится в UTC. При необходимости дополнительно
сохраняется информация о временной зоне (смещение и/или название).
. Для вывода на экран время переводится в местное.
. При выводе на экран отличного от местного времени необходимо указывать
название часового пояса или типа исчисления (например, Юлианский
календарь).
=== Системное время для администратора
Системный администратор должен следить за тем, чтобы файлы базы данных
описания временных зон *tzdata* имели одну версию в рамках комплекса и
обновлялись регулярно, чтобы минимизировать расхождения с внешними
системами. Особенно это важно делать при издании новых правил учёта
зимнего или летнего времени.
На серверах аппаратные часы всегда должны использовать UTC. Операционные
системы тоже должны использовать UTC, чтобы при возникновении проблем в
файлах журналов было указано время в едином формате.
В рамках комплекса следует использовать синхронизацию времени, даже если
нет доверенного источника более высокого уровня.
=== Клиентские приложения
В общем случае нельзя доверять временным отметкам внешних клиентов, так
как невозможно гарантировать их корректность. Программа должна
самостоятельно ставить временные отметки для происходящих событий.
Исключением являются программные комплексы, в которых предусмотрено
наличие доверенных приложений, ответственных за установку временных
отметок.
=== Postgresql
Сервер базы данных должен использовать только временную зону UTC. Для
этого в файле настройки сервера `postgresql.conf` должна быть строка
....
timezone = 'UTC'
....
При создании таблиц необходимо использовать типы данных
`timestamp without time zone` и `time without time zone`. Если данные о
времени должны содержать информацию о временной зоне или смещении
относительно UTC, то нужно создать дополнительные столбцы, информацию из
которых должно обрабатывать клиентское приложение. Например, временные
отметки можно хранить в таком виде
[source,sql]
----
CREATE TABLE time_stamps (
time_stamp time without time zone, -- временная отметка
time_zone character(12), -- текстовое название временной зоны
shift integer -- смещение локального времени относительно UTC в секундах
);
----
Смещение следует записывать в четырёхбайтное знаковое целое, так как оно
может быть как положительным, так и отрицательным, а его максимальное
значение может составлять 14 * 60 * 60 = 50400 секунд. Несмотря на
приведённый выше пример с временной зоной Нидерландов, микросекундами
можно пренебречь, так как современные временные зоны имеют смещения
кратные минутам, а точность до микросекунд в далёком прошлом обычно не
требуется.
Чтобы клиентская программа могла получить выборку, привязанную к
некоторой временной зоне можно использовать оператор `AT TIME ZONE`,
например
[source,sql]
----
SELECT TIMESTAMP '2001-02-16 20:38:40Z' AT TIME ZONE 'MSK';
----
В результате время будет преобразовано из временной зоны UTC в MSK.
Модификатор `Z` в записи времени указывает на принадлежность зоне UTC.
=== Qt
Класс `QTimeZone` предназначен для получения информации о временной зоне
и перевода времени из одной временной зоны в другую.

View File

@ -1,159 +0,0 @@
---
title: "Работа с датами и временем"
category: Программирование
tags: программирование, время, часы, дата,
summary:
toc: yes
toc-depth: 4
...
[TOC]
### Временные шкалы
В идеале системы учёта времени должны обладать тремя характеристиками:
1. очность_ (время базируется на атомном стандарте, каждая секунда
отсчитывается как секунда в системе СИ, нет високосных секунд, переводов
на зимнее или летнее время и т.п.);
2. _простота_ (каждый "день" состоит из 86400 "секунд");
3. алендарные дни_ (дни календаря точно соответствуют вращению Земли).
На практике есть возможность выбрать шкалу только с двумя характеристиками
из трёх.
1. точность и календарные дни. Примером такой шкалы является UTC,
в которой отсчёт дней и секунд ведётся разными методами (секунды
исчисляются по атомному стандарту, а дни по суточному вращению Земли),
а соответствие достигается вводом _секунды координации_;
2. календарные дни и простота. Примером такой шкалы является POSIX
(IEEE Std 1003.1-1988), в которой день всегда равен 86400 секундам;
3. точность и простота. Этими характеристиками обладают технические
шкалы (атомные часы, GPS), в которых не важен учёт дней.
### Классы времени
Время можно условно поделить на два класса: физическое и гражданское.
1. _Физическое_ время представляет собой точки на непрерывной шкале, такую
концепцию достаточно точно отражает UTC, если можно пренебречь _секундой
координации_ (дополнительная секунда, добавляемая к UTC 30 июня или 31 декабря
для согласования со средним солнечным временем UT1. В этот момент время
условно обозначается как 23:59:60, а на шкале UTC две секунды отображаются
как одна).
2. ражданское_ время представляется полями (год, месяц, число, час, минута,
секунда, доли секунды, а также временная зона и календарь, который по умолчанию
считается Григорианским).
Почти всегда существует возможность однозначно перевести физическое время
в гражданское и наоборот, но при этом следует различать их свойства и
применение (ближайшая аналогия — массивы байтов и символьные строки).
Основная проблема состоит в том, что в обычном употреблении не всегда можно
сделать вывод о том, какой класс времени подразумевается, и гражданское
время меняется на основании юридических актов (указов, постановлений и т.п.),
что приводит к неоднозначности при планировании событий.
### Обработка на компьютере
#### Хранение и отображение
Для ссылки на момент во времени необходимо использовать единую шкалу,
на которой нет разрывов, связанных с летним временем. Примером стандарта
времени с такой шкалой является UTC. Локальное или местное время для таких
целей не подходит, так как на его шкале имеются разрывы и неоднозначности,
связанные с переходами на летнее время и обратно.
Если нужно сохранить значение локального времени, то необходимо сохранить
также смещение относительно UTC, чтобы временную отметку можно было
интерпретировать однозначно. Необходимо помнить, что местное время может
отличаться от UTC на интервал не кратный часу (например, в Нидерландах
с 1909-05-01 по 1937-06-30 смещение времени от UTC составляло
19 минут и 32.13 секунд).
Правила хранения и отображения времени:
1. Время всегда хранится в UTC. При необходимости дополнительно сохраняется
информация о временной зоне (смещение и/или название).
2. Для вывода на экран время переводится в местное.
3. При выводе на экран отличного от местного времени необходимо указывать
название часового пояса или типа исчисления (например, Юлианский календарь).
#### Системное время для администратора
Системный администратор должен следить за тем, чтобы файлы базы данных
описания временных зон **tzdata** имели одну версию в рамках комплекса
и обновлялись регулярно, чтобы минимизировать расхождения с внешними
системами. Особенно это важно делать при издании новых правил учёта
зимнего или летнего времени.
На серверах аппаратные часы всегда должны использовать UTC. Операционные
системы тоже должны использовать UTC, чтобы при возникновении проблем
в файлах журналов было указано время в едином формате.
В рамках комплекса следует использовать синхронизацию времени, даже
если нет доверенного источника более высокого уровня.
#### Клиентские приложения
В общем случае нельзя доверять временным отметкам внешних клиентов,
так как невозможно гарантировать их корректность. Программа должна
самостоятельно ставить временные отметки для происходящих событий.
Исключением являются программные комплексы, в которых предусмотрено
наличие доверенных приложений, ответственных за установку временных отметок.
#### Postgresql
Сервер базы данных должен использовать только временную зону UTC. Для этого
в файле настройки сервера `postgresql.conf` должна быть строка
```
timezone = 'UTC'
```
При создании таблиц необходимо использовать типы данных `timestamp without time zone`
и `time without time zone`. Если данные о времени должны содержать информацию
о временной зоне или смещении относительно UTC, то нужно создать дополнительные
столбцы, информацию из которых должно обрабатывать клиентское приложение.
Например, временные отметки можно хранить в таком виде
```sql
CREATE TABLE time_stamps (
time_stamp time without time zone, -- временная отметка
time_zone character(12), -- текстовое название временной зоны
shift integer -- смещение локального времени относительно UTC в секундах
);
```
Смещение следует записывать в четырёхбайтное знаковое целое, так как оно
может быть как положительным, так и отрицательным, а его максимальное
значение может составлять 14 * 60 * 60 = 50400 секунд. Несмотря на приведённый
выше пример с временной зоной Нидерландов, микросекундами можно пренебречь,
так как современные временные зоны имеют смещения кратные минутам, а точность
до микросекунд в далёком прошлом обычно не требуется.
Чтобы клиентская программа могла получить выборку, привязанную к некоторой
временной зоне можно использовать оператор `AT TIME ZONE`, например
```sql
SELECT TIMESTAMP '2001-02-16 20:38:40Z' AT TIME ZONE 'MSK';
```
В результате время будет преобразовано из временной зоны UTC в MSK.
Модификатор `Z` в записи времени указывает на принадлежность зоне UTC.
#### Qt
Класс `QTimeZone` предназначен для получения информации о временной зоне
и перевода времени из одной временной зоны в другую.