asciidoc вместо markdown
This commit is contained in:
@ -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
|
||||
Hitchhiker’s Guide to the CMake]
|
||||
|
||||
### Полезные ссылки
|
||||
|
||||
* [Каталог ссылок](https://github.com/onqtam/awesome-cmake)
|
||||
* [CGold: The Hitchhiker’s 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`.
|
38
wiki/Prog/Development/Intel Parallel Studio.adoc
Normal file
38
wiki/Prog/Development/Intel Parallel Studio.adoc
Normal 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
|
||||
----
|
@ -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
|
||||
```
|
@ -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 " открытие результатов в нижнем окне
|
||||
```
|
||||
|
||||
----
|
36
wiki/Prog/Development/Подбор ключей компиляции GCC.adoc
Normal file
36
wiki/Prog/Development/Подбор ключей компиляции GCC.adoc
Normal 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
|
||||
----
|
@ -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
|
||||
```
|
77
wiki/Prog/Development/Профилирование кода.adoc
Normal file
77
wiki/Prog/Development/Профилирование кода.adoc
Normal 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]
|
@ -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)
|
||||
|
@ -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
|
49
wiki/Prog/GIS/Построение профиля местности в QGis.adoc
Normal file
49
wiki/Prog/GIS/Построение профиля местности в QGis.adoc
Normal 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[Матрица высот]
|
@ -1,51 +0,0 @@
|
||||
---
|
||||
title: "Построение профиля местности в QGis"
|
||||
category: Картография
|
||||
tags: картография, qgis, sxf, shp, gdal,
|
||||
summary:
|
||||
...
|
||||
|
||||
|
||||
1) В главном меню QGis **Слой** — **Добавить слой** — **Добавить векторный слой**
|
||||
выбрать и открыть файл с векторным слоем, например, `map.sxf`.
|
||||
|
||||
2) Среди слоёв выбрать слой с рельефом местности и типом геометрии `LineString`.
|
||||
|
||||

|
||||
|
||||
3) На панели **Панель слоёв** правой кнопкой мыши щелкнуть на слое,
|
||||
содержащем данные о высотах, и выбрать **Фильтр...**.
|
||||
|
||||
4) Построить выражение выбирающие только данные с высотами, например,
|
||||
`"CLNAME" ILIKE '%ГОРИЗОНТАЛИ ОСНОВ%'` и нажить **OK**.
|
||||
|
||||
5) На панели **Панель слоёв** правой кнопкой мыши щелкнуть на слое,
|
||||
содержащем данные о высотах, и выбрать **Сохранить как...**. Появившийся
|
||||
новый слой **heights** следует удалить.
|
||||
|
||||
6) В появившемся диалоговом окне выбрать имя выходного файла, например, `heights`.
|
||||
|
||||

|
||||
|
||||
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**.
|
||||
После этого на карте можно строить профили местности.
|
||||
|
||||

|
@ -0,0 +1 @@
|
||||
{"checksum":"81886ef1b8d31cdb2b865473bbeb2cf9","width":671,"height":550}
|
@ -0,0 +1 @@
|
||||
{"checksum":"e76d88ee3db613b3f806d8c773281fdc","width":685,"height":363}
|
@ -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
|
||||
----
|
@ -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
|
||||
```
|
@ -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
|
||||
```
|
||||
|
||||
----
|
391
wiki/Prog/Git/Git основные команды.adoc
Normal file
391
wiki/Prog/Git/Git основные команды.adoc
Normal 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
|
||||
----
|
@ -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
|
||||
```
|
10
wiki/Prog/Git/Git распаковка объекта.adoc
Normal file
10
wiki/Prog/Git/Git распаковка объекта.adoc
Normal file
@ -0,0 +1,10 @@
|
||||
= Git: распаковка объекта
|
||||
:category: Программирование
|
||||
:tags: программирование, git,
|
||||
|
||||
В случае повреждения репозитория можно восстановить отдельные объекты,
|
||||
которые сохраняются в формате zlib. Пример команды:
|
||||
|
||||
....
|
||||
perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' < 1234567890abcdef1234567890abcdef012345 > file
|
||||
....
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
title: "Git: распаковка объекта"
|
||||
category: Программирование
|
||||
tags: программирование, git,
|
||||
monofontoptions:
|
||||
- Scale=0.7
|
||||
...
|
||||
|
||||
В случае повреждения репозитория можно восстановить отдельные
|
||||
объекты, которые сохраняются в формате zlib. Пример команды:
|
||||
|
||||
```
|
||||
perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' < 1234567890abcdef1234567890abcdef012345 > 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
|
||||
```
|
||||
----
|
29
wiki/Prog/Git/Git частичная копия репозитория.adoc
Normal file
29
wiki/Prog/Git/Git частичная копия репозитория.adoc
Normal 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
|
||||
----
|
@ -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
|
||||
```
|
38
wiki/Prog/Git/Gitlab выполнение по расписанию.adoc
Normal file
38
wiki/Prog/Git/Gitlab выполнение по расписанию.adoc
Normal 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
|
||||
----
|
@ -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
|
||||
```
|
@ -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]
|
1364
wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.adoc
Normal file
1364
wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.adoc
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
29
wiki/Prog/Links/Библиотеки C CPP.adoc
Normal file
29
wiki/Prog/Links/Библиотеки C CPP.adoc
Normal 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]
|
@ -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)
|
||||
|
156
wiki/Prog/Time/Работа с датами и временем.adoc
Normal file
156
wiki/Prog/Time/Работа с датами и временем.adoc
Normal 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` предназначен для получения информации о временной зоне
|
||||
и перевода времени из одной временной зоны в другую.
|
@ -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` предназначен для получения информации о временной зоне
|
||||
и перевода времени из одной временной зоны в другую.
|
||||
|
Reference in New Issue
Block a user